flow
Kokkos cut-cell IBM incompressible Navier-Stokes solver + pnm pore extraction
Loading...
Searching...
No Matches
mac_ibm.hpp
Go to the documentation of this file.
1
11#ifndef PECLET_FLOW_MAC_IBM_HPP
12#define PECLET_FLOW_MAC_IBM_HPP
13
14#include <Kokkos_Core.hpp>
15
16#include "cut_cell_ibm.hpp" // IbmOverlay, ibmFillEntry
17#include "mac_cutcell.hpp" // peclet::flow::C3, peclet::flow::ccSampleExt, CCConst
18
19namespace peclet::flow {
20
21using mreal = float; // matrix coefficient type (matches cfd's mreal)
22using MConst = Kokkos::View<const float*, CCMem>;
23
24struct Off3 {
25 float x, y, z;
26};
27
28// Cut cell = fluid centre with at least one solid axis neighbour.
29KOKKOS_INLINE_FUNCTION bool ibmIsCut(float sc, const float sn[6]) {
30 if (sc <= 0.0f)
31 return false;
32 for (int k = 0; k < 6; ++k)
33 if (sn[k] < 0.0f)
34 return true;
35 return false;
36}
37
38// Find cut cells over the inner block and build the Robust-Scaled overlay (port of ibm_count_ext_k
39// + ibm_geometry_ext_k): per inner cell, gather the 7 staggered SDF samples; if cut, atomically
40// claim a slot, set idMap[cell]=slot, and fill the overlay. counter/idMap are reset here. Returns
41// the cut count (overlay arrays must be sized >= number of inner cells). bc_type 0=Dirichlet,
42// 1=Neumann.
43template <int SCHEME>
44inline int buildIbmOverlay(CCConst sdf, C3 ext, int g, Off3 off, int bc_type, const IbmOverlay& ov,
45 Kokkos::View<int*, CCMem> idMap, Kokkos::View<int, CCMem> counter) {
46 CCExec space;
47 Kokkos::deep_copy(space, counter, 0);
48 Kokkos::deep_copy(space, idMap, -1);
49 using MD = Kokkos::MDRangePolicy<CCExec, Kokkos::Rank<3>>;
50 Kokkos::parallel_for(
51 "peclet::flow::ibm_build_overlay", MD(space, {g, g, g}, {ext.x - g, ext.y - g, ext.z - g}),
52 KOKKOS_LAMBDA(int lx, int ly, int lz) {
53 const long idx = (long)lx + (long)ly * ext.x + (long)lz * (long)ext.x * ext.y;
54 const float sc = (float)ccSampleExt(sdf, ext, lx + off.x, ly + off.y, lz + off.z);
55 const int d[6][3] = {{1, 0, 0}, {-1, 0, 0}, {0, 1, 0}, {0, -1, 0}, {0, 0, 1}, {0, 0, -1}};
56 float sn[6];
57 for (int k = 0; k < 6; ++k)
58 sn[k] = (float)ccSampleExt(sdf, ext, lx + d[k][0] + off.x, ly + d[k][1] + off.y,
59 lz + d[k][2] + off.z);
60 if (!ibmIsCut(sc, sn))
61 return;
62 const int slot = Kokkos::atomic_fetch_add(&counter(), 1);
63 idMap(idx) = slot;
64 ibmFillEntry<SCHEME>(ov, slot, (int)idx, sc, sn, bc_type);
65 });
66
67 int cnt = 0;
68 Kokkos::deep_copy(cnt, counter);
69 return cnt;
70}
71
72// Volume fraction theta = clamp(0.5 + sdf_sample, 0, 1) at the staggered point (lx+off, ...).
73inline void ibmVolfrac(CCField theta, CCConst sdf, C3 ext, Off3 off) {
74 CCExec space;
75 using MD = Kokkos::MDRangePolicy<CCExec, Kokkos::Rank<3>>;
76 Kokkos::parallel_for(
77 "peclet::flow::ibm_volfrac", MD(space, {0, 0, 0}, {ext.x, ext.y, ext.z}),
78 KOKKOS_LAMBDA(int lx, int ly, int lz) {
79 const long i = (long)lx + (long)ly * ext.x + (long)lz * (long)ext.x * ext.y;
80 const double sd = ccSampleExt(sdf, ext, lx + off.x, ly + off.y, lz + off.z);
81 const double t = 0.5 + sd;
82 theta(i) = t < 0.0 ? 0.0 : (t > 1.0 ? 1.0 : t);
83 });
84}
85
86// Solid mask: 1 where the staggered SDF point is inside the solid (sd<0), else 0.
87inline void ibmSolidMask(CCField mask, CCConst sdf, C3 ext, Off3 off) {
88 CCExec space;
89 using MD = Kokkos::MDRangePolicy<CCExec, Kokkos::Rank<3>>;
90 Kokkos::parallel_for(
91 "peclet::flow::ibm_solid", MD(space, {0, 0, 0}, {ext.x, ext.y, ext.z}),
92 KOKKOS_LAMBDA(int lx, int ly, int lz) {
93 const long i = (long)lx + (long)ly * ext.x + (long)lz * (long)ext.x * ext.y;
94 const double sd = ccSampleExt(sdf, ext, lx + off.x, ly + off.y, lz + off.z);
95 mask(i) = (sd < 0.0) ? 1.0 : 0.0;
96 });
97}
98
99// Clean-fluid-interior mask: 1 only at fluid cells with no solid neighbour (not cut, not solid).
100inline void ibmCleanFluidMask(CCField m, CCConst sdf, C3 ext, Off3 off) {
101 CCExec space;
102 using MD = Kokkos::MDRangePolicy<CCExec, Kokkos::Rank<3>>;
103 Kokkos::parallel_for(
104 "peclet::flow::ibm_clean", MD(space, {0, 0, 0}, {ext.x, ext.y, ext.z}),
105 KOKKOS_LAMBDA(int lx, int ly, int lz) {
106 const long i = (long)lx + (long)ly * ext.x + (long)lz * (long)ext.x * ext.y;
107 const float sc = (float)ccSampleExt(sdf, ext, lx + off.x, ly + off.y, lz + off.z);
108 const int d[6][3] = {{1, 0, 0}, {-1, 0, 0}, {0, 1, 0}, {0, -1, 0}, {0, 0, 1}, {0, 0, -1}};
109 float sn[6];
110 for (int k = 0; k < 6; ++k)
111 sn[k] = (float)ccSampleExt(sdf, ext, lx + d[k][0] + off.x, ly + d[k][1] + off.y,
112 lz + d[k][2] + off.z);
113 const bool solid = (sc <= 0.0f);
114 m(i) = (solid || ibmIsCut(sc, sn)) ? 0.0 : 1.0;
115 });
116}
117
118// One Red-Black sweep of the variable-coefficient stencil: x[i] = (b[i] - sum(A_off*x_nbr)) /
119// A_C[i]. float matrix coeffs promote to double; solid cells pinned to 0. Call colour 0 then 1.
121 MConst AN, MConst AB, MConst AT, CCConst solidmask, C3 ext, C3 og,
122 int g, int color) {
123 CCExec space;
124 const bool hasMask = (solidmask.extent(0) != 0);
125 using MD = Kokkos::MDRangePolicy<CCExec, Kokkos::Rank<3>>;
126 Kokkos::parallel_for(
127 "peclet::flow::ibm_rbgs", MD(space, {g, g, g}, {ext.x - g, ext.y - g, ext.z - g}),
128 KOKKOS_LAMBDA(int lx, int ly, int lz) {
129 if (((og.x + lx + og.y + ly + og.z + lz) & 1) != color)
130 return;
131 const long sx = 1, sy = ext.x, sz = (long)ext.x * ext.y;
132 const long i = (long)lx + (long)ly * ext.x + (long)lz * sz;
133 if (hasMask && solidmask(i) > 0.5) {
134 x(i) = 0.0;
135 return;
136 }
137 const double ac = AC(i);
138 if (Kokkos::fabs(ac) < 1e-30)
139 return;
140 const double s = (double)AE(i) * x(i + sx) + (double)AW(i) * x(i - sx) +
141 (double)AN(i) * x(i + sy) + (double)AS(i) * x(i - sy) +
142 (double)AT(i) * x(i + sz) + (double)AB(i) * x(i - sz);
143 x(i) = (b(i) - s) / ac;
144 });
145}
146
147inline void ibmRbgsSweep(CCField x, CCConst b, MConst AC, MConst AW, MConst AE, MConst AS,
148 MConst AN, MConst AB, MConst AT, CCConst solidmask, C3 ext, C3 og, int g) {
149 ibmRbgsStencilColor(x, b, AC, AW, AE, AS, AN, AB, AT, solidmask, ext, og, g, 0);
150 ibmRbgsStencilColor(x, b, AC, AW, AE, AS, AN, AB, AT, solidmask, ext, og, g, 1);
151}
152
153} // namespace peclet::flow
154
155#endif // PECLET_FLOW_MAC_IBM_HPP
flow — portable (Kokkos) Robust-Scaled cut-cell IBM primitives + per-cut-cell overlay build.
flow — portable (Kokkos) cut-cell pressure-operator face openness from an SDF.
int buildIbmOverlay(CCConst sdf, C3 ext, int g, Off3 off, int bc_type, const IbmOverlay &ov, Kokkos::View< int *, CCMem > idMap, Kokkos::View< int, CCMem > counter)
Definition mac_ibm.hpp:44
void ibmSolidMask(CCField mask, CCConst sdf, C3 ext, Off3 off)
Definition mac_ibm.hpp:87
void ibmCleanFluidMask(CCField m, CCConst sdf, C3 ext, Off3 off)
Definition mac_ibm.hpp:100
void ibmRbgsStencilColor(CCField x, CCConst b, MConst AC, MConst AW, MConst AE, MConst AS, MConst AN, MConst AB, MConst AT, CCConst solidmask, C3 ext, C3 og, int g, int color)
Definition mac_ibm.hpp:120
bool ibmIsCut(float sc, const float sn[6])
Definition mac_ibm.hpp:29
void ibmRbgsSweep(CCField x, CCConst b, MConst AC, MConst AW, MConst AE, MConst AS, MConst AN, MConst AB, MConst AT, CCConst solidmask, C3 ext, C3 og, int g)
Definition mac_ibm.hpp:147
Kokkos::View< double *, CCMem > CCField
float mreal
Definition mac_ibm.hpp:21
Kokkos::DefaultExecutionSpace CCExec
Kokkos::View< const float *, CCMem > MConst
double ccSampleExt(CCConst sdf, C3 ext, double x, double y, double z)
Kokkos::View< const double *, CCMem > CCConst
void ibmVolfrac(CCField theta, CCConst sdf, C3 ext, Off3 off)
Definition mac_ibm.hpp:73
static constexpr double AC