Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <cstddef>
7 : #include <memory>
8 : #include <optional>
9 :
10 : #include "DataStructures/DataBox/Tag.hpp"
11 : #include "DataStructures/DataVector.hpp"
12 : #include "DataStructures/Tensor/EagerMath/DotProduct.hpp"
13 : #include "DataStructures/Tensor/EagerMath/Magnitude.hpp"
14 : #include "DataStructures/Tensor/Tensor.hpp"
15 : #include "DataStructures/Variables.hpp"
16 : #include "Domain/CoordinateMaps/CoordinateMap.hpp"
17 : #include "Domain/Structure/Direction.hpp"
18 : #include "Domain/Structure/DirectionMap.hpp"
19 : #include "Evolution/DiscontinuousGalerkin/Actions/ComputeTimeDerivativeHelpers.hpp"
20 : #include "Evolution/DiscontinuousGalerkin/NormalVectorTags.hpp"
21 : #include "Utilities/Gsl.hpp"
22 : #include "Utilities/TMPL.hpp"
23 :
24 : namespace evolution::dg::Actions::detail {
25 : struct OneOverNormalVectorMagnitude : db::SimpleTag {
26 : using type = Scalar<DataVector>;
27 : };
28 :
29 : template <size_t Dim>
30 : struct NormalVector : db::SimpleTag {
31 : using type = tnsr::I<DataVector, Dim, Frame::Inertial>;
32 : };
33 :
34 : /*!
35 : * \brief Computes the normal covector, magnitude of the unnormalized normal
36 : * covector, and in curved spacetimes the normal vector.
37 : *
38 : * The `fields_on_face` argument is used as a temporary buffer via the
39 : * `OneOverNormalVectorMagnitude` tag and also used to return the normalized
40 : * normal vector via the `NormalVector<Dim>` tag. The `fields_on_face` argument
41 : * also serves as the input for the inverse spatial metric when the spacetime is
42 : * curved. The `fields_on_face` argument must have tags `NormalVector<Dim>` and
43 : * `OneOverNormalVectorMagnitude`. If the system specifies
44 : * `System::inverse_spatial_metric_tag` then this tag must also be in the
45 : * Variables.
46 : */
47 : template <typename System, size_t Dim, typename FieldsOnFaceTags>
48 : void unit_normal_vector_and_covector_and_magnitude_impl(
49 : const gsl::not_null<Scalar<DataVector>*> face_normal_magnitude,
50 : const gsl::not_null<tnsr::i<DataVector, Dim, Frame::Inertial>*>
51 : unit_normal_covector,
52 : const gsl::not_null<Variables<FieldsOnFaceTags>*> fields_on_face,
53 : const tnsr::i<DataVector, Dim, Frame::Inertial>&
54 : unnormalized_normal_covector) {
55 : if constexpr (has_inverse_spatial_metric_tag_v<System>) {
56 : using inverse_spatial_metric_tag =
57 : typename System::inverse_spatial_metric_tag;
58 : auto& normal_vector = get<NormalVector<Dim>>(*fields_on_face);
59 : const auto& inverse_spatial_metric =
60 : get<inverse_spatial_metric_tag>(*fields_on_face);
61 : // Compute unnormalized normal vector
62 : for (size_t i = 0; i < Dim; ++i) {
63 : normal_vector.get(i) = inverse_spatial_metric.get(i, 0) *
64 : get<0>(unnormalized_normal_covector);
65 : for (size_t j = 1; j < Dim; ++j) {
66 : normal_vector.get(i) += inverse_spatial_metric.get(i, j) *
67 : unnormalized_normal_covector.get(j);
68 : }
69 : }
70 : // Perform normalization
71 : dot_product(face_normal_magnitude, normal_vector,
72 : unnormalized_normal_covector);
73 : get(*face_normal_magnitude) = sqrt(get(*face_normal_magnitude));
74 : auto& one_over_normal_vector_magnitude =
75 : get<OneOverNormalVectorMagnitude>(*fields_on_face);
76 : get(one_over_normal_vector_magnitude) = 1.0 / get(*face_normal_magnitude);
77 : for (size_t i = 0; i < Dim; ++i) {
78 : unit_normal_covector->get(i) = unnormalized_normal_covector.get(i) *
79 : get(one_over_normal_vector_magnitude);
80 : normal_vector.get(i) *= get(one_over_normal_vector_magnitude);
81 : }
82 : } else {
83 : magnitude(face_normal_magnitude, unnormalized_normal_covector);
84 : auto& one_over_normal_vector_magnitude =
85 : get<OneOverNormalVectorMagnitude>(*fields_on_face);
86 : get(one_over_normal_vector_magnitude) = 1.0 / get(*face_normal_magnitude);
87 : for (size_t i = 0; i < Dim; ++i) {
88 : unit_normal_covector->get(i) = unnormalized_normal_covector.get(i) *
89 : get(one_over_normal_vector_magnitude);
90 : }
91 : }
92 : }
93 :
94 : /*!
95 : * \brief Computes the normal vector, covector, and their magnitude on the face
96 : * in the given direction.
97 : *
98 : * The normal covector and its magnitude are returned using the
99 : * `normal_covector_quantities` function argument. The `fields_on_face` argument
100 : * is used as a temporary buffer via the `OneOverNormalVectorMagnitude` tag and
101 : * also used to return the normalized normal vector via the `NormalVector<Dim>`
102 : * tag. The `fields_on_face` argument also serves as the input for the inverse
103 : * spatial metric when the spacetime is curved. The `fields_on_face` argument
104 : * must have tags `NormalVector<Dim>` and `OneOverNormalVectorMagnitude`. If the
105 : * system specifies `System::inverse_spatial_metric_tag` then this tag must also
106 : * be in the Variables.
107 : */
108 : template <typename System, size_t Dim, typename FieldsOnFaceTags>
109 : void unit_normal_vector_and_covector_and_magnitude(
110 : const gsl::not_null<
111 : DirectionMap<Dim, std::optional<Variables<tmpl::list<
112 : evolution::dg::Tags::MagnitudeOfNormal,
113 : evolution::dg::Tags::NormalCovector<Dim>>>>>*>
114 : normal_covector_quantities,
115 : const gsl::not_null<Variables<FieldsOnFaceTags>*> fields_on_face,
116 : const Direction<Dim>& direction,
117 : const std::unordered_map<Direction<Dim>, tnsr::i<DataVector, Dim>>&
118 : unnormalized_normal_covectors,
119 : const domain::CoordinateMapBase<Frame::Grid, Frame::Inertial, Dim>&
120 : moving_mesh_map) {
121 : const bool mesh_is_moving = not moving_mesh_map.is_identity();
122 : const auto& unnormalized_normal_covector =
123 : unnormalized_normal_covectors.at(direction);
124 :
125 : if (auto& normal_covector_quantity =
126 : normal_covector_quantities->at(direction);
127 : detail::has_inverse_spatial_metric_tag_v<System> or mesh_is_moving or
128 : not normal_covector_quantity.has_value()) {
129 : if (not normal_covector_quantity.has_value()) {
130 : normal_covector_quantity =
131 : Variables<tmpl::list<evolution::dg::Tags::MagnitudeOfNormal,
132 : evolution::dg::Tags::NormalCovector<Dim>>>{
133 : fields_on_face->number_of_grid_points()};
134 : }
135 : detail::unit_normal_vector_and_covector_and_magnitude_impl<System>(
136 : make_not_null(&get<evolution::dg::Tags::MagnitudeOfNormal>(
137 : *normal_covector_quantity)),
138 : make_not_null(&get<evolution::dg::Tags::NormalCovector<Dim>>(
139 : *normal_covector_quantity)),
140 : fields_on_face, unnormalized_normal_covector);
141 : }
142 : }
143 : } // namespace evolution::dg::Actions::detail
|