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