#include #include #include #include #include #include #include #include #include #include #include #include #include namespace Carpet { using namespace std; static int GroupStorageCrease (const cGH* cctkGH, int n_groups, const int* groups, const int* tls, int* status, const bool inc); static void GroupStorageCheck (cGH const * const cctkGH, int const group, int const ml, int const rl); int GroupStorageCrease (const cGH* cctkGH, int n_groups, const int* groups, const int* tls, int* status, const bool inc) { DECLARE_CCTK_PARAMETERS; assert (cctkGH); assert (n_groups >= 0); assert (groups); assert (tls); for (int n=0; n= CCTK_NumGroups()) { CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING, "Group index %d is illegal", groups[n]); return -1; } assert (groups[n] >= 0 and groups[n] < CCTK_NumGroups()); // TODO: tls[n] can also be -1; in that case, all time // levels should be activated / deactivated assert (tls[n] >= 0); } #ifdef REQUIREMENTS_HH vector vgroups, vtimelevels; vgroups.reserve(n_groups); vtimelevels.reserve(n_groups); for (int i=0; i ntls); } if (do_change) { vgroups.push_back(gi); vtimelevels.push_back(ntls); } } if (not vgroups.empty()) { Requirements::ChangeStorage(vgroups, vtimelevels, reflevel); } #endif bool const can_do = is_meta_mode() or is_global_mode() or is_level_mode(); bool const all_ml = is_meta_mode(); int const min_ml = all_ml ? 0 : mglevel; int const max_ml = all_ml ? mglevels : mglevel+1; int min_num_timelevels = INT_MAX; for (int n=0; n= 0 and firstvarindex < CCTK_NumVars())); // Check an assumption if (not gp.vectorgroup) assert (gp.vectorlength == 1); // Allocate the time levels for (int ml=min_ml; ml groupdata.AT(group).activetimelevels.AT(ml).AT(rl); const bool do_decrease = not inc and tls[n] < groupdata.AT(group).activetimelevels.AT(ml).AT(rl); if (do_increase or do_decrease) { if (not can_do) { char * const groupname = CCTK_GroupName (group); char const * const modestring = (is_meta_mode() ? "meta" : is_global_mode() ? "global" : is_level_mode() ? "level" : is_singlemap_mode() ? "singlemap" : is_local_mode() ? "local" : NULL); CCTK_VWarn (0, __LINE__, __FILE__, CCTK_THORNSTRING, "Cannot change storage for group \"%s\" in %s mode", groupname, modestring); free (groupname); } assert (can_do); // No storage change in local mode // TODO: This this seems superfluous, given the test above if (gp.grouptype == CCTK_GF) { assert ((map == -1 or maps == 1) and (component == -1 or vhh.AT(0)->local_components(reflevel) == 1)); } // Set the new number of active time levels groupdata.AT(group).activetimelevels.AT(ml).AT(rl) = tls[n]; // Allocate storage only on map 0? const bool ismap0group = IsMap0Group(group); for (int m=0; m<(int)arrdata.AT(group).size(); ++m) { if (m>0 and ismap0group) continue; for (int var=0; var=0 and vectorindex0 and vectorlength<=gp.numvars); ggf* const vectorleader = (vectorindex>0 ? arrdata.AT(group).AT(m).data.AT(var - vectorindex) : NULL); const int varindex = firstvarindex + var; // TODO: allocate these in SetupGH, and after recomposing if (not arrdata.AT(group).AT(m).data.AT(var)) { switch (specific_cactus_type(gp.vartype)) { #define TYPECASE(N,T) \ case N: \ arrdata.AT(group).AT(m).data.AT(var) = new gf \ (varindex, \ groupdata.AT(group).transport_operator, \ *arrdata.AT(group).AT(m).tt, \ *arrdata.AT(group).AT(m).dd, \ prolongation_order_time, \ vectorlength, vectorindex, (gf*)vectorleader); \ break; #include "typecase.hh" #undef TYPECASE default: UnsupportedVarType (varindex); } // switch gp.vartype } // if not allocated arrdata.AT(group).AT(m).data.AT(var)->set_timelevels (ml, rl, tls[n]); // Set the data pointers for grid arrays if (gp.grouptype != CCTK_GF) { assert (rl==0 and m==0); for (int tl=0; tldata_pointer(tl, 0, 0, 0)->storage(); cctkGH->data[varindex][tl] = ptr; } else { cctkGH->data[varindex][tl] = NULL; } } } // if grouptype != GF } // for var } // for m } // if really change the number of active time levels // Complain if there are not enough active time levels GroupStorageCheck (cctkGH, group, ml, rl); // Record (minimum of) current number of time levels min_num_timelevels = min(min_num_timelevels, groupdata.AT(group).activetimelevels.AT(ml).AT(rl)); } // for rl } // for ml } // for n if (min_num_timelevels == INT_MAX) { min_num_timelevels = 0; } return do_allow_past_timelevels ? min_num_timelevels : min(1,min_num_timelevels); } int GroupStorageIncrease (const cGH* cctkGH, int n_groups, const int* groups, const int* tls, int* status) { DECLARE_CCTK_PARAMETERS if(storage_verbose) { Checkpoint ("GroupStorageIncrease"); } return GroupStorageCrease (cctkGH, n_groups, groups, tls, status, true); } int GroupStorageDecrease (const cGH* cctkGH, int n_groups, const int* groups, const int* tls, int* status) { DECLARE_CCTK_PARAMETERS if(storage_verbose) { Checkpoint ("GroupStorageDecrease"); } return GroupStorageCrease (cctkGH, n_groups, groups, tls, status, false); } int EnableGroupStorage (const cGH* cctkGH, const char* groupname) { const int group = CCTK_GroupIndex(groupname); assert (group>=0 and group=0 and group=CCTK_NumGroups()) { CCTK_WARN (1, "QueryGroupStorage: illegal group specified"); return -1; } int const grouptype = CCTK_GroupTypeI (group); if (is_meta_mode() or is_global_mode()) { if (grouptype == CCTK_GF) return -2; } if (groupdata.size() == 0) return -3; int const rl = grouptype == CCTK_GF ? reflevel : 0; // Return whether storage is allocated CCTK_INT const deadbeef = get_deadbeef(); assert (groupdata.AT(group).activetimelevels.AT(mglevel).AT(rl) != deadbeef); return groupdata.AT(group).activetimelevels.AT(mglevel).AT(rl) > 0; } const int* ArrayGroupSizeB (const cGH* cctkGH, int dir, int group, const char* groupname) { static const int zero = 0; static const int error = 0; if (groupname) { group = CCTK_GroupIndex(groupname); } assert (group>=0 and group=0 and dir=0 and group=0 and group didwarn; didwarn.resize (CCTK_NumGroups(), false); if (not didwarn.AT(group)) { // Warn only once per group didwarn.AT(group) = true; char * const groupname = CCTK_GroupName (group); CCTK_VInfo (CCTK_THORNSTRING, "There are not enough time levels for the desired temporal prolongation order in the grid function group \"%s\". With Carpet::prolongation_order_time=%d, you need at least %d time levels.", groupname, (int)prolongation_order_time, (int)(prolongation_order_time+1)); free (groupname); } } } } } void GroupsStorageCheck (cGH const * const cctkGH) { for (int group = 0; group < CCTK_NumGroups(); ++ group) { for (int ml = 0; ml < mglevels; ++ ml) { for (int rl = 0; rl < reflevels; ++ rl) { GroupStorageCheck (cctkGH, group, ml, rl); } } } } } // namespace Carpet