chombo-discharge
Loading...
Searching...
No Matches
CD_MirrorDepositionImplem.H
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2021-2026 SINTEF Energy Research
3 *
4 * SPDX-License-Identifier: GPL-3.0-or-later
5 */
6
13#ifndef CD_MIRRORDEPOSITIONIMPLEM_H
14#define CD_MIRRORDEPOSITIONIMPLEM_H
15
16// Std includes
17#include <cmath>
18
19// Our includes
20#include <CD_MirrorDeposition.H>
21#include <CD_NamespaceHeader.H>
22
23namespace MirrorDeposition {
24
25inline int
26shapeIndex(const int a_i, const int a_j) noexcept
27{
28 // Upper triangle in row-major order: (0,0),(0,1),...,(0,D-1),(1,1),... The row offset is the number of entries
29 // in the preceding rows, i.e. sum_{k<i} (D - k).
30 const int lo = (a_i < a_j) ? a_i : a_j;
31 const int hi = (a_i < a_j) ? a_j : a_i;
32
33 return lo * SpaceDim - (lo * (lo - 1)) / 2 + (hi - lo);
34}
35
36inline void
37liftShapeOperator(const RealVect (&a_tangents)[numTangents],
38 const Real (&a_S)[numTangents][numTangents],
39 Real (&a_shape)[numShapeComp]) noexcept
40{
41 // S_c = P S P^T with P = [t_1 ... t_(D-1)]. Only the upper triangle is stored; the tensor is symmetric because
42 // the fit symmetrizes S before it gets here.
43 for (int i = 0; i < SpaceDim; i++) {
44 for (int j = i; j < SpaceDim; j++) {
45 Real sum = 0.0;
46
47 for (int a = 0; a < numTangents; a++) {
48 for (int b = 0; b < numTangents; b++) {
49 sum += a_tangents[a][i] * a_S[a][b] * a_tangents[b][j];
50 }
51 }
52
53 a_shape[shapeIndex(i, j)] = sum;
54 }
55 }
56}
57
58inline Real
59shapeEntry(const Real* a_shape, const int a_i, const int a_j) noexcept
60{
61 return a_shape[shapeIndex(a_i, a_j)];
62}
63
64inline RealVect
65applyShapeOperator(const Real* a_shape, const RealVect& a_vec) noexcept
66{
67 RealVect ret = RealVect::Zero;
68
69 for (int i = 0; i < SpaceDim; i++) {
70 Real sum = 0.0;
71
72 for (int j = 0; j < SpaceDim; j++) {
73 sum += shapeEntry(a_shape, i, j) * a_vec[j];
74 }
75
76 ret[i] = sum;
77 }
78
79 return ret;
80}
81
82inline Real
83meanCurvatureTimesTwo(const Real* a_shape) noexcept
84{
85 Real tr = 0.0;
86
87 for (int i = 0; i < SpaceDim; i++) {
88 tr += shapeEntry(a_shape, i, i);
89 }
90
91 return tr;
92}
93
94inline Real
95gaussianCurvature(const Real* a_shape) noexcept
96{
97 // K = (1/2)[(tr S)^2 - tr(S^2)]. See the header for why this is NOT det(S).
98 const Real tr = meanCurvatureTimesTwo(a_shape);
99
100 Real trSq = 0.0;
101
102 for (int i = 0; i < SpaceDim; i++) {
103 for (int j = 0; j < SpaceDim; j++) {
104 const Real sij = shapeEntry(a_shape, i, j);
105
106 trSq += sij * sij;
107 }
108 }
109
110 return 0.5 * (tr * tr - trSq);
111}
112
113inline Real
114jacobian(const Real a_twoH, const Real a_K, const Real a_d, Real& a_denominator) noexcept
115{
116 const Real dSq = a_d * a_d;
117
118 a_denominator = 1.0 + a_twoH * a_d + a_K * dSq;
119
120 return (1.0 - a_twoH * a_d + a_K * dSq) / a_denominator;
121}
122
123inline bool
124reflect(const RealVect& a_pos,
125 const Real* a_surfaceData,
126 const Real a_maxJacobian,
127 const Real a_minDenominator,
128 RealVect& a_image,
129 Real& a_jacobian,
130 Real& a_signedDistance,
131 Refusal& a_refusal) noexcept
132{
133 RealVect centroid;
134 RealVect normal;
135
136 for (int dir = 0; dir < SpaceDim; dir++) {
137 centroid[dir] = a_surfaceData[compCentroid + dir];
138 normal[dir] = a_surfaceData[compNormal + dir];
139 }
140
141 const Real* shape = a_surfaceData + compShape;
142
143 // The local quadratic patch. Note that d is the first iterate of the signed distance, not the signed distance.
144 const RealVect w = a_pos - centroid;
145 const RealVect Sw = applyShapeOperator(shape, w);
146 const Real eta = normal.dotProduct(w);
147 const Real d = eta + 0.5 * w.dotProduct(Sw);
148
149 // The patch normal at the foot point. S_c annihilates n_c, so the normal component of w contributes nothing here
150 // and no tangential projection of w is needed.
151 RealVect nhat = normal + Sw;
152 const Real len = nhat.vectorLength();
153
154 if (len > 0.0) {
155 nhat /= len;
156 }
157 else {
158 nhat = normal;
159 }
160
161 a_image = a_pos - 2.0 * d * nhat;
162 a_signedDistance = d;
163
164 Real denominator = 0.0;
165 const Real J = jacobian(meanCurvatureTimesTwo(shape), gaussianCurvature(shape), d, denominator);
166
167 a_refusal = Refusal::None;
168
169 if (std::abs(denominator) < a_minDenominator) {
170 a_refusal = Refusal::SmallDenominator;
171 }
172 else if (!(J > 0.0)) {
174 }
175 else if (J > a_maxJacobian) {
176 a_refusal = Refusal::LargeJacobian;
177 }
178
179 // A refused image still deposits, with unit weight -- dropping it would remove the correction precisely where it
180 // is largest. See the header.
181 a_jacobian = (a_refusal == Refusal::None) ? J : 1.0;
182
183 return a_refusal == Refusal::None;
184}
185
186} // namespace MirrorDeposition
187
188#include <CD_NamespaceFooter.H>
189
190#endif
Namespace containing the geometry used by mirrored cut-cell deposition.
Geometry for mirrored cut-cell deposition, i.e. the even extension of the density about an embedded b...
Definition CD_MirrorDeposition.H:38
constexpr int compCentroid
First of the SpaceDim components holding the boundary centroid, as a PHYSICAL position.
Definition CD_MirrorDeposition.H:58
constexpr int numTangents
Number of tangent directions on the surface. One in 2-D, two in 3-D.
Definition CD_MirrorDeposition.H:43
int shapeIndex(const int a_i, const int a_j) noexcept
Index into the stored upper triangle of a symmetric SpaceDim x SpaceDim tensor.
Definition CD_MirrorDepositionImplem.H:26
Refusal
Why reflect() refused to trust its Jacobian.
Definition CD_MirrorDeposition.H:108
@ NonPositiveJacobian
The Jacobian came out non-positive, i.e. the reflection is past the surface's centre of curvature.
@ SmallDenominator
The Jacobian's denominator came too close to zero.
@ LargeJacobian
The Jacobian exceeded the permitted magnitude.
@ None
No refusal; the Jacobian was accepted.
constexpr int compShape
First of the numShapeComp components holding the world-frame shape operator's upper triangle.
Definition CD_MirrorDeposition.H:68
Real shapeEntry(const Real *a_shape, const int a_i, const int a_j) noexcept
Read one entry of a world-frame shape operator stored as an upper triangle.
Definition CD_MirrorDepositionImplem.H:59
constexpr int compNormal
First of the SpaceDim components holding the unit normal, pointing INTO the fluid.
Definition CD_MirrorDeposition.H:63
constexpr int numShapeComp
Number of independent entries in a symmetric SpaceDim x SpaceDim tensor. Three in 2-D,...
Definition CD_MirrorDeposition.H:48
Real meanCurvatureTimesTwo(const Real *a_shape) noexcept
Twice the mean curvature, i.e. the first invariant of the shape operator.
Definition CD_MirrorDepositionImplem.H:83
bool reflect(const RealVect &a_pos, const Real *a_surfaceData, const Real a_maxJacobian, const Real a_minDenominator, RealVect &a_image, Real &a_jacobian, Real &a_signedDistance, Refusal &a_refusal) noexcept
Reflect a position across the quadratic surface patch stored for its cell, and weight the image.
Definition CD_MirrorDepositionImplem.H:124
Real jacobian(const Real a_twoH, const Real a_K, const Real a_d, Real &a_denominator) noexcept
The exact area/volume Jacobian of the reflection across a curved surface.
Definition CD_MirrorDepositionImplem.H:114
RealVect applyShapeOperator(const Real *a_shape, const RealVect &a_vec) noexcept
Apply a world-frame shape operator to a vector.
Definition CD_MirrorDepositionImplem.H:65
Real gaussianCurvature(const Real *a_shape) noexcept
Gaussian curvature, i.e. the second invariant of the shape operator.
Definition CD_MirrorDepositionImplem.H:95
void liftShapeOperator(const RealVect(&a_tangents)[numTangents], const Real(&a_S)[numTangents][numTangents], Real(&a_shape)[numShapeComp]) noexcept
Lift a shape operator from the tangent frame into world coordinates.
Definition CD_MirrorDepositionImplem.H:37