T3TZRPPAIA24I3YL3JFB4XEAYCWU3HJAJUCF7NNIFMP4I5X4SM5QC
IVNZPCEYT3E2XEQBDIXHNA6WAZ6WVSAPFVLJTLPC7D7O4UPOU2OAC
KK3NMMOX7Z77JZ4D6UDD44VVQOGYRUN4SSFCSHJDELRFZMQE7HXAC
NUNYA5E7NMMUTVAQKVO34GUQI3U2TJTCEIZZT3PAPZ3ZU5LB44BQC
KOOPA77MHDMNHAKH7YXUD2POVQCT3R2HHDHEFBW3G7MVM7QJQVYAC
BJDGFYBMECTJG7BHLNHLSCUCBVYHAY6OGY37FIJP6JDGNDXQNQVAC
WV2J4VRLSW42SGIRDLF326LLC7L2ABAMSZ3YKABS532K27U3X3CAC
WZPFZTNOJMA2ANRX22OL6QUCU6KUWSZVQJSL46KKBEB37MWRVNNAC
WTDXZR735D7JBS4XVLTEXBVFMLSRLZUHZNVHH7ZWVGFGATD6DFNAC
M5R6KQLXLGYSVKHVAX5AJKD6NYE6IM5Z6WVTR3BTKPJDNNKF3ARAC
722HZ7UFINNE3YKSYKP2NHZ5XEG5QQLQHSKC7PREJZR3EX6RDYUAC
KCIWCVZOHG44WBOLKI2XK33WPHPRI5FWCETF4AOGTPZISKCW3CLQC
MF53IYPRC7HEG2LRV347PTVBWENVKHMUYN6FIAEVTTVPIXH4FMGQC
VIK5E6DBUCP5HGDVHDP6SWTHH7ODEUIGKOGSXR7VLVK46LDD4W6QC
E3MBKFT4GEFDAGZQQW4OROY5F6FWC46G6MRH54GDYTGO7O5YSRIAC
BPRNUTY7MHK7LK4EY5MY5OFFG3ABOL7LWXD574L35M74YSQPULFAC
YIQN7NJTGEVKW7JZHL6CTH6EPCIXCNBYNURIGXPYZAOUX3VAJQMAC
FEMASUBNU32NSG4DNXZX54CGCA57PVRGYO46L3A6F2EJ4BCSJ3SAC
OHAARXLBTFOIV5FOTY7IDMOIAE275CKXCE6XQMWV3EC63YCSMIWAC
CWFPG3JOFDQGDQEN56PEE6FLJXF665S4BEOKMYX7V5KGXM4ACIHAC
BVR7DVINVPQG7PA6Z7QYVYNQ43YZL7XCC6AOMSMWMGAAB2Q43STAC
BSMJ4V7GV3EOGY4KCSTOJQUOFE2OOCIKQETE4WC2WRNLWBQIBW3QC
GECUITHDXKCWB7HBCM7EA5Q56JDDWUVUWHMW2K6OM7UW36DFAZ3QC
A7ETPFXEHA2RM4LINSBVMJJ3G62NF7Q5ZQOKJPNJK3YOQ5WS5HKAC
EHF2P5PKVTMAUL5R5QSZ3DS3VLE7Z6SHJTCZAGRBTQ66Y7HZKNYQC
IV3MLV677VWS7GLESBQZ4HRFNW5TBFBIGIBWXTCHAER3FQ7VG3GQC
UEZKNPXXK5WU6B5LYRKGGYGBZ6T6TAZI26CWTJFUBUW2SJJOMV2AC
2A2A26IPPHUXJP36FFK3YPT2PJA36CEADQNNTDEYLMDLVANNCJEQC
IL5XPFSWQX3OWZHEUSDP3R2IKVWHHOI6MNNBKU3P6MNBT6MVYJ2QC
W4XMGPEHBCV6AAPJBI4SSEMCDB6KKCGRUC2X2F5YLBY22OR3ICPAC
RFUF3QUEOYDFA5H5BZJP7HVQ5LMCWCIO7MV32RQBDMVDULGQGO5QC
3ROBI6IPLFHSSNMGTZHYWIPCO342OKQLXHNWFJ3KMNQRNYMAMLKAC
UTHNLH3J3VG7BBJPOKGE6DY7Z2QHDLY72TR2VMEDQYP73SIWZGKAC
coarsegroupdata.valid.at(tl).at(vi).valid_bnd;
groupdata.valid.at(tl).at(vi).valid_bnd = false;
coarsegroupdata.valid.at(tl).at(vi).valid_outer &&
coarsegroupdata.valid.at(tl).at(vi).valid_ghosts;
groupdata.valid.at(tl).at(vi).valid_outer = false;
groupdata.valid.at(tl).at(vi).valid_ghosts = false;
const bool cond = coarsegroupdata.valid.at(tl).at(vi).valid_int &&
coarsegroupdata.valid.at(tl).at(vi).valid_bnd &&
const bool cond =
coarsegroupdata.valid.at(tl).at(vi).valid_int &&
coarsegroupdata.valid.at(tl).at(vi).valid_outer &&
coarsegroupdata.valid.at(tl).at(vi).valid_ghosts &&
groupdata.valid.at(tl).at(vi).valid_bnd;
valid.at(vi).valid_bnd = false;
groupdata.valid.at(tl).at(vi).valid_outer &&
groupdata.valid.at(tl).at(vi).valid_ghosts;
valid.at(vi).valid_outer = false;
valid.at(vi).valid_ghosts = false;
for (int dir = 0; dir < dim; ++dir) {
for (int face = 0; face < 2; ++face) {
if (bbox[2 * dir + face]) {
for (int nk = -1; nk <= +1; ++nk) {
for (int nj = -1; nj <= +1; ++nj) {
for (int ni = -1; ni <= +1; ++ni) {
if ((ni != 0 && bbox[0 + (ni == -1 ? 0 : 1)]) ||
(nj != 0 && bbox[2 + (nj == -1 ? 0 : 1)]) ||
(nk != 0 && bbox[4 + (nk == -1 ? 0 : 1)])) {
const array<int, dim> inormal{ni, nj, nk};
array<int, dim> imin, imax;
for (int d = 0; d < dim; ++d) {
// by default, include interior and outer boundaries and ghosts
int ghost_offset = nghostzones[d] - group_nghostzones[d];
imin[d] = ghost_offset;
imax[d] = lsh[d] + offset[d] - ghost_offset;
array<int, dim> imin, imax;
for (int d = 0; d < dim; ++d) {
const int ghost_offset = nghostzones[d] - group_nghostzones[d];
const int begin_bnd = ghost_offset;
const int begin_int = nghostzones[d];
const int end_int = lsh[d] + offset[d] - nghostzones[d];
const int end_bnd = lsh[d] + offset[d] - ghost_offset;
switch (inormal[d]) {
case -1: // lower boundary
imin[d] = begin_bnd;
imax[d] = begin_int;
break;
case 0: // interior
imin[d] = begin_int;
imax[d] = end_int;
break;
case +1: // upper boundary
imin[d] = end_int;
imax[d] = end_bnd;
break;
default:
assert(0);
}
// avoid covering edges and corners multiple times
if (d < dir) {
if (bbox[2 * d])
imin[d] = nghostzones[d]; // only interior
if (bbox[2 * d + 1])
imax[d] = lsh[d] + offset[d] - nghostzones[d]; // only interior
imin[d] = max(tmin[d], imin[d]);
imax[d] =
min(tmax[d] + (tmax[d] >= lsh[d] ? offset[d] : 0), imax[d]);
loop_box<CI, CJ, CK>(f, imin, imax);
for (int nk = -1; nk <= +1; ++nk) {
for (int nj = -1; nj <= +1; ++nj) {
for (int ni = -1; ni <= +1; ++ni) {
if ((ni != 0 && !bbox[0 + (ni == -1 ? 0 : 1)]) ||
(nj != 0 && !bbox[2 + (nj == -1 ? 0 : 1)]) ||
(nk != 0 && !bbox[4 + (nk == -1 ? 0 : 1)])) {
const array<int, dim> inormal{ni, nj, nk};
array<int, dim> imin, imax;
for (int d = 0; d < dim; ++d) {
const int ghost_offset = nghostzones[d] - group_nghostzones[d];
const int begin_bnd = ghost_offset;
const int begin_int = nghostzones[d];
const int end_int = lsh[d] + offset[d] - nghostzones[d];
const int end_bnd = lsh[d] + offset[d] - ghost_offset;
switch (inormal[d]) {
case -1: // lower boundary
imin[d] = begin_bnd;
imax[d] = begin_int;
break;
case 0: // interior
imin[d] = begin_int;
imax[d] = end_int;
break;
case +1: // upper boundary
imin[d] = end_int;
imax[d] = end_bnd;
break;
default:
assert(0);
}
imin[d] = max(tmin[d], imin[d]);
imax[d] =
min(tmax[d] + (tmax[d] >= lsh[d] ? offset[d] : 0), imax[d]);
}
loop_box<CI, CJ, CK>(f, imin, imax, inormal);
}
where_t where;
if (!valid.valid_int) {
if (!valid.valid_bnd)
where = where_t::everywhere;
else
where = where_t::interior;
if (!valid.valid_int && !valid.valid_outer && !valid.valid_ghosts) {
grid.loop_idx(where_t::everywhere, groupdata.indextype,
groupdata.nghostzones,
[&](const Loop::PointDesc &p) { ptr_(p.I) = 0.0 / 0.0; });
if (!valid.valid_bnd)
where = where_t::boundary;
else
assert(0);
if (!valid.valid_int)
grid.loop_idx(where_t::interior, groupdata.indextype,
groupdata.nghostzones,
[&](const Loop::PointDesc &p) { ptr_(p.I) = 0.0 / 0.0; });
if (!valid.valid_outer)
grid.loop_idx(where_t::boundary, groupdata.indextype,
groupdata.nghostzones,
[&](const Loop::PointDesc &p) { ptr_(p.I) = 0.0 / 0.0; });
if (!valid.valid_ghosts)
grid.loop_idx(where_t::ghosts, groupdata.indextype,
groupdata.nghostzones,
[&](const Loop::PointDesc &p) { ptr_(p.I) = 0.0 / 0.0; });
where_t where;
if (valid.valid_int) {
if (valid.valid_bnd)
where = where_t::everywhere;
else
where = where_t::interior;
if (valid.valid_int && valid.valid_outer && valid.valid_ghosts) {
grid.loop_idx(where_t::everywhere, groupdata.indextype,
groupdata.nghostzones, [&](const Loop::PointDesc &p) {
if (CCTK_BUILTIN_EXPECT(CCTK_isnan(ptr_(p.I)), false))
found_nan = true;
});
if (valid.valid_bnd)
where = where_t::boundary;
else
assert(0);
}
grid.loop_idx(where, groupdata.indextype, groupdata.nghostzones,
[&](const Loop::PointDesc &p) {
if (CCTK_BUILTIN_EXPECT(isnan(ptr_(p.I)), false))
if (valid.valid_int)
grid.loop_idx(where_t::interior, groupdata.indextype,
groupdata.nghostzones, [&](const Loop::PointDesc &p) {
if (CCTK_BUILTIN_EXPECT(CCTK_isnan(ptr_(p.I)), false))
found_nan = true;
});
if (valid.valid_outer)
grid.loop_idx(where_t::boundary, groupdata.indextype,
groupdata.nghostzones, [&](const Loop::PointDesc &p) {
if (CCTK_BUILTIN_EXPECT(CCTK_isnan(ptr_(p.I)), false))
found_nan = true;
});
if (valid.valid_ghosts)
grid.loop_idx(where_t::ghosts, groupdata.indextype,
groupdata.nghostzones, [&](const Loop::PointDesc &p) {
if (CCTK_BUILTIN_EXPECT(CCTK_isnan(ptr_(p.I)), false))
if (where & WH_INTERIOR)
valid.valid_int = true;
// We treat "ghost" and "boundary" as the same
if (where & (WH_GHOSTS | WH_BOUNDARY))
valid.valid_bnd = true;
valid.valid_int = where & WH_INTERIOR;
valid.valid_outer = where & WH_BOUNDARY;
valid.valid_ghosts = where & WH_GHOSTS;
for (int vi = 0; vi < groupdata.numvars; ++vi)
groupdata.valid.at(tl).at(vi).valid_bnd = false;
for (int vi = 0; vi < groupdata.numvars; ++vi) {
groupdata.valid.at(tl).at(vi).valid_outer = false;
groupdata.valid.at(tl).at(vi).valid_ghosts = false;
}