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