17 Kokkos::initialize(
argc, argv);
21 const double dx = 1.0, dy = 1.0, dz = 1.0;
22 const std::size_t n = (std::size_t)ext.x * ext.y * ext.z;
23 auto IDX = [&](
int x,
int y,
int z) {
24 return (std::size_t)x + (std::size_t)y * ext.x + (std::size_t)z * (std::size_t)ext.x * ext.y;
28 std::vector<double>
hsdf(n);
29 const double cx = 8, cy = 8, cz = 8, R = 5;
30 for (
int z = 0; z < ext.z; ++z)
31 for (
int y = 0; y < ext.y; ++y)
32 for (
int x = 0; x < ext.x; ++x)
34 std::sqrt((x - cx) * (x - cx) + (y - cy) * (y - cy) + (z - cz) * (z - cz)) - R;
36 auto upC = [&](
const char*
nm, std::vector<double>& h) {
38 auto m = Kokkos::create_mirror_view(v);
39 for (std::size_t i = 0; i < n; ++i)
41 Kokkos::deep_copy(v, m);
45 std::vector<double> o(n);
46 auto m = Kokkos::create_mirror_view(v);
47 Kokkos::deep_copy(m, v);
48 for (std::size_t i = 0; i < n; ++i)
53 CCField sdf =
upC(
"sdf",
hsdf), ox(
"ox", n), oy(
"oy", n), oz(
"oz", n);
58 auto close = [](
double a,
double b) {
59 return std::fabs(a - b) <= 1e-10 * (1.0 + std::fabs(b));
63 auto sampleH = [&](
double X,
double Y,
double Z) {
64 double fx = std::floor(X),
fy = std::floor(Y),
fz = std::floor(Z);
66 int x0 = (int)
fx, y0 = (
int)
fy,
z0 = (int)
fz;
67 auto cl = [&](
int v,
int nn) {
return v < 0 ? 0 : (v >=
nn ?
nn - 1 : v); };
68 int x1 =
cl(x0 + 1, ext.x), y1 =
cl(y0 + 1, ext.y),
z1 =
cl(
z0 + 1, ext.z);
78 return c0 * (1 -
wz) + c1 *
wz;
80 auto faceH = [&](
double X,
double Y,
double Z,
int type) {
85 return ccFractionCore(
sd,
sampleH(X + e, Y, Z),
sampleH(X - e, Y, Z),
sampleH(X, Y + e, Z),
86 sampleH(X, Y - e, Z),
sampleH(X, Y, Z + e),
sampleH(X, Y, Z - e), type,
89 for (
int z = 0; z < ext.z; ++z)
90 for (
int y = 0; y < ext.y; ++y)
91 for (
int x = 0; x < ext.x; ++x) {
92 std::size_t i =
IDX(x, y, z);
101 std::fprintf(
stderr,
"FAIL: %d openness faces differ\n",
bad);
107 for (std::size_t i = 0; i < n; ++i) {
109 if (v > 1e-9 && v < 1 - 1e-9)
111 else if (v > 1 - 1e-9)
118 std::vector<double>
allf(n, 100.0),
alls(n, -100.0);
122 for (std::size_t i = 0; i < n; ++i)
127 for (std::size_t i = 0; i < n; ++i)
130 if (
bad && !status) {
131 std::fprintf(
stderr,
"FAIL: all-fluid/all-solid property\n");
137 "[mac_cutcell] PASS: openness matches host (%d cut / %d open / %d closed x-faces) + "
138 "properties (exec: %s)\n",
159 static const double kSphereC[8][3] = {
160 {0.16457049781272215, 0.32582370748774664, 0.19776029572245485},
161 {0.23444960590393615, 0.24547940157936873, 0.70554692087486348},
162 {0.16793243789302340, 0.78893356813158244, 0.27166348678329372},
163 {0.13282821621926860, 0.89084457926273108, 0.80810981434511542},
164 {0.70443676917452958, 0.30413189645273508, 0.22198280960076699},
165 {0.74635862887577831, 0.29733066067115205, 0.67459991201161940},
166 {0.78455145086375566, 0.83393873968342314, 0.32933788364396716},
167 {0.73201808908205368, 0.80417516048550364, 0.65270503594906770}};
169 static const double kRingC[3][3] = {{0.30, 0.32, 0.30}, {0.70, 0.68, 0.55}, {0.45, 0.50, 0.78}};
170 static const int kRingA[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
172 auto minimg = [](
double d,
double N) {
return d -
N * std::round(d /
N); };
175 auto sdfSpheres = [&](
double X,
double Y,
double Z,
double N) {
176 const double R = 0.18 *
N;
178 for (
int s = 0; s < 8; ++s) {
181 best = std::min(
best, std::sqrt(dx * dx + dy * dy + dz * dz) - R);
185 auto sdfRings = [&](
double X,
double Y,
double Z,
double N) {
186 const double rO = 0.22 *
N,
rI = 0.12 *
N, H = 0.34 *
N;
188 for (
int r = 0; r < 3; ++r) {
192 const double zc = dx * ax + dy * ay + dz *
az;
193 const double rx = dx -
zc * ax,
ry = dy -
zc * ay,
rz = dz -
zc *
az;
194 const double rho = std::sqrt(
rx *
rx +
ry *
ry +
rz *
rz);
195 best = std::min(
best, std::max(std::max(
rI - rho, rho -
rO), std::fabs(
zc) - 0.5 * H));
200 const char*
bedName[2] = {
"random_spheres",
"hollow_rings"};
201 const int grids[2] = {32, 64};
202 for (
int bed = 0; bed < 2 && !status; ++bed)
203 for (
int gi = 0;
gi < 2 && !status; ++
gi) {
206 const C3 e{
N + 2 *
G,
N + 2 *
G,
N + 2 *
G};
207 const std::size_t
nn = (std::size_t)e.x * e.y * e.z;
211 std::vector<double>
hs(
nn);
212 for (
int z = 0; z < e.z; ++z)
213 for (
int y = 0; y < e.y; ++y)
214 for (
int x = 0; x < e.x; ++x) {
215 const double X = (x -
G) + 0.5, Y = (y -
G) + 0.5, Z = (z -
G) + 0.5;
216 hs[(std::size_t)x + (std::size_t)y * e.x + (std::size_t)z * (std::size_t)e.x * e.y] =
221 auto m = Kokkos::create_mirror_view(
sdfB);
222 for (std::size_t i = 0; i <
nn; ++i)
224 Kokkos::deep_copy(
sdfB, m);
229 FPV AC(
"AC",
nn), AW(
"AW",
nn), AE(
"AE",
nn), AS(
"AS",
nn), AN(
"AN",
nn), AB(
"AB",
nn),
231 buildCutcellOp(
AC, AW, AE, AS, AN, AB, AT,
CCConst(box),
CCConst(
boy),
CCConst(
boz), e,
G,
236 Kokkos::deep_copy(one, 1.0);
242 auto hb = Kokkos::create_mirror_view(
yBand),
hx = Kokkos::create_mirror_view(
yEx);
243 auto hAC = Kokkos::create_mirror_view(
AC);
244 auto hox = Kokkos::create_mirror_view(box),
hoy = Kokkos::create_mirror_view(
boy),
245 hoz = Kokkos::create_mirror_view(
boz);
246 Kokkos::deep_copy(hb,
yBand);
247 Kokkos::deep_copy(
hx,
yEx);
248 Kokkos::deep_copy(
hAC,
AC);
249 Kokkos::deep_copy(
hox, box);
250 Kokkos::deep_copy(
hoy,
boy);
251 Kokkos::deep_copy(
hoz,
boz);
255 for (
int z =
G; z < e.z -
G; ++z)
256 for (
int y =
G; y < e.y -
G; ++y)
257 for (
int x =
G; x < e.x -
G; ++x) {
258 const std::size_t i =
259 (std::size_t)x + (std::size_t)y * e.x + (std::size_t)z * (std::size_t)e.x * e.y;
263 const double sum =
hox(i) +
hox(i + 1) +
hoy(i) +
hoy(i + e.x) +
hoz(i) +
264 hoz(i + (std::size_t)e.x * e.y);
267 if (
hx(i) != 0.0 || hb(i) != 0.0)
269 }
else if (sum < 6.0) {
276 std::fprintf(
stderr,
"FAIL: %s N=%d exact A*1 = %.17g, expected bitwise 0\n",
281 std::fprintf(
stderr,
"FAIL: %s N=%d %ld solid cells with nonzero A*1\n",
bedName[bed],
N,
286 "[cutcell/P1] %-15s N=%2d max|A_exact*1| = %.3e (bitwise 0) "
287 "max|A_bands*1| = %.3e (rel to max AC %.3e: %.2e) %ld cut / %ld solid cells\n",
295 auto m = Kokkos::create_mirror_view(
xr);
297 for (std::size_t i = 0; i <
nn; ++i) {
298 s32 =
s32 * 1664525u + 1013904223u;
301 Kokkos::deep_copy(
xr, m);
307 Kokkos::deep_copy(hb,
yBand);
308 Kokkos::deep_copy(
hx,
yEx);
310 for (
int z =
G; z < e.z -
G; ++z)
311 for (
int y =
G; y < e.y -
G; ++y)
312 for (
int x =
G; x < e.x -
G; ++x) {
313 const std::size_t i =
314 (std::size_t)x + (std::size_t)y * e.x + (std::size_t)z * (std::size_t)e.x * e.y;
315 dmax = std::max(
dmax, std::fabs(hb(i) -
hx(i)));
321 const double tol =
sizeof(
MReal) ==
sizeof(
float) ? 1e-5 : 1e-13;
323 std::fprintf(
stderr,
"FAIL: %s N=%d bands vs exact rel diff %.3e >= %.1e\n",
bedName[bed],
327 std::printf(
"[cutcell/P1] %-15s N=%2d bands vs exact on random x: rel %.3e (< %.0e)\n",
331 std::printf(
"[cutcell/P1] PASS: exact flux-form apply annihilates the constants bitwise\n");
void buildCutcellOp(OpV AC, OpV AW, OpV AE, OpV AS, OpV AN, OpV AB, OpV AT, CCConst ox, CCConst oy, CCConst oz, C3 e, int g, double gfx, double gfy, double gfz)