UUGQGVC4WEKN64WAP7F5QPS2UHGQB5ZLMFRIYNWKMIEBDO3QRX4AC
AEVGZIZEUIC52MCK3J4V547YEV2R4YQL3JUJW7FSP4R34PSZ43DAC
722HZ7UFINNE3YKSYKP2NHZ5XEG5QQLQHSKC7PREJZR3EX6RDYUAC
U77PE56ICORZNQW33NXGSEMW7GDHCSSZ4EXB6OHBJSHEG6WHYSSQC
ORAAQXS3UNKXYDJBCTHNEIDJIZDHWMM5EVCZKVMFRKQK2NIQNJGAC
BVR7DVINVPQG7PA6Z7QYVYNQ43YZL7XCC6AOMSMWMGAAB2Q43STAC
6JG4USUIDVMK7A4VPF5DA3VMYFALQXDRRUDF7FJQ5FZ3VCGGINIQC
SHARES: Cactus
USES BOOLEAN terminate_next
USES KEYWORD terminate
USES CCTK_INT cctk_itlast
USES CCTK_REAL cctk_initial_time
USES CCTK_REAL cctk_final_time
USES CCTK_REAL max_runtime
// Allocate grid hierarchy
ghext->mfab = MultiFab(ghext->ba, dm, nvars, ghext->nghostzones);
const int numgroups = CCTK_NumGroups();
ghext->groupdata.resize(numgroups);
for (int gi = 0; gi < numgroups; ++gi) {
cGroup group;
int ierr = CCTK_GroupData(gi, &group);
assert(!ierr);
assert(group.grouptype == CCTK_GF);
assert(group.vartype == CCTK_VARIABLE_REAL);
assert(group.disttype == CCTK_DISTRIB_DEFAULT);
assert(group.dim == dim);
GHExt::GroupData &groupdata = ghext->groupdata.at(gi);
groupdata.firstvarindex = CCTK_FirstVarIndexI(gi);
groupdata.numvars = group.numvars;
groupdata.numtimelevels = group.numtimelevels;
// Allocate grid hierarchy
groupdata.mfab =
MultiFab(ghext->ba, dm, groupdata.numvars * groupdata.numtimelevels,
ghext->nghostzones);
}
const Array4<CCTK_REAL> &vars = ghext->mfab.array(mfi);
for (int vi = 0; vi < 4; ++vi)
cctkGH->data[vi][0] = vars.ptr(imin.x, imin.y, imin.z, vi);
for (auto &restrict groupdata : ghext->groupdata) {
const Array4<CCTK_REAL> &vars = groupdata.mfab.array(mfi);
for (int tl = 0; tl < groupdata.numtimelevels; ++tl)
for (int n = 0; n < groupdata.numvars; ++n)
cctkGH->data[groupdata.firstvarindex + n][tl] =
vars.ptr(imin.x, imin.y, imin.z, tl * groupdata.numvars + n);
}
int nvars = CCTK_NumVars();
for (int vi = 0; vi < nvars; ++vi)
cctkGH->data[vi][0] = nullptr;
for (auto &restrict groupdata : ghext->groupdata) {
for (int tl = 0; tl < groupdata.numtimelevels; ++tl)
for (int n = 0; n < groupdata.numvars; ++n)
cctkGH->data[groupdata.firstvarindex + n][tl] = nullptr;
}
// Schedule initialisation
int Initialise(tFleshConfig *config) {
cGH *restrict const cctkGH = CCTK_SetupGH(config, 0);
CCTKi_AddGH(config, 0, cctkGH);
// Initialise iteration and time
cctkGH->cctk_iteration = 0;
cctkGH->cctk_time = *static_cast<const CCTK_REAL *>(
CCTK_ParameterGet("cctk_initial_time", "Cactus", nullptr));
// Initialise schedule
CCTKi_ScheduleGHInit(cctkGH);
// Initialise all grid extensions
CCTKi_InitGHExtensions(cctkGH);
CCTK_Traverse(cctkGH, "CCTK_WRAGH");
CCTK_Traverse(cctkGH, "CCTK_PARAMCHECK");
CCTKi_FinaliseParamWarn();
CCTK_Traverse(cctkGH, "CCTK_BASEGRID");
const char *recovery_mode = *static_cast<const char *const *>(
CCTK_ParameterGet("recovery_mode", "Cactus", nullptr));
if (!config->recovered || !CCTK_Equals(recovery_mode, "strict")) {
// Set up initial conditions
CCTK_Traverse(cctkGH, "CCTK_INITIAL");
CCTK_Traverse(cctkGH, "CCTK_POSTINITIAL");
CCTK_Traverse(cctkGH, "CCTK_POSTPOSTINITIAL");
CCTK_Traverse(cctkGH, "CCTK_POSTSTEP");
}
if (config->recovered) {
// Recover
CCTK_Traverse(cctkGH, "CCTK_RECOVER_VARIABLES");
CCTK_Traverse(cctkGH, "CCTK_POST_RECOVER_VARIABLES");
}
// Checkpoint, analysis, output
CCTK_Traverse(cctkGH, "CCTK_CPINITIAL");
CCTK_Traverse(cctkGH, "CCTK_ANALYSIS");
CCTK_OutputGH(cctkGH);
return 0;
}
bool EvolutionIsDone(cGH *restrict const cctkGH) {
DECLARE_CCTK_PARAMETERS;
static timeval starttime = {0, 0};
// On the first time through, get the start time
if (starttime.tv_sec == 0 && starttime.tv_usec == 0)
gettimeofday(&starttime, nullptr);
if (terminate_next || CCTK_TerminationReached(cctkGH))
return true;
if (CCTK_Equals(terminate, "never"))
return false;
bool max_iteration_reached = cctkGH->cctk_iteration >= cctk_itlast;
bool max_simulation_time_reached = cctk_initial_time < cctk_final_time
? cctkGH->cctk_time >= cctk_final_time
: cctkGH->cctk_time <= cctk_final_time;
// Get the elapsed runtime in minutes and compare with max_runtime
timeval currenttime;
gettimeofday(¤ttime, NULL);
bool max_runtime_reached =
CCTK_REAL(currenttime.tv_sec - starttime.tv_sec) / 60 >= max_runtime;
if (CCTK_Equals(terminate, "iteration"))
return max_iteration_reached;
if (CCTK_Equals(terminate, "time"))
return max_simulation_time_reached;
if (CCTK_Equals(terminate, "runtime"))
return max_runtime_reached;
if (CCTK_Equals(terminate, "any"))
return max_iteration_reached || max_simulation_time_reached ||
max_runtime_reached;
if (CCTK_Equals(terminate, "all"))
return max_iteration_reached && max_simulation_time_reached &&
max_runtime_reached;
if (CCTK_Equals(terminate, "either"))
return max_iteration_reached || max_simulation_time_reached;
if (CCTK_Equals(terminate, "both"))
return max_iteration_reached && max_simulation_time_reached;
assert(0);
}
void CycleTimelevels(cGH *restrict const cctkGH) {
for (auto &restrict groupdata : ghext->groupdata) {
for (int tl = groupdata.numtimelevels - 1; tl > 0; --tl)
MultiFab::Copy(groupdata.mfab, groupdata.mfab,
(tl - 1) * groupdata.numvars, tl * groupdata.numvars,
groupdata.numvars, ghext->nghostzones);
}
}
// Schedule evolution
int Evolve(tFleshConfig *config) {
assert(config);
cGH *restrict const cctkGH = config->GH[0];
assert(cctkGH);
while (!EvolutionIsDone(cctkGH)) {
cctkGH->cctk_iteration += 1;
cctkGH->cctk_time += cctkGH->cctk_delta_time;
CycleTimelevels(cctkGH);
CCTK_Traverse(cctkGH, "CCTK_PRESTEP");
CCTK_Traverse(cctkGH, "CCTK_EVOL");
CCTK_Traverse(cctkGH, "CCTK_POSTSTEP");
CCTK_Traverse(cctkGH, "CCTK_CHECKPOINT");
CCTK_Traverse(cctkGH, "CCTK_ANALYSIS");
CCTK_OutputGH(cctkGH);
}
return 0;
}
// Schedule shutdown
int Shutdown(tFleshConfig *config) {
assert(config);
cGH *restrict const cctkGH = config->GH[0];
assert(cctkGH);
CCTK_Traverse(cctkGH, "CCTK_TERMINATE");
CCTK_Traverse(cctkGH, "CCTK_SHUTDOWN");
return 0;
}
// CCTK_VINFO("gsh=[%d,%d,%d]", cctkGH->cctk_gsh[0], cctkGH->cctk_gsh[1],
// cctkGH->cctk_gsh[2]);
// CCTK_VINFO("ash=[%d,%d,%d]", cctkGH->cctk_ash[0], cctkGH->cctk_ash[1],
// cctkGH->cctk_ash[2]);
// CCTK_VINFO("lbnd=[%d,%d,%d]", cctkGH->cctk_lbnd[0], cctkGH->cctk_lbnd[1],
// cctkGH->cctk_lbnd[2]);
// CCTK_VINFO("lsh=[%d,%d,%d]", cctkGH->cctk_lsh[0], cctkGH->cctk_lsh[1],
// cctkGH->cctk_lsh[2]);
// CCTK_VINFO("nghostzones=[%d,%d,%d]", cctkGH->cctk_nghostzones[0],
// cctkGH->cctk_nghostzones[1], cctkGH->cctk_nghostzones[2]);
CCTK_REAL check TYPE=gf
{
check
} "Grid function for index checking"
}
extern "C" void WaveToyAMReX_Cycle(CCTK_ARGUMENTS) {
DECLARE_CCTK_ARGUMENTS;
DECLARE_CCTK_PARAMETERS;
// Cycle time levels
MultiFab::Copy(ghext->mfab, ghext->mfab, 1, 2, 1, ghext->nghostzones);
MultiFab::Copy(ghext->mfab, ghext->mfab, 0, 1, 1, ghext->nghostzones);
// Step time
// cctkGH->cctk_time += cctkGH->cctk_delta_time;
CCTK_VINFO("t=%g", cctkGH->cctk_time);
string filename = amrex::Concatenate("wavetoy/phi", cctk_iteration, 6);
WriteSingleLevelPlotfile(filename, ghext->mfab,
{"phi", "phi_p", "phi_p_p", "err"}, ghext->geom,
cctk_time, cctk_iteration);
const int numgroups = CCTK_NumGroups();
for (int gi = 0; gi < numgroups; ++gi) {
auto &restrict groupdata = ghext->groupdata.at(gi);
string groupname = unique_ptr<char>(CCTK_GroupName(gi)).get();
groupname = regex_replace(groupname, regex("::"), "-");
for (auto &c : groupname)
c = tolower(c);
ostringstream buf;
buf << "wavetoy/" << groupname << "." << setw(6) << setfill('0')
<< cctk_iteration;
string filename = buf.str();
Vector<string> varnames(groupdata.numvars * groupdata.numtimelevels);
for (int tl = 0; tl < groupdata.numtimelevels; ++tl) {
for (int n = 0; n < groupdata.numvars; ++n) {
ostringstream buf;
buf << CCTK_VarName(groupdata.firstvarindex + n);
for (int i = 0; i < tl; ++i)
buf << "_p";
varnames.at(tl * groupdata.numvars + n) = buf.str();
}
}
WriteSingleLevelPlotfile(filename, groupdata.mfab, varnames, ghext->geom,
cctk_time, cctk_iteration);
}