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 Affine;
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 = tmpl::list<
101 : domain::CoordinateMap<Frame::BlockLogical, Frame::Inertial,
102 : CoordinateMaps::Affine>,
103 : domain::CoordinateMap<
104 : Frame::BlockLogical, Frame::Inertial,
105 : CoordinateMaps::ProductOf2Maps<CoordinateMaps::Affine,
106 : CoordinateMaps::Affine>>,
107 : domain::CoordinateMap<Frame::BlockLogical, Frame::Inertial,
108 : CoordinateMaps::ProductOf3Maps<
109 : CoordinateMaps::Affine, CoordinateMaps::Affine,
110 : CoordinateMaps::Affine>>>;
111 :
112 0 : struct BlockBounds {
113 0 : using type = std::array<std::vector<double>, Dim>;
114 0 : static constexpr Options::String help = {
115 : "Coordinates of block boundaries in each dimension."};
116 : };
117 :
118 0 : struct IsPeriodicIn {
119 0 : using type = std::array<bool, Dim>;
120 0 : static constexpr Options::String help = {
121 : "Whether the domain is periodic in each dimension."};
122 : };
123 :
124 0 : struct InitialLevels {
125 0 : using type = std::array<size_t, Dim>;
126 0 : static constexpr Options::String help = {
127 : "Initial refinement level in each dimension."};
128 : };
129 :
130 0 : struct InitialGridPoints {
131 0 : using type = std::array<size_t, Dim>;
132 0 : static constexpr Options::String help = {
133 : "Initial number of grid points in each dimension."};
134 : };
135 :
136 0 : struct RefinedLevels {
137 0 : using type = std::vector<RefinementRegion<Dim>>;
138 0 : static constexpr Options::String help = {
139 : "h-refined regions. Later entries take priority."};
140 : };
141 :
142 0 : struct RefinedGridPoints {
143 0 : using type = std::vector<RefinementRegion<Dim>>;
144 0 : static constexpr Options::String help = {
145 : "p-refined regions. Later entries take priority."};
146 : };
147 :
148 0 : struct BlocksToExclude {
149 0 : using type = std::vector<std::array<size_t, Dim>>;
150 0 : static constexpr Options::String help = {
151 : "List of Block indices to exclude, if any."};
152 : };
153 :
154 : template <typename Metavariables>
155 0 : using options = tmpl::list<
156 : BlockBounds, InitialLevels, InitialGridPoints, RefinedLevels,
157 : RefinedGridPoints, BlocksToExclude,
158 : tmpl::conditional_t<
159 : domain::BoundaryConditions::has_boundary_conditions_base_v<
160 : typename Metavariables::system>,
161 : typename Rectilinear<Dim>::template BoundaryConditions<
162 : domain::BoundaryConditions::get_boundary_conditions_base<
163 : typename Metavariables::system>>,
164 : IsPeriodicIn>>;
165 :
166 0 : static constexpr Options::String help = {
167 : "AlignedLattice creates a regular lattice of blocks whose corners are\n"
168 : "given by tensor products of the specified BlockBounds. Each Block in\n"
169 : "the lattice is identified by a Dim-tuple of zero-based indices\n"
170 : "Supplying a list of these tuples to BlocksToExclude will result in\n"
171 : "the domain having the corresponding Blocks excluded. See the Domain\n"
172 : "Creation tutorial in the documentation for more information on Block\n"
173 : "numberings in rectilinear domains. Note that if any Blocks are\n"
174 : "excluded, setting the option IsPeriodicIn to `true` in any dimension\n"
175 : "will trigger an error, as periodic boundary\n"
176 : "conditions for this domain with holes is not supported."};
177 :
178 0 : AlignedLattice(std::array<std::vector<double>, Dim> block_bounds,
179 : std::array<size_t, Dim> initial_refinement_levels,
180 : std::array<size_t, Dim> initial_number_of_grid_points,
181 : std::vector<RefinementRegion<Dim>> refined_refinement,
182 : std::vector<RefinementRegion<Dim>> refined_grid_points,
183 : std::vector<std::array<size_t, Dim>> blocks_to_exclude,
184 : std::array<bool, Dim> is_periodic_in = make_array<Dim>(false),
185 : const Options::Context& context = {});
186 :
187 0 : AlignedLattice(
188 : std::array<std::vector<double>, Dim> block_bounds,
189 : std::array<size_t, Dim> initial_refinement_levels,
190 : std::array<size_t, Dim> initial_number_of_grid_points,
191 : std::vector<RefinementRegion<Dim>> refined_refinement,
192 : std::vector<RefinementRegion<Dim>> refined_grid_points,
193 : std::vector<std::array<size_t, Dim>> blocks_to_exclude,
194 : std::array<std::array<std::unique_ptr<
195 : domain::BoundaryConditions::BoundaryCondition>,
196 : 2>,
197 : Dim>
198 : boundary_conditions,
199 : const Options::Context& context = {});
200 :
201 : template <typename BoundaryConditionsBase>
202 0 : AlignedLattice(
203 : std::array<std::vector<double>, Dim> block_bounds,
204 : std::array<size_t, Dim> initial_refinement_levels,
205 : std::array<size_t, Dim> initial_number_of_grid_points,
206 : std::vector<RefinementRegion<Dim>> refined_refinement,
207 : std::vector<RefinementRegion<Dim>> refined_grid_points,
208 : std::vector<std::array<size_t, Dim>> blocks_to_exclude,
209 : std::array<std::variant<std::unique_ptr<BoundaryConditionsBase>,
210 : typename Rectilinear<Dim>::
211 : template LowerUpperBoundaryCondition<
212 : BoundaryConditionsBase>>,
213 : Dim>
214 : boundary_conditions,
215 : const Options::Context& context = {})
216 : : AlignedLattice(std::move(block_bounds), initial_refinement_levels,
217 : initial_number_of_grid_points, refined_refinement,
218 : refined_grid_points, blocks_to_exclude,
219 : Rectilinear<Dim>::transform_boundary_conditions(
220 : std::move(boundary_conditions)),
221 : context) {}
222 :
223 0 : AlignedLattice() = default;
224 0 : AlignedLattice(const AlignedLattice&) = delete;
225 0 : AlignedLattice(AlignedLattice&&) = default;
226 0 : AlignedLattice& operator=(const AlignedLattice&) = delete;
227 0 : AlignedLattice& operator=(AlignedLattice&&) = default;
228 0 : ~AlignedLattice() override = default;
229 :
230 0 : Domain<Dim> create_domain() const override;
231 :
232 : std::vector<DirectionMap<
233 : Dim, std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>>>
234 1 : external_boundary_conditions() const override;
235 :
236 1 : std::vector<std::array<size_t, Dim>> initial_extents() const override;
237 :
238 1 : std::vector<std::array<size_t, Dim>> initial_refinement_levels()
239 : const override;
240 :
241 : private:
242 0 : std::array<std::vector<double>, Dim> block_bounds_{
243 : make_array<Dim, std::vector<double>>({})};
244 0 : std::array<bool, Dim> is_periodic_in_{make_array<Dim>(false)};
245 0 : std::array<size_t, Dim> initial_refinement_levels_{
246 : make_array<Dim>(std::numeric_limits<size_t>::max())};
247 0 : std::array<size_t, Dim> initial_number_of_grid_points_{
248 : make_array<Dim>(std::numeric_limits<size_t>::max())};
249 0 : std::vector<RefinementRegion<Dim>> refined_refinement_{};
250 0 : std::vector<RefinementRegion<Dim>> refined_grid_points_{};
251 0 : std::vector<std::array<size_t, Dim>> blocks_to_exclude_{};
252 0 : Index<Dim> number_of_blocks_by_dim_{};
253 : std::array<
254 : std::array<std::unique_ptr<domain::BoundaryConditions::BoundaryCondition>,
255 : 2>,
256 : Dim>
257 0 : boundary_conditions_{};
258 : };
259 : } // namespace creators
260 : } // namespace domain
|