Line data Source code
1 1 : // Distributed under the MIT License. 2 : // See LICENSE.txt for details. 3 : 4 : /// \file 5 : /// Defines class template Block. 6 : 7 : #pragma once 8 : 9 : #include <cstddef> 10 : #include <iosfwd> 11 : #include <memory> 12 : #include <string> 13 : #include <unordered_set> 14 : 15 : #include "Domain/CoordinateMaps/CoordinateMap.hpp" 16 : #include "Domain/Structure/BlockNeighbor.hpp" 17 : #include "Domain/Structure/Direction.hpp" 18 : #include "Domain/Structure/DirectionMap.hpp" 19 : 20 : /// \cond 21 : namespace Frame { 22 : struct BlockLogical; 23 : struct Inertial; 24 : } // namespace Frame 25 : namespace PUP { 26 : class er; 27 : } // namespace PUP 28 : /// \endcond 29 : 30 : /// \ingroup ComputationalDomainGroup 31 : /// A Block<VolumeDim> is a region of a VolumeDim-dimensional computational 32 : /// domain that defines the root node of a tree which is used to construct the 33 : /// Elements that cover a region of the computational domain. 34 : /// 35 : /// Each codimension 1 boundary of a Block<VolumeDim> is either an external 36 : /// boundary or identical to a boundary of one other Block. 37 : /// 38 : /// A Block has logical coordinates that go from -1 to +1 in each 39 : /// dimension. The global coordinates are obtained from the logical 40 : /// coordinates from the Coordinatemap: CoordinateMap::operator() takes 41 : /// Points in the BlockLogical Frame (i.e., block logical coordinates) and 42 : /// returns Points in the Inertial Frame (i.e., the global coordinate frame in 43 : /// which the problem to be solved is set up). 44 : template <size_t VolumeDim> 45 1 : class Block { 46 : public: 47 : /// \param stationary_map the CoordinateMap. 48 : /// \param id a unique ID. 49 : /// \param neighbors info about the Blocks that share a codimension 1 50 : /// boundary with this Block. 51 : /// \param name Human-readable name for the block 52 1 : Block(std::unique_ptr<domain::CoordinateMapBase< 53 : Frame::BlockLogical, Frame::Inertial, VolumeDim>>&& stationary_map, 54 : size_t id, DirectionMap<VolumeDim, BlockNeighbor<VolumeDim>> neighbors, 55 : std::string name = ""); 56 : 57 0 : Block() = default; 58 0 : ~Block() = default; 59 0 : Block(const Block&) = delete; 60 0 : Block(Block&&) = default; 61 0 : Block& operator=(const Block&) = delete; 62 0 : Block& operator=(Block&&) = default; 63 : 64 : /// \brief The map used when the coordinate map is time-independent. 65 : /// 66 : /// \see is_time_dependent() 67 : const domain::CoordinateMapBase<Frame::BlockLogical, Frame::Inertial, 68 : VolumeDim>& 69 1 : stationary_map() const; 70 : 71 : /// \brief The map going from the block logical frame to the last time 72 : /// independent frame. Only used when the coordinate map is time-dependent. 73 : /// 74 : /// \see is_time_dependent() moving_mesh_grid_to_inertial_map() 75 : const domain::CoordinateMapBase<Frame::BlockLogical, Frame::Grid, VolumeDim>& 76 1 : moving_mesh_logical_to_grid_map() const; 77 : 78 : /// \brief The map going from the last time independent frame to the frame in 79 : /// which the equations are solved. Only used when the coordinate map is 80 : /// time-dependent. 81 : /// 82 : /// \see is_time_dependent() moving_mesh_logical_to_grid_map() 83 : const domain::CoordinateMapBase<Frame::Grid, Frame::Inertial, VolumeDim>& 84 1 : moving_mesh_grid_to_inertial_map() const; 85 : 86 : /// \brief The map going from the last time independent frame to the 87 : /// distorted frame. Only used when the coordinate map is 88 : /// time-dependent. See \ref domain_concepts to see how the distorted 89 : /// frame is defined. 90 : /// 91 : /// \see is_time_dependent() moving_mesh_distorted_to_grid_map() 92 : const domain::CoordinateMapBase<Frame::Grid, Frame::Distorted, VolumeDim>& 93 1 : moving_mesh_grid_to_distorted_map() const; 94 : 95 : /// \brief The map going from the distorted frame to the frame in 96 : /// which the equations are solved. Only used when the coordinate map is 97 : /// time-dependent. See \ref domain_concepts to see how the distorted 98 : /// frame is defined. 99 : /// 100 : /// \see is_time_dependent() moving_mesh_grid_to_distorted_map() 101 : const domain::CoordinateMapBase<Frame::Distorted, Frame::Inertial, VolumeDim>& 102 1 : moving_mesh_distorted_to_inertial_map() const; 103 : 104 : /// \brief Returns `true` if the block has time-dependent maps. 105 1 : bool is_time_dependent() const { return stationary_map_ == nullptr; } 106 : 107 : /// \brief Returns `true` if the block has a distorted frame. 108 : /// 109 : /// If a block has a distorted frame, then 110 : /// - moving_mesh_grid_to_distorted_map() is non-null 111 : /// - moving_mesh_distorted_to_inertial_map() is non-null 112 : /// - moving_mesh_grid_to_inertial_map() is non-null 113 : /// Note in particular the last point above: If the block is time-dependent, 114 : /// then the block must have a grid_to_inertial map independent of whether 115 : /// it has a distorted frame. This allows us to write more efficient maps. 116 : /// In particular, we often care only about the grid_to_inertial map, so we 117 : /// can code that map directly instead of composing 118 : /// grid_to_distorted + distorted_to_inertial maps at runtime. 119 : /// 120 : /// If a block does not have a distorted frame, then 121 : /// - moving_mesh_grid_to_distorted_map() is null 122 : /// - moving_mesh_distorted_to_inertial_map() is null 123 : /// - moving_mesh_grid_to_inertial_map() is non-null 124 : /// - If we ever find ourselves needing ::Frame::Distorted coordinates 125 : /// in that block, we can assume that ::Frame::Distorted and ::Frame::Grid 126 : /// are the same. Usually this case will not occur. 127 1 : bool has_distorted_frame() const { 128 : return moving_mesh_grid_to_distorted_map_ != nullptr and 129 : moving_mesh_distorted_to_inertial_map_ != nullptr; 130 : } 131 : 132 : /// \brief Given a Block that has a time-independent map, injects the 133 : /// time-dependent map into the Block. 134 1 : void inject_time_dependent_map( 135 : std::unique_ptr< 136 : domain::CoordinateMapBase<Frame::Grid, Frame::Inertial, VolumeDim>> 137 : moving_mesh_grid_to_inertial_map, 138 : std::unique_ptr< 139 : domain::CoordinateMapBase<Frame::Grid, Frame::Distorted, VolumeDim>> 140 : moving_mesh_grid_to_distorted_map = nullptr, 141 : std::unique_ptr<domain::CoordinateMapBase<Frame::Distorted, 142 : Frame::Inertial, VolumeDim>> 143 : moving_mesh_distorted_to_inertial_map = nullptr); 144 : 145 : /// A unique identifier for the Block that is in the range 146 : /// [0, number_of_blocks -1] where number_of_blocks is the number 147 : /// of Blocks that cover the computational domain. 148 1 : size_t id() const { return id_; } 149 : 150 : /// Information about the neighboring Blocks. 151 1 : const DirectionMap<VolumeDim, BlockNeighbor<VolumeDim>>& neighbors() const { 152 : return neighbors_; 153 : } 154 : 155 : /// The directions of the faces of the Block that are external boundaries. 156 1 : const std::unordered_set<Direction<VolumeDim>>& external_boundaries() const { 157 : return external_boundaries_; 158 : } 159 : 160 0 : const std::string& name() const { return name_; } 161 : 162 : /// Serialization for Charm++ 163 : // NOLINTNEXTLINE(google-runtime-references) 164 1 : void pup(PUP::er& p); 165 : 166 : private: 167 : template <size_t LocalVolumeDim> 168 : // NOLINTNEXTLINE(readability-redundant-declaration) 169 0 : friend bool operator==(const Block<LocalVolumeDim>& lhs, 170 : const Block<LocalVolumeDim>& rhs); 171 : 172 : std::unique_ptr<domain::CoordinateMapBase<Frame::BlockLogical, 173 : Frame::Inertial, VolumeDim>> 174 0 : stationary_map_{nullptr}; 175 : std::unique_ptr< 176 : domain::CoordinateMapBase<Frame::BlockLogical, Frame::Grid, VolumeDim>> 177 0 : moving_mesh_logical_to_grid_map_{nullptr}; 178 : std::unique_ptr< 179 : domain::CoordinateMapBase<Frame::Grid, Frame::Inertial, VolumeDim>> 180 0 : moving_mesh_grid_to_inertial_map_{nullptr}; 181 : std::unique_ptr< 182 : domain::CoordinateMapBase<Frame::Grid, Frame::Distorted, VolumeDim>> 183 0 : moving_mesh_grid_to_distorted_map_{nullptr}; 184 : std::unique_ptr< 185 : domain::CoordinateMapBase<Frame::Distorted, Frame::Inertial, VolumeDim>> 186 0 : moving_mesh_distorted_to_inertial_map_{nullptr}; 187 : 188 0 : size_t id_{0}; 189 0 : DirectionMap<VolumeDim, BlockNeighbor<VolumeDim>> neighbors_; 190 0 : std::unordered_set<Direction<VolumeDim>> external_boundaries_; 191 0 : std::string name_; 192 : }; 193 : 194 : template <size_t VolumeDim> 195 0 : std::ostream& operator<<(std::ostream& os, const Block<VolumeDim>& block); 196 : 197 : template <size_t VolumeDim> 198 0 : bool operator!=(const Block<VolumeDim>& lhs, const Block<VolumeDim>& rhs);