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);
|