6OFN2SJK2MPLZQWYF4RBKSVAZ6BX3LINXR3OXUJED6CWLDTAU7UQC N3ST2ENQFPLBIKAALNBVNOK4G7Q4TM2RZT4ZOH5ZPOR25MLDBM2QC D6H2FWRX5NTSSGXL2263KT7DHM3BXQBAYXTNKNJTSMRPD7VEJYHAC 3QWZBYJLGJFSLSL2ZG4JVCSUGF73TQJNPHV3MRMIIBUA7XNUU7NAC 722HZ7UFINNE3YKSYKP2NHZ5XEG5QQLQHSKC7PREJZR3EX6RDYUAC 5B6D6UREX556XOAM75B3WOIGE6DT43HIS6JOVJYNXUT3FSZDUPBAC ANVJBTFKJDVQBSYMHQ455IQVAOCD3YVYZLDH5K2BS67UTSF5JNBQC M5R6KQLXLGYSVKHVAX5AJKD6NYE6IM5Z6WVTR3BTKPJDNNKF3ARAC RCLGQ2LZMFVPBPTU2G55DJ6HZPOGGTPZRZCY54VGP6YLHANJ2LAQC FS7Q6TUHBK5WSRDC3TM6KV2BPGWATRBLDHFGEJ72BR3FRDEOC3WAC N42E473LAYAM5NC4UXPM6WD37FLCUM26JCCKCARQEMXM7V6GWYNQC WASO7G5FJXRXWNH2U2FLUNEKU6VE63OI3HUYP64BVD4LMD6KE7OQC TPRT57JJWUDQ6C24ZJETKIDWODKWGYDISPYR3B42BNA25UAOVT3AC 67UXOK4QSZFAPVZXU2MJMD7I2232JCK4QDMIOMVMEQNQUGN7632AC J3SP5HQRWGMM6EM4ZIWPNUIY5HYFRJA4SH2X4OWGESSK7AWA3RNQC BVR7DVINVPQG7PA6Z7QYVYNQ43YZL7XCC6AOMSMWMGAAB2Q43STAC JN2TPHENEBIY2OE5FRCQ2E6QCL6FPVHJHUCP4UODD6DITRVV2LIQC ZARZZPSISIOCXZOWNJQMMQSQPXFSZLDDIDAFY35X2GV37RBB7WUAC T3TZRPPAIA24I3YL3JFB4XEAYCWU3HJAJUCF7NNIFMP4I5X4SM5QC EHF2P5PKVTMAUL5R5QSZ3DS3VLE7Z6SHJTCZAGRBTQ66Y7HZKNYQC UEZKNPXXK5WU6B5LYRKGGYGBZ6T6TAZI26CWTJFUBUW2SJJOMV2AC LHPZHX4FMRYBM7NI22QTP3VZDBYFRSNTY3L6BEEFPPF5KWCFFIHQC R5ZPKCVY742K4RWVAJ4O6OGMIYH563GNCSVVSVF2Y66ILIUH7B4AC WV2J4VRLSW42SGIRDLF326LLC7L2ABAMSZ3YKABS532K27U3X3CAC IV3MLV677VWS7GLESBQZ4HRFNW5TBFBIGIBWXTCHAER3FQ7VG3GQC WZPFZTNOJMA2ANRX22OL6QUCU6KUWSZVQJSL46KKBEB37MWRVNNAC 3HPNY5XHNPWR6RVX4LYEVDFJQWSB2CMS7J6XPAKATQ2UPFTXD33QC XU5HOJREK4XY4NBCJINLZPKQNKSYOLUDTWR47REFSNQKDOSNDXLQC AUKF4PR4JSOVB2EE3YFXJTH3DK2OY7HXV5AXUWVYHOSAQLY2CYEQC WNYN6LX3FYXXW3TKGRA7GRLFMIR4YXQMFAWJCB76QAXLY6JR4Q7AC VMCDMDXKME66ESRMB3PYSUZZH2XG2GIQMEOEKRH33WGCEBPXTWUQC FYLM4H3VFAC5MR4QQH5Q4LQKVEIIMVAE65BSGS6A7EP6CG47RXFQC 3I2VE3RJ4E4WZZSUGJKOMHP2FKOAZA6SLVMVYE3B54SZCYXGIU4QC W4XMGPEHBCV6AAPJBI4SSEMCDB6KKCGRUC2X2F5YLBY22OR3ICPAC BPRNUTY7MHK7LK4EY5MY5OFFG3ABOL7LWXD574L35M74YSQPULFAC KCIWCVZOHG44WBOLKI2XK33WPHPRI5FWCETF4AOGTPZISKCW3CLQC RFUF3QUEOYDFA5H5BZJP7HVQ5LMCWCIO7MV32RQBDMVDULGQGO5QC FEMASUBNU32NSG4DNXZX54CGCA57PVRGYO46L3A6F2EJ4BCSJ3SAC } else if (group.grouptype == CCTK_SCALAR) {assert(group.vartype == CCTK_VARIABLE_REAL);assert(group.disttype == CCTK_DISTRIB_CONSTANT);assert(group.dim == 0);globaldata.scalargroupdata.at(gi) =make_unique<GHExt::GlobalData::ScalarGroupData>();GHExt::GlobalData::ScalarGroupData &scalargroupdata =*globaldata.scalargroupdata.at(gi);scalargroupdata.groupindex = gi;scalargroupdata.firstvarindex = CCTK_FirstVarIndexI(gi);scalargroupdata.numvars = group.numvars;scalargroupdata.do_checkpoint = get_group_checkpoint_flag(gi);scalargroupdata.do_restrict = get_group_restrict_flag(gi);// Set up dynamic datascalargroupdata.dimension = 0;scalargroupdata.activetimelevels = 1;// Allocate datascalargroupdata.data.resize(group.numtimelevels);scalargroupdata.valid.resize(group.numtimelevels);for (int tl = 0; tl < int(scalargroupdata.data.size()); ++tl) {scalargroupdata.data.at(tl).resize(scalargroupdata.numvars);why_valid_t why([] { return "SetupGlobals"; });scalargroupdata.valid.at(tl).resize(scalargroupdata.numvars, why);for (int vi = 0; vi < scalargroupdata.numvars; ++vi) {// TODO: decide that valid_bnd == false always and rely on// initialization magic?valid_t valid;valid.valid_int = false;valid.valid_outer = true;valid.valid_ghosts = true;scalargroupdata.valid.at(tl).at(vi).set(valid,[] { return "SetupGlobals"; });// TODO: make poison_invalid and check_invalid virtual members of// CommonGroupDatapoison_invalid(scalargroupdata, vi, tl);check_valid(scalargroupdata, vi, tl, [] { return "SetupGlobals"; });}}
const GHExt::GlobalData::ScalarGroupData &scalargroupdata) {yaml << YAML::LocalTag("scalargroupdata-1.0.0");yaml << YAML::BeginMap;yaml << YAML::Key << "commongroupdata" << YAML::Value<< (GHExt::CommonGroupData)scalargroupdata;yaml << YAML::Key << "data" << YAML::Value << scalargroupdata.data;yaml << YAML::EndMap;return yaml;}YAML::Emitter &operator<<(YAML::Emitter &yaml,
yaml << YAML::Key << "scalargroupdata" << YAML::Value << YAML::BeginSeq;for (const auto &scalargroupdata : globaldata.scalargroupdata)if (scalargroupdata)yaml << *scalargroupdata;
yaml << YAML::Key << "arraygroupdata" << YAML::Value << YAML::BeginSeq;for (const auto &arraygroupdata : globaldata.arraygroupdata)if (arraygroupdata)yaml << *arraygroupdata;
} else if (group.grouptype == CCTK_SCALAR) {GHExt::GlobalData &globaldata = ghext->globaldata;GHExt::GlobalData::ScalarGroupData &scalargroupdata =*globaldata.scalargroupdata.at(gi);data->dim = scalargroupdata.dimension;data->lsh = scalargroupdata.lsh;data->ash = scalargroupdata.ash;data->gsh = scalargroupdata.gsh;data->lbnd = scalargroupdata.lbnd;data->ubnd = scalargroupdata.ubnd;data->bbox = scalargroupdata.bbox;data->nghostzones = scalargroupdata.nghostzones;data->activetimelevels = scalargroupdata.activetimelevels;} else { // CCTK_ARRAY
} else { // CCTK_ARRAY or CCTK_SCALAR
for (int vi = 0; vi < scalargroupdata.numvars; ++vi) {file << sep << scalargroupdata.data.at(tl).at(vi);
for (int vi = 0; vi < arraygroupdata.numvars; ++vi) {file << sep << arraygroupdata.data.at(tl).at(vi);
}}// Ensure grid scalars are validvoid error_if_invalid(const GHExt::GlobalData::ScalarGroupData &groupdata,int vi, int tl, const valid_t &required,const function<string()> &msg) {const valid_t &have = groupdata.valid.at(tl).at(vi).get();if (CCTK_BUILTIN_EXPECT((required & ~have).valid_any(), false))CCTK_VERROR("%s: Grid Scalar \"%s\" is invalid on time level %d; ""required %s, found %s",msg().c_str(), CCTK_FullVarName(groupdata.firstvarindex + vi),tl, string(required).c_str(),string(groupdata.valid.at(tl).at(vi)).c_str());}void warn_if_invalid(const GHExt::GlobalData::ScalarGroupData &groupdata,int vi, int tl, const valid_t &required,const function<string()> &msg) {const valid_t &have = groupdata.valid.at(tl).at(vi).get();if (CCTK_BUILTIN_EXPECT((required & ~have).valid_any(), false))CCTK_VWARN(CCTK_WARN_ALERT,"%s: Grid Scalar \"%s\" is invalid on time level %d; ""required %s, found %s",msg().c_str(), CCTK_FullVarName(groupdata.firstvarindex + vi),tl, string(required).c_str(),string(groupdata.valid.at(tl).at(vi)).c_str());}// Set grid scalars to nanvoid poison_invalid(const GHExt::GlobalData::ScalarGroupData &scalargroupdata,int vi, int tl) {DECLARE_CCTK_PARAMETERS;if (!poison_undefined_values)return;const valid_t &valid = scalargroupdata.valid.at(tl).at(vi).get();if (valid.valid_all())return;if (!valid.valid_int) {CCTK_REAL *restrict const ptr =const_cast<CCTK_REAL *>(&scalargroupdata.data.at(tl).at(vi));*ptr = 0.0 / 0.0;
// Ensure grid scalars are not nanvoid check_valid(const GHExt::GlobalData::ScalarGroupData &scalargroupdata,int vi, int tl, const function<string()> &msg) {DECLARE_CCTK_PARAMETERS;if (!poison_undefined_values)return;
const valid_t &valid = scalargroupdata.valid.at(tl).at(vi).get();if (!valid.valid_any())return;// scalars have no boundary so we expect them to alway be validassert(valid.valid_outer && valid.valid_ghosts);atomic<size_t> nan_count{0};if (valid.valid_int) {const CCTK_REAL *restrict const ptr = &scalargroupdata.data.at(tl).at(vi);if (CCTK_BUILTIN_EXPECT(!CCTK_isfinite(*ptr), false)) {++nan_count;}}if (CCTK_BUILTIN_EXPECT(nan_count > 0, false))CCTK_VERROR("%s: Grid Scalar \"%s\" has %td nans on time level %d; ""expected valid %s",msg().c_str(),CCTK_FullVarName(scalargroupdata.firstvarindex + vi),size_t(nan_count), tl,string(scalargroupdata.valid.at(tl).at(vi)).c_str());}// Ensure grid arrays are valid
// Ensure arrays are valid
int dimension = arraygroupdata.dimension;atomic<size_t> nan_count{0};if (dimension == 0) {return;} else {const int *gsh = arraygroupdata.gsh;int n_elems = 1;for (int i = 0; i < dimension; i++) n_elems *= gsh[i];if (valid.valid_int) {CCTK_REAL *restrict const ptr =const_cast<CCTK_REAL *>(&arraygroupdata.data.at(tl).at(vi));for (int i = 0; i < n_elems; i++) {ptr[i] = 0.0 / 0.0;}
if (!valid.valid_int) {int dimension = arraygroupdata.dimension;atomic<size_t> nan_count{0};CCTK_REAL *restrict const ptr =const_cast<CCTK_REAL *>(&arraygroupdata.data.at(tl).at(vi));if (dimension == 0) {*ptr = 0.0 / 0.0;} else {const int *gsh = arraygroupdata.gsh;int n_elems = 1;for (int i = 0; i < dimension; i++) n_elems *= gsh[i];for (int i = 0; i < n_elems; i++) ptr[i] = 0.0 / 0.0;
if (dimension == 0) {return;} else {const int *gsh = arraygroupdata.gsh;int n_elems = 1;for (int i = 0; i < dimension; i++) n_elems *= gsh[i];if (valid.valid_int) {const CCTK_REAL *restrict const ptr = &arraygroupdata.data.at(tl).at(vi);
if (valid.valid_int) {const CCTK_REAL *restrict const ptr = &arraygroupdata.data.at(tl).at(vi);int dimension = arraygroupdata.dimension;if (dimension == 0) {if (CCTK_BUILTIN_EXPECT(!CCTK_isfinite(*ptr), false)) {++nan_count;}} else {const int *gsh = arraygroupdata.gsh;int n_elems = 1;for (int i = 0; i < dimension; i++) {n_elems *= gsh[i];}
} else if (group.grouptype == CCTK_SCALAR) {auto &restrict scalargroupdata = *globaldata.scalargroupdata.at(gi);for (int tl = 0; tl < int(scalargroupdata.data.size()); ++tl) {const auto &restrict vars = scalargroupdata.data.at(tl);for (int vi = 0; vi < scalargroupdata.numvars; ++vi) {cctkGH->data[scalargroupdata.firstvarindex + vi][tl] =const_cast<CCTK_REAL *>(&vars.at(vi));}}} else { // CCTK_ARRAY
} else { // CCTK_ARRAY or CCTK_SCALAR
} else if (group.grouptype == CCTK_SCALAR) {auto &restrict scalargroupdata = *globaldata.scalargroupdata.at(gi);for (int tl = 0; tl < int(scalargroupdata.data.size()); ++tl) {for (int vi = 0; vi < scalargroupdata.numvars; ++vi) {cctkGH->data[scalargroupdata.firstvarindex + vi][tl] = nullptr;}}} else { // CCTK_ARRAY
} else { // CCTK_ARRAY or CCTK_SCALAR
auto &restrict scalargroupdata = *globaldata.scalargroupdata.at(gi);if (!scalargroupdata.do_checkpoint) {// Invalidate all time levelsconst int ntls = scalargroupdata.data.size();for (int tl = 0; tl < ntls; ++tl) {for (int vi = 0; vi < scalargroupdata.numvars; ++vi) {// TODO: handle this more nicelyscalargroupdata.valid.at(tl).at(vi).set_int(false, [] {return "InvalidateTimelevels (invalidate all non-checkpointed ""variables)";});poison_invalid(scalargroupdata, vi, tl);}}}} else { // CCTK_ARRAYauto &restrict globaldata = ghext->globaldata;
} else if (group.grouptype == CCTK_SCALAR) {auto &restrict globaldata = ghext->globaldata;auto &restrict scalargroupdata = *globaldata.scalargroupdata.at(gi);const int ntls = scalargroupdata.data.size();// Rotate time levels and invalidate current time levelif (ntls > 1) {rotate(scalargroupdata.data.begin(), scalargroupdata.data.end() - 1,scalargroupdata.data.end());rotate(scalargroupdata.valid.begin(), scalargroupdata.valid.end() - 1,scalargroupdata.valid.end());for (int vi = 0; vi < scalargroupdata.numvars; ++vi) {scalargroupdata.valid.at(0).at(vi).set_int(false, [] {return "CycletimeLevels (invalidate current time level)";});poison_invalid(scalargroupdata, vi, 0);}}for (int tl = 0; tl < ntls; ++tl)for (int vi = 0; vi < scalargroupdata.numvars; ++vi)check_valid(scalargroupdata, vi, tl,[&]() { return "CycleTimelevels"; });} else { // CCTK_ARRAY
} else { // CCTK_ARRAY or CCTK_SCALAR
} else if (CCTK_GroupTypeI(rd.gi) == CCTK_SCALAR) {const auto &restrict scalargroupdata =*ghext->globaldata.scalargroupdata.at(rd.gi);const valid_t &need = rd.valid;error_if_invalid(scalargroupdata, rd.vi, rd.tl, need, [&] {ostringstream buf;buf << "CallFunction iteration " << cctkGH->cctk_iteration << " "<< attribute->where << ": " << attribute->thorn<< "::" << attribute->routine << " checking input";return buf.str();});check_valid(scalargroupdata, rd.vi, rd.tl, [&] {ostringstream buf;buf << "CallFunction iteration " << cctkGH->cctk_iteration << " "<< attribute->where << ": " << attribute->thorn<< "::" << attribute->routine << " checking input";return buf.str();});} else { // CCTK_ARRAY
} else if (CCTK_GroupTypeI(wr.gi) == CCTK_SCALAR) {auto &restrict scalargroupdata =*ghext->globaldata.scalargroupdata.at(wr.gi);const valid_t &provided = wr.valid;scalargroupdata.valid.at(wr.tl).at(wr.vi).set_and(need | ~provided,[iteration = cctkGH->cctk_iteration, where = attribute->where,thorn = attribute->thorn, routine = attribute->routine] {ostringstream buf;buf << "CallFunction iteration " << iteration << " " << where<< ": " << thorn << "::" << routine<< ": Poison output variables that are not input variables";return buf.str();});poison_invalid(scalargroupdata, wr.vi, wr.tl);} else { // CCTK_ARRAY
} else { // CCTK_ARRAY or CCTK_SCALAR
} else if (CCTK_GroupTypeI(wr.gi) == CCTK_SCALAR) {auto &restrict scalargroupdata =*ghext->globaldata.scalargroupdata.at(wr.gi);const valid_t &provided = wr.valid;scalargroupdata.valid.at(wr.tl).at(wr.vi).set_or(provided,[iteration = cctkGH->cctk_iteration, where = attribute->where,thorn = attribute->thorn, routine = attribute->routine] {ostringstream buf;buf << "CallFunction iteration " << iteration << " " << where<< ": " << thorn << "::" << routine<< ": Mark output variables as valid";return buf.str();});check_valid(scalargroupdata, wr.vi, wr.tl, [&]() {ostringstream buf;buf << "CallFunction iteration " << cctkGH->cctk_iteration << " "<< attribute->where << ": " << attribute->thorn<< "::" << attribute->routine << " checking output";return buf.str();});} else { // CCTK_ARRAY
} else { // CCTK_ARRAY or CCTK_SCALAR
});} else if (CCTK_GroupTypeI(inv.gi) == CCTK_SCALAR) {auto &restrict scalargroupdata =*ghext->globaldata.scalargroupdata.at(inv.gi);const valid_t &provided = inv.valid;scalargroupdata.valid.at(inv.tl).at(inv.vi).set_and(~provided,[iteration = cctkGH->cctk_iteration, where = attribute->where,thorn = attribute->thorn, routine = attribute->routine] {ostringstream buf;buf << "CallFunction iteration " << iteration << " " << where<< ": " << thorn << "::" << routine<< ": Mark invalid variables as invalid";return buf.str();});check_valid(scalargroupdata, inv.vi, inv.tl, [&]() {ostringstream buf;buf << "CallFunction iteration " << cctkGH->cctk_iteration << " "<< attribute->where << ": " << attribute->thorn<< "::" << attribute->routine << " checking output";return buf.str();
void error_if_invalid(const GHExt::GlobalData::ScalarGroupData &groupdata,int vi, int tl, const valid_t &required,const function<string()> &msg);void warn_if_invalid(const GHExt::GlobalData::ScalarGroupData &groupdata,int vi, int tl, const valid_t &required,const function<string()> &msg);void poison_invalid(const GHExt::GlobalData::ScalarGroupData &groupdata, int vi,int tl);void check_valid(const GHExt::GlobalData::ScalarGroupData &groupdata, int vi,int tl, const function<string()> &msg);