flow 1.3.0
Kokkos cut-cell IBM incompressible Navier-Stokes solver + pnm pore extraction
Loading...
Searching...
No Matches
collocated_varrho.hpp
Go to the documentation of this file.
1
41#ifndef PECLET_FLOW_COLLOCATED_VARRHO_HPP
42#define PECLET_FLOW_COLLOCATED_VARRHO_HPP
43
44#include <Kokkos_Core.hpp>
45
47#include "mac_cutcell.hpp"
48#include "policy.hpp"
50
51namespace peclet::flow {
52
53// The face acceleration of ONE component, WITHOUT the openness (the cell reconstruction applies
54// it):
55//
56// af(i) = scale * ( fc + [½(fb(i)+fb(i-s))] - [w_a (P(i) - P(i-s))] ) / rho_f(i)
57//
58// `s` is the component's own face stride (the face at index `i` separates cells `i-s` and `i`, the
59// solver's low-face convention). `rho_f` = arithmetic face mean when `haveRho`, the scalar `rhoC`
60// otherwise. The V8 predictor calls it with `haveFb = false` (per-cell forces are volumetric: the
61// cell value times the weight sum) and `scale = 1`.
62//
63// RANGE: the face range `[g, e-g]` on every axis. The cell reconstruction of cell `i` reads the
64// face at `i+s`, so the high plane is needed; every input it reads there is a depth-1 ghost, which
65// every property fill has already written, and because the face at index `e-g` is formed from
66// exactly the same two ghost values the neighbouring rank forms its own index-`g` face from, in the
67// same order, the plane is bitwise decomposition-independent. PHASE 2 (anisotropic cells,
68// doc/anisotropic_metric.md §1.2/§3): of the three terms only the PRESSURE difference carries a
69// metric. `fc` is the body force already converted per axis by Phase 1's `forceToInt(a)`, `fb` is a
70// per-cell force in the same per-axis normalisation, and `1/rho_f` is unit-free -- while `-grad_a
71// P'` carries `w_a = 1/h_a'^2`, exactly as it does in the staggered `buildRhs*` predictor and in
72// `projectCorrect`. `wa == 1.0` isotropic (exact).
74 bool haveRho, double rhoC, double fc, bool incr, double scale, long s,
75 C3 e, int g, double wa = 1.0) {
77 using MD = MDRange3<CCExec>;
78 Kokkos::parallel_for(
79 "peclet::flow::colo_face_accel",
80 MD(space, {g, g, g}, {e.x - g + 1, e.y - g + 1, e.z - g + 1}),
81 KOKKOS_LAMBDA(int x, int y, int z) {
82 const long i = (long)x + (long)y * e.x + (long)z * (long)e.x * e.y;
83 const double rf = haveRho ? 0.5 * (rho(i) + rho(i - s)) : rhoC;
84 const double f = fc + (haveFb ? 0.5 * (fb(i) + fb(i - s)) : 0.0) -
85 (incr ? wa * (P(i) - P((long)i - s)) : 0.0);
86 af(i) = scale * f / rf;
87 });
88}
89
90// ADDITIVE balanced-force CSF at the same face, with the same `1/rho_f` and the same `scale`:
91//
92// af(i) += scale * sigma * kappa_f * (C(i) - C(i-s)) / hGrad / rho_f(i)
93//
94// `hGrad` is the axis's PRESSURE-GRADIENT WEIGHT denominator `h_a'^2` (Phase 3, V3.1 — the same
95// symbol the pressure face difference carries); 1.0 on every isotropic run.
96//
97// `kappa_f` is the V4 pairing (`vof::csfFaceCurvature`): the mean of the two cells' curvatures
98// where both carry one, the single available one where only one does. The force is the
99// projection's OWN difference operator applied to `sigma*kappa*C`, so for a constant kappa it lies
100// exactly in the range of the pressure gradient and is balanced by a pressure (exactly from step 1
101// under the balanced-force projection, §4.6).
103 bool haveRho, double rhoC, double sigma, double hGrad, double scale,
104 long s, C3 e, int g) {
106 using MD = MDRange3<CCExec>;
107 Kokkos::parallel_for(
108 "peclet::flow::colo_face_csf", MD(space, {g, g, g}, {e.x - g + 1, e.y - g + 1, e.z - g + 1}),
109 KOKKOS_LAMBDA(int x, int y, int z) {
110 const long i = (long)x + (long)y * e.x + (long)z * (long)e.x * e.y;
111 const double dC = cv(i) - cv((long)i - s);
112 if (dC == 0.0)
113 return; // no interface across this face -> no force, and no orphan either
114 double kf = 0.0;
115 vof::csfFaceCurvature(kp((long)i - s), kb((long)i - s), kp(i), kb(i), kf);
116 const double rf = haveRho ? 0.5 * (rho(i) + rho(i - s)) : rhoC;
117 af(i) += scale * vof::csfFaceForce(sigma, kf, dC, hGrad) / rf;
118 });
119}
120
121// The projection's constraint face field Pi_rho u: the MOMENTUM-weighted centre-to-face map
122// uf(i) = (rho(i-s) U(i-s) + rho(i) U(i)) / (rho(i-s) + rho(i))
123// on the face range `[g, e-g]` of every axis (it reads the density's depth-1 ghosts and the cell
124// velocity ghosts, which the caller fills first). Faces outside that range are not written: the
125// divergence reads only these, and the face ghosts are re-filled after the correction.
127 CCConst W, CCConst rho, C3 e, int g) {
129 using MD = MDRange3<CCExec>;
130 Kokkos::parallel_for(
131 "peclet::flow::center_to_face_mass",
132 MD(space, {g, g, g}, {e.x - g + 1, e.y - g + 1, e.z - g + 1}),
133 KOKKOS_LAMBDA(int x, int y, int z) {
134 const long sx = 1, sy = e.x, sz = (long)e.x * e.y;
135 const long i = (long)x + (long)y * sy + (long)z * sz;
136 uf(i) = varrho::faceMassWeighted(U(i - sx), U(i), rho(i - sx), rho(i));
137 vf(i) = varrho::faceMassWeighted(V(i - sy), V(i), rho(i - sy), rho(i));
138 wf(i) = varrho::faceMassWeighted(W(i - sz), W(i), rho(i - sz), rho(i));
139 });
140}
141
142// The projection's CELL correction for one component: the face-to-cell reconstruction of the face
143// corrections,
144// u(i) -= cellFromFaces(k(i), k(i+s), o(i), o(i+s)), k(j) = w_a (rho0/rho_f(j)) (phi(j) -
145// phi(j-s))
146// with `k` written EXACTLY as `projectCorrectVar` writes the face correction (same grouping, same
147// order), so the cell is corrected by the transpose of what the constraint's faces received; with
148// `haveRho` false it is the plain `projectCorrect` difference. Inner cells.
149inline void correctCellFaceAverageVar(CCField u, CCConst phi, CCConst rho, CCConst o, bool haveRho,
150 double rho0, long s, C3 e, int g, double wa = 1.0) {
152 using MD = MDRange3<CCExec>;
153 Kokkos::parallel_for(
154 "peclet::flow::colo_cell_corr_var", MD(space, {g, g, g}, {e.x - g, e.y - g, e.z - g}),
155 KOKKOS_LAMBDA(int x, int y, int z) {
156 const long i = (long)x + (long)y * e.x + (long)z * (long)e.x * e.y;
157 const long j = i + s;
158 const double kLo = haveRho
159 ? wa * (rho0 / (0.5 * (rho(i) + rho(i - s))) * (phi(i) - phi(i - s)))
160 : wa * (phi(i) - phi(i - s));
161 const double kHi = haveRho
162 ? wa * (rho0 / (0.5 * (rho(j) + rho(j - s))) * (phi(j) - phi(j - s)))
163 : wa * (phi(j) - phi(j - s));
164 u(i) -= varrho::cellFromFaces(kLo, kHi, o(i), o(j));
165 });
166}
167
168} // namespace peclet::flow
169
170#endif // PECLET_FLOW_COLLOCATED_VARRHO_HPP
flow — the POINTWISE formulas of the collocated variable-density ABC pair (doc/collocated_varrho_forc...
flow — portable (Kokkos) cut-cell pressure-operator face openness from an SDF.
double faceMassWeighted(double uL, double uR, double rL, double rR)
double cellFromFaces(double aLo, double aHi, double oLo, double oHi)
double csfFaceForce(double sigma, double kf, double dC, double hGrad)
The balanced-force CSF contribution to the momentum RHS at one staggered velocity unknown,...
bool csfFaceCurvature(double k0, double b0, double k1, double b1, double &kf)
Face curvature for the balanced-force CSF, from the two cells sharing the face.
void correctCellFaceAverageVar(CCField u, CCConst phi, CCConst rho, CCConst o, bool haveRho, double rho0, long s, C3 e, int g, double wa=1.0)
void buildFaceAccelVar(CCField af, CCConst P, CCConst rho, CCConst fb, bool haveFb, bool haveRho, double rhoC, double fc, bool incr, double scale, long s, C3 e, int g, double wa=1.0)
Kokkos::View< double *, CCMem > CCField
Kokkos::DefaultExecutionSpace CCExec
void centerToFaceMassWeighted(CCField uf, CCField vf, CCField wf, CCConst U, CCConst V, CCConst W, CCConst rho, C3 e, int g)
void addFaceAccelCsf(CCField af, CCConst cv, CCConst kp, CCConst kb, CCConst rho, bool haveRho, double rhoC, double sigma, double hGrad, double scale, long s, C3 e, int g)
Kokkos::View< const double *, CCMem > CCConst
flow — the multidimensional iteration policies: iteration order follows storage.
flow — VoF rung V4 (WO-P): balanced-force continuum surface force + the capillary Δt.
static constexpr double U