Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <cstddef>
7 : #include <string>
8 :
9 : #include "DataStructures/Tensor/Tensor.hpp"
10 : #include "Domain/CoordinateMaps/Distribution.hpp"
11 : #include "Domain/Tags.hpp"
12 : #include "Options/Auto.hpp"
13 : #include "Options/String.hpp"
14 : #include "Utilities/Gsl.hpp"
15 : #include "Utilities/TMPL.hpp"
16 :
17 : /// \cond
18 : class DataVector;
19 : /// \endcond
20 :
21 : namespace domain {
22 :
23 : /// @{
24 : /*!
25 : * \ingroup ComputationalDomainGroup
26 : * \brief Coordinates suitable for visualizing large radii by compressing them
27 : * logarithmically or inversely.
28 : *
29 : * Rescales the coordinates $\boldsymbol{x}$ as
30 : *
31 : * \begin{equation}
32 : * \hat{\boldsymbol{x}} = \frac{\hat{r}}{r} \boldsymbol{x}
33 : * \text{,}
34 : * \end{equation}
35 : *
36 : * for $r > r_0$, where $r=\sqrt{x^2+y^2+z^2}$ is the Euclidean coordinate
37 : * radius and $r_0$ is the `inner_radius`.
38 : * The coordinates are compressed from $r \in [r_0, r_1]$ to $\hat{r} \in [r_0,
39 : * \hat{r}_1]$, where the `outer_radius` $r_1$ can be incomprehensibly large
40 : * like $10^9$ and the compressed outer radius $\hat{r}_1$ is reasonably small
41 : * so it can be visualized well. We choose
42 : *
43 : * \begin{equation}
44 : * \hat{r}_1 = r_0 \log_{10}(r_1)
45 : * \end{equation}
46 : *
47 : * so the compressed outer radius is a multiple of the inner radius and
48 : * increases with the outer radius as well, but exponentials are tamed.
49 : *
50 : * The radial compression map $\hat{r}(r)$ is just the inverse of the
51 : * `domain::CoordinateMaps::Interval` map, which is also used to distribute grid
52 : * points radially. Therefore, radial grid points will be distributed linearly
53 : * in the radially compressed coordinates if you use the same `compression`
54 : * distribution that you used to distribute radial grid points in the
55 : * `CoordsFrame`.
56 : *
57 : * \see domain::CoordinateMaps::Interval
58 : */
59 : template <typename DataType, size_t Dim, typename CoordsFrame>
60 1 : void radially_compressed_coordinates(
61 : gsl::not_null<tnsr::I<DataType, Dim, CoordsFrame>*> result,
62 : const tnsr::I<DataType, Dim, CoordsFrame>& coordinates, double inner_radius,
63 : double outer_radius, CoordinateMaps::Distribution compression);
64 : template <typename DataType, size_t Dim, typename CoordsFrame>
65 1 : tnsr::I<DataType, Dim, CoordsFrame> radially_compressed_coordinates(
66 : const tnsr::I<DataType, Dim, CoordsFrame>& coordinates, double inner_radius,
67 : double outer_radius, CoordinateMaps::Distribution compression);
68 : /// @}
69 :
70 : /// Options for radially compressed coordinates
71 : ///
72 : /// \see radially_compressed_coordinates
73 1 : struct RadiallyCompressedCoordinatesOptions {
74 0 : static constexpr Options::String help =
75 : "Define radially compressed coordinates for visualizing large outer "
76 : "radii.";
77 0 : struct InnerRadius {
78 0 : using type = double;
79 0 : static constexpr Options::String help =
80 : "Radially compressed coordinates begin at this radius, and coincide "
81 : "with the original coordinates for smaller radii.";
82 : };
83 0 : struct OuterRadius {
84 0 : using type = double;
85 0 : static constexpr Options::String help =
86 : "Outer radius of the domain which will be compressed down to a "
87 : "comprehensible radius, namely to r_inner * log10(r_outer).";
88 : };
89 0 : struct Compression {
90 0 : using type = CoordinateMaps::Distribution;
91 0 : static constexpr Options::String help =
92 : "Compression mode: 'Logarithmic' or 'Inverse'. If you use the same "
93 : "mode that you used to distribute radial grid points then the "
94 : "grid points will be distributed linearly in the radially compressed "
95 : "coordinates.";
96 : };
97 0 : using options = tmpl::list<InnerRadius, OuterRadius, Compression>;
98 0 : void pup(PUP::er& p);
99 0 : double inner_radius;
100 0 : double outer_radius;
101 0 : CoordinateMaps::Distribution compression;
102 : };
103 :
104 : namespace OptionTags {
105 :
106 0 : struct RadiallyCompressedCoordinates {
107 0 : using type = Options::Auto<domain::RadiallyCompressedCoordinatesOptions,
108 : Options::AutoLabel::None>;
109 0 : static constexpr Options::String help =
110 : "Define radially compressed coordinates for visualizing large outer "
111 : "radii.";
112 : };
113 :
114 : } // namespace OptionTags
115 :
116 : namespace Tags {
117 :
118 : /// Options for radially compressed coordinates, or `std::nullopt` if none
119 : /// were specified in the input file
120 : ///
121 : /// \see radially_compressed_coordinates
122 1 : struct RadiallyCompressedCoordinatesOptions : db::SimpleTag {
123 0 : using type = std::optional<domain::RadiallyCompressedCoordinatesOptions>;
124 0 : static constexpr bool pass_metavariables = false;
125 0 : using option_tags = tmpl::list<OptionTags::RadiallyCompressedCoordinates>;
126 0 : static type create_from_options(type value) { return value; };
127 : };
128 :
129 : /// @{
130 : /*!
131 : * \brief Coordinates suitable for visualizing large radii by compressing them
132 : * logarithmically or inversely.
133 : *
134 : * The coordinate map reduces to the identity if no options for radially
135 : * compressed coordinates were specified in the input file.
136 : *
137 : * \see radially_compressed_coordinates
138 : */
139 : template <size_t Dim, typename CoordsFrame>
140 1 : struct RadiallyCompressedCoordinates : db::SimpleTag {
141 0 : using type = tnsr::I<DataVector, Dim, CoordsFrame>;
142 : };
143 :
144 : template <size_t Dim, typename CoordsFrame>
145 0 : struct RadiallyCompressedCoordinatesCompute
146 : : RadiallyCompressedCoordinates<Dim, CoordsFrame>,
147 : db::ComputeTag {
148 0 : using base = RadiallyCompressedCoordinates<Dim, CoordsFrame>;
149 0 : using return_type = tnsr::I<DataVector, Dim, CoordsFrame>;
150 0 : using argument_tags = tmpl::list<Tags::Coordinates<Dim, CoordsFrame>,
151 : Tags::RadiallyCompressedCoordinatesOptions>;
152 0 : static void function(
153 : const gsl::not_null<tnsr::I<DataVector, Dim, CoordsFrame>*> result,
154 : const tnsr::I<DataVector, Dim, CoordsFrame>& coords,
155 : const std::optional<domain::RadiallyCompressedCoordinatesOptions>&
156 : options) {
157 : if (options.has_value()) {
158 : radially_compressed_coordinates(result, coords, options->inner_radius,
159 : options->outer_radius,
160 : options->compression);
161 : } else {
162 : *result = coords;
163 : }
164 : }
165 : };
166 : /// @}
167 :
168 : } // namespace Tags
169 : } // namespace domain
|