50#ifndef PECLET_CORE_VOF_PLIC_HPP
51#define PECLET_CORE_VOF_PLIC_HPP
53#include <Kokkos_Core.hpp>
54#include <Kokkos_MathematicalFunctions.hpp>
71 const double s = Kokkos::fabs(
m[0]) + Kokkos::fabs(
m[1]) + Kokkos::fabs(
m[2]);
73 const double inv = 1.0 / s;
109 double h[3] = {1.0, 1.0, 1.0};
114 const double m =
h[0] >
h[1] ?
h[0] :
h[1];
115 return m >
h[2] ?
m :
h[2];
118 const double m =
h[0] <
h[1] ?
h[0] :
h[1];
119 return m <
h[2] ?
m :
h[2];
123 out[0] =
X[0] *
h[0];
124 out[1] =
X[1] *
h[1];
125 out[2] =
X[2] *
h[2];
144 const double q = Kokkos::sqrt(
m[0] *
m[0] +
m[1] *
m[1] +
m[2] *
m[2]);
147 const double p[3] = {
m[0] / g.
h[0],
m[1] / g.
h[1],
m[2] / g.
h[2]};
148 const double pn = Kokkos::sqrt(p[0] * p[0] + p[1] * p[1] + p[2] * p[2]);
161 const double q = Kokkos::sqrt(
m[0] *
m[0] +
m[1] *
m[1] +
m[2] *
m[2]);
164 const double p[3] = {
m[0] / g.
h[0],
m[1] / g.
h[1],
m[2] / g.
h[2]};
165 const double n2 = p[0] * p[0] + p[1] * p[1] + p[2] * p[2];
168 const double invn = 1.0 / Kokkos::sqrt(
n2);
172 return Kokkos::sqrt(
n2) /
q;
178 m[0] = n[0] * g.
h[0];
179 m[1] = n[1] * g.
h[1];
180 m[2] = n[2] * g.
h[2];
204 if (
n12 <= w && w <=
n3)
205 return (w - 0.5 *
n12) /
n3;
212 const double t3 = Kokkos::fmax(w -
n3, 0.0);
222 const double ax = Kokkos::fabs(
mx),
ay = Kokkos::fabs(
my),
az = Kokkos::fabs(
mz);
223 const double s =
ax +
ay +
az;
225 return alpha > 0.0 ? 1.0 : 0.0;
237 const double a1 =
beta / s;
244 const double n1 = Kokkos::fmin(Kokkos::fmin(
ax,
ay),
az) / s;
245 const double n3 = Kokkos::fmax(Kokkos::fmax(
ax,
ay),
az) / s;
246 const double n2 = Kokkos::fmax(1.0 -
n1 -
n3, 0.0);
250 return (
a1 <= 0.5) ? v : 1.0 - v;
271 return 0.5 * (
n1 + Kokkos::sqrt(
sqn1 + 8.0 *
n2 * (
n3v -
v1)));
275 return Kokkos::cbrt(
v6);
291 const double t = Kokkos::sqrt(c * c - b);
295 Kokkos::fmin(Kokkos::fmax((
plicCube(c) - 0.5 * a - 1.5 * b * c) /
plicCube(
t), -1.0), 1.0);
296 return c - 2.0 *
t * Kokkos::sin((1.0 / 3.0) * Kokkos::asin(
arg));
304 const double ax = Kokkos::fabs(
mx),
ay = Kokkos::fabs(
my),
az = Kokkos::fabs(
mz);
305 const double s =
ax +
ay +
az;
309 const double n1 = Kokkos::fmin(Kokkos::fmin(
ax,
ay),
az) / s;
310 const double n3 = Kokkos::fmax(Kokkos::fmax(
ax,
ay),
az) / s;
311 const double n2 = Kokkos::fmax(1.0 -
n1 -
n3, 0.0);
313 const double vc = Kokkos::fmin(Kokkos::fmax(v, 0.0), 1.0);
315 const double a1 = (
vc <= 0.5) ? w : 1.0 - w;
340 double a,
double b) {
341 const double len = b - a;
362 double a0,
double b0,
double a1,
double b1,
double a2,
365 if (!(
len[0] > 0.0) || !(
len[1] > 0.0) || !(
len[2] > 0.0))
367 const double m[3] = {
mx,
my,
mz};
386 return i + 3 *
j + 9 *
k;
389#define PECLET_VOF_C(dx, dy, dz) c[plicSt(1 + (dx), 1 + (dy), 1 + (dz))]
452 double m1, m2,
mm[4][3], t0, t1,
t2;
460 mm[0][0] = m1 > m2 ? 1.0 : -1.0;
464 mm[0][1] = 0.5 * (m1 - m2);
468 mm[0][2] = 0.5 * (m1 - m2);
473 mm[1][0] = 0.5 * (m1 - m2);
479 mm[1][1] = m1 > m2 ? 1.0 : -1.0;
483 mm[1][2] = 0.5 * (m1 - m2);
488 mm[2][0] = 0.5 * (m1 - m2);
492 mm[2][1] = 0.5 * (m1 - m2);
498 mm[2][2] = m1 > m2 ? 1.0 : -1.0;
505 t0 = Kokkos::fabs(
mm[0][0]);
506 t1 = Kokkos::fabs(
mm[1][1]);
507 t2 = Kokkos::fabs(
mm[2][2]);
518 t0 = Kokkos::fabs(
mm[3][0]);
519 t1 = Kokkos::fabs(
mm[3][1]);
520 t2 = Kokkos::fabs(
mm[3][2]);
525 if (Kokkos::fabs(
mm[
cn][
cn]) > t0)
543 double x0,
double y0,
double z0,
double h) {
570 double x0,
double y0,
double z0,
double h,
584 const double kHalfDiag = 0.86602540378443865;
588 const double half = 0.5 * b.s;
589 const double dx = b.x + half - cx,
dy = b.y + half - cy,
dz = b.z + half - cz;
593 vol += b.s * b.s * b.s;
598 if (b.lev >= levels || !(
d > 0.0)) {
600 const double inv = 1.0 /
d;
603 vol += b.s * b.s * b.s *
604 planeCellFraction(nx, ny, nz, r + nx * cx + ny * cy + nz * cz, b.x, b.y, b.z, b.s);
608 for (
int q = 0;
q < 8; ++
q)
609 stack[
top++] =
Box{b.x + ((
q & 1) ? half : 0.0), b.y + ((
q & 2) ? half : 0.0),
610 b.z + ((
q & 4) ? half : 0.0), half, b.lev + 1};
612 return vol / (h * h * h);
double faceFluxVolume(double mx, double my, double mz, double alpha, int dir, double f)
Donor-cell geometric flux volume: the fluid volume swept out of the slab [0, f] along dir,...
void youngsNormal(const double c[27], double m[3])
Youngs' normal: the 27-point weighted gradient (corner 1, edge 2, face 4 on each of the two opposing ...
double sphereCellFraction(double cx, double cy, double cz, double r, double x0, double y0, double z0, double h, int levels)
Fluid fraction of a cell for a sphere (fluid = INSIDE the sphere), by recursive octree subdivision wi...
void vofIndexNormal(const double n[3], const VofMetric &g, double m[3])
The INDEX-space normal of a physical normal n (any scale): m = H n, returned unnormalized (plicAlpha ...
double plicBoxVolume(double mx, double my, double mz, double alpha, double a0, double b0, double a1, double b1, double a2, double b2)
Fluid volume of the PLIC polyhedron inside the axis-aligned BOX [a0,b0] x [a1,b1] x [a2,...
double plicSlabVolume(double mx, double my, double mz, double alpha, int dir, double a, double b)
Fluid volume of the PLIC polyhedron inside the axis-aligned slab a <= x_dir <= b, expressed as a frac...
double plicAlphaReduced(double v, double n1, double n2, double n3)
Reduced-symmetry analytic inverse of plicVolumeReduced.
double vofPhysNormal(const double m[3], const VofMetric &g, double n[3])
The PHYSICAL unit normal of an index-space normal m (any scale), i.e.
double planeCellFractionAniso(double mx, double my, double mz, double alphaGlobal, double x0, double y0, double z0, const VofMetric &g)
The same for an anisotropic cell [x0, x0+g.h[0]] x [y0, y0+g.h[1]] x [z0, z0+g.h[2]]: the index norma...
int plicSt(int i, int j, int k)
Stencil index: x-fastest, offsets (i-1, j-1, k-1) with i,j,k in {0,1,2} (suite/docs/CONVENTIONS....
double plicCube(double x)
double planeCellFraction(double mx, double my, double mz, double alphaGlobal, double x0, double y0, double z0, double h)
Exact fluid fraction of the axis-aligned cell [x0,x0+h] x [y0,y0+h] x [z0,z0+h] under the GLOBAL plan...
double plicVolumeReduced(double w, double n1, double n2, double n3)
Reduced-symmetry forward relation.
double plicAlpha(double mx, double my, double mz, double v)
Plane offset alpha such that plicVolume(mx,my,mz,alpha) == V, exactly (analytic inverse).
double plicNormalizeL1(double m[3])
L1-normalize a normal in place. Returns the L1 norm before normalization (0 => untouched).
double plicVolume(double mx, double my, double mz, double alpha)
Volume fraction of the unit cell [0,1]^3 lying on the fluid side m .
void mycNormal(const double c[27], double m[3])
MYC — Mixed Youngs-Centred normal (Aulisa et al.
double vofPhysNormalInv(const double m[3], const VofMetric &g, double n[3])
vofPhysNormal in the RECIPROCAL-MULTIPLY form — n = (H^-1 m) * (1/|H^-1 m|), which is what the curvat...
Kokkos::View< T *, MemSpace > View
1D device array.
#define PECLET_VOF_C(dx, dy, dz)
A physical, axis-aligned box with per-axis periodicity. Continuous — no cells.
The per-axis cell size, in the solver's reference length (hRef), of the cell these kernels map to the...
void toPhys(const double X[3], double out[3]) const
Index displacement -> physical displacement (in hRef): ‘X’_a = h[a] X_a`.