Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <algorithm>
7 : #include <array>
8 : #include <cstddef>
9 : #include <functional>
10 : #include <tuple>
11 : #include <type_traits>
12 : #include <utility>
13 :
14 : #include "DataStructures/ApplyMatrices.hpp"
15 : #include "DataStructures/DataBox/PrefixHelpers.hpp"
16 : #include "DataStructures/DataBox/Prefixes.hpp"
17 : #include "DataStructures/Matrix.hpp"
18 : #include "DataStructures/Variables.hpp"
19 : #include "Domain/Structure/Direction.hpp"
20 : #include "Domain/Structure/DirectionalId.hpp"
21 : #include "Domain/Structure/DirectionalIdMap.hpp"
22 : #include "Domain/Structure/ElementId.hpp"
23 : #include "Domain/Structure/SegmentId.hpp"
24 : #include "NumericalAlgorithms/DiscontinuousGalerkin/LiftFlux.hpp"
25 : #include "NumericalAlgorithms/Spectral/Mesh.hpp"
26 : #include "NumericalAlgorithms/Spectral/Projection.hpp"
27 : #include "NumericalAlgorithms/Spectral/SegmentSize.hpp"
28 : #include "Utilities/Algorithm.hpp"
29 : #include "Utilities/ConstantExpressions.hpp"
30 : #include "Utilities/ErrorHandling/Assert.hpp"
31 : #include "Utilities/Gsl.hpp"
32 : #include "Utilities/MakeArray.hpp"
33 : #include "Utilities/TMPL.hpp"
34 : /// \cond
35 : template <size_t VolumeDim>
36 : class ElementId;
37 : template <size_t VolumeDim>
38 : class OrientationMap;
39 :
40 : /// \endcond
41 :
42 : namespace dg {
43 :
44 : template <size_t VolumeDim>
45 0 : using MortarId = DirectionalId<VolumeDim>;
46 : template <size_t MortarDim>
47 0 : using MortarSize = std::array<Spectral::SegmentSize, MortarDim>;
48 : template <size_t VolumeDim, typename ValueType>
49 0 : using MortarMap = DirectionalIdMap<VolumeDim, ValueType>;
50 :
51 : /// \ingroup DiscontinuousGalerkinGroup
52 : /// Find a mesh for a mortar capable of representing data from either
53 : /// of two faces.
54 : ///
55 : /// \warning Make sure the two face meshes are oriented the same, i.e.
56 : /// their dimensions align. This is facilitated by the `orientation`
57 : /// passed to `domain::create_initial_mesh`, for example.
58 : template <size_t Dim>
59 1 : Mesh<Dim> mortar_mesh(const Mesh<Dim>& face_mesh1, const Mesh<Dim>& face_mesh2);
60 :
61 : /// \ingroup DiscontinuousGalerkinGroup
62 : /// Determine the size of the mortar (i.e., the part of the face it
63 : /// covers) for communicating with a neighbor. This is the size
64 : /// relative to the size of \p self, and will not generally agree with
65 : /// that determined by \p neighbor.
66 : template <size_t Dim>
67 1 : MortarSize<Dim - 1> mortar_size(const ElementId<Dim>& self,
68 : const ElementId<Dim>& neighbor,
69 : size_t dimension,
70 : const OrientationMap<Dim>& orientation);
71 :
72 : /// \ingroup DiscontinuousGalerkinGroup
73 : /// Determine the size of the mortar in block coordinates. The
74 : /// segments are given in the block of \p self.
75 : template <size_t Dim>
76 1 : std::array<SegmentId, Dim - 1> mortar_segments(
77 : const ElementId<Dim>& self, const ElementId<Dim>& neighbor,
78 : size_t dimension, const OrientationMap<Dim>& orientation);
79 :
80 : /// @{
81 : /// \ingroup DiscontinuousGalerkinGroup
82 : /// Project variables from a face to a mortar.
83 : template <typename Tags, size_t Dim>
84 1 : void project_to_mortar(const gsl::not_null<Variables<Tags>*> result,
85 : const Variables<Tags>& vars, const Mesh<Dim>& face_mesh,
86 : const Mesh<Dim>& mortar_mesh,
87 : const MortarSize<Dim>& mortar_size) {
88 : const auto projection_matrices = Spectral::projection_matrix_parent_to_child(
89 : face_mesh, mortar_mesh, mortar_size);
90 : // We don't add an ASSERT about sizes here because there's already one in
91 : // apply_matrices
92 : apply_matrices(result, projection_matrices, vars, face_mesh.extents());
93 : }
94 :
95 : template <typename Tags, size_t Dim>
96 1 : Variables<Tags> project_to_mortar(const Variables<Tags>& vars,
97 : const Mesh<Dim>& face_mesh,
98 : const Mesh<Dim>& mortar_mesh,
99 : const MortarSize<Dim>& mortar_size) {
100 : Variables<Tags> result{mortar_mesh.number_of_grid_points()};
101 : project_to_mortar(make_not_null(&result), vars, face_mesh, mortar_mesh,
102 : mortar_size);
103 : return result;
104 : }
105 : /// @}
106 :
107 : /// @{
108 : /// \ingroup DiscontinuousGalerkinGroup
109 : /// Project variables from a mortar to a face.
110 : template <typename Tags, size_t Dim>
111 1 : void project_from_mortar(const gsl::not_null<Variables<Tags>*> result,
112 : const Variables<Tags>& vars,
113 : const Mesh<Dim>& face_mesh,
114 : const Mesh<Dim>& mortar_mesh,
115 : const MortarSize<Dim>& mortar_size) {
116 : ASSERT(Spectral::needs_projection(face_mesh, mortar_mesh, mortar_size),
117 : "project_from_mortar should not be called if the interface mesh and "
118 : "mortar mesh are identical. Please elide the copy instead.");
119 : const auto projection_matrices = Spectral::projection_matrix_child_to_parent(
120 : mortar_mesh, face_mesh, mortar_size);
121 : // We don't add an ASSERT about sizes here because there's already one in
122 : // apply_matrices
123 : apply_matrices(result, projection_matrices, vars, mortar_mesh.extents());
124 : }
125 :
126 : template <typename Tags, size_t Dim>
127 1 : Variables<Tags> project_from_mortar(const Variables<Tags>& vars,
128 : const Mesh<Dim>& face_mesh,
129 : const Mesh<Dim>& mortar_mesh,
130 : const MortarSize<Dim>& mortar_size) {
131 : ASSERT(Spectral::needs_projection(face_mesh, mortar_mesh, mortar_size),
132 : "project_from_mortar should not be called if the interface mesh and "
133 : "mortar mesh are identical. Please elide the copy instead.");
134 : Variables<Tags> result{face_mesh.number_of_grid_points()};
135 : project_from_mortar(make_not_null(&result), vars, face_mesh, mortar_mesh,
136 : mortar_size);
137 : return result;
138 : }
139 : /// @}
140 : } // namespace dg
|