flow 0.4.0
Kokkos cut-cell IBM incompressible Navier-Stokes solver + pnm pore extraction
Loading...
Searching...
No Matches
mac_pressure.hpp
Go to the documentation of this file.
1
10#ifndef PECLET_FLOW_MAC_PRESSURE_HPP
11#define PECLET_FLOW_MAC_PRESSURE_HPP
12
13#include <Kokkos_Core.hpp>
14#include <type_traits>
15
16#include "mac_cutcell.hpp"
17
18namespace peclet::flow {
19
20// A = -div(open grad): AC = sum of the 6 face terms (openness*gf), off-diagonal across each face =
21// -term. ox[i] is the -x face openness of cell i (== +x face of cell i-1). (mg_build_op_k port.)
22// OpV is the operator-coefficient view type (float `mreal` to match CUDA, or double).
23template <class OpV>
24inline void buildCutcellOp(OpV AC, OpV AW, OpV AE, OpV AS, OpV AN, OpV AB, OpV AT, CCConst ox,
25 CCConst oy, CCConst oz, C3 e, int g, double gfx, double gfy,
26 double gfz) {
28 using MD = Kokkos::MDRangePolicy<CCExec, Kokkos::Rank<3>>;
29 Kokkos::parallel_for(
30 "peclet::flow::cc_build_op", MD(space, {g, g, g}, {e.x - g, e.y - g, e.z - g}),
31 KOKKOS_LAMBDA(int lx, int ly, int lz) {
32 const long sx = 1, sy = e.x, sz = (long)e.x * e.y;
33 const long i = (long)lx + (long)ly * sy + (long)lz * sz;
34 const double tw = ox(i) * gfx, te = ox(i + sx) * gfx;
35 const double ts = oy(i) * gfy, tn = oy(i + sy) * gfy;
36 const double tb = oz(i) * gfz, tt = oz(i + sz) * gfz;
37 AW(i) = -tw;
38 AE(i) = -te;
39 AS(i) = -ts;
40 AN(i) = -tn;
41 AB(i) = -tb;
42 AT(i) = -tt;
43 AC(i) = te + tw + tn + ts + tt + tb;
44 });
45}
46
47// Open-weighted flux divergence d_i = sum_f signed(o_f * face-velocity), consistent with A
48// (diverg_open_k).
49inline void divergOpen(CCConst u, CCConst v, CCConst w, CCConst ox, CCConst oy, CCConst oz,
50 CCField d, C3 e, int g) {
51 ccFor3(
52 "peclet::flow::diverg_open", C3{g, g, g}, C3{e.x - g, e.y - g, e.z - g},
53 KOKKOS_LAMBDA(int x, int y, int z) {
54 const long sx = 1, sy = e.x, sz = (long)e.x * e.y;
55 const long i = (long)x + (long)y * sy + (long)z * sz;
56 d(i) = (ox(i + sx) * u(i + sx) - ox(i) * u(i)) + (oy(i + sy) * v(i + sy) - oy(i) * v(i)) +
57 (oz(i + sz) * w(i + sz) - oz(i) * w(i));
58 });
59}
60
61// One red/black sweep of the variable operator: phi=(b - offdiag)/AC; AC~0 (fully solid) cells
62// decoupled. b carries the negated divergence so the system is A phi = -div(u*) (matches the
63// validated const-coeff sign).
64template <class OpV>
65inline void cutcellSmoothColor(CCField phi, CCConst b, OpV AC, OpV AW, OpV AE, OpV AS, OpV AN,
66 OpV AB, OpV AT, C3 e, C3 og, int g, int color) {
68 // Host backends: line-sweep form (one (y,z) pencil per task, stride-2 x-loop at the colour's
69 // parity) — bit-identical (same-colour cells are independent); device keeps MDRange untouched.
70 if constexpr (std::is_same_v<typename CCExec::memory_space, Kokkos::HostSpace>) {
71 const int nyi = e.y - 2 * g, nzi = e.z - 2 * g;
72 const long cells = (long)nyi * nzi * (e.x - 2 * g);
73 auto pencil = KOKKOS_LAMBDA(long t) {
74 const int ly = g + (int)(t % nyi), lz = g + (int)(t / nyi);
75 const long sx = 1, sy = e.x, sz = (long)e.x * e.y;
76 const int P = (color + og.x + og.y + ly + og.z + lz) & 1;
77 for (int lx = g + ((P ^ (g & 1)) & 1); lx < e.x - g; lx += 2) {
78 const long i = (long)lx + (long)ly * sy + (long)lz * sz;
79 const double ac = AC(i);
80 if (ac < 1e-30)
81 continue; // fully closed (solid) cell: decoupled, phi stays 0
82 const double s = AE(i) * phi(i + sx) + AW(i) * phi(i - sx) + AN(i) * phi(i + sy) +
83 AS(i) * phi(i - sy) + AT(i) * phi(i + sz) + AB(i) * phi(i - sz);
84 phi(i) = (b(i) - s) / ac;
85 }
86 };
87 if (hostRunSerial(cells)) { // coarse MG level: the fork/join costs more than the sweep
88 for (long t = 0; t < (long)nyi * nzi; ++t)
89 pencil(t);
90 return;
91 }
92 Kokkos::parallel_for("peclet::flow::cc_smooth",
93 Kokkos::RangePolicy<CCExec>(space, 0, (long)nyi * nzi), pencil);
94 return;
95 }
96 using MD = Kokkos::MDRangePolicy<CCExec, Kokkos::Rank<3>>;
97 Kokkos::parallel_for(
98 "peclet::flow::cc_smooth", MD(space, {g, g, g}, {e.x - g, e.y - g, e.z - g}),
99 KOKKOS_LAMBDA(int lx, int ly, int lz) {
100 if (((og.x + lx + og.y + ly + og.z + lz) & 1) != color)
101 return;
102 const long sx = 1, sy = e.x, sz = (long)e.x * e.y;
103 const long i = (long)lx + (long)ly * sy + (long)lz * sz;
104 const double ac = AC(i);
105 if (ac < 1e-30)
106 return; // fully closed (solid) cell: decoupled, phi stays 0
107 const double s = AE(i) * phi(i + sx) + AW(i) * phi(i - sx) + AN(i) * phi(i + sy) +
108 AS(i) * phi(i - sy) + AT(i) * phi(i + sz) + AB(i) * phi(i - sz);
109 phi(i) = (b(i) - s) / ac;
110 });
111}
112
113// Box-restricted red/black sweep for the distributed overlap smoother: sweeps [rlo,rhi) only,
114// skipping the box [slo,shi) (pass slo==shi to skip nothing). Used to split one color's sweep into
115// an INTERIOR pass (cells whose 7-point stencil reads no ghost cell — runs while the halo exchange
116// is in flight) and a boundary-SHELL pass (after the exchange lands). A color's cells never read
117// same-color cells, so interior-then-shell ordering is bit-identical to the full blocking sweep
118// (and a cell swept twice recomputes the identical value — overlapping shell slabs are safe).
119template <class OpV>
120inline void cutcellSmoothColorBox(CCField phi, CCConst b, OpV AC, OpV AW, OpV AE, OpV AS, OpV AN,
121 OpV AB, OpV AT, C3 e, C3 og, int color, C3 rlo, C3 rhi, C3 slo,
122 C3 shi) {
123 if (rhi.x <= rlo.x || rhi.y <= rlo.y || rhi.z <= rlo.z)
124 return;
126 if constexpr (std::is_same_v<typename CCExec::memory_space, Kokkos::HostSpace>) {
127 // Host line-sweep form of the box sweep (see cutcellSmoothColor); the (ly,lz)-level skip test
128 // hoists out of the x-loop, the x-range skip stays per cell.
129 const int nyi = rhi.y - rlo.y, nzi = rhi.z - rlo.z;
130 const long cells = (long)nyi * nzi * (rhi.x - rlo.x);
131 auto pencil = KOKKOS_LAMBDA(long t) {
132 const int ly = rlo.y + (int)(t % nyi), lz = rlo.z + (int)(t / nyi);
133 const bool yzSkip = ly >= slo.y && ly < shi.y && lz >= slo.z && lz < shi.z;
134 const long sx = 1, sy = e.x, sz = (long)e.x * e.y;
135 const int P = (color + og.x + og.y + ly + og.z + lz) & 1;
136 for (int lx = rlo.x + ((P ^ (rlo.x & 1)) & 1); lx < rhi.x; lx += 2) {
137 if (yzSkip && lx >= slo.x && lx < shi.x)
138 continue; // inside the skip box (already swept by the interior pass)
139 const long i = (long)lx + (long)ly * sy + (long)lz * sz;
140 const double ac = AC(i);
141 if (ac < 1e-30)
142 continue;
143 const double s = AE(i) * phi(i + sx) + AW(i) * phi(i - sx) + AN(i) * phi(i + sy) +
144 AS(i) * phi(i - sy) + AT(i) * phi(i + sz) + AB(i) * phi(i - sz);
145 phi(i) = (b(i) - s) / ac;
146 }
147 };
148 if (hostRunSerial(cells)) { // coarse MG level: the fork/join costs more than the sweep
149 for (long t = 0; t < (long)nyi * nzi; ++t)
150 pencil(t);
151 return;
152 }
153 Kokkos::parallel_for("peclet::flow::cc_smooth_box",
154 Kokkos::RangePolicy<CCExec>(space, 0, (long)nyi * nzi), pencil);
155 return;
156 }
157 using MD = Kokkos::MDRangePolicy<CCExec, Kokkos::Rank<3>>;
158 Kokkos::parallel_for(
159 "peclet::flow::cc_smooth_box", MD(space, {rlo.x, rlo.y, rlo.z}, {rhi.x, rhi.y, rhi.z}),
160 KOKKOS_LAMBDA(int lx, int ly, int lz) {
161 if (lx >= slo.x && lx < shi.x && ly >= slo.y && ly < shi.y && lz >= slo.z && lz < shi.z)
162 return; // inside the skip box (already swept by the interior pass)
163 if (((og.x + lx + og.y + ly + og.z + lz) & 1) != color)
164 return;
165 const long sx = 1, sy = e.x, sz = (long)e.x * e.y;
166 const long i = (long)lx + (long)ly * sy + (long)lz * sz;
167 const double ac = AC(i);
168 if (ac < 1e-30)
169 return;
170 const double s = AE(i) * phi(i + sx) + AW(i) * phi(i - sx) + AN(i) * phi(i + sy) +
171 AS(i) * phi(i - sy) + AT(i) * phi(i + sz) + AB(i) * phi(i - sz);
172 phi(i) = (b(i) - s) / ac;
173 });
174}
175
176// y = A x for the cut-cell operator over inner cells (matvec for PCG; mg_apply_var_k port).
177template <class OpV>
178inline void applyCutcellOp(CCField y, CCConst x, OpV AC, OpV AW, OpV AE, OpV AS, OpV AN, OpV AB,
179 OpV AT, C3 e, int g) {
180 ccFor3(
181 "peclet::flow::cc_apply", C3{g, g, g}, C3{e.x - g, e.y - g, e.z - g},
182 KOKKOS_LAMBDA(int lx, int ly, int lz) {
183 const long sx = 1, sy = e.x, sz = (long)e.x * e.y;
184 const long i = (long)lx + (long)ly * sy + (long)lz * sz;
185 y(i) = AC(i) * x(i) + AE(i) * x(i + sx) + AW(i) * x(i - sx) + AN(i) * x(i + sy) +
186 AS(i) * x(i - sy) + AT(i) * x(i + sz) + AB(i) * x(i - sz);
187 });
188}
189
190// Box-restricted matvec for the distributed overlap: rows in [rlo,rhi) skipping [slo,shi). Reads
191// x, writes y (no aliasing), so the interior rows can apply while x's ghost exchange is in flight
192// and the shell rows apply after it lands — trivially bit-identical to the blocking order.
193template <class OpV>
194inline void applyCutcellOpBox(CCField y, CCConst x, OpV AC, OpV AW, OpV AE, OpV AS, OpV AN, OpV AB,
195 OpV AT, C3 e, C3 rlo, C3 rhi, C3 slo, C3 shi) {
196 if (rhi.x <= rlo.x || rhi.y <= rlo.y || rhi.z <= rlo.z)
197 return;
199 using MD = Kokkos::MDRangePolicy<CCExec, Kokkos::Rank<3>>;
200 Kokkos::parallel_for(
201 "peclet::flow::cc_apply_box", MD(space, {rlo.x, rlo.y, rlo.z}, {rhi.x, rhi.y, rhi.z}),
202 KOKKOS_LAMBDA(int lx, int ly, int lz) {
203 if (lx >= slo.x && lx < shi.x && ly >= slo.y && ly < shi.y && lz >= slo.z && lz < shi.z)
204 return;
205 const long sx = 1, sy = e.x, sz = (long)e.x * e.y;
206 const long i = (long)lx + (long)ly * sy + (long)lz * sz;
207 y(i) = AC(i) * x(i) + AE(i) * x(i + sx) + AW(i) * x(i - sx) + AN(i) * x(i + sy) +
208 AS(i) * x(i - sy) + AT(i) * x(i + sz) + AB(i) * x(i - sz);
209 });
210}
211
212// Projection correction u -= grad(phi) on the staggered faces (correct_k port). No openness here —
213// the openness lives in the operator + divergence; closed faces carry phi~0 on both sides so stay
214// unchanged.
215inline void projectCorrect(CCField u, CCField v, CCField w, CCConst phi, C3 e, int g) {
216 ccFor3(
217 "peclet::flow::correct", C3{g, g, g}, C3{e.x - g, e.y - g, e.z - g},
218 KOKKOS_LAMBDA(int x, int y, int z) {
219 const long sx = 1, sy = e.x, sz = (long)e.x * e.y;
220 const long i = (long)x + (long)y * sy + (long)z * sz;
221 u(i) -= phi(i) - phi(i - sx);
222 v(i) -= phi(i) - phi(i - sy);
223 w(i) -= phi(i) - phi(i - sz);
224 });
225}
226
227// Variable-density projection correction (sibling of projectCorrect): u_f -= (rho0/rho_f) grad(phi)
228// with rho_f the arithmetic face mean — the SAME face density that scaled the Poisson coefficient
229// c_f = open_f*rho0/rho_f, so the corrected open flux telescopes to A*phi exactly (discrete
230// consistency; constant rho == rho0 reduces to projectCorrect identically, ratio 1.0 exact in FP).
232 double rho0, C3 e, int g) {
234 using MD = Kokkos::MDRangePolicy<CCExec, Kokkos::Rank<3>>;
235 Kokkos::parallel_for(
236 "peclet::flow::correct_var", MD(space, {g, g, g}, {e.x - g, e.y - g, e.z - g}),
237 KOKKOS_LAMBDA(int x, int y, int z) {
238 const long sx = 1, sy = e.x, sz = (long)e.x * e.y;
239 const long i = (long)x + (long)y * sy + (long)z * sz;
240 u(i) -= rho0 / (0.5 * (rho(i) + rho(i - sx))) * (phi(i) - phi(i - sx));
241 v(i) -= rho0 / (0.5 * (rho(i) + rho(i - sy))) * (phi(i) - phi(i - sy));
242 w(i) -= rho0 / (0.5 * (rho(i) + rho(i - sz))) * (phi(i) - phi(i - sz));
243 });
244}
245
246// Variable-density Poisson face coefficients on the MG (g=1) block: c_f = open_f * rho0 / rho_f,
247// rho_f = arithmetic face mean. Computed over the inner cells only — CutcellMG::setOpenness runs
248// its own periodic/halo ghost fill + non-periodic boundary re-imposition on whatever level-0 fields
249// it receives, exactly as for the raw openness (the coefficient "rides the openness rails"). The
250// rho ghost ring of the g=1 block must be valid (bridged from the filled G=2 field).
252 CCConst rho, double rho0, C3 e, int g) {
254 using MD = Kokkos::MDRangePolicy<CCExec, Kokkos::Rank<3>>;
255 Kokkos::parallel_for(
256 "peclet::flow::rho_coeff", MD(space, {g, g, g}, {e.x - g, e.y - g, e.z - g}),
257 KOKKOS_LAMBDA(int x, int y, int z) {
258 const long sx = 1, sy = e.x, sz = (long)e.x * e.y;
259 const long i = (long)x + (long)y * sy + (long)z * sz;
260 cx(i) = ox(i) * rho0 / (0.5 * (rho(i) + rho(i - sx)));
261 cy(i) = oy(i) * rho0 / (0.5 * (rho(i) + rho(i - sy)));
262 cz(i) = oz(i) * rho0 / (0.5 * (rho(i) + rho(i - sz)));
263 });
264}
265
266// --- Volume-averaged (porous) continuity for unresolved CFD-DEM
267// ----------------------------------- The proper continuity is d(eps)/dt + div(eps u) = 0 (eps =
268// void fraction from the particles), so the velocity is NOT solenoidal: div(eps u) = -d(eps)/dt.
269// These size the projection to that constraint.
270
271// eps-weighted open-face divergence: d = div(open * eps_f * u), eps_f = arithmetic face mean.
272// Reduces to divergOpen when eps == 1 everywhere (no particles).
274 CCConst eps, CCField d, C3 e, int g) {
276 using MD = Kokkos::MDRangePolicy<CCExec, Kokkos::Rank<3>>;
277 Kokkos::parallel_for(
278 "peclet::flow::diverg_open_eps", MD(space, {g, g, g}, {e.x - g, e.y - g, e.z - g}),
279 KOKKOS_LAMBDA(int x, int y, int z) {
280 const long sx = 1, sy = e.x, sz = (long)e.x * e.y;
281 const long i = (long)x + (long)y * sy + (long)z * sz;
282 const double exp = 0.5 * (eps(i) + eps(i + sx)), exm = 0.5 * (eps(i) + eps(i - sx));
283 const double eyp = 0.5 * (eps(i) + eps(i + sy)), eym = 0.5 * (eps(i) + eps(i - sy));
284 const double ezp = 0.5 * (eps(i) + eps(i + sz)), ezm = 0.5 * (eps(i) + eps(i - sz));
285 d(i) = (ox(i + sx) * exp * u(i + sx) - ox(i) * exm * u(i)) +
286 (oy(i + sy) * eyp * v(i + sy) - oy(i) * eym * v(i)) +
287 (oz(i + sz) * ezp * w(i + sz) - oz(i) * ezm * w(i));
288 });
289}
290
291// Porous Poisson face coefficient c_f = open_f * eps_f (eps_f = arithmetic face mean).
292// Constant-density gas: the correction stays u -= grad(phi) (projectCorrect) so the open*eps flux
293// telescopes to A*phi. (Combining with variable rho — c_f *= rho0/rho_f, projectCorrectVar — is a
294// later composition.)
296 CCConst eps, C3 e, int g) {
298 using MD = Kokkos::MDRangePolicy<CCExec, Kokkos::Rank<3>>;
299 Kokkos::parallel_for(
300 "peclet::flow::porous_coeff", MD(space, {g, g, g}, {e.x - g, e.y - g, e.z - g}),
301 KOKKOS_LAMBDA(int x, int y, int z) {
302 const long sx = 1, sy = e.x, sz = (long)e.x * e.y;
303 const long i = (long)x + (long)y * sy + (long)z * sz;
304 cx(i) = ox(i) * 0.5 * (eps(i) + eps(i - sx));
305 cy(i) = oy(i) * 0.5 * (eps(i) + eps(i - sy));
306 cz(i) = oz(i) * 0.5 * (eps(i) + eps(i - sz));
307 });
308}
309
310// Semi-implicit-drag porous coefficient: c_f = open_f * eps_f * w_f, with the face drag-relaxation
311// w_f = idt/(idt + beta_f) (idt = rho/dt, beta = the momentum-diagonal drag coefficient). This
312// makes the pressure correction CONSISTENT with the drag-loaded momentum diagonal A_P = idt + beta:
313// where the drag is stiff (dense bed) w_f -> 0 and the pressure barely moves the velocity (the drag
314// holds it) — the SIMPLE/PISO-with-implicit-drag scheme (OpenFOAM rAU, MFIX). Reduces to
315// buildPorousCoeff when beta==0 (w==1). The correction MUST use the same w_f
316// (projectCorrectPorousDrag) so the open*eps*w flux telescopes to A*phi.
318 CCConst oz, CCConst eps, CCConst beta, double idt, C3 e, int g) {
320 using MD = Kokkos::MDRangePolicy<CCExec, Kokkos::Rank<3>>;
321 Kokkos::parallel_for(
322 "peclet::flow::porous_coeff_drag", MD(space, {g, g, g}, {e.x - g, e.y - g, e.z - g}),
323 KOKKOS_LAMBDA(int x, int y, int z) {
324 const long sx = 1, sy = e.x, sz = (long)e.x * e.y;
325 const long i = (long)x + (long)y * sy + (long)z * sz;
326 cx(i) = ox(i) * 0.5 * (eps(i) + eps(i - sx)) * idt / (idt + 0.5 * (beta(i) + beta(i - sx)));
327 cy(i) = oy(i) * 0.5 * (eps(i) + eps(i - sy)) * idt / (idt + 0.5 * (beta(i) + beta(i - sy)));
328 cz(i) = oz(i) * 0.5 * (eps(i) + eps(i - sz)) * idt / (idt + 0.5 * (beta(i) + beta(i - sz)));
329 });
330}
331
332// --- eps-CONSERVATIVE porous projection pair -------------------------------------------------
333// For the conservative volume-averaged momentum (time term (eps_f rho/dt) u, Model-B full -grad p)
334// the face momentum diagonal is D_f = eps_f*rho*idt + beta_f, the velocity correction is
335// u_f -= (rho*idt / D_f) * grad(phi) (beta=0, eps=1 -> plain projectCorrect exactly)
336// and the flux constraint div(eps u) = rhs makes the Poisson coefficient
337// c_f = open_f * eps_f * (rho*idt/D_f) = open_f * (eps_f*rho*idt) / D_f
338// — the eps of the flux cancels against the eps of the inertia, unlike the plain-u pair above
339// (buildPorousCoeff*/projectCorrectPorousDrag), which is consistent only for the non-conservative
340// momentum form and kinematically drags gas along with the moving porosity (energy injection).
342 CCConst oz, CCConst eps, CCConst beta, bool useBeta, double rhoidt,
343 C3 e, int g) {
345 using MD = Kokkos::MDRangePolicy<CCExec, Kokkos::Rank<3>>;
346 Kokkos::parallel_for(
347 "peclet::flow::porous_coeff_cons", MD(space, {g, g, g}, {e.x - g, e.y - g, e.z - g}),
348 KOKKOS_LAMBDA(int x, int y, int z) {
349 const long sx = 1, sy = e.x, sz = (long)e.x * e.y;
350 const long i = (long)x + (long)y * sy + (long)z * sz;
351 auto cf = [&](long s, CCConst o) {
352 const double epsF = 0.5 * (eps(i) + eps(i - s));
353 const double bF = useBeta ? 0.5 * (beta(i) + beta(i - s)) : 0.0;
354 const double inert = epsF * rhoidt;
355 return o(i) * inert / (inert + bF) * 1.0;
356 };
357 cx(i) = cf(sx, ox);
358 cy(i) = cf(sy, oy);
359 cz(i) = cf(sz, oz);
360 });
361}
363 CCConst beta, bool useBeta, double rhoidt, C3 e, int g) {
365 using MD = Kokkos::MDRangePolicy<CCExec, Kokkos::Rank<3>>;
366 Kokkos::parallel_for(
367 "peclet::flow::correct_porous_cons", MD(space, {g, g, g}, {e.x - g, e.y - g, e.z - g}),
368 KOKKOS_LAMBDA(int x, int y, int z) {
369 const long sx = 1, sy = e.x, sz = (long)e.x * e.y;
370 const long i = (long)x + (long)y * sy + (long)z * sz;
371 auto wf = [&](long s) {
372 const double epsF = 0.5 * (eps(i) + eps(i - s));
373 const double bF = useBeta ? 0.5 * (beta(i) + beta(i - s)) : 0.0;
374 return rhoidt / (epsF * rhoidt + bF);
375 };
376 u(i) -= wf(sx) * (phi(i) - phi(i - sx));
377 v(i) -= wf(sy) * (phi(i) - phi(i - sy));
378 w(i) -= wf(sz) * (phi(i) - phi(i - sz));
379 });
380}
381
382// Drag-relaxed velocity correction (sibling of projectCorrect): u_f -= w_f * grad(phi), w_f the
383// SAME face drag relaxation as buildPorousCoeffDrag. beta==0 -> w==1 -> projectCorrect exactly.
385 double idt, C3 e, int g) {
387 using MD = Kokkos::MDRangePolicy<CCExec, Kokkos::Rank<3>>;
388 Kokkos::parallel_for(
389 "peclet::flow::correct_porous_drag", MD(space, {g, g, g}, {e.x - g, e.y - g, e.z - g}),
390 KOKKOS_LAMBDA(int x, int y, int z) {
391 const long sx = 1, sy = e.x, sz = (long)e.x * e.y;
392 const long i = (long)x + (long)y * sy + (long)z * sz;
393 u(i) -= idt / (idt + 0.5 * (beta(i) + beta(i - sx))) * (phi(i) - phi(i - sx));
394 v(i) -= idt / (idt + 0.5 * (beta(i) + beta(i - sy))) * (phi(i) - phi(i - sy));
395 w(i) -= idt / (idt + 0.5 * (beta(i) + beta(i - sz))) * (phi(i) - phi(i - sz));
396 });
397}
398
399} // namespace peclet::flow
400
401#endif // PECLET_FLOW_MAC_PRESSURE_HPP
flow — portable (Kokkos) cut-cell pressure-operator face openness from an SDF.
void buildPorousCoeffDrag(CCField cx, CCField cy, CCField cz, CCConst ox, CCConst oy, CCConst oz, CCConst eps, CCConst beta, double idt, C3 e, int g)
void projectCorrectPorousDrag(CCField u, CCField v, CCField w, CCConst phi, CCConst beta, double idt, C3 e, int g)
void buildRhoCoeff(CCField cx, CCField cy, CCField cz, CCConst ox, CCConst oy, CCConst oz, CCConst rho, double rho0, C3 e, int g)
void buildPorousCoeffCons(CCField cx, CCField cy, CCField cz, CCConst ox, CCConst oy, CCConst oz, CCConst eps, CCConst beta, bool useBeta, double rhoidt, C3 e, int g)
void divergOpen(CCConst u, CCConst v, CCConst w, CCConst ox, CCConst oy, CCConst oz, CCField d, C3 e, int g)
void cutcellSmoothColorBox(CCField phi, CCConst b, OpV AC, OpV AW, OpV AE, OpV AS, OpV AN, OpV AB, OpV AT, C3 e, C3 og, int color, C3 rlo, C3 rhi, C3 slo, C3 shi)
void applyCutcellOp(CCField y, CCConst x, OpV AC, OpV AW, OpV AE, OpV AS, OpV AN, OpV AB, OpV AT, C3 e, int g)
void projectCorrectVar(CCField u, CCField v, CCField w, CCConst phi, CCConst rho, double rho0, C3 e, int g)
void ccFor3(const char *name, C3 lo, C3 hi, F f)
void ibmFillEntry(const OV &o, int list_idx, int c_idx, float sdf_c, const float sdf_n[6], int bc_type, const float *thEx)
void buildCutcellOp(OpV AC, OpV AW, OpV AE, OpV AS, OpV AN, OpV AB, OpV AT, CCConst ox, CCConst oy, CCConst oz, C3 e, int g, double gfx, double gfy, double gfz)
Kokkos::View< double *, CCMem > CCField
void cutcellSmoothColor(CCField phi, CCConst b, OpV AC, OpV AW, OpV AE, OpV AS, OpV AN, OpV AB, OpV AT, C3 e, C3 og, int g, int color)
void buildPorousCoeff(CCField cx, CCField cy, CCField cz, CCConst ox, CCConst oy, CCConst oz, CCConst eps, C3 e, int g)
Kokkos::DefaultExecutionSpace CCExec
void divergOpenEps(CCConst u, CCConst v, CCConst w, CCConst ox, CCConst oy, CCConst oz, CCConst eps, CCField d, C3 e, int g)
void projectCorrectPorousCons(CCField u, CCField v, CCField w, CCConst phi, CCConst eps, CCConst beta, bool useBeta, double rhoidt, C3 e, int g)
bool hostRunSerial(long cells)
void applyCutcellOpBox(CCField y, CCConst x, OpV AC, OpV AW, OpV AE, OpV AS, OpV AN, OpV AB, OpV AT, C3 e, C3 rlo, C3 rhi, C3 slo, C3 shi)
Kokkos::View< const double *, CCMem > CCConst
void projectCorrect(CCField u, CCField v, CCField w, CCConst phi, C3 e, int g)
static constexpr double AC
Kokkos::View< double *, peclet::flow::CCMem > OpV