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 <iosfwd>
9 : #include <limits>
10 : #include <memory>
11 : #include <vector>
12 :
13 : #include "DataStructures/Index.hpp"
14 : #include "Domain/BoundaryConditions/BoundaryCondition.hpp"
15 : #include "Domain/BoundaryConditions/GetBoundaryConditionsBase.hpp"
16 : #include "Domain/Creators/DomainCreator.hpp"
17 : #include "Domain/Creators/Rectilinear.hpp"
18 : #include "Domain/Domain.hpp"
19 : #include "Domain/Structure/DirectionMap.hpp"
20 : #include "Options/Context.hpp"
21 : #include "Options/String.hpp"
22 : #include "Utilities/MakeArray.hpp"
23 : #include "Utilities/TMPL.hpp"
24 :
25 : /// \cond
26 : namespace domain {
27 : namespace CoordinateMaps {
28 : class Interval;
29 : template <typename Map1, typename Map2>
30 : class ProductOf2Maps;
31 : template <typename Map1, typename Map2, typename Map3>
32 : class ProductOf3Maps;
33 : } // namespace CoordinateMaps
34 :
35 : template <typename SourceFrame, typename TargetFrame, typename... Maps>
36 : class CoordinateMap;
37 : } // namespace domain
38 : /// \endcond
39 :
40 : namespace domain {
41 1 : namespace creators {
42 :
43 : template <size_t Dim>
44 0 : struct RefinementRegion {
45 0 : std::array<size_t, Dim> lower_corner_index;
46 0 : std::array<size_t, Dim> upper_corner_index;
47 0 : std::array<size_t, Dim> refinement;
48 :
49 0 : struct LowerCornerIndex {
50 0 : using type = std::array<size_t, Dim>;
51 0 : static constexpr Options::String help = {"Lower bound of refined region."};
52 : };
53 :
54 0 : struct UpperCornerIndex {
55 0 : using type = std::array<size_t, Dim>;
56 0 : static constexpr Options::String help = {"Upper bound of refined region."};
57 : };
58 :
59 0 : struct Refinement {
60 0 : using type = std::array<size_t, Dim>;
61 0 : static constexpr Options::String help = {"Refinement inside region."};
62 : };
63 :
64 0 : static constexpr Options::String help = {
65 : "A region to be refined differently from the default for the lattice.\n"
66 : "The region is a box between the block boundaries indexed by the\n"
67 : "Lower- and UpperCornerIndex options."};
68 0 : using options = tmpl::list<LowerCornerIndex, UpperCornerIndex, Refinement>;
69 0 : RefinementRegion(const std::array<size_t, Dim>& lower_corner_index_in,
70 : const std::array<size_t, Dim>& upper_corner_index_in,
71 : const std::array<size_t, Dim>& refinement_in)
72 : : lower_corner_index(lower_corner_index_in),
73 : upper_corner_index(upper_corner_index_in),
74 : refinement(refinement_in) {}
75 0 : RefinementRegion() = default;
76 : };
77 :
78 : /// \cond
79 : // This is needed to print the default value for the RefinedGridPoints
80 : // option. Since the default value is an empty vector, this function
81 : // is never actually called.
82 : template <size_t Dim>
83 : [[noreturn]] std::ostream& operator<<(std::ostream& /*s*/,
84 : const RefinementRegion<Dim>& /*unused*/);
85 : /// \endcond
86 :
87 : /// \brief Create a Domain consisting of multiple aligned Blocks arrayed in a
88 : /// lattice.
89 : ///
90 : /// This is useful for setting up problems with piecewise smooth initial data,
91 : /// problems that specify different boundary conditions on distinct parts of
92 : /// the boundary, or problems that need different length scales initially.
93 : ///
94 : /// \note Adaptive mesh refinement can never join Block%s, so use the fewest
95 : /// number of Block%s that your problem needs. More initial Element%s can be
96 : /// created by specifying a larger `InitialRefinement`.
97 : template <size_t Dim>
98 1 : class AlignedLattice : public DomainCreator<Dim> {
99 : public:
100 0 : using maps_list =
101 : tmpl::list<domain::CoordinateMap<Frame::BlockLogical, Frame::Inertial,
102 : CoordinateMaps::Interval>,
103 : domain::CoordinateMap<
104 : Frame::BlockLogical, Frame::Inertial,
105 : CoordinateMaps::ProductOf2Maps<CoordinateMaps::Interval,
106 : CoordinateMaps::Interval>>,
107 : domain::CoordinateMap<
108 : Frame::BlockLogical, Frame::Inertial,
109 : CoordinateMaps::ProductOf3Maps<CoordinateMaps::Interval,
110 : CoordinateMaps::Interval,
111 : CoordinateMaps::Interval>>>;
112 :
113 0 : struct BlockBounds {
114 0 : using type = std::array<std::vector<double>, Dim>;
115 0 : static constexpr Options::String help = {
116 : "Coordinates of block boundaries in each dimension."};
117 : };
118 :
119 0 : struct Distributions {
120 0 : using type =
121 : std::array<std::vector<domain::CoordinateMaps::Distribution>, Dim>;
122 0 : static constexpr Options::String help = {
123 : "Grid point distribution in each dimension."};
124 : };
125 :
126 0 : struct SingularityPositions {
127 0 : using type = std::array<std::vector<double>, Dim>;
128 0 : static constexpr Options::String help = {
129 : "Singularity positions in each dimension."};
130 : };
131 :
132 0 : struct IsPeriodicIn {
133 0 : using type = std::array<bool, Dim>;
134 0 : static constexpr Options::String help = {
135 : "Whether the domain is periodic in each dimension."};
136 : };
137 :
138 0 : struct InitialLevels {
139 0 : using type = std::array<size_t, Dim>;
140 0 : static constexpr Options::String help = {
141 : "Initial refinement level in each dimension."};
142 : };
143 :
144 0 : struct InitialGridPoints {
145 0 : using type = std::array<size_t, Dim>;
146 0 : static constexpr Options::String help = {
147 : "Initial number of grid points in each dimension."};
148 : };
149 :
150 0 : struct RefinedLevels {
151 0 : using type = std::vector<RefinementRegion<Dim>>;
152 0 : static constexpr Options::String help = {
153 : "h-refined regions. Later entries take priority."};
154 : };
155 :
156 0 : struct RefinedGridPoints {
157 0 : using type = std::vector<RefinementRegion<Dim>>;
158 0 : static constexpr Options::String help = {
159 : "p-refined regions. Later entries take priority."};
160 : };
161 :
162 0 : struct BlocksToExclude {
163 0 : using type = std::vector<std::array<size_t, Dim>>;
164 0 : static constexpr Options::String help = {
165 : "List of Block indices to exclude, if any."};
166 : };
167 :
168 : template <typename Metavariables>
169 0 : using options = tmpl::list<
170 : BlockBounds, Distributions, SingularityPositions, InitialLevels,
171 : InitialGridPoints, RefinedLevels, RefinedGridPoints, BlocksToExclude,
172 : tmpl::conditional_t<
173 : domain::BoundaryConditions::has_boundary_conditions_base_v<
174 : typename Metavariables::system>,
175 : typename Rectilinear<Dim>::template BoundaryConditions<
176 : domain::BoundaryConditions::get_boundary_conditions_base<
177 : typename Metavariables::system>>,
178 : IsPeriodicIn>>;
179 :
180 0 : static constexpr Options::String help = {
181 : "AlignedLattice creates a regular lattice of blocks whose corners are\n"
182 : "given by tensor products of the specified BlockBounds. Each Block in\n"
183 : "the lattice is identified by a Dim-tuple of zero-based indices\n"
184 : "Supplying a list of these tuples to BlocksToExclude will result in\n"
185 : "the domain having the corresponding Blocks excluded. See the Domain\n"
186 : "Creation tutorial in the documentation for more information on Block\n"
187 : "numberings in rectilinear domains. Note that if any Blocks are\n"
188 : "excluded, setting the option IsPeriodicIn to `true` in any dimension\n"
189 : "will trigger an error, as periodic boundary\n"
190 : "conditions for this domain with holes is not supported."};
191 :
192 0 : AlignedLattice(
193 : std::array<std::vector<double>, Dim> block_bounds,
194 : std::array<std::vector<domain::CoordinateMaps::Distribution>, Dim>
195 : distributions,
196 : std::array<std::vector<double>, Dim> singularity_positions,
197 : std::array<size_t, Dim> initial_refinement_levels,
198 : std::array<size_t, Dim> initial_number_of_grid_points,
199 : std::vector<RefinementRegion<Dim>> refined_refinement,
200 : std::vector<RefinementRegion<Dim>> refined_grid_points,
201 : std::vector<std::array<size_t, Dim>> blocks_to_exclude,
202 : std::array<bool, Dim> is_periodic_in = make_array<Dim>(false),
203 : const Options::Context& context = {});
204 :
205 0 : AlignedLattice(
206 : std::array<std::vector<double>, Dim> block_bounds,
207 : std::array<std::vector<domain::CoordinateMaps::Distribution>, Dim>
208 : distributions,
209 : std::array<std::vector<double>, Dim> singularity_positions,
210 : std::array<size_t, Dim> initial_refinement_levels,
211 : std::array<size_t, Dim> initial_number_of_grid_points,
212 : std::vector<RefinementRegion<Dim>> refined_refinement,
213 : std::vector<RefinementRegion<Dim>> refined_grid_points,
214 : std::vector<std::array<size_t, Dim>> blocks_to_exclude,
215 : std::array<std::array<std::unique_ptr<
216 : domain::BoundaryConditions::BoundaryCondition>,
217 : 2>,
218 : Dim>
219 : boundary_conditions,
220 : const Options::Context& context = {});
221 :
222 : template <typename BoundaryConditionsBase>
223 0 : AlignedLattice(
224 : std::array<std::vector<double>, Dim> block_bounds,
225 : std::array<std::vector<domain::CoordinateMaps::Distribution>, Dim>
226 : distributions,
227 : std::array<std::vector<double>, Dim> singularity_positions,
228 : std::array<size_t, Dim> initial_refinement_levels,
229 : std::array<size_t, Dim> initial_number_of_grid_points,
230 : std::vector<RefinementRegion<Dim>> refined_refinement,
231 : std::vector<RefinementRegion<Dim>> refined_grid_points,
232 : std::vector<std::array<size_t, Dim>> blocks_to_exclude,
233 : std::array<std::variant<std::unique_ptr<BoundaryConditionsBase>,
234 : typename Rectilinear<Dim>::
235 : template LowerUpperBoundaryCondition<
236 : BoundaryConditionsBase>>,
237 : Dim>
238 : boundary_conditions,
239 : const Options::Context& context = {})
240 : : AlignedLattice(std::move(block_bounds), std::move(distributions),
241 : std::move(singularity_positions),
242 : initial_refinement_levels, initial_number_of_grid_points,
243 : refined_refinement, refined_grid_points,
244 : blocks_to_exclude,
245 : Rectilinear<Dim>::transform_boundary_conditions(
246 : std::move(boundary_conditions)),
247 : context) {}
248 :
249 0 : AlignedLattice() = default;
250 0 : AlignedLattice(const AlignedLattice&) = delete;
251 0 : AlignedLattice(AlignedLattice&&) = default;
252 0 : AlignedLattice& operator=(const AlignedLattice&) = delete;
253 0 : AlignedLattice& operator=(AlignedLattice&&) = default;
254 0 : ~AlignedLattice() override = default;
255 :
256 0 : Domain<Dim> create_domain() const override;
257 :
258 : std::vector<DirectionMap<
259 : Dim, std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>>>
260 1 : external_boundary_conditions() const override;
261 :
262 1 : std::vector<std::string> block_names() const override;
263 :
264 1 : std::vector<std::array<size_t, Dim>> initial_extents() const override;
265 :
266 1 : std::vector<std::array<size_t, Dim>> initial_refinement_levels()
267 : const override;
268 :
269 : private:
270 0 : std::array<std::vector<double>, Dim> block_bounds_{
271 : make_array<Dim, std::vector<double>>({})};
272 : std::array<std::vector<domain::CoordinateMaps::Distribution>, Dim>
273 0 : distributions_{};
274 0 : std::array<std::vector<std::optional<double>>, Dim> singularity_positions_{};
275 0 : std::array<bool, Dim> is_periodic_in_{make_array<Dim>(false)};
276 0 : std::array<size_t, Dim> initial_refinement_levels_{
277 : make_array<Dim>(std::numeric_limits<size_t>::max())};
278 0 : std::array<size_t, Dim> initial_number_of_grid_points_{
279 : make_array<Dim>(std::numeric_limits<size_t>::max())};
280 0 : std::vector<RefinementRegion<Dim>> refined_refinement_{};
281 0 : std::vector<RefinementRegion<Dim>> refined_grid_points_{};
282 0 : std::vector<std::array<size_t, Dim>> blocks_to_exclude_{};
283 0 : Index<Dim> number_of_blocks_by_dim_{};
284 : std::array<
285 : std::array<std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>,
286 : 2>,
287 : Dim>
288 0 : boundary_conditions_{};
289 : };
290 : } // namespace creators
291 : } // namespace domain
|