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