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 :
8 : #include "DataStructures/Tensor/TypeAliases.hpp"
9 :
10 : /// \cond
11 : class DataVector;
12 : template <size_t Dim>
13 : class Mesh;
14 : namespace gsl {
15 : template <typename T>
16 : class not_null;
17 : } // namespace gsl
18 : /// \endcond
19 :
20 : namespace dg {
21 : /*!
22 : * \ingroup DiscontinuousGalerkinGroup
23 : * \brief Compute the Jacobian determinant times the inverse Jacobian so that
24 : * the result is divergence-free.
25 : *
26 : * The metric identities are given by
27 : *
28 : * \f{align*}{
29 : *
30 : * \partial_{\hat{\imath}}\left(J\frac{\partial\xi^{\hat{\imath}}}
31 : * {\partial x^i}\right)=0.
32 : *
33 : * \f}
34 : *
35 : * We want to compute \f$J\partial\xi^{\hat{\imath}}/\partial x^i\f$ in such a
36 : * way that the above metric identity is satisfied numerically/discretely. We
37 : * refer to the inverse Jacobian computed this way as the "metric
38 : * identity-satisfying inverse Jacobian".
39 : *
40 : * The discretized form, with the Jacobian determinant \f$J\f$ expanded, is
41 : * given by
42 : *
43 : * \f{align*}{
44 : *
45 : * 2\left(J\frac{\partial \xi^{\hat{\imath}}}{\partial x^i}\right)_{s}
46 : * &=\epsilon_{ijk}
47 : * \sum_{t_{\hat{1}}} \epsilon^{\hat{\imath}\hat{1}\hat{k}}
48 : * D^{(\hat{1})}_{s t_1}
49 : * \left(x^j\frac{\partial x^k}{\partial \xi^{\hat{k}}}\right)_{t}
50 : * \notag \\
51 : * &+\epsilon_{ijk}
52 : * \sum_{t_{\hat{2}}} \epsilon^{\hat{\imath}\hat{2}\hat{k}}
53 : * D^{(\hat{2})}_{st_2}
54 : * \left(x^j\frac{\partial x^k}{\partial \xi^{\hat{k}}}\right)_{t}
55 : * \notag \\
56 : * &+\epsilon_{ijk}
57 : * \sum_{t_{\hat{3}}}\epsilon^{\hat{\imath}\hat{3}\hat{k}}
58 : * D^{(\hat{3})}_{st_3}
59 : * \left(x^j\frac{\partial x^k}{\partial \xi^{\hat{k}}}\right)_{t}.
60 : *
61 : * \f}
62 : *
63 : * where indices \f$s,t,t_1,t_2\f$ and \f$t_3\f$ are over grid points. \f$t_i\f$
64 : * are the grid points in the particular logical direction.
65 : *
66 : * In 1d we have:
67 : *
68 : * \f{align*}{
69 : *
70 : * J\frac{\partial \xi^{\hat{\imath}}}{\partial x^i}=
71 : * = J\frac{\partial \xi^{\hat{i}}}{\partial x^i} = 1
72 : *
73 : * \f}
74 : *
75 : * In 2d we have:
76 : *
77 : * \f{align*}{
78 : *
79 : * J\frac{\partial \xi^{\hat{1}}}{\partial x^1}&=D^{\hat{(2)}}x^2 &
80 : * J\frac{\partial \xi^{\hat{2}}}{\partial x^1}&=-D^{\hat{(1)}}x^2 \\
81 : * J\frac{\partial \xi^{\hat{1}}}{\partial x^2}&=-D^{\hat{(2)}}x^1 &
82 : * J\frac{\partial \xi^{\hat{2}}}{\partial x^2}&=D^{\hat{(1)}}x^1 \\
83 : *
84 : * \f}
85 : *
86 : * In 3d we have:
87 : *
88 : * \f{align*}{
89 : *
90 : * 2J\frac{\partial \xi^{\hat{1}}}{\partial x^1}&=
91 : * D^{(\hat{2})}\left(x^2\frac{\partial x^3}{\partial \xi^{\hat{3}}}\right)
92 : * -D^{(\hat{2})}\left(x^3\frac{\partial x^2}{\partial \xi^{\hat{3}}}\right)
93 : * +D^{(\hat{3})}\left(x^3\frac{\partial x^2}{\partial \xi^{\hat{2}}}\right)
94 : * -D^{(\hat{3})}\left(x^2\frac{\partial x^3}{\partial \xi^{\hat{2}}}\right)\\
95 : * 2J\frac{\partial \xi^{\hat{2}}}{\partial x^1}&=
96 : * D^{(\hat{1})}\left(x^3\frac{\partial x^2}{\partial\xi^{\hat{3}}}\right)
97 : * -D^{(\hat{1})}\left(x^2\frac{\partial x^3}{\partial\xi^{\hat{3}}}\right)
98 : * +D^{(\hat{3})}\left(x^2\frac{\partial x^3}{\partial\xi^{\hat{1}}}\right)
99 : * -D^{(\hat{3})}\left(x^3\frac{\partial x^2}{\partial\xi^{\hat{1}}}\right) \\
100 : * 2J\frac{\partial \xi^{\hat{3}}}{\partial x^1}&=
101 : * D^{(\hat{1})}\left(x^2\frac{\partial x^3}{\partial\xi^{\hat{2}}}\right)
102 : * -D^{(\hat{1})}\left(x^3\frac{\partial x^2}{\partial\xi^{\hat{2}}}\right)
103 : * +D^{(\hat{2})}\left(x^3\frac{\partial x^2}{\partial\xi^{\hat{1}}}\right)
104 : * -D^{(\hat{2})}\left(x^2\frac{\partial x^3}{\partial\xi^{\hat{1}}}\right)\\
105 : * 2J\frac{\partial \xi^{\hat{1}}}{\partial x^2}&=
106 : * D^{(\hat{2})}\left(x^3\frac{\partial x^1}{\partial \xi^{\hat{3}}}\right)
107 : * -D^{(\hat{2})}\left(x^1\frac{\partial x^3}{\partial \xi^{\hat{3}}}\right)
108 : * +D^{(\hat{3})}\left(x^1\frac{\partial x^3}{\partial \xi^{\hat{2}}}\right)
109 : * -D^{(\hat{3})}\left(x^3\frac{\partial x^1}{\partial \xi^{\hat{2}}}\right) \\
110 : * 2J\frac{\partial \xi^{\hat{2}}}{\partial x^2}&=
111 : * D^{(\hat{1})}\left(x^1\frac{\partial x^3}{\partial \xi^{\hat{3}}}\right)
112 : * -D^{(\hat{1})}\left(x^3\frac{\partial x^1}{\partial \xi^{\hat{3}}}\right)
113 : * +D^{(\hat{3})}\left(x^3\frac{\partial x^1}{\partial \xi^{\hat{1}}}\right)
114 : * -D^{(\hat{3})}\left(x^1\frac{\partial x^3}{\partial \xi^{\hat{1}}}\right)\\
115 : * 2J\frac{\partial \xi^{\hat{3}}}{\partial x^2}&=
116 : * D^{(\hat{1})}\left(x^3\frac{\partial x^1}{\partial \xi^{\hat{2}}}\right)
117 : * -D^{(\hat{1})}\left(x^1\frac{\partial x^3}{\partial \xi^{\hat{2}}}\right)
118 : * +D^{(\hat{2})}\left(x^1\frac{\partial x^3}{\partial \xi^{\hat{1}}}\right)
119 : * -D^{(\hat{2})}\left(x^3\frac{\partial x^1}{\partial \xi^{\hat{1}}}\right) \\
120 : * 2J\frac{\partial \xi^{\hat{1}}}{\partial x^3}&=
121 : * D^{(\hat{2})}\left(x^1\frac{\partial x^2}{\partial \xi^{\hat{3}}}\right)
122 : * -D^{(\hat{2})}\left(x^2\frac{\partial x^1}{\partial \xi^{\hat{3}}}\right)
123 : * +D^{(\hat{3})}\left(x^2\frac{\partial x^1}{\partial \xi^{\hat{2}}}\right)
124 : * -D^{(\hat{3})}\left(x^1\frac{\partial x^2}{\partial \xi^{\hat{2}}}\right) \\
125 : * 2J\frac{\partial \xi^{\hat{2}}}{\partial x^3}&=
126 : * D^{(\hat{1})}\left(x^2\frac{\partial x^1}{\partial \xi^{\hat{3}}}\right)
127 : * -D^{(\hat{1})}\left(x^1\frac{\partial x^2}{\partial \xi^{\hat{3}}}\right)
128 : * +D^{(\hat{3})}\left(x^1\frac{\partial x^2}{\partial \xi^{\hat{1}}}\right)
129 : * -D^{(\hat{3})}\left(x^2\frac{\partial x^1}{\partial \xi^{\hat{1}}}\right) \\
130 : * 2J\frac{\partial \xi^{\hat{3}}}{\partial x^3}&=
131 : * D^{(\hat{1})}\left(x^1\frac{\partial x^2}{\partial \xi^{\hat{2}}}\right)
132 : * -D^{(\hat{1})}\left(x^2\frac{\partial x^1}{\partial \xi^{\hat{2}}}\right)
133 : * +D^{(\hat{2})}\left(x^2\frac{\partial x^1}{\partial \xi^{\hat{1}}}\right)
134 : * -D^{(\hat{2})}\left(x^1\frac{\partial x^2}{\partial \xi^{\hat{1}}}\right)
135 : *
136 : * \f}
137 : *
138 : * Again, this ensures that the metric identities are satisfied discretely. That
139 : * is,
140 : *
141 : * \f{align*}{
142 : *
143 : * \partial_{\hat{\imath}}\left(J\frac{\partial\xi^{\hat{\imath}}}
144 : * {\partial x^i}\right)=0
145 : *
146 : * \f}
147 : *
148 : * numerically.
149 : *
150 : * The reason for calculating \f$J\partial\xi^{\hat{\imath}}/\partial x^i\f$ in
151 : * this manner is because in the weak form of DG (and most spectral-type methods
152 : * can be recast as DG) we effectively evaluate
153 : *
154 : * \f{align*}{
155 : *
156 : * \partial_{\hat{\imath}}\left(J\frac{\partial\xi^{\hat{\imath}}}
157 : * {\partial x^i} F^i\right),
158 : *
159 : * \f}
160 : *
161 : * which should be identically zero if \f$F^i\f$ is constant. This feature of a
162 : * scheme is referred to as free-stream preserving. Note that another way to
163 : * achieve free-stream preservation is to subtract off the metric identity
164 : * violations. That is,
165 : *
166 : * \f{align*}{
167 : *
168 : * \partial_{\hat{\imath}}\left(J\frac{\partial\xi^{\hat{\imath}}}
169 : * {\partial x^i} F^i\right) -
170 : * F^i \partial_{\hat{\imath}}\left(J\frac{\partial\xi^{\hat{\imath}}}
171 : * {\partial x^i}\right).
172 : *
173 : * \f}
174 : *
175 : * The subtraction technique is most commonly used in finite difference codes.
176 : */
177 : template <size_t Dim>
178 1 : void metric_identity_det_jac_times_inv_jac(
179 : gsl::not_null<InverseJacobian<DataVector, Dim, Frame::ElementLogical,
180 : Frame::Inertial>*>
181 : det_jac_times_inverse_jacobian,
182 : const Mesh<Dim>& mesh,
183 : const tnsr::I<DataVector, Dim, Frame::Inertial>& inertial_coords,
184 : const Jacobian<DataVector, Dim, Frame::ElementLogical, Frame::Inertial>&
185 : jacobian);
186 :
187 : /*!
188 : * \ingroup DiscontinuousGalerkinGroup
189 : * \brief Compute the Jacobian, inverse Jacobian, and determinant of the
190 : * Jacobian so that they satisfy the metric identities.
191 : *
192 : * Uses `dg::metric_identity_jacobian()` to compute the determinant of the
193 : * Jacobian times the inverse Jacobian. By taking the determinant of this
194 : * product, we can isolate \f$J\f$, the determinant of the Jacobian. In \f$d\f$
195 : * dimensions, we have:
196 : *
197 : * \f{align}{
198 : *
199 : * \mathrm{det}\left(J\frac{\partial \xi^{\hat{\imath}}}{\partial x^i}\right)
200 : * = J^{d-1}.
201 : *
202 : * \f}
203 : *
204 : * We assume the determinant of the Jacobian is positive, which means logical
205 : * and inertial coordinates have the same handedness. With this assumption, we
206 : * have
207 : *
208 : * \f{align}{
209 : *
210 : * J = \sqrt[(d-1)]{\mathrm{det}\left(J\frac{\partial
211 : * \xi^{\hat{\imath}}}{\partial x^i}\right)}
212 : *
213 : * \f}
214 : *
215 : * We can now compute the inverse Jacobian using:
216 : *
217 : * \f{align}{
218 : *
219 : * \frac{\partial \xi^{\hat{\imath}}}{\partial x^i}=
220 : * \frac{1}{J}\left(J\frac{\partial \xi^{\hat{\imath}}}{\partial x^i}\right)
221 : *
222 : * \f}
223 : *
224 : * This guarantees that multiplying the determinant of the Jacobian by the
225 : * inverse Jacobian gives a result that satisfies the metric identities. We also
226 : * compute the Jacobian by inverting the inverse Jacobian, which guarantees they
227 : * are (numerical) inverses of each other.
228 : *
229 : * \warning on entry `jacobian` must be the Jacobian to use for computing the
230 : * determinant of the Jacobian times the inverse Jacobian so that it satisfies
231 : * the metric identities. The `jacobian` can be computed analytically or
232 : * numerically, either is fine. On output the `jacobian` is the inverse of the
233 : * inverse Jacobian that satisfies the metric identities.
234 : */
235 : template <size_t Dim>
236 1 : void metric_identity_jacobian_quantities(
237 : gsl::not_null<InverseJacobian<DataVector, Dim, Frame::ElementLogical,
238 : Frame::Inertial>*>
239 : det_jac_times_inverse_jacobian,
240 : gsl::not_null<InverseJacobian<DataVector, Dim, Frame::ElementLogical,
241 : Frame::Inertial>*>
242 : inverse_jacobian,
243 : gsl::not_null<
244 : Jacobian<DataVector, Dim, Frame::ElementLogical, Frame::Inertial>*>
245 : jacobian,
246 : gsl::not_null<Scalar<DataVector>*> det_jacobian, const Mesh<Dim>& mesh,
247 : const tnsr::I<DataVector, Dim, Frame::Inertial>& inertial_coords);
248 : } // namespace dg
|