82 const auto& r = s.scalarCutGeometry();
83 auto H = Kokkos::HostSpace();
84 h.sdf = Kokkos::create_mirror_view_and_copy(H, s.fieldView(
"sdf"));
85 h.kappa = Kokkos::create_mirror_view_and_copy(H, r.kappa);
86 h.sax = Kokkos::create_mirror_view_and_copy(H, r.sax);
87 h.say = Kokkos::create_mirror_view_and_copy(H, r.say);
88 h.saz = Kokkos::create_mirror_view_and_copy(H, r.saz);
89 h.unknown = Kokkos::create_mirror_view_and_copy(H, r.unknown);
90 auto cell = Kokkos::create_mirror_view_and_copy(H, r.fac.cell);
91 auto alpha = Kokkos::create_mirror_view_and_copy(H, r.fac.alpha);
92 auto nrm = Kokkos::create_mirror_view_and_copy(H, r.fac.normal);
93 auto cen = Kokkos::create_mirror_view_and_copy(H, r.fac.centroid);
94 auto body = Kokkos::create_mirror_view_and_copy(H, r.fac.body);
95 auto sF = Kokkos::create_mirror_view_and_copy(H, r.fac.sF);
96 auto off = Kokkos::create_mirror_view_and_copy(H, r.fac.offF);
97 auto w = Kokkos::create_mirror_view_and_copy(H, r.fac.wF);
98 auto rung = Kokkos::create_mirror_view_and_copy(H, r.fac.rungF);
99 const long sxy = (long)h.ex * h.ey;
100 for (
long f = 0; f < r.fac.n; ++f) {
101 h.fcell.push_back(cell(f));
102 h.byCell[cell(f)].push_back(f);
103 h.fdat.push_back(alpha(f));
104 for (
int d = 0; d < 3; ++d)
105 h.fdat.push_back(nrm(f, d));
106 for (
int d = 0; d < 3; ++d)
107 h.fdat.push_back(cen(f, d));
108 h.fdat.push_back(sF(f));
109 for (
int k = 0; k < 8; ++k)
110 h.fdat.push_back(w(f, k));
111 h.fint.push_back(body(f));
112 h.fint.push_back((
int)rung(f));
113 for (
int k = 0; k < 8; ++k) {
114 const long o = off(f, k);
115 const long dz = std::lround((
double)o / (
double)sxy);
116 const long rem = o - dz * sxy;
117 const long dy = std::lround((
double)rem / (
double)h.ex);
118 const long dx = rem - dy * h.ex;
119 h.fint.push_back((
int)dx);
120 h.fint.push_back((
int)dy);
121 h.fint.push_back((
int)dz);
127static void runCase(
const char* label,
const double c[3],
double R,
const int bc[6],
int rank,
129 const std::vector<double> gsdf =
sphereSdf(c, R);
130 peclet::core::decomp::BlockDecomposer<3> dec =
131 peclet::flow::CutcellMG::decomposition(
static_cast<std::size_t
>(size),
N,
N,
N);
132 const auto blk = dec.block(rank);
133 const int ox = (int)blk.origin[0], oy = (
int)blk.origin[1], oz = (int)blk.origin[2];
134 const int lnx = (int)blk.size[0], lny = (
int)blk.size[1], lnz = (int)blk.size[2];
135 std::vector<double> lsdf((std::size_t)lnx * lny * lnz);
136 for (
int z = 0; z < lnz; ++z)
137 for (
int y = 0; y < lny; ++y)
138 for (
int x = 0; x < lnx; ++x)
139 lsdf[(std::size_t)x + (std::size_t)y * lnx + (std::size_t)z * lnx * lny] =
140 gsdf[(std::size_t)(x + ox) + (std::size_t)(y + oy) *
N + (std::size_t)(z + oz) *
N *
N];
143 for (
int f = 0; f < 6; ++f)
146 sd.initMpi(
N,
N,
N, MPI_COMM_WORLD);
149 for (
int f = 0; f < 6; ++f)
156 const long dsy = D.ex, dsz = (long)D.ex * D.ey, rsy = Rf.
ex, rsz = (
long)Rf.
ex * Rf.
ey;
157 auto gIndex = [&](
int lx,
int ly,
int lz) {
158 return (
long)(lx -
G + ox +
G) + (
long)(ly -
G + oy +
G) * rsy + (
long)(lz -
G + oz +
G) * rsz;
162 long ghostBad = 0, ghostChecked = 0;
163 const int ln[3] = {lnx, lny, lnz}, org[3] = {ox, oy, oz};
164 for (
int a = 0; a < 3; ++a)
165 for (
int side = 0; side < 2; ++side)
166 for (
int layer = 1; layer <=
G; ++layer) {
167 const int b = (a + 1) % 3, cc = (a + 2) % 3;
168 for (
int jb = 0; jb < ln[b]; ++jb)
169 for (
int jc = 0;
jc < ln[cc]; ++
jc) {
171 l3[a] = side ? ln[a] - 1 + layer : -layer;
175 for (
int d = 0; d < 3; ++d)
178 D.sdf((
long)(
l3[0] +
G) + (
long)(
l3[1] +
G) * dsy + (
long)(
l3[2] +
G) * dsz);
182 gsdf[(std::size_t)g3[0] + (std::size_t)g3[1] *
N + (std::size_t)g3[2] *
N *
N]))
188 long cellBad = 0, faceBad = 0, facetBad = 0, facetCount = 0;
189 for (
int z =
G; z < lnz +
G; ++z)
190 for (
int y =
G; y < lny +
G; ++y)
191 for (
int x =
G; x < lnx +
G; ++x) {
192 const long i = x + y * dsy + z * dsz, j = gIndex(x, y, z);
196 if (x == lnx +
G - 1 && (!
same(D.sax(i + 1), Rf.
sax(gIndex(x + 1, y, z)))))
198 if (y == lny +
G - 1 && (!
same(D.say(i + dsy), Rf.
say(gIndex(x, y + 1, z)))))
200 if (z == lnz +
G - 1 && (!
same(D.saz(i + dsz), Rf.
saz(gIndex(x, y, z + 1)))))
203 auto itD = D.byCell.find(i);
204 auto itR = Rf.
byCell.find(j);
205 const std::size_t nD = itD == D.byCell.end() ? 0 : itD->second.size();
206 const std::size_t nR = itR == Rf.
byCell.end() ? 0 : itR->second.size();
211 for (std::size_t k = 0; k < nD; ++k) {
212 const long fd = itD->second[k], fr = itR->second[k];
215 for (
int q = 0; q < 16; ++q)
216 ok = ok &&
same(D.fdat[fd * 16 + q], Rf.
fdat[fr * 16 + q]);
217 for (
int q = 0; q < 26; ++q)
218 ok = ok && D.fint[fd * 26 + q] == Rf.
fint[fr * 26 + q];
224 long loc[6] = {ghostBad, ghostChecked, cellBad, faceBad, facetBad, facetCount}, glob[6];
225 MPI_Allreduce(loc, glob, 6, MPI_LONG, MPI_SUM, MPI_COMM_WORLD);
228 const bool censusOk = cD.
numUnknowns == cR.numUnknowns && cD.numCutCells == cR.numCutCells &&
229 cD.numFacets == cR.numFacets && cD.numTwoSided == cR.numTwoSided &&
230 cD.numThinSolid == cR.numThinSolid && cD.numSealed == cR.numSealed &&
231 cD.rungs[0] == cR.rungs[0] && cD.rungs[1] == cR.rungs[1] &&
232 cD.rungs[2] == cR.rungs[2] && cD.rungs[3] == cR.rungs[3];
235 " np=%d %-22s: ghosts %ld/%ld stale, cells %ld, high faces %ld, facets %ld/%ld "
236 "differ; census facets %ld (R0 %ld) unknowns %ld sealed %ld vs single-rank %ld "
238 size, label, glob[0], glob[1], glob[2], glob[3], glob[4], glob[5], cD.numFacets,
239 cD.rungs[0], cD.numUnknowns, cD.numSealed, cR.numFacets, cR.numUnknowns, cR.numSealed,
240 censusOk ?
"equal" :
"DIFFER");
241 CHECK(glob[0] == 0 && glob[1] > 0);
242 CHECK(glob[2] == 0 && glob[3] == 0 && glob[4] == 0);
243 CHECK(glob[5] == cR.numFacets);
247int main(
int argc,
char** argv) {
248 MPI_Init(&argc, &argv);
249 int rank = 0, size = 1;
250 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
251 MPI_Comm_size(MPI_COMM_WORLD, &size);
252 Kokkos::initialize(argc, argv);
254 const int periodic[6] = {0, 0, 0, 0, 0, 0};
255 const int walls[6] = {1, 1, 4, 4, 0, 0};
256 const double c1[3] = {15.3, 16.1, 14.7}, c2[3] = {2.2, 16.4, 15.6};
257 runCase(
"periodic sphere", c1, 9.3, periodic, rank, size);
258 runCase(
"x walls + y slip", c2, 7.7, walls, rank, size);
262 MPI_Allreduce(&
failures, &all, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
264 std::printf(all ?
"%d failure(s)\n" :
"OK\n", all);