17#include <Kokkos_Core.hpp>
23#include "peclet/core/geom/scene_builder.hpp"
25using peclet::core::solver::AndersonRole;
33void check(
bool ok,
const std::string& what) {
34 std::printf(
" [%s] %s\n", ok ?
"ok" :
"FAIL", what.c_str());
41std::vector<double>
sphereSdf(
double radius) {
42 std::vector<double> sdf((std::size_t)
N *
N *
N);
43 const double c = 0.5 *
N;
44 for (
int z = 0; z <
N; ++z)
45 for (
int y = 0; y <
N; ++y)
46 for (
int x = 0; x <
N; ++x) {
47 const double dx = x + 0.5 - c, dy = y + 0.5 - c, dz = z + 0.5 - c;
48 sdf[(std::size_t)x + (std::size_t)
N * (y + (std::size_t)
N * z)] =
49 std::sqrt(dx * dx + dy * dy + dz * dz) - radius;
54std::vector<double> allFluid() {
55 return std::vector<double>((std::size_t)
N *
N *
N, 1.0);
63 s.setBodyForce(1e-3, 0.0, 0.0);
64 s.setPressurePcg(
true, 200, 1e-8);
69void checkFields(S& s,
const typename S::MarchState& ms,
const std::vector<std::string>& names,
70 int carriedFrom,
const std::string& tag) {
71 check(ms.fields.size() == names.size() && ms.roles.size() == names.size(),
72 tag +
": " + std::to_string(names.size()) +
" fields and roles");
73 if (ms.fields.size() != names.size() || ms.roles.size() != names.size())
75 const std::size_t nPad = (std::size_t)ms.e.x * ms.e.y * ms.e.z;
76 check(ms.G == 2 && ms.e.x ==
N + 4 && ms.e.y ==
N + 4 && ms.e.z ==
N + 4,
77 tag +
": e = n + 2G, G = 2");
78 for (std::size_t f = 0; f < names.size(); ++f) {
79 const AndersonRole want = (int)f < carriedFrom ? AndersonRole::Velocity : AndersonRole::Carried;
80 const bool same = ms.fields[f].data() == s.fieldView(names[f]).data();
81 check(ms.roles[f] == want && ms.fields[f].extent(0) == nPad &&
same,
82 tag +
": field " + std::to_string(f) +
" is '" + names[f] +
"' (" +
83 (want == AndersonRole::Velocity ?
"Velocity" :
"Carried") +
", padded)");
88 std::printf(
"rows of §3.1\n");
94 const auto ms = s.marchState();
95 checkFields(s, ms, {
"u",
"v",
"w",
"p"}, 3,
"staggered + advection");
96 check(ms.signature[0] == 6.0 && ms.signature[1] == 1.0 && ms.signature[2] == 1.0 &&
97 ms.signature[3] == 1e-3 && ms.signature[4] == 0.0 && ms.signature[5] == 0.0,
98 "staggered: signature (dt, rho, mu, F) in cell units");
99 check(ms.signature[6] == 1.0 && ms.signature[7] == 0.0 && ms.signature[8] == 0.0,
100 "staggered: signature advection (on, scheme SOU, explicit)");
101 s.setAdvectionScheme(1);
102 s.setImplicitAdvection(
true);
103 const auto ms2 = s.marchState();
104 check(ms2.signature[7] == 1.0 && ms2.signature[8] == 1.0,
105 "staggered: signature follows set_advection_scheme / set_implicit_advection");
110 s.setAdvection(
false);
112 checkFields(s, s.marchState(), {
"u",
"v",
"w",
"p"}, 3,
"collocated AUTO ghost, Stokes");
117 s.setCollocatedScheme(
"ghost");
118 s.setAdvection(
true);
119 s.setUfAdvection(
false);
121 checkFields(s, s.marchState(), {
"u",
"v",
"w",
"p"}, 3,
122 "collocated ghost + advection, set_uf_advection(False)");
127 s.setCollocatedScheme(
"ghost");
128 s.setAdvection(
true);
130 const auto ms = s.marchState();
133 first4.fields.resize(std::min<std::size_t>(4, ms.fields.size()));
134 first4.roles.resize(std::min<std::size_t>(4, ms.roles.size()));
135 checkFields(s, first4, {
"u",
"v",
"w",
"p"}, 3,
136 "collocated ghost + projected-face advection (first 4)");
137 bool faces = ms.fields.size() == 7;
138 for (std::size_t f = 4; faces && f < 7; ++f)
139 faces = ms.roles[f] == AndersonRole::Carried &&
140 ms.fields[f].extent(0) == (std::size_t)ms.e.x * ms.e.y * ms.e.z;
142 bool distinct =
true;
143 for (std::size_t f = 4; f < 7; ++f)
144 for (std::size_t g = 0; g < f; ++g)
145 distinct = distinct && ms.fields[f].data() != ms.fields[g].data();
148 check(faces,
"collocated ghost + projected-face advection: + uf, vf, wf (Carried, padded)");
154template <
class S,
class Make>
155void refusal(
const std::string& tag,
const std::string& token, Make make) {
161 (void)s.marchState();
162 }
catch (
const std::runtime_error& e) {
165 const bool own = what.find(token) != std::string::npos;
166 const bool hint = what.find(
"pass accelerate=False") != std::string::npos;
167 check(own && hint,
"refusal " + tag +
": \"" + what +
"\"");
171 namespace g = peclet::core::geom;
172 std::vector<int> ni(g::kNodeIntStride, 0), ii(g::kInstanceIntStride, 0);
173 std::vector<double> nr(g::kNodeRealStride, 0.0), ir(g::kInstanceRealStride, 0.0);
182 ir[0] = ir[1] = ir[2] = 0.5 *
N;
185 s.setScene(ni, nr, ii, ir,
true);
186 s.setSolidFromScene(
true);
190 std::printf(
"refusals (§5.3)\n");
191 refusal<Colo>(
"1 collocated gauge-exact",
"not the fluid-only 'ghost' projection", [](
Colo& s) {
192 s.setCollocatedScheme(
"gauge-exact");
195 refusal<Colo>(
"1 collocated embed",
"not the fluid-only 'ghost' projection", [](
Colo& s) {
196 s.setCollocatedScheme(
"embed");
199 refusal<Stag>(
"2 VoF",
"VoF", [](
Stag& s) {
200 s.setPressureGeometry(allFluid());
203 refusal<Stag>(
"3 phase change",
"phase change", [](
Stag& s) {
204 s.setPressureGeometry(allFluid());
205 s.enablePhaseChange(1.0, 10.0, 1.0);
207 refusal<Stag>(
"4 scalar",
"transported scalar", [](
Stag& s) { s.addScalar(
"T", 0.1, 0, 1); });
208 refusal<Stag>(
"5 porous",
"porous", [](
Stag& s) { s.setPorousContinuity(
true); });
209 refusal<Stag>(
"6 variable rho (closure)",
"variable density or viscosity", [](
Stag& s) {
213 refusal<Stag>(
"6 mu field",
"variable density or viscosity", [](
Stag& s) { s.addField(
"mu"); });
214 refusal<Stag>(
"7 drag",
"drag_beta", [](
Stag& s) { s.enableDrag(); });
215 refusal<Stag>(
"8 cell force",
"cell force", [](
Stag& s) { s.enableCellForce(); });
216 refusal<Stag>(
"9 moving scene",
"moving scene", [](
Stag& s) {
218 s.setInstanceMotion(0, {1e-3, 0.0, 0.0}, {0.0, 0.0, 0.0},
nullptr);
220 refusal<Stag>(
"10 superficial velocity",
"set_superficial_velocity",
221 [](
Stag& s) { s.setSuperficialVelocity(
true, 0, 1e-3); });
222 refusal<Stag>(
"11 pressure warm start",
"warm start",
223 [](
Stag& s) { s.setPressureWarmstart(
true); });
224 refusal<Stag>(
"12 balanced-force projection",
"balanced-force projection",
225 [](
Stag& s) { s.setBalancedForceProjection(
true); });
233 (void)s.marchState();
234 }
catch (
const std::exception&) {
237 check(ok,
"a static scene is allowed");
243int main(
int argc,
char** argv) {
244 Kokkos::initialize(argc, argv);
251 std::fprintf(stderr,
"\n%d CHECK(s) failed\n",
failures);
254 std::printf(
"\nAll march-state checks passed.\n");
flow — host-facing Kokkos IBM Navier-Stokes solver (drop-in flow-style API).
static std::vector< double > sphereSdf()
static void sphereScene(std::vector< int > &ni, std::vector< double > &nr, std::vector< int > &ii, std::vector< double > &ir)
static bool same(double a, double b)