flow
Kokkos cut-cell IBM incompressible Navier-Stokes solver + pnm pore extraction
Loading...
Searching...
No Matches
staggered_advection.hpp
Go to the documentation of this file.
1
9#ifndef PECLET_FLOW_STAGGERED_ADVECTION_HPP
10#define PECLET_FLOW_STAGGERED_ADVECTION_HPP
11
12#include <Kokkos_Core.hpp>
13#include <Kokkos_MathematicalFunctions.hpp>
14
15namespace sadv {
16
17KOKKOS_INLINE_FUNCTION double koren(double up_m1, double up, double down, double vel) {
18 const double num = up - up_m1, den = down - up;
19 double r = (Kokkos::fabs(den) < 1e-10) ? 0.0 : num / den;
20 if (Kokkos::fabs(den) < 1e-10 && Kokkos::fabs(num) < 1e-10)
21 r = 1.0;
22 const double psi =
23 Kokkos::fmax(0.0, Kokkos::fmin(2.0 * r, Kokkos::fmin((1.0 + 2.0 * r) / 3.0, 2.0)));
24 return vel * (up + 0.5 * psi * (down - up));
25}
26KOKKOS_INLINE_FUNCTION double tvd(double LL, double L, double R, double RR, double vel) {
27 return (vel > 0.0) ? koren(LL, L, R, vel) : koren(RR, R, L, vel);
28}
29KOKKOS_INLINE_FUNCTION double fou_flux(double L, double R, double vel) {
30 return vel * (vel > 0.0 ? L : R);
31}
32// Second-order upwind (SOU) face flux: linear extrapolation from the two upwind
33// cells (unlimited; 2nd-order everywhere, including smooth extrema where the TVD
34// limiter clips to 1st order). vel>0 uses LL,L; vel<0 uses RR,R.
35KOKKOS_INLINE_FUNCTION double sou(double LL, double L, double R, double RR, double vel) {
36 return (vel > 0.0) ? vel * (1.5 * L - 0.5 * LL) : vel * (1.5 * R - 0.5 * RR);
37}
38
39// Local extended-block accessor over a Kokkos View (direct strides, x-fastest; no wrap).
40struct ViewAcc {
41 Kokkos::View<const double*, Kokkos::DefaultExecutionSpace::memory_space> d;
42 int ex, ey;
43 KOKKOS_INLINE_FUNCTION double operator()(int x, int y, int z) const {
44 return d(static_cast<long>(x) + static_cast<long>(y) * ex +
45 static_cast<long>(z) * static_cast<long>(ex) * ey);
46 }
47};
48
49// Advecting velocity at the +fd face of the comp control volume at (x,y,z).
50template <class A>
51KOKKOS_INLINE_FUNCTION double adv_vel(int comp, int fd, int x, int y, int z, A U, A V, A W) {
52 if (comp == 0) {
53 if (fd == 0)
54 return 0.5 * (U(x, y, z) + U(x + 1, y, z));
55 if (fd == 1)
56 return 0.5 * (V(x - 1, y + 1, z) + V(x, y + 1, z));
57 return 0.5 * (W(x - 1, y, z + 1) + W(x, y, z + 1));
58 }
59 if (comp == 1) {
60 if (fd == 0)
61 return 0.5 * (U(x + 1, y - 1, z) + U(x + 1, y, z));
62 if (fd == 1)
63 return 0.5 * (V(x, y, z) + V(x, y + 1, z));
64 return 0.5 * (W(x, y - 1, z + 1) + W(x, y, z + 1));
65 }
66 if (fd == 0)
67 return 0.5 * (U(x + 1, y, z - 1) + U(x + 1, y, z));
68 if (fd == 1)
69 return 0.5 * (V(x, y + 1, z - 1) + V(x, y + 1, z));
70 return 0.5 * (W(x, y, z) + W(x, y, z + 1));
71}
72
73// Conservative Koren-TVD advection A = sum_dir (F_plus - F_minus) of component comp; PHI is its
74// field.
75template <class A>
76KOKKOS_INLINE_FUNCTION double advect(int comp, int x, int y, int z, A U, A V, A W, A PHI) {
77 double out = 0.0;
78 for (int fd = 0; fd < 3; ++fd) {
79 const int ox = (fd == 0), oy = (fd == 1), oz = (fd == 2);
80 const double velp = adv_vel(comp, fd, x, y, z, U, V, W);
81 const double velm = adv_vel(comp, fd, x - ox, y - oy, z - oz, U, V, W);
82 const double Fp = tvd(PHI(x - ox, y - oy, z - oz), PHI(x, y, z), PHI(x + ox, y + oy, z + oz),
83 PHI(x + 2 * ox, y + 2 * oy, z + 2 * oz), velp);
84 const double Fm = tvd(PHI(x - 2 * ox, y - 2 * oy, z - 2 * oz), PHI(x - ox, y - oy, z - oz),
85 PHI(x, y, z), PHI(x + ox, y + oy, z + oz), velm);
86 out += Fp - Fm;
87 }
88 return out;
89}
90
91// Conservative second-order-upwind advection (same control volume / advecting
92// velocities as advect(); SOU flux instead of the Koren limiter).
93template <class A>
94KOKKOS_INLINE_FUNCTION double advect_sou(int comp, int x, int y, int z, A U, A V, A W, A PHI) {
95 double out = 0.0;
96 for (int fd = 0; fd < 3; ++fd) {
97 const int ox = (fd == 0), oy = (fd == 1), oz = (fd == 2);
98 const double velp = adv_vel(comp, fd, x, y, z, U, V, W);
99 const double velm = adv_vel(comp, fd, x - ox, y - oy, z - oz, U, V, W);
100 const double Fp = sou(PHI(x - ox, y - oy, z - oz), PHI(x, y, z), PHI(x + ox, y + oy, z + oz),
101 PHI(x + 2 * ox, y + 2 * oy, z + 2 * oz), velp);
102 const double Fm = sou(PHI(x - 2 * ox, y - 2 * oy, z - 2 * oz), PHI(x - ox, y - oy, z - oz),
103 PHI(x, y, z), PHI(x + ox, y + oy, z + oz), velm);
104 out += Fp - Fm;
105 }
106 return out;
107}
108
109// FOU advection OPERATOR coefficients added to a cell's 7-point stencil (consistent with advect_fou
110// applied to the field): diagonal cC gets max(velp,0)-min(velm,0) >= 0, off-diagonals <= 0. Added
111// (not assigned) into the out-params. Port of fou_operator (staggered_advection.cuh).
112template <class A>
113KOKKOS_INLINE_FUNCTION void fou_operator(int comp, int x, int y, int z, A U, A V, A W, double dt,
114 double& cC, double& cxm, double& cxp, double& cym,
115 double& cyp, double& czm, double& czp) {
116 for (int fd = 0; fd < 3; ++fd) {
117 const int ox = (fd == 0), oy = (fd == 1), oz = (fd == 2);
118 const double velp = adv_vel(comp, fd, x, y, z, U, V, W);
119 const double velm = adv_vel(comp, fd, x - ox, y - oy, z - oz, U, V, W);
120 cC += dt * (Kokkos::fmax(velp, 0.0) - Kokkos::fmin(velm, 0.0));
121 const double cp = dt * Kokkos::fmin(velp, 0.0), cm = dt * (-Kokkos::fmax(velm, 0.0));
122 if (fd == 0) {
123 cxp += cp;
124 cxm += cm;
125 } else if (fd == 1) {
126 cyp += cp;
127 cym += cm;
128 } else {
129 czp += cp;
130 czm += cm;
131 }
132 }
133}
134
135// Anisotropic (per-axis inverse spacing) FOU operator for the velocity multigrid coarse levels:
136// the advecting velocity along face-axis fd is scaled by s_fd = 1/h_fd. sx=sy=sz=1 == fou_operator.
137template <class A>
138KOKKOS_INLINE_FUNCTION void fou_operator_aniso(int comp, int x, int y, int z, A U, A V, A W,
139 double dt, double sx, double sy, double sz,
140 double& cC, double& cxm, double& cxp, double& cym,
141 double& cyp, double& czm, double& czp) {
142 for (int fd = 0; fd < 3; ++fd) {
143 const int ox = (fd == 0), oy = (fd == 1), oz = (fd == 2);
144 const double s = (fd == 0) ? sx : (fd == 1) ? sy : sz;
145 const double velp = s * adv_vel(comp, fd, x, y, z, U, V, W);
146 const double velm = s * adv_vel(comp, fd, x - ox, y - oy, z - oz, U, V, W);
147 cC += dt * (Kokkos::fmax(velp, 0.0) - Kokkos::fmin(velm, 0.0));
148 const double cp = dt * Kokkos::fmin(velp, 0.0), cm = dt * (-Kokkos::fmax(velm, 0.0));
149 if (fd == 0) {
150 cxp += cp;
151 cxm += cm;
152 } else if (fd == 1) {
153 cyp += cp;
154 cym += cm;
155 } else {
156 czp += cp;
157 czm += cm;
158 }
159 }
160}
161
162// Conservative first-order-upwind advection of comp (low-order flux, same advecting velocities).
163template <class A>
164KOKKOS_INLINE_FUNCTION double advect_fou(int comp, int x, int y, int z, A U, A V, A W, A PHI) {
165 double out = 0.0;
166 for (int fd = 0; fd < 3; ++fd) {
167 const int ox = (fd == 0), oy = (fd == 1), oz = (fd == 2);
168 const double velp = adv_vel(comp, fd, x, y, z, U, V, W);
169 const double velm = adv_vel(comp, fd, x - ox, y - oy, z - oz, U, V, W);
170 out += fou_flux(PHI(x, y, z), PHI(x + ox, y + oy, z + oz), velp) -
171 fou_flux(PHI(x - ox, y - oy, z - oz), PHI(x, y, z), velm);
172 }
173 return out;
174}
175
176} // namespace sadv
177
178#endif // PECLET_FLOW_STAGGERED_ADVECTION_HPP
double adv_vel(int comp, int fd, int x, int y, int z, A U, A V, A W)
double advect(int comp, int x, int y, int z, A U, A V, A W, A PHI)
double advect_sou(int comp, int x, int y, int z, A U, A V, A W, A PHI)
double fou_flux(double L, double R, double vel)
void fou_operator_aniso(int comp, int x, int y, int z, A U, A V, A W, double dt, double sx, double sy, double sz, double &cC, double &cxm, double &cxp, double &cym, double &cyp, double &czm, double &czp)
void fou_operator(int comp, int x, int y, int z, A U, A V, A W, double dt, double &cC, double &cxm, double &cxp, double &cym, double &cyp, double &czm, double &czp)
double tvd(double LL, double L, double R, double RR, double vel)
double sou(double LL, double L, double R, double RR, double vel)
double advect_fou(int comp, int x, int y, int z, A U, A V, A W, A PHI)
double koren(double up_m1, double up, double down, double vel)
double operator()(int x, int y, int z) const
Kokkos::View< const double *, Kokkos::DefaultExecutionSpace::memory_space > d