Line data Source code
1 1 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : /// \file
5 : /// Declares function unnormalized_face_normal
6 :
7 : #pragma once
8 :
9 : #include <algorithm>
10 : #include <cstddef>
11 : #include <functional>
12 : #include <string>
13 : #include <unordered_map>
14 :
15 : #include "DataStructures/DataBox/Tag.hpp"
16 : #include "DataStructures/Tensor/TypeAliases.hpp"
17 : #include "Domain/CoordinateMaps/Tags.hpp"
18 : #include "Domain/FunctionsOfTime/Tags.hpp"
19 : #include "Domain/InterfaceComputeTags.hpp"
20 : #include "Domain/Tags.hpp" // IWYU pragma: keep
21 : #include "Utilities/Gsl.hpp"
22 : #include "Utilities/TMPL.hpp"
23 :
24 : /// \cond
25 : namespace Tags {
26 : struct Time;
27 : } // namespace Tags
28 : namespace domain {
29 : template <typename, typename, size_t>
30 : class CoordinateMapBase;
31 : } // namespace domain
32 : class DataVector;
33 : template <size_t>
34 : class Direction;
35 : template <size_t Dim, typename Frame>
36 : class ElementMap;
37 : template <size_t>
38 : class Mesh;
39 : /// \endcond
40 :
41 : /// @{
42 : /*!
43 : * \ingroup ComputationalDomainGroup
44 : * \brief Compute the outward grid normal on a face of an Element
45 : *
46 : * \details
47 : * Computes the grid-frame normal by taking the logical-frame unit
48 : * one-form in the given Direction and mapping it to the grid frame
49 : * with the given map, or the given inverse Jacobian.
50 : *
51 : * \example
52 : * \snippet Test_FaceNormal.cpp face_normal_example
53 : */
54 : template <size_t VolumeDim, typename TargetFrame>
55 1 : void unnormalized_face_normal(
56 : const gsl::not_null<tnsr::i<DataVector, VolumeDim, TargetFrame>*> result,
57 : const Mesh<VolumeDim - 1>& interface_mesh,
58 : const InverseJacobian<DataVector, VolumeDim, Frame::ElementLogical,
59 : TargetFrame>& inv_jacobian_on_interface,
60 : const Direction<VolumeDim>& direction);
61 :
62 : template <size_t VolumeDim, typename TargetFrame>
63 1 : tnsr::i<DataVector, VolumeDim, TargetFrame> unnormalized_face_normal(
64 : const Mesh<VolumeDim - 1>& interface_mesh,
65 : const InverseJacobian<DataVector, VolumeDim, Frame::ElementLogical,
66 : TargetFrame>& inv_jacobian_on_interface,
67 : const Direction<VolumeDim>& direction);
68 :
69 : template <size_t VolumeDim, typename TargetFrame>
70 1 : void unnormalized_face_normal(
71 : gsl::not_null<tnsr::i<DataVector, VolumeDim, TargetFrame>*> result,
72 : const Mesh<VolumeDim - 1>& interface_mesh,
73 : const ElementMap<VolumeDim, TargetFrame>& map,
74 : const Direction<VolumeDim>& direction);
75 :
76 : template <size_t VolumeDim, typename TargetFrame>
77 1 : tnsr::i<DataVector, VolumeDim, TargetFrame> unnormalized_face_normal(
78 : const Mesh<VolumeDim - 1>& interface_mesh,
79 : const ElementMap<VolumeDim, TargetFrame>& map,
80 : const Direction<VolumeDim>& direction);
81 :
82 : template <size_t VolumeDim, typename TargetFrame>
83 1 : void unnormalized_face_normal(
84 : gsl::not_null<tnsr::i<DataVector, VolumeDim, TargetFrame>*> result,
85 : const Mesh<VolumeDim - 1>& interface_mesh,
86 : const domain::CoordinateMapBase<Frame::ElementLogical, TargetFrame,
87 : VolumeDim>& map,
88 : const Direction<VolumeDim>& direction);
89 :
90 : template <size_t VolumeDim, typename TargetFrame>
91 1 : tnsr::i<DataVector, VolumeDim, TargetFrame> unnormalized_face_normal(
92 : const Mesh<VolumeDim - 1>& interface_mesh,
93 : const domain::CoordinateMapBase<Frame::ElementLogical, TargetFrame,
94 : VolumeDim>& map,
95 : const Direction<VolumeDim>& direction);
96 :
97 : template <size_t VolumeDim>
98 1 : void unnormalized_face_normal(
99 : gsl::not_null<tnsr::i<DataVector, VolumeDim, Frame::Inertial>*> result,
100 : const Mesh<VolumeDim - 1>& interface_mesh,
101 : const ElementMap<VolumeDim, Frame::Grid>& logical_to_grid_map,
102 : const domain::CoordinateMapBase<Frame::Grid, Frame::Inertial, VolumeDim>&
103 : grid_to_inertial_map,
104 : double time,
105 : const std::unordered_map<
106 : std::string, std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
107 : functions_of_time,
108 : const Direction<VolumeDim>& direction);
109 :
110 : template <size_t VolumeDim>
111 1 : tnsr::i<DataVector, VolumeDim, Frame::Inertial> unnormalized_face_normal(
112 : const Mesh<VolumeDim - 1>& interface_mesh,
113 : const ElementMap<VolumeDim, Frame::Grid>& logical_to_grid_map,
114 : const domain::CoordinateMapBase<Frame::Grid, Frame::Inertial, VolumeDim>&
115 : grid_to_inertial_map,
116 : double time,
117 : const std::unordered_map<
118 : std::string, std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
119 : functions_of_time,
120 : const Direction<VolumeDim>& direction);
121 : /// @}
122 :
123 : namespace domain {
124 : namespace Tags {
125 : /// \ingroup DataBoxTagsGroup
126 : /// \ingroup ComputationalDomainGroup
127 : /// The unnormalized face normal one form
128 : template <size_t VolumeDim, typename Frame = ::Frame::Inertial>
129 1 : struct UnnormalizedFaceNormal : db::SimpleTag {
130 0 : using type = tnsr::i<DataVector, VolumeDim, Frame>;
131 : };
132 :
133 : template <size_t VolumeDim, typename Frame = ::Frame::Inertial>
134 0 : struct UnnormalizedFaceNormalCompute
135 : : db::ComputeTag, UnnormalizedFaceNormal<VolumeDim, Frame> {
136 0 : using base = UnnormalizedFaceNormal<VolumeDim, Frame>;
137 0 : using return_type = typename base::type;
138 0 : static constexpr auto function = static_cast<void (*)(
139 : gsl::not_null<return_type*>, const ::Mesh<VolumeDim - 1>&,
140 : const ::ElementMap<VolumeDim, Frame>&, const ::Direction<VolumeDim>&)>(
141 : &unnormalized_face_normal);
142 0 : using argument_tags =
143 : tmpl::list<Mesh<VolumeDim - 1>, ElementMap<VolumeDim, Frame>,
144 : Direction<VolumeDim>>;
145 0 : using volume_tags = tmpl::list<ElementMap<VolumeDim, Frame>>;
146 : };
147 :
148 : template <size_t VolumeDim>
149 0 : struct UnnormalizedFaceNormalMovingMeshCompute
150 : : db::ComputeTag,
151 : UnnormalizedFaceNormal<VolumeDim, Frame::Inertial> {
152 0 : using base = UnnormalizedFaceNormal<VolumeDim, Frame::Inertial>;
153 0 : using return_type = typename base::type;
154 0 : static constexpr auto function = static_cast<void (*)(
155 : gsl::not_null<return_type*>, const ::Mesh<VolumeDim - 1>&,
156 : const ::ElementMap<VolumeDim, Frame::Grid>&,
157 : const domain::CoordinateMapBase<Frame::Grid, Frame::Inertial, VolumeDim>&,
158 : double,
159 : const std::unordered_map<
160 : std::string,
161 : std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&,
162 : const ::Direction<VolumeDim>&)>(&unnormalized_face_normal);
163 0 : using argument_tags =
164 : tmpl::list<Mesh<VolumeDim - 1>, ElementMap<VolumeDim, Frame::Grid>,
165 : CoordinateMaps::Tags::CoordinateMap<VolumeDim, Frame::Grid,
166 : Frame::Inertial>,
167 : ::Tags::Time, Tags::FunctionsOfTime, Direction<VolumeDim>>;
168 0 : using volume_tags =
169 : tmpl::list<ElementMap<VolumeDim, Frame::Grid>,
170 : CoordinateMaps::Tags::CoordinateMap<VolumeDim, Frame::Grid,
171 : Frame::Inertial>,
172 : ::Tags::Time, Tags::FunctionsOfTime>;
173 : };
174 :
175 : /// \ingroup DataBoxTagsGroup
176 : /// \ingroup ComputationalDomainGroup
177 : /// Specialisation of UnnormalizedFaceNormal for the external boundaries which
178 : /// inverts the normals. Since ExternalBoundariesDirections are meant to
179 : /// represent ghost elements, the normals should correspond to the normals in
180 : /// said element, which are inverted with respect to the current element.
181 : template <size_t VolumeDim, typename Frame>
182 1 : struct InterfaceCompute<Tags::BoundaryDirectionsExterior<VolumeDim>,
183 : UnnormalizedFaceNormalCompute<VolumeDim, Frame>>
184 : : db::ComputeTag,
185 : Tags::Interface<Tags::BoundaryDirectionsExterior<VolumeDim>,
186 : Tags::UnnormalizedFaceNormal<VolumeDim, Frame>> {
187 0 : using base = Tags::Interface<Tags::BoundaryDirectionsExterior<VolumeDim>,
188 : Tags::UnnormalizedFaceNormal<VolumeDim, Frame>>;
189 0 : using dirs = BoundaryDirectionsExterior<VolumeDim>;
190 :
191 0 : static std::string name() {
192 : return "BoundaryDirectionsExterior<UnnormalizedFaceNormal>";
193 : }
194 0 : using return_type = std::unordered_map<::Direction<VolumeDim>,
195 : tnsr::i<DataVector, VolumeDim, Frame>>;
196 0 : static void function(const gsl::not_null<return_type*> normals,
197 : const std::unordered_map<::Direction<VolumeDim>,
198 : ::Mesh<VolumeDim - 1>>& meshes,
199 : const ::ElementMap<VolumeDim, Frame>& map) {
200 : for (const auto& direction_and_mesh : meshes) {
201 : const auto& direction = direction_and_mesh.first;
202 : const auto& mesh = direction_and_mesh.second;
203 : auto internal_face_normal =
204 : unnormalized_face_normal(mesh, map, direction);
205 : std::transform(internal_face_normal.begin(), internal_face_normal.end(),
206 : internal_face_normal.begin(), std::negate<>());
207 : (*normals)[direction] = std::move(internal_face_normal);
208 : }
209 : }
210 :
211 0 : using argument_tags = tmpl::list<Tags::Interface<dirs, Mesh<VolumeDim - 1>>,
212 : Tags::ElementMap<VolumeDim, Frame>>;
213 : };
214 :
215 : template <size_t VolumeDim>
216 0 : struct InterfaceCompute<Tags::BoundaryDirectionsExterior<VolumeDim>,
217 : UnnormalizedFaceNormalMovingMeshCompute<VolumeDim>>
218 : : db::ComputeTag,
219 : Tags::Interface<
220 : Tags::BoundaryDirectionsExterior<VolumeDim>,
221 : Tags::UnnormalizedFaceNormal<VolumeDim, Frame::Inertial>> {
222 0 : using base =
223 : Tags::Interface<Tags::BoundaryDirectionsExterior<VolumeDim>,
224 : Tags::UnnormalizedFaceNormal<VolumeDim, Frame::Inertial>>;
225 0 : using dirs = BoundaryDirectionsExterior<VolumeDim>;
226 :
227 0 : static std::string name() {
228 : return "BoundaryDirectionsExterior<UnnormalizedFaceNormal>";
229 : }
230 0 : using return_type =
231 : std::unordered_map<::Direction<VolumeDim>,
232 : tnsr::i<DataVector, VolumeDim, Frame::Inertial>>;
233 0 : static void function(
234 : const gsl::not_null<return_type*> normals,
235 : const std::unordered_map<::Direction<VolumeDim>, ::Mesh<VolumeDim - 1>>&
236 : meshes,
237 : const ::ElementMap<VolumeDim, Frame::Grid>& logical_to_grid_map,
238 : const domain::CoordinateMapBase<Frame::Grid, Frame::Inertial, VolumeDim>&
239 : grid_to_inertial_map,
240 : const double time,
241 : const std::unordered_map<
242 : std::string,
243 : std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
244 : functions_of_time) {
245 : for (const auto& direction_and_mesh : meshes) {
246 : const auto& direction = direction_and_mesh.first;
247 : const auto& mesh = direction_and_mesh.second;
248 : auto internal_face_normal = unnormalized_face_normal(
249 : mesh, logical_to_grid_map, grid_to_inertial_map, time,
250 : functions_of_time, direction);
251 : std::transform(internal_face_normal.begin(), internal_face_normal.end(),
252 : internal_face_normal.begin(), std::negate<>());
253 : (*normals)[direction] = std::move(internal_face_normal);
254 : }
255 : }
256 :
257 0 : using argument_tags =
258 : tmpl::list<Tags::Interface<dirs, Mesh<VolumeDim - 1>>,
259 : Tags::ElementMap<VolumeDim, Frame::Grid>,
260 : CoordinateMaps::Tags::CoordinateMap<VolumeDim, Frame::Grid,
261 : Frame::Inertial>,
262 : ::Tags::Time, Tags::FunctionsOfTime>;
263 : };
264 :
265 : } // namespace Tags
266 : } // namespace domain
|