41#include <Kokkos_Core.hpp>
45#include "peclet/core/common/types.hpp"
46#include "peclet/core/decomp/block_decomposer.hpp"
50static constexpr int NX = 16,
NY = 16,
NZ = 32;
53static std::vector<double>
gatherGlobal(
const std::vector<double>&
local,
int ox,
int oy,
int oz,
54 int lnx,
int lny,
int lnz,
int rank,
int size) {
55 std::vector<double>
global;
58 for (
int r = 0; r < size; ++r) {
62 for (
int z = 0; z <
lnz; ++z)
63 for (
int y = 0; y <
lny; ++y)
64 std::memcpy(&
global[(std::size_t)ox + (std::size_t)(y + oy) *
NX +
65 (std::size_t)(z + oz) *
NX *
NY],
67 (std::size_t)
lnx *
sizeof(
double));
73 }
else if (rank == 0) {
78 for (
int z = 0; z <
meta[5]; ++z)
79 for (
int y = 0; y <
meta[4]; ++y)
81 (std::size_t)(z +
meta[2]) *
NX *
NY],
82 &
buf[(std::size_t)
meta[3] * 0 + (std::size_t)y *
meta[3] +
84 (std::size_t)
meta[3] *
sizeof(
double));
91 const double sp[5][4] = {{4.5, 4.5, 11, 3.4},
92 {11.5, 11.5, 11, 3.4},
96 std::vector<double> f((std::size_t)
lnx *
lny *
lnz, 1
e30);
97 for (
int z = 0; z <
lnz; ++z)
98 for (
int y = 0; y <
lny; ++y)
99 for (
int x = 0; x <
lnx; ++x) {
101 for (
const auto& q : sp) {
102 const double dx = x + ox + 0.5 - q[0], dy = y + oy + 0.5 - q[1], dz = z + oz + 0.5 - q[2];
103 d = std::fmin(d, std::sqrt(dx * dx + dy * dy + dz * dz) - q[3]);
105 f[(std::size_t)x + (std::size_t)y *
lnx + (std::size_t)z *
lnx *
lny] = d;
111 const char* v = std::getenv(k);
112 return v ? std::atof(v) :
dflt;
120 for (
int f = 0; f < 4; ++f)
127 if (!std::getenv(
"PROBE_NOSOLID"))
130 const double rtol =
envd(
"PROBE_RTOL", 0.0);
133 const double wisp =
envd(
"PROBE_WISP", -1.0);
136 std::vector<double> c0((std::size_t)
lnx *
lny *
lnz, 0.0);
137 for (
int z = 0; z <
lnz; ++z)
138 if (z + oz >=
NZ / 2)
139 for (
int y = 0; y <
lny; ++y)
140 for (
int x = 0; x <
lnx; ++x)
141 c0[(std::size_t)x + (std::size_t)y *
lnx + (std::size_t)z *
lnx *
lny] = 1.0;
146 const std::size_t kp =
147 (std::size_t)0 + (std::size_t)0 *
lnx + (std::size_t)(
lnz - 1) *
lnx *
lny;
148 c0[kp] = std::nextafter(1.0, 0.0);
153 if (std::getenv(
"PROBE_KINEMATIC")) {
158 const bool vary = std::atoi(std::getenv(
"PROBE_KINEMATIC")) >= 2;
160 for (
int z = 0; z <
lnz; ++z)
161 for (
int y = 0; y <
lny; ++y)
162 for (
int x = 0; x <
lnx; ++x) {
163 const std::size_t k = (std::size_t)x + (std::size_t)y *
lnx + (std::size_t)z *
lnx *
lny;
164 const double gx = x + ox + 0.5,
gy = y + oy + 0.5,
gz = z + oz + 0.5;
169 const double pi = 3.14159265358979323846;
170 fu[k] = 0.10 * std::sin(2 *
pi *
gx /
NX) * std::cos(2 *
pi *
gy /
NY) *
172 fv[k] = 0.10 * std::cos(2 *
pi *
gx /
NX) * std::sin(2 *
pi *
gy /
NY) *
174 fw[k] = 0.50 + 0.10 * std::cos(2 *
pi *
gx /
NX) * std::cos(2 *
pi *
gy /
NY) *
185 Kokkos::initialize(
argc, argv);
187 int rank = 0, size = 1;
190 auto dec = peclet::flow::CutcellMG::decomposition(
static_cast<std::size_t
>(size),
NX,
NY,
NZ);
191 auto blk =
dec.block(rank);
192 const int ox = (int)blk.origin[0], oy = (
int)blk.origin[1], oz = (int)blk.origin[2];
193 const int lnx = (int)blk.size[0],
lny = (
int)blk.size[1],
lnz = (int)blk.size[2];
194 const int steps = (int)
envd(
"PROBE_STEPS", 40);
195 const double wisp =
envd(
"PROBE_WISP", 1e-8);
205 std::printf(
"PROBE packing np=%d steps=%d wisp=%.3e rtol=%s solid=%s\n", size, steps,
wisp,
206 std::getenv(
"PROBE_RTOL") ? std::getenv(
"PROBE_RTOL") :
"default",
207 std::getenv(
"PROBE_NOSOLID") ?
"off" :
"on");
208 std::printf(
"%5s %11s %-16s %10s %11s %11s %11s %7s\n",
"step",
"dc",
"argmax(x,y,z)",
209 "n>1e-11",
"C_np",
"C_ref",
"dc|mixed",
"its d/r");
212 std::printf(
"fields:");
214 std::printf(
" %s", n.c_str());
217 const char*
flds[4] = {
"u",
"v",
"w",
"p"};
218 const bool kin = std::getenv(
"PROBE_KINEMATIC") !=
nullptr;
219 for (
int i = 0; i < steps; ++i) {
224 const std::vector<double> gc =
226 std::vector<std::vector<double>>
gf;
227 for (
int f = 0; f < 4; ++f)
236 const std::vector<double> rc = ref->getVof();
237 double dfld[4] = {0, 0, 0, 0},
mfld[4] = {0, 0, 0, 0};
238 for (
int f = 0; f < 4; ++f) {
239 const std::vector<double> rf = ref->getField(
flds[f]);
240 for (std::size_t k = 0; k <
GCELLS; ++k) {
241 dfld[f] = std::fmax(
dfld[f], std::fabs(
gf[f][k] - rf[k]));
242 mfld[f] = std::fmax(
mfld[f], std::fabs(rf[k]));
247 for (std::size_t k = 0; k <
GCELLS; ++k) {
248 if ((gc[k] > 0.5) != (rc[k] > 0.5))
255 for (std::size_t k = 0; k <
GCELLS; ++k) {
256 const double a = gc[k], b = rc[k];
257 const double d = std::fabs(a - b);
268 const int ax = (int)(am %
NX), ay = (int)((am /
NX) %
NY),
az = (
int)(am / (
NX *
NY));
270 "%4d dc %10.3e @(%2d,%2d,%2d) C %.5f n>tol %3ld | du %8.2e dv %8.2e dw %8.2e "
271 "dp %8.2e (|p| %8.2e) | flip05 %ld |C-.5|min %8.2e wispflip %ld | its %ld/%ld "
273 i,
dc, ax, ay,
az, rc[am],
nbad,
dfld[0],
dfld[1],
dfld[2],
dfld[3],
mfld[3],
nflip05,
278 if (std::getenv(
"PROBE_PAD")) {
280 const auto rh = ref->blockShape();
281 const char* pf[5] = {
"u",
"v",
"w",
"p",
"C"};
282 for (
int f = 0; f < 5; ++f) {
284 auto vr = ref->fieldView(pf[f]);
285 auto hd = Kokkos::create_mirror_view(
vd);
286 Kokkos::deep_copy(
hd,
vd);
287 auto hr2 = Kokkos::create_mirror_view(
vr);
288 Kokkos::deep_copy(
hr2,
vr);
290 int bi = -1,
bj = -1,
bk = -1;
293 for (
int k = 0; k < std::min(sh[2],
rh[2]); ++k)
294 for (
int j = 0; j < std::min(sh[1],
rh[1]); ++j)
295 for (
int ii = 0;
ii < std::min(sh[0],
rh[0]); ++
ii) {
297 hd((std::size_t)
ii + (std::size_t)j * sh[0] + (std::size_t)k * sh[0] * sh[1]);
298 const double b =
hr2((std::size_t)
ii + (std::size_t)j *
rh[0] +
299 (std::size_t)k *
rh[0] *
rh[1]);
300 const double d = std::fabs(a - b);
310 std::printf(
" pad %s max %.3e @(%3d,%3d,%3d) %s\n", pf[f],
md, bi,
bj,
bk,
311 bg ?
"GHOST" :
"inner");
314 if (std::getenv(
"PROBE_PADCELL")) {
316 const auto rh = ref->blockShape();
318 const char* pf[4] = {
"u",
"v",
"w",
"C"};
319 for (
int f = 0; f < 4; ++f) {
321 auto vr = ref->fieldView(pf[f]);
322 auto hd = Kokkos::create_mirror_view(
vd);
323 Kokkos::deep_copy(
hd,
vd);
324 auto h2 = Kokkos::create_mirror_view(
vr);
325 Kokkos::deep_copy(h2,
vr);
326 for (
int z = -
G2; z <= 1; ++z)
327 for (
int y = -
G2; y <= 1; ++y)
328 for (
int x = 13; x < 13 + 3 +
G2; ++x) {
329 const int i = x +
G2, j = y +
G2, k = z +
G2;
330 if (i >= sh[0] || j >= sh[1] || k >= sh[2])
333 hd((std::size_t)i + (std::size_t)j * sh[0] + (std::size_t)k * sh[0] * sh[1]);
335 h2((std::size_t)i + (std::size_t)j *
rh[0] + (std::size_t)k *
rh[0] *
rh[1]);
337 std::printf(
" DIFF %s (%3d,%3d,%3d) np %.17g ref %.17g d %.3e\n", pf[f], x,
342 if (std::getenv(
"PROBE_CELL")) {
343 const char*
nm[3] = {
"u",
"v",
"w"};
344 std::vector<std::vector<double>>
rr;
345 for (
int f = 0; f < 3; ++f)
346 rr.push_back(ref->getField(
nm[f]));
347 for (
int z = 0; z <= 1; ++z)
348 for (
int y = 0; y <= 1; ++y)
349 for (
int x = 13; x <= 15; ++x) {
350 const std::size_t k =
351 (std::size_t)x + (std::size_t)y *
NX + (std::size_t)z *
NX *
NY;
352 std::printf(
" (%2d,%2d,%2d)", x, y, z);
353 for (
int f = 0; f < 3; ++f)
354 std::printf(
" %s np %.17g ref %.17g",
nm[f],
gf[f][k],
rr[f][k]);
358 if (std::getenv(
"PROBE_LIST")) {
360 for (std::size_t k = 0; k <
GCELLS &&
shown < 24; ++k)
361 if (std::fabs(gc[k] - rc[k]) > 1e-11) {
362 std::printf(
" (%2d,%2d,%2d) np %.17g ref %.17g d %.3e\n", (
int)(k %
NX),
363 (
int)((k /
NX) %
NY), (
int)(k / (
NX *
NY)), gc[k], rc[k], gc[k] - rc[k]);
void setSolid(const std::vector< double > &sdfInner, bool cutcellPressure)
Host entry point: upload the inner SDF once and delegate.
void setDomainBc(int face, int type, double vx, double vy, double vz)
std::vector< double > getField(const std::string &name)
double maxOpenDivergence()
std::vector< double > getVof()
void setVelocityIterations(int it)
void setVof(const std::vector< double > &c)
void setPressureLevels(int levels)
void setVofBackflow(int f, double value)
inletOutlet backflow colour on outflow face f (default 0 = gas): where the boundary face velocity poi...
void setField(const std::string &name, const std::vector< double > &v)
std::array< int, 3 > blockShape() const
void setVofInflow(int f, double value)
Colour of the fluid entering through inflow face f (0..5 = -x,+x,-y,+y,-z,+z), in [0,...
long lastPressureIterations() const
void setPressurePcg(bool on, int maxit, double rtol)
void setMu(double m)
Dynamic viscosity, in the caller's units.
void setPressureIterations(int it)
void setVofWispEps(double eps)
WO-R2 item 4 — the wisp threshold on the advector's mixed-cell predicate and on the interface Courant...
CCField fieldView(const std::string &name)
void setRho(double r)
Fluid density, in the caller's units.
std::vector< std::string > fieldNames() const
flow — host-facing Kokkos IBM Navier-Stokes solver (drop-in flow-style API).
static std::vector< double > gatherGlobal(const std::vector< double > &local, int ox, int oy, int oz, int lnx, int lny, int lnz, int rank, int size)
static double envd(const char *k, double dflt)
static std::vector< double > packingSdf(int ox, int oy, int oz, int lnx, int lny, int lnz)
static void configurePacking(IbmSolver &s, int ox, int oy, int oz, int lnx, int lny, int lnz, bool perturb=false)
static constexpr std::size_t GCELLS
peclet::flow::IbmSolver IbmSolver