Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <array>
7 : #include <cstddef>
8 : #include <limits>
9 : #include <memory>
10 : #include <vector>
11 :
12 : #include "Domain/BoundaryConditions/BoundaryCondition.hpp"
13 : #include "Domain/BoundaryConditions/GetBoundaryConditionsBase.hpp"
14 : #include "Domain/Creators/DomainCreator.hpp" // IWYU pragma: keep
15 : #include "Domain/Domain.hpp"
16 : #include "Domain/Structure/DirectionMap.hpp"
17 : #include "Options/Context.hpp"
18 : #include "Options/String.hpp"
19 : #include "Utilities/TMPL.hpp"
20 :
21 : /// \cond
22 : namespace domain {
23 : namespace CoordinateMaps {
24 : class Affine;
25 : template <size_t VolumeDim>
26 : class DiscreteRotation;
27 : template <typename Map1, typename Map2, typename Map3>
28 : class ProductOf3Maps;
29 : } // namespace CoordinateMaps
30 :
31 : template <typename SourceFrame, typename TargetFrame, typename... Maps>
32 : class CoordinateMap;
33 : } // namespace domain
34 : /// \endcond
35 :
36 : namespace domain {
37 : namespace creators {
38 : /// Create a 3D Domain consisting of eight rotated Blocks.
39 : ///
40 : /// \image html eightcubes_rotated_exploded.png
41 : ///
42 : /// The orientations of the blocks are described in two different ways:
43 : ///
44 : /// - 1 - As orientations of blocks relative to the physical cartesian axes.
45 : ///
46 : /// - 2 - As rotations relative to the physical cartesian axes written using
47 : /// Rubik's cube rotation notation, for the sake of shorter variable names.
48 : ///
49 : /// For reference, this is the notation used:
50 : ///
51 : /// - U - A clockwise 90 degree rotation about the +z axis (The "up" side)
52 : ///
53 : /// - R - A clockwise 90 degree rotation about the +x axis (The "right" side)
54 : ///
55 : /// - F - A clockwise 90 degree rotation about the -y axis (The "front" side)
56 : ///
57 : /// For reference, D, L, and B ("down", "left", and "back") are the inverse
58 : /// rotation to the aforementioned ones, respectively.
59 : /// Note: Whereas Rubik's cube rotations rotate a layer of the 3x3 puzzle
60 : /// cube, we are adopting the notation to apply to rotations of the
61 : /// cube itself.
62 : ///
63 : /// - The -x, -y, -z block has the aligned orientation, that is,
64 : /// xi is aligned with x, eta is aligned with y, and zeta with z.
65 : /// This has block ID 0.
66 : ///
67 : /// - The +x, -y, -z block has the orientation (zeta, eta, -xi).
68 : /// It corresponds to the orientation obtained by the rotation F.
69 : /// This has block ID 1.
70 : ///
71 : /// - The -x, +y, -z block has the orientation (xi, zeta, -eta).
72 : /// It corresponds to the orientation obtained by the rotation R.
73 : /// This has block ID 2.
74 : ///
75 : /// - The +x, +y, -z block has the orientation (zeta, -xi, -eta).
76 : /// It corresponds to the orientation obtained by the rotation F
77 : /// followed by the rotation R.
78 : /// This has block ID 3.
79 : ///
80 : /// - The -x, -y, +z block has the orientation (eta, -xi, zeta).
81 : /// It corresponds to the orientation obtained by the rotation U.
82 : /// This has block ID 4.
83 : ///
84 : /// - The +x, -y, +z block has the orientation (eta, -zeta, -xi).
85 : /// It corresponds to the orientation obtained by the rotation F
86 : /// followed by the rotation U.
87 : /// This has block ID 5.
88 : ///
89 : /// - The -x, +y, +z block has the orientation (zeta, -xi, -eta).
90 : /// It corresponds to the orientation obtained by the rotation R
91 : /// followed by the rotation U (equivalently, F followed by R).
92 : /// This has block ID 6.
93 : ///
94 : /// - The +x, +y, +z block also has the aligned orientation
95 : /// (xi, eta, zeta), relative to the edifice. It is not aligned
96 : /// relative to its neighbors.
97 : /// This has block ID 7.
98 : ///
99 : /// This DomainCreator is useful for testing code that deals with
100 : /// unaligned blocks.
101 1 : class RotatedBricks : public DomainCreator<3> {
102 : public:
103 0 : using maps_list = tmpl::list<
104 : domain::CoordinateMap<Frame::BlockLogical, Frame::Inertial,
105 : CoordinateMaps::ProductOf3Maps<
106 : CoordinateMaps::Affine, CoordinateMaps::Affine,
107 : CoordinateMaps::Affine>>,
108 : domain::CoordinateMap<Frame::BlockLogical, Frame::Inertial,
109 : CoordinateMaps::DiscreteRotation<3>,
110 : CoordinateMaps::ProductOf3Maps<
111 : CoordinateMaps::Affine, CoordinateMaps::Affine,
112 : CoordinateMaps::Affine>>>;
113 :
114 0 : struct LowerBound {
115 0 : using type = std::array<double, 3>;
116 0 : static constexpr Options::String help = {
117 : "Sequence [x,y,z] for lower bound in the target frame."};
118 : };
119 :
120 0 : struct Midpoint {
121 0 : using type = std::array<double, 3>;
122 0 : static constexpr Options::String help = {
123 : "Sequence [x,y,z] for midpoint in the target frame."};
124 : };
125 :
126 0 : struct UpperBound {
127 0 : using type = std::array<double, 3>;
128 0 : static constexpr Options::String help = {
129 : "Sequence [x,y,z] for upper bound in the target frame."};
130 : };
131 :
132 0 : struct IsPeriodicIn {
133 0 : using type = std::array<bool, 3>;
134 0 : static constexpr Options::String help = {
135 : "Sequence in [x,y,z], true if periodic."};
136 : };
137 :
138 0 : struct InitialRefinement {
139 0 : using type = std::array<size_t, 3>;
140 0 : static constexpr Options::String help = {
141 : "Initial refinement level in [x, y, z]."};
142 : };
143 :
144 0 : struct InitialGridPoints {
145 0 : using type = std::array<std::array<size_t, 2>, 3>;
146 0 : static constexpr Options::String help = {
147 : "Initial number of grid points in [[x], [y], [z]]."};
148 : };
149 :
150 : template <typename BoundaryConditionsBase>
151 0 : struct BoundaryCondition {
152 0 : static std::string name() { return "BoundaryCondition"; }
153 0 : static constexpr Options::String help =
154 : "The boundary condition to impose on all sides.";
155 0 : using type = std::unique_ptr<BoundaryConditionsBase>;
156 : };
157 :
158 0 : using common_options = tmpl::list<LowerBound, Midpoint, UpperBound,
159 : InitialRefinement, InitialGridPoints>;
160 0 : using options_periodic = tmpl::list<IsPeriodicIn>;
161 :
162 : template <typename Metavariables>
163 0 : using options = tmpl::append<
164 : common_options,
165 : tmpl::conditional_t<
166 : domain::BoundaryConditions::has_boundary_conditions_base_v<
167 : typename Metavariables::system>,
168 : tmpl::list<BoundaryCondition<
169 : domain::BoundaryConditions::get_boundary_conditions_base<
170 : typename Metavariables::system>>>,
171 : options_periodic>>;
172 :
173 0 : static constexpr Options::String help = {
174 : "A DomainCreator useful for testing purposes.\n"
175 : "RotatedBricks uses eight rotated Blocks to create the rectangular\n"
176 : "prism [LowerX,UpperX] x [LowerY,UpperY] x [LowerZ,UpperZ]. The\n"
177 : "outermost index to InitialGridPoints is the dimension index, and\n"
178 : "the innermost index is the block index along that dimension."};
179 :
180 0 : RotatedBricks(
181 : typename LowerBound::type lower_xyz, typename Midpoint::type midpoint_xyz,
182 : typename UpperBound::type upper_xyz,
183 : typename InitialRefinement::type initial_refinement_level_xyz,
184 : typename InitialGridPoints::type initial_number_of_grid_points_in_xyz,
185 : typename IsPeriodicIn::type is_periodic_in);
186 :
187 0 : RotatedBricks(
188 : typename LowerBound::type lower_xyz, typename Midpoint::type midpoint_xyz,
189 : typename UpperBound::type upper_xyz,
190 : typename InitialRefinement::type initial_refinement_level_xyz,
191 : typename InitialGridPoints::type initial_number_of_grid_points_in_xyz,
192 : std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>
193 : boundary_condition,
194 : const Options::Context& context = {});
195 :
196 0 : RotatedBricks() = default;
197 0 : RotatedBricks(const RotatedBricks&) = delete;
198 0 : RotatedBricks(RotatedBricks&&) = default;
199 0 : RotatedBricks& operator=(const RotatedBricks&) = delete;
200 0 : RotatedBricks& operator=(RotatedBricks&&) = default;
201 0 : ~RotatedBricks() override = default;
202 :
203 0 : Domain<3> create_domain() const override;
204 :
205 : std::vector<DirectionMap<
206 : 3, std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>>>
207 1 : external_boundary_conditions() const override;
208 :
209 1 : std::vector<std::array<size_t, 3>> initial_extents() const override;
210 :
211 1 : std::vector<std::array<size_t, 3>> initial_refinement_levels() const override;
212 :
213 : private:
214 0 : typename LowerBound::type lower_xyz_{
215 : {std::numeric_limits<double>::signaling_NaN()}};
216 0 : typename Midpoint::type midpoint_xyz_{
217 : {std::numeric_limits<double>::signaling_NaN()}};
218 0 : typename UpperBound::type upper_xyz_{
219 : {std::numeric_limits<double>::signaling_NaN()}};
220 0 : typename IsPeriodicIn::type is_periodic_in_{{false, false, false}};
221 0 : typename InitialRefinement::type initial_refinement_level_xyz_{
222 : {std::numeric_limits<size_t>::max()}};
223 0 : typename InitialGridPoints::type initial_number_of_grid_points_in_xyz_{
224 : {{{std::numeric_limits<size_t>::max()}}}};
225 : std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>
226 0 : boundary_condition_;
227 : };
228 : } // namespace creators
229 : } // namespace domain
|