87#ifndef PECLET_FLOW_VOF_MARCHING_CUBES_HPP
88#define PECLET_FLOW_VOF_MARCHING_CUBES_HPP
90#include <Kokkos_Core.hpp>
91#include <Kokkos_MathematicalFunctions.hpp>
120 double n[3] = {0.0, 0.0, 0.0};
126 p[0] =
static_cast<double>(k & 1);
127 p[1] =
static_cast<double>((k >> 1) & 1);
128 p[2] =
static_cast<double>((k >> 2) & 1);
145 const double g = a.n[0] * dv[0] + a.n[1] * dv[1] + a.n[2] * dv[2];
146 if (Kokkos::fabs(g) > 1e-12) {
147 const double t = -a.d / g;
148 if (t > -0.5 && t < 1.5) {
155 const double g = b.n[0] * dv[0] + b.n[1] * dv[1] + b.n[2] * dv[2];
156 if (Kokkos::fabs(g) > 1e-12) {
157 const double t = 1.0 - b.d / g;
158 if (t > -0.5 && t < 1.5) {
165 double t = acc /
static_cast<double>(cnt);
166 if (a.has && b.has) {
170 const double ga = a.n[0] * dv[0] + a.n[1] * dv[1] + a.n[2] * dv[2];
171 const double gb = b.n[0] * dv[0] + b.n[1] * dv[1] + b.n[2] * dv[2];
172 const double A =
gb -
ga, B = (
ga -
gb) + (b.d - a.d), C0 = a.d;
174 if (Kokkos::fabs(A) < 1e-12 * (Kokkos::fabs(B) + 1e-30)) {
175 if (Kokkos::fabs(B) > 0.0)
178 const double disc = B * B - 4.0 * A * C0;
180 const double sq = Kokkos::sqrt(
disc);
181 const double r1 = (-B +
sq) / (2.0 * A), r2 = (-B -
sq) / (2.0 * A);
182 const bool o1 = (r1 >= 0.0 && r1 <= 1.0),
o2 = (r2 >= 0.0 && r2 <= 1.0);
188 s2 = (Kokkos::fabs(r1 - t) < Kokkos::fabs(r2 - t)) ? r1 : r2;
191 if (s2 >= 0.0 && s2 <= 1.0)
194 return t < 0.0 ? 0.0 : (t > 1.0 ? 1.0 : t);
197 const double den = a.psi - b.psi;
198 if (!(Kokkos::fabs(den) > 0.0))
200 const double t = a.psi / den;
201 return t < 0.0 ? 0.0 : (t > 1.0 ? 1.0 : t);
206 const double p2[3],
const VofMetric& g) {
210 const double ux = (
p1[0] - p0[0]) * g.h[0],
uy = (
p1[1] - p0[1]) * g.h[1],
211 uz = (
p1[2] - p0[2]) * g.h[2];
212 const double vx = (
p2[0] - p0[0]) * g.h[0],
vy = (
p2[1] - p0[1]) * g.h[1],
213 vz = (
p2[2] - p0[2]) * g.h[2];
215 return Kokkos::sqrt(cx * cx + cy * cy + cz * cz);
225 const double c0 = g.h[1] * g.h[2], c1 = g.h[2] * g.h[0], c2 = g.h[0] * g.h[1];
226 double sx = 0.0, sy = 0.0, sz = 0.0;
227 for (
int i = 0; i < n; ++i) {
228 const int j = (i + 1 == n) ? 0 : i + 1;
229 sx += p[i][1] * p[j][2] - p[i][2] * p[j][1];
230 sy += p[i][2] * p[j][0] - p[i][0] * p[j][2];
231 sz += p[i][0] * p[j][1] - p[i][1] * p[j][0];
236 return 0.5 * Kokkos::sqrt(
sx *
sx + sy * sy + sz * sz);
244 for (
int i = 0; i < n; ++i) {
245 const int j = (i + 1 == n) ? 0 : i + 1;
246 const double si =
keepAbove ? (p[i][axis] - c) : (c - p[i][axis]);
247 const double sj =
keepAbove ? (p[j][axis] - c) : (c - p[j][axis]);
255 if (
ini !=
inj && m < 8) {
256 const double den =
si -
sj;
257 const double t = (Kokkos::fabs(den) > 0.0) ?
si / den : 0.0;
258 q[m][0] = p[i][0] + t * (p[j][0] - p[i][0]);
259 q[m][1] = p[i][1] + t * (p[j][1] - p[i][1]);
260 q[m][2] = p[i][2] + t * (p[j][2] - p[i][2]);
264 for (
int i = 0; i < m; ++i) {
274 const double p2[3],
int k,
const VofMetric& g) {
276 for (
int d = 0; d < 3; ++d) {
292 for (
int k = 0; k < 8; ++k) {
293 if (!((mask >> k) & 1))
297 const double dx = p[0] - q[0], dy = p[1] - q[1], dz = p[2] - q[2];
298 const double d2 = dx * dx + dy * dy + dz * dz;
318 if (mask == 0 || ((mask >> k) & 1))
323 return t < 0 ? k : t;
335 const VofMetric& g) {
338 for (
int d = 0; d < 3; ++d)
339 ctr[d] = (p0[d] +
p1[d] +
p2[d]) * (1.0 / 3.0);
341 for (
int d = 0; d < 3; ++d)
344 if (mask != 0 && !((mask >>
corner) & 1)) {
352 if (mask == 0 || ((mask >>
lc) & 1))
354 if (mask != 0 && mask != 255)
355 for (
int k = 0; k < 8; ++k)
368 const VofMetric& g) {
370 const int TET[6][4] = {{0, 1, 3, 7}, {0, 1, 5, 7}, {0, 2, 3, 7},
371 {0, 2, 6, 7}, {0, 4, 5, 7}, {0, 4, 6, 7}};
373 for (
int k = 0; k < 8; ++k)
384 for (
int t = 0; t < 6; ++t) {
386 for (
int j = 0; j < 4; ++j)
387 if (v[
TET[t][j]].psi < 0.0)
392 for (
int j = 0; j < 4; ++j)
401 for (
int j = 0; j < 4; ++j)
406 for (
int j = 0; j < 4; ++j) {
413 const double dv[3] = {
pb[0] -
pa[0],
pb[1] -
pa[1],
pb[2] -
pa[2]};
414 const double s =
mcEdgeT(v[ca], v[cb], dv, src);
415 for (
int d = 0; d < 3; ++d)
422 int neg[2], pos[2],
nn = 0,
np = 0;
423 for (
int j = 0; j < 4; ++j)
425 const int pair[4][2] = {
426 {
neg[0], pos[0]}, {
neg[0], pos[1]}, {
neg[1], pos[1]}, {
neg[1], pos[0]}};
427 for (
int q = 0; q < 4; ++q) {
432 const double dv[3] = {
pb[0] -
pa[0],
pb[1] -
pa[1],
pb[2] -
pa[2]};
433 const double s =
mcEdgeT(v[ca], v[cb], dv, src);
434 for (
int d = 0; d < 3; ++d)
435 tri[q][d] =
pa[d] + s * dv[d];
McDeposit
Which cell a triangle's area is booked to.
@ kMcDepositSplit
clipped to each cell's cube, each cell gets its own piece
@ kMcDepositCentroid
the whole triangle to the cell holding its centroid
int mcClipHalf(double p[8][3], int n, int axis, double c, bool keepAbove)
One Sutherland-Hodgman clip of a convex polygon against the half-space keepAbove ?...
int mcNearestMasked(const double p[3], int mask)
The corner in mask nearest the point p; the lowest index breaks a tie.
double mcTwiceArea(const double p0[3], const double p1[3], const double p2[3], const VofMetric &g)
Twice the area of the triangle (p0, p1, p2) — i.e. |(p1-p0) x (p2-p0)|.
double mcPolygonArea(const double p[8][3], int n, const VofMetric &g)
Area of a PLANAR polygon of n vertices, 1/2 |sum p_i x p_{i+1}|.
double mcTriangleToCorner(const double p0[3], const double p1[3], const double p2[3], int lc, int deposit, int mask, const VofMetric &g)
The part of one triangle that belongs to local corner lc of the dual cube.
McSource
What the edge crossing interpolates.
@ kMcSrcColour
the C = 1/2 level set (the WO's design)
@ kMcSrcPlic
the zero of the PLIC-reconstructed signed distance (the smooth variant)
double mcClipToCorner(const double p0[3], const double p1[3], const double p2[3], int k, const VofMetric &g)
The area of the part of one triangle inside corner k's octant of the dual cube.
void mcCornerPos(int k, double p[3])
Local coordinates of dual-cube corner k (bit 0 = x, bit 1 = y, bit 2 = z).
int mcRetarget(int k, int mask)
The retarget rule.
double mcEdgeT(const McVertex &a, const McVertex &b, const double dv[3], int src)
The parameter t in [0,1] at which the level set cuts the edge from corner a to corner b.
double mcCubeCornerArea(const McVertex v[8], int lc, int src, int deposit, const VofMetric &g)
The interfacial area inside one dual cube that belongs to its local corner lc.
One dual-cube corner = one cell centre.