flow 1.3.0
Kokkos cut-cell IBM incompressible Navier-Stokes solver + pnm pore extraction
Loading...
Searching...
No Matches
interface_area.hpp
Go to the documentation of this file.
1
51#ifndef PECLET_FLOW_VOF_INTERFACE_AREA_HPP
52#define PECLET_FLOW_VOF_INTERFACE_AREA_HPP
53
54#include <Kokkos_Core.hpp>
55#include <Kokkos_MathematicalFunctions.hpp>
56
57#include "vof/curvature.hpp" // core: hfColumnHeight, curvFrame, PvFit, paraboloidKappa, ...
58#include "vof/phase_change.hpp" // plicArea
59#include "vof/plic.hpp"
60
61namespace peclet::flow::vof {
62
70 // ---- WO-P3d: a JOINED surface (marching tetrahedra on the cell-centre lattice). No per-cell
71 // construction converges (see `vof/marching_cubes.hpp`); these four do not build a per-cell
72 // piece at all, they cut ONE watertight sheet and book each triangle to a cell.
77};
78
87KOKKOS_INLINE_FUNCTION double hfAreaElement(const double h[9]) {
88 const double hx = 0.5 * (h[2 + 3 * 1] - h[0 + 3 * 1]);
89 const double hy = 0.5 * (h[1 + 3 * 2] - h[1 + 3 * 0]);
90 return Kokkos::sqrt(1.0 + hx * hx + hy * hy);
91}
92
96KOKKOS_INLINE_FUNCTION double hfAreaElement(const double h[9], const VofMetric& g, int d) {
97 const int d1 = (d + 1) % 3, d2 = (d + 2) % 3;
98 const double hx = 0.5 * (h[2 + 3 * 1] - h[0 + 3 * 1]) * (g.h[d] / g.h[d1]);
99 const double hy = 0.5 * (h[1 + 3 * 2] - h[1 + 3 * 0]) * (g.h[d] / g.h[d2]);
100 return Kokkos::sqrt(1.0 + hx * hx + hy * hy);
101}
102
128KOKKOS_INLINE_FUNCTION double hfFootprintArea(const double h[9]) {
129 const double hx = 0.5 * (h[2 + 3 * 1] - h[0 + 3 * 1]);
130 const double hy = 0.5 * (h[1 + 3 * 2] - h[1 + 3 * 0]);
131 const double h0 = h[1 + 3 * 1];
132 const double off = 0.5 * (hx + hy) - h0;
133 const double f = plicVolume(hx, hy, 0.0, 0.5 + off) - plicVolume(hx, hy, 0.0, -0.5 + off);
134 return f * Kokkos::sqrt(1.0 + hx * hx + hy * hy);
135}
136
141KOKKOS_INLINE_FUNCTION double hfFootprintArea(const double h[9], const VofMetric& g, int d) {
142 const int d1 = (d + 1) % 3, d2 = (d + 2) % 3;
143 const double hx = 0.5 * (h[2 + 3 * 1] - h[0 + 3 * 1]);
144 const double hy = 0.5 * (h[1 + 3 * 2] - h[1 + 3 * 0]);
145 const double h0 = h[1 + 3 * 1];
146 const double off = 0.5 * (hx + hy) - h0;
147 const double f = plicVolume(hx, hy, 0.0, 0.5 + off) - plicVolume(hx, hy, 0.0, -0.5 + off);
148 return f * (g.h[d1] * g.h[d2]) * hfAreaElement(h, g, d);
149}
150
157KOKKOS_INLINE_FUNCTION void hfSurfaceNormal(const double h[9], int d, double m[3]) {
158 const double hx = 0.5 * (h[2 + 3 * 1] - h[0 + 3 * 1]);
159 const double hy = 0.5 * (h[1 + 3 * 2] - h[1 + 3 * 0]);
160 const int d1 = (d + 1) % 3, d2 = (d + 2) % 3;
161 const double inv = 1.0 / Kokkos::sqrt(1.0 + hx * hx + hy * hy);
162 m[d1] = -hx * inv;
163 m[d2] = -hy * inv;
164 m[d] = inv;
165}
166
169KOKKOS_INLINE_FUNCTION void hfSurfaceNormal(const double h[9], int d, const VofMetric& g,
170 double m[3]) {
171 const int d1 = (d + 1) % 3, d2 = (d + 2) % 3;
172 const double hx = 0.5 * (h[2 + 3 * 1] - h[0 + 3 * 1]) * (g.h[d] / g.h[d1]);
173 const double hy = 0.5 * (h[1 + 3 * 2] - h[1 + 3 * 0]) * (g.h[d] / g.h[d2]);
174 const double inv = 1.0 / Kokkos::sqrt(1.0 + hx * hx + hy * hy);
175 m[d1] = -hx * inv;
176 m[d2] = -hy * inv;
177 m[d] = inv;
178}
179
184KOKKOS_INLINE_FUNCTION void pvSurfaceNormal(const double a[6], const double t1[3],
185 const double t2[3], const double nn[3], double m[3]) {
186 const double inv = 1.0 / Kokkos::sqrt(1.0 + a[1] * a[1] + a[2] * a[2]);
187 for (int i = 0; i < 3; ++i)
188 m[i] = (-a[1] * t1[i] - a[2] * t2[i] + nn[i]) * inv;
189}
190
205KOKKOS_INLINE_FUNCTION double interfaceAreaFromNormal(int mode, double mx, double my, double mz,
206 double alpha, double c, const double ns[3],
207 const VofMetric& g) {
208 const double m[3] = {mx, my, mz};
209 const double aPlic = plicAreaMetric(mx, my, mz, alpha, g);
210 if (mode == kAreaPlic)
211 return aPlic;
212 if (mode == kAreaNormal) {
213 double mi[3];
214 vofIndexNormal(ns, g, mi); // the accurate PHYSICAL normal, pushed to index space
215 const double al = plicAlpha(mi[0], mi[1], mi[2], c);
216 return plicAreaMetric(mi[0], mi[1], mi[2], al, g);
217 }
218 // kAreaMetric: keep the PLIC footprint, replace the slope.
219 int d = 0;
220 double best = Kokkos::fabs(ns[0]);
221 if (Kokkos::fabs(ns[1]) > best) {
222 best = Kokkos::fabs(ns[1]);
223 d = 1;
224 }
225 if (Kokkos::fabs(ns[2]) > best) {
226 best = Kokkos::fabs(ns[2]);
227 d = 2;
228 }
229 if (!(best > 0.0))
230 return aPlic;
231 double np[3];
232 if (!(vofPhysNormal(m, g, np) > 0.0))
233 return aPlic;
234 return aPlic * Kokkos::fabs(np[d]) / best;
235}
236
238KOKKOS_INLINE_FUNCTION double interfaceAreaFromNormal(int mode, double mx, double my, double mz,
239 double alpha, double c, const double ns[3]) {
240 return interfaceAreaFromNormal(mode, mx, my, mz, alpha, c, ns, VofMetric{});
241}
242
243} // namespace peclet::flow::vof
244
245#endif // PECLET_FLOW_VOF_INTERFACE_AREA_HPP
flow — thin shim: the container-free VoF height-function / paraboloid curvature kernels (rung V3) now...
double hfAreaElement(const double h[9])
The height function's area element sqrt(1 + h_x^2 + h_y^2), with the same central differences hfPatch...
InterfaceAreaMode
Which construction turns the cascade's normal into an area.
@ kAreaFootprint
variant C: the height function's OWN footprint x its own metric.
@ kAreaMcPlicSplit
the PLIC signed-distance level set, clipped deposit
@ kAreaMcPlic
the PLIC signed-distance level set, centroid deposit
@ kAreaMcColour
the C = 1/2 level set, whole triangles to the centroid's cell
@ kAreaNormal
variant B: plicArea rebuilt on the cascade's normal.
@ kAreaMetric
variant A: the PLIC footprint x the cascade's slope. DEFAULT.
@ kAreaPlic
rung P0/P1: plicArea on the MYC normal. The old numbers.
@ kAreaMcColourSplit
the same sheet, triangles CLIPPED to each cell's cube
double plicAreaMetric(double mx, double my, double mz, double alpha, const VofMetric &g)
The PHYSICAL area of the PLIC polygon of an ANISOTROPIC cell, in hRef^2 (flow/doc/anisotropic_vof....
void pvSurfaceNormal(const double a[6], const double t1[3], const double t2[3], const double nn[3], double m[3])
The unit normal of the fitted paraboloid z = a0 + a1 x + a2 y + ... AT THE ORIGIN of its own frame (t...
double interfaceAreaFromNormal(int mode, double mx, double my, double mz, double alpha, double c, const double ns[3], const VofMetric &g)
The projection axis of kAreaMetric is the one ns is most aligned with — the column direction on tiers...
double hfFootprintArea(const double h[9])
Variant C — the height function's own footprint times its own metric (kAreaFootprint).
void hfSurfaceNormal(const double h[9], int d, double m[3])
The unit surface normal implied by the SAME 3x3 patch of heights, in world components.
flow — VoF phase change (Part II, rungs P0/P1): the container-free kernel set.
flow — thin shim: the container-free VoF PLIC geometric toolbox (rung V0) now live in core.