Line data Source code
1 1 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : /// \file
5 : /// Defines class template Domain.
6 :
7 : #pragma once
8 :
9 : #include <array>
10 : #include <cstddef>
11 : #include <iosfwd>
12 : #include <memory>
13 : #include <string>
14 : #include <unordered_map>
15 : #include <unordered_set>
16 : #include <vector>
17 :
18 : #include "Domain/Block.hpp"
19 : #include "Domain/DomainHelpers.hpp"
20 : #include "Domain/ExcisionSphere.hpp"
21 : #include "Utilities/ConstantExpressions.hpp"
22 :
23 : namespace Frame {
24 : struct BlockLogical;
25 : } // namespace Frame
26 : namespace PUP {
27 : class er;
28 : } // namespace PUP
29 : /// \cond
30 : namespace domain {
31 : template <typename SourceFrame, typename TargetFrame, size_t Dim>
32 : class CoordinateMapBase;
33 : } // namespace domain
34 : /// \endcond
35 :
36 : /*!
37 : * \brief Holds entities related to the computational domain.
38 : */
39 : namespace domain {}
40 :
41 : /*!
42 : * \ingroup ComputationalDomainGroup
43 : * \brief A wrapper around a vector of Blocks that represent the computational
44 : * domain.
45 : *
46 : * ### Serialization and versioning
47 : *
48 : * The domain will be serialized and written to output files so it can be used
49 : * for interpolations, as are `domain::FunctionOfTime` classes. To be able to
50 : * read in domains written by older versions of the code the `pup` function in
51 : * this class and all `pup` functions it invokes support lightweight versioning.
52 : * A `version` integer is written alongside the data when serializing, and read
53 : * back in when deserializing. Increment the version number every time you make
54 : * changes to the `pup` function. Retain support for unpacking data written by
55 : * previous versions whenever possible. When adding a new field to serialize,
56 : * you can simply pack/unpack the new field only for newer versions like this:
57 : *
58 : * ```cpp
59 : * void pup(PUP::er& p) {
60 : * size_t version = 1; // Incremented from 0 to 1
61 : * p | version;
62 : * if (version >= 0) {
63 : * p | some_data_;
64 : * }
65 : * if (version >= 1) {
66 : * p | added_data_;
67 : * } else if (p.isUnpacking()) {
68 : * // You may have to initialize added_data_ here if default-construction
69 : * // isn't sufficient.
70 : * }
71 : * }
72 : * ```
73 : *
74 : * When removing or changing a field, make sure to deserialize old data
75 : * consistent with how it was written:
76 : *
77 : * ```cpp
78 : * void pup(PUP::er& p) {
79 : * size_t version = 2; // Incremented from 1 to 2
80 : * p | version;
81 : * if (version < 2) {
82 : * // The field some_data_ was changed in version 2
83 : * OldDataType old_some_data_;
84 : * p | old_some_data_;
85 : * // Possibly use the old deserialized data to initialize the changed field
86 : * some_data_ = old_some_data_ * 2.;
87 : * } else {
88 : * p | some_data_;
89 : * }
90 : * // ...
91 : * }
92 : * ```
93 : *
94 : * Make sure that all data types you serialize in the `pup` function also
95 : * support versioning. Also make sure to keep all factory-creatable classes
96 : * registered that were written by old versions of the code.
97 : */
98 : template <size_t VolumeDim>
99 1 : class Domain {
100 : public:
101 : /// \brief Create a Domain from its blocks
102 : ///
103 : /// \param blocks each Block of the domain.
104 : /// \param excision_spheres Any ExcisionSphere%s in the domain.
105 : /// \param block_groups Labels to refer to groups of blocks. The groups can
106 : /// overlap, and they don't have to cover all blocks in the domain.
107 : /// The groups can be used to refer to multiple blocks at once.
108 1 : explicit Domain(
109 : std::vector<Block<VolumeDim>> blocks,
110 : std::unordered_map<std::string, ExcisionSphere<VolumeDim>>
111 : excision_spheres = {},
112 : std::unordered_map<std::string, std::unordered_set<std::string>>
113 : block_groups = {});
114 :
115 : /*!
116 : * \brief Create a Domain using CoordinateMaps to encode the Orientations.
117 : * This constructor does not support periodic boundary conditions.
118 : *
119 : * \details A constructor that does not require the user to provide a corner
120 : * numbering scheme. Constructs a global corner numbering for each pair
121 : * of abutting Blocks from their maps alone. The numbering is used to
122 : * set up the corresponding Orientation, and then is discarded; the
123 : * next pair of blocks uses a new global corner numbering, and so on,
124 : * until all pairs of abutting Blocks have had their Orientations
125 : * determined. For more information on setting up domains, see the
126 : * [domain creation tutorial](\ref tutorial_domain_creation).
127 : *
128 : * \param maps The BlockLogical -> Inertial coordinate map for each block.
129 : * \param excision_spheres Any ExcisionSphere%s in the domain.
130 : * \param block_names A human-readable name for every block, or empty if no
131 : * block names have been chosen (yet).
132 : * \param block_groups Labels to refer to groups of blocks. The groups can
133 : * overlap, and they don't have to cover all blocks in the domain. The groups
134 : * can be used to refer to multiple blocks at once.
135 : */
136 1 : explicit Domain(
137 : std::vector<std::unique_ptr<domain::CoordinateMapBase<
138 : Frame::BlockLogical, Frame::Inertial, VolumeDim>>>
139 : maps,
140 : std::unordered_map<std::string, ExcisionSphere<VolumeDim>>
141 : excision_spheres = {},
142 : std::vector<std::string> block_names = {},
143 : std::unordered_map<std::string, std::unordered_set<std::string>>
144 : block_groups = {});
145 :
146 : /*!
147 : * \brief Create a Domain using a corner numbering scheme to encode the
148 : * Orientations
149 : *
150 : * \see [domain creation tutorial](@ref tutorial_domain_creation)
151 : *
152 : * \param maps The BlockLogical -> Inertial coordinate map for each block.
153 : * \param corners_of_all_blocks The corner numbering for each block's corners
154 : * according to the global corner number scheme. The details of the corner
155 : * numbering scheme are described in the
156 : * [tutorial](@ref tutorial_orientations).
157 : * \param identifications Used to impose periodic boundary conditions on the
158 : * domain. To identify faces, `identifications` should contain the PairOfFaces
159 : * containing the corners of each pair of faces that you wish to identify with
160 : * one another. The number of `identifications` must be even.
161 : * \param excision_spheres Any ExcisionSphere%s in the domain.
162 : * \param block_names A human-readable name for every block, or empty if no
163 : * block names have been chosen (yet).
164 : * \param block_groups Labels to refer to groups of blocks. The groups can
165 : * overlap, and they don't have to cover all blocks in the domain. The groups
166 : * can be used to refer to multiple blocks at once.
167 : */
168 1 : Domain(std::vector<std::unique_ptr<domain::CoordinateMapBase<
169 : Frame::BlockLogical, Frame::Inertial, VolumeDim>>>
170 : maps,
171 : const std::vector<std::array<size_t, two_to_the(VolumeDim)>>&
172 : corners_of_all_blocks,
173 : const std::vector<PairOfFaces>& identifications = {},
174 : std::unordered_map<std::string, ExcisionSphere<VolumeDim>>
175 : excision_spheres = {},
176 : std::vector<std::string> block_names = {},
177 : std::unordered_map<std::string, std::unordered_set<std::string>>
178 : block_groups = {});
179 :
180 0 : Domain() = default;
181 0 : ~Domain() = default;
182 0 : Domain(const Domain&) = delete;
183 0 : Domain(Domain&&) = default;
184 0 : Domain<VolumeDim>& operator=(const Domain<VolumeDim>&) = delete;
185 0 : Domain<VolumeDim>& operator=(Domain<VolumeDim>&&) = default;
186 :
187 0 : void inject_time_dependent_map_for_block(
188 : size_t block_id,
189 : std::unique_ptr<
190 : domain::CoordinateMapBase<Frame::Grid, Frame::Inertial, VolumeDim>>
191 : moving_mesh_grid_to_inertial_map,
192 : std::unique_ptr<
193 : domain::CoordinateMapBase<Frame::Grid, Frame::Distorted, VolumeDim>>
194 : moving_mesh_grid_to_distorted_map = nullptr,
195 : std::unique_ptr<domain::CoordinateMapBase<Frame::Distorted,
196 : Frame::Inertial, VolumeDim>>
197 : moving_mesh_distorted_to_inertial_map = nullptr);
198 :
199 0 : void inject_time_dependent_map_for_excision_sphere(
200 : const std::string& excision_sphere_name,
201 : std::unique_ptr<
202 : domain::CoordinateMapBase<Frame::Grid, Frame::Inertial, VolumeDim>>
203 : moving_mesh_grid_to_inertial_map);
204 :
205 0 : const std::vector<Block<VolumeDim>>& blocks() const { return blocks_; }
206 :
207 0 : bool is_time_dependent() const;
208 :
209 : const std::unordered_map<std::string, ExcisionSphere<VolumeDim>>&
210 0 : excision_spheres() const {
211 : return excision_spheres_;
212 : }
213 :
214 : /// Labels to refer to groups of blocks. The groups can overlap, and they
215 : /// don't have to cover all blocks in the domain. The groups can be used to
216 : /// refer to multiple blocks at once.
217 : const std::unordered_map<std::string, std::unordered_set<std::string>>&
218 1 : block_groups() const {
219 : return block_groups_;
220 : }
221 :
222 : /// The block names in the current domain.
223 1 : std::vector<std::string> block_names() const;
224 :
225 : // NOLINTNEXTLINE(google-runtime-references)
226 0 : void pup(PUP::er& p);
227 :
228 : private:
229 0 : std::vector<Block<VolumeDim>> blocks_{};
230 : std::unordered_map<std::string, ExcisionSphere<VolumeDim>>
231 0 : excision_spheres_{};
232 : std::unordered_map<std::string, std::unordered_set<std::string>>
233 0 : block_groups_{};
234 : };
235 :
236 : template <size_t VolumeDim>
237 0 : bool operator==(const Domain<VolumeDim>& lhs, const Domain<VolumeDim>& rhs);
238 :
239 : template <size_t VolumeDim>
240 0 : bool operator!=(const Domain<VolumeDim>& lhs, const Domain<VolumeDim>& rhs);
241 :
242 : template <size_t VolumeDim>
243 0 : std::ostream& operator<<(std::ostream& os, const Domain<VolumeDim>& d);
|