#include #include #include #include #include #include #include using namespace std; namespace Requirements { // Ignore requirements in these variables; these variables are // always considered valid std::vector ignored_variables; static void add_ignored_variable(int const id, const char *const opstring, void *const callback_arg) { std::vector& ivs = *static_cast*>(callback_arg); ivs.AT(id) = true; } void all_state_t::setup(int const maps) { DECLARE_CCTK_PARAMETERS; assert(vars.empty()); vars.resize(CCTK_NumVars()); for (variables_t::iterator ivar = vars.begin(); ivar != vars.end(); ++ivar) { reflevels_t& rls = *ivar; int const vi = &*ivar - &*vars.begin(); assert(rls.empty()); // Allocate one refinement level initially int const nrls = 1; rls.resize(nrls); for (reflevels_t::iterator irl = rls.begin(); irl != rls.end(); ++irl) { maps_t& ms = *irl; assert(ms.empty()); int const group_type = CCTK_GroupTypeFromVarI(vi); int const nms = group_type==CCTK_GF ? maps : 1; if (verbose) { char* const fullname = CCTK_FullName(vi); int const rl = &*irl - &*rls.begin(); CCTK_VInfo(CCTK_THORNSTRING, "Setting up %d maps for variable %s(rl=%d)", nms, fullname, rl); free(fullname); } ms.resize(nms); for (maps_t::iterator im = ms.begin(); im != ms.end(); ++im) { timelevels_t& tls = *im; assert(tls.empty()); // Not allocating any time levels here } } } assert(ignored_variables.empty()); ignored_variables.resize(CCTK_NumVars()); CCTK_TraverseString(ignore_these_variables, add_ignored_variable, (void*)&ignored_variables, CCTK_GROUP_OR_VAR); } // Update internal data structures when Carpet changes the number of // active timelevels for a group void all_state_t::change_storage(vector const& groups, vector const& timelevels, int const reflevel) { DECLARE_CCTK_PARAMETERS; assert(groups.size() == timelevels.size()); for (vector::const_iterator igi = groups.begin(), itl = timelevels.begin(); igi != groups.end(); ++igi, ++itl) { int const gi = *igi; int const tl = *itl; bool const is_array = CCTK_GroupTypeI(gi) != CCTK_GF; int const v0 = CCTK_FirstVarIndexI(gi); int const nv = CCTK_NumVarsInGroupI(gi); for (int vi=v0; vi=0 and max_rl<=reflevels); for (int rl=min_rl; rl ntls) { // Allocate new storage if (verbose) { char* const fullname = CCTK_FullName(vi); int const m = &*im - &*ms.begin(); CCTK_VInfo(CCTK_THORNSTRING, "Increasing storage to %d time levels for variable %s(rl=%d,m=%d)", tl, fullname, rl, m); free(fullname); } // The default constructor for gridpoint_t sets all // data to "invalid" tls.resize(tl); } } } } } } // Update internal data structures when Carpet regrids void all_state_t::regrid(int const reflevels) { DECLARE_CCTK_PARAMETERS; assert(old_vars.empty()); old_vars.resize(vars.size()); int const ng = CCTK_NumGroups(); for (int gi=0; gi= 0; break; default: assert(0); } if (do_cycle) { // Translate global mode to refinement level 0 int const rl = reflevel >= 0 ? reflevel : 0; int const v0 = CCTK_FirstVarIndexI(gi); int const nv = CCTK_NumVarsInGroupI(gi); for (int vi=v0; vi= 1) { // Only cycle variables with sufficient storage for (int tl=ntl-1; tl>0; --tl) { tls.AT(tl) = tls.AT(tl-1); } // The new time level is uninitialised // TODO: keep it valid to save time, since MoL will // copy it anyway? tls.AT(0) = gridpoint_t(); } } } } } } // Check that the grid is in the required state before a given // function is executed void all_state_t::before_routine(cFunctionData const* const function_data, all_clauses_t &all_clauses, int const iteration, int const reflevel, int const map, int const timelevel, int const timelevel_offset) const { location_t loc("routine", function_data); loc.it = iteration; // Loop over all clauses clauses_t const& clauses = all_clauses.get_clauses(function_data); for (vector::const_iterator iclause = clauses.reads.begin(); iclause != clauses.reads.end(); ++iclause) { clause_t const& clause = *iclause; for (vector::const_iterator ivar = clause.vars.begin(); ivar != clause.vars.end(); ++ivar) { int const vi = *ivar; loc.vi = vi; if (ignored_variables.AT(vi)) continue; // Loop over all (refinement levels, maps, time levels) reflevels_t const& rls = vars.AT(vi); int const reflevels = int(rls.size()); int min_rl, max_rl; if (clause.all_reflevels or reflevel==-1) { min_rl = 0; max_rl = reflevels; } else { min_rl = reflevel; max_rl = min_rl+1; } for (int rl=min_rl; rl= clause.min_num_timelevels()); assert(timelevel != -1); for (int tl=0; tl= timelevel_offset and clause.active_on_timelevel(tl - timelevel_offset)) { gridpoint_t const& gp = tls.AT(tl); gp.check_state(clause, loc); } } } } } } } // Update internal data structures after a function has been // executed to reflect the fact that some variables are now valid void all_state_t::after_routine(cFunctionData const* const function_data, all_clauses_t &all_clauses, int const iteration, int const reflevel, int const map, int const timelevel, int const timelevel_offset) { location_t loc("routine", function_data); loc.it = iteration; // Loop over all clauses clauses_t const& clauses = all_clauses.get_clauses(function_data); for (vector::const_iterator iclause = clauses.writes.begin(); iclause != clauses.writes.end(); ++iclause) { clause_t const& clause = *iclause; for (vector::const_iterator ivar = clause.vars.begin(); ivar != clause.vars.end(); ++ivar) { int const vi = *ivar; loc.vi = vi; // Loop over all (refinement levels, maps, time levels) reflevels_t& rls = vars.AT(vi); int const reflevels = int(rls.size()); int min_rl, max_rl; if (clause.all_reflevels or reflevel==-1) { min_rl = 0; max_rl = reflevels; } else { min_rl = reflevel; max_rl = min_rl+1; } for (int rl=min_rl; rl= clause.min_num_timelevels()); assert(timelevel != -1); for (int tl=0; tl= timelevel_offset and clause.active_on_timelevel(tl - timelevel_offset)) { gridpoint_t& gp = tls.AT(tl); // TODO: If this variable is both read and written // (i.e. if this is a projection), then only the // written region remains valid gp.update_state(clause, loc); } } } } } } } // Update internal data structures when Carpet syncs void all_state_t::sync(cFunctionData const* const function_data, vector const& groups, int const iteration, int const reflevel, int const timelevel) { location_t loc("synchronisation", function_data); loc.it = iteration; loc.rl = reflevel; loc.tl = timelevel; // Loop over all variables for (vector::const_iterator igi = groups.begin(); igi != groups.end(); ++igi) { int const gi = *igi; bool do_sync; int const group_type = CCTK_GroupTypeI(gi); switch (group_type) { case CCTK_SCALAR: case CCTK_ARRAY: // Grid arrays are synced in global mode do_sync = reflevel == -1; break; case CCTK_GF: // Grid functions are synced in level mode do_sync = reflevel >= 0; break; default: assert(0); } if (do_sync) { // Translate global mode to refinement level 0 int const rl = reflevel >= 0 ? reflevel : 0; int const v0 = CCTK_FirstVarIndexI(gi); int const nv = CCTK_NumVarsInGroupI(gi); for (int vi=v0; vi 0) { location_t cloc(loc); cloc.info = "prolongation"; int const crl = rl-1; cloc.rl = crl; maps_t const& cms = rls.AT(crl); timelevels_t const& ctls = cms.AT(m); // TODO: use prolongation_order_time instead? int const ctimelevels = int(ctls.size()); for (int ctl=0; ctl const& groups, int const iteration, int const reflevel) { location_t loc("restriction"); loc.it = iteration; loc.rl = reflevel; // Loop over all variables for (vector::const_iterator igi = groups.begin(); igi != groups.end(); ++igi) { int const gi = *igi; bool do_restrict; int const group_type = CCTK_GroupTypeI(gi); switch (group_type) { case CCTK_SCALAR: case CCTK_ARRAY: // Grid arrays are synced in global mode do_restrict = reflevel == -1; break; case CCTK_GF: // Grid functions are synced in level mode do_restrict = reflevel >= 0; break; default: assert(0); } if (do_restrict) { // Translate global mode to refinement level 0 int const rl = reflevel >= 0 ? reflevel : 0; int const v0 = CCTK_FirstVarIndexI(gi); int const nv = CCTK_NumVarsInGroupI(gi); for (int vi=v0; vi& v); template ostream& output (ostream& os, const vector& v); template ostream& output (ostream& os, const vector& v); template ostream& output (ostream& os, const vector& v); void all_state_t::invalidate(vector const& vars1, int const reflevel, int const map, int const timelevel) { // Loop over all variables for (vector::const_iterator ivi = vars1.begin(); ivi != vars1.end(); ++ivi) { int const vi = *ivi; reflevels_t& rls = vars.AT(vi); maps_t& ms = rls.AT(reflevel); timelevels_t& tls = ms.AT(map); // This time level is uninitialised tls.AT(timelevel) = gridpoint_t(); } } }