aboutsummaryrefslogtreecommitdiff
path: root/Carpet/Requirements
diff options
context:
space:
mode:
authorIan Hinder <ian.hinder@aei.mpg.de>2013-04-04 13:02:36 +0200
committerIan Hinder <ian.hinder@aei.mpg.de>2013-04-04 13:02:36 +0200
commitbb6832fb2ed0698286aa79f513480dfd7dd37d3b (patch)
tree4a0af688f8304c260d42674ffa091cc79939fe10 /Carpet/Requirements
parenta2a996243971db0c9eb4b10f93a00c8bb16c2b5c (diff)
Requirements: Move all_state class to separate files
Diffstat (limited to 'Carpet/Requirements')
-rw-r--r--Carpet/Requirements/src/Requirements.cc778
-rw-r--r--Carpet/Requirements/src/all_state.cc715
-rw-r--r--Carpet/Requirements/src/all_state.hh64
-rw-r--r--Carpet/Requirements/src/make.code.defn2
4 files changed, 784 insertions, 775 deletions
diff --git a/Carpet/Requirements/src/Requirements.cc b/Carpet/Requirements/src/Requirements.cc
index 0584a5972..75bc567bb 100644
--- a/Carpet/Requirements/src/Requirements.cc
+++ b/Carpet/Requirements/src/Requirements.cc
@@ -24,6 +24,7 @@
#include <location.hh>
#include <util.hh>
#include <gridpoint.hh>
+#include <all_state.hh>
using namespace std;
@@ -36,74 +37,15 @@ namespace Requirements {
//
// 2. Things can be provided only once, not multiple times.
// Except when they are also required.
-
-
-
+
inline ostream& operator<< (ostream& os, const all_clauses_t& a) {
a.output(os);
return os;
}
all_clauses_t all_clauses;
-
-
-
- // Keep track of which time levels contain good data; modify this
- // while time level cycling; routines should specify how many time
- // levels they require/provide
-
- // The state (valid/invalid) of parts of the grid for all
- // timelevels, maps, refinement levels and variables
- class all_state_t {
- typedef vector<gridpoint_t> timelevels_t;
- typedef vector<timelevels_t> maps_t;
- typedef vector<maps_t> reflevels_t;
- typedef vector<reflevels_t> variables_t;
- variables_t vars;
- variables_t old_vars; // for regridding
- public:
- void setup(int maps);
- void change_storage(vector<int> const& groups,
- vector<int> const& timelevels,
- int reflevel);
- void regrid(int reflevels);
- void recompose(int reflevel, valid::valid_t where);
- void regrid_free();
- void cycle(int reflevel);
- void before_routine(cFunctionData const* function_data,
- int reflevel, int map,
- int timelevel, int timelevel_offset) const;
- void after_routine(cFunctionData const* function_data,
- CCTK_INT cctk_iteration,
- int reflevel, int map,
- int timelevel, int timelevel_offset);
- void sync(cFunctionData const* function_data, CCTK_INT cctk_iteration,
- vector<int> const& groups, int reflevel, int timelevel);
- void restrict1(vector<int> const& groups, CCTK_INT cctk_iteration, int reflevel);
- void invalidate(vector<int> const& vars,
- int reflevel, int map, int timelevel);
-
- // Input/Output helpers
- void input (istream& is);
- void output (ostream& os) const;
- };
-
all_state_t all_state;
- // Ignore requirements in these variables; these variables are
- // always considered valid
- std::vector<bool> ignored_variables;
-
-
-
- static void add_ignored_variable(int const id, const char *const opstring,
- void *const callback_arg)
- {
- std::vector<bool>& ivs = *static_cast<std::vector<bool>*>(callback_arg);
-
- ivs.AT(id) = true;
- }
-
void Setup(int const maps)
{
DECLARE_CCTK_PARAMETERS;
@@ -120,50 +62,6 @@ namespace Requirements {
}
}
- 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);
- }
-
-
-
void ChangeStorage(vector<int> const& groups,
vector<int> const& timelevels,
int const reflevel)
@@ -185,68 +83,6 @@ namespace Requirements {
}
}
- // Update internal data structures when Carpet changes the number of
- // active timelevels for a group
- void all_state_t::change_storage(vector<int> const& groups,
- vector<int> const& timelevels,
- int const reflevel)
- {
- DECLARE_CCTK_PARAMETERS;
- assert(groups.size() == timelevels.size());
- for (vector<int>::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<v0+nv; ++vi) {
- reflevels_t& rls = vars.AT(vi);
- int const reflevels = int(rls.size());
- bool const all_rl = reflevel==-1;
- int const min_rl = is_array ? 0 : all_rl ? 0 : reflevel;
- int const max_rl = is_array ? 1 : all_rl ? reflevels : reflevel+1;
- assert(min_rl>=0 and max_rl<=reflevels);
- for (int rl=min_rl; rl<max_rl; ++rl) {
- maps_t& ms = rls.AT(rl);
- for (maps_t::iterator im = ms.begin(); im != ms.end(); ++im) {
- timelevels_t& tls = *im;
- int const ntls = int(tls.size());
- if (tl < ntls) {
- // Free some storage
- if (verbose) {
- char* const fullname = CCTK_FullName(vi);
- int const m = &*im - &*ms.begin();
- CCTK_VInfo(CCTK_THORNSTRING,
- "Decreasing storage to %d time levels for variable %s(rl=%d,m=%d)",
- tl, fullname, rl, m);
- free(fullname);
- }
- tls.resize(tl);
- } else if (tl > 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);
- }
- }
- }
- }
- }
- }
-
-
-
void Regrid(int const reflevels)
{
DECLARE_CCTK_PARAMETERS;
@@ -262,80 +98,7 @@ namespace Requirements {
"Aborting because schedule clauses were not satisfied");
}
}
-
- // 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<ng; ++gi) {
- int const group_type = CCTK_GroupTypeI(gi);
- switch (group_type) {
- case CCTK_SCALAR:
- case CCTK_ARRAY:
- // Grid arrays remain unchanged
- break;
- case CCTK_GF: {
- // Only grid functions are regridded
- int const v0 = CCTK_FirstVarIndexI(gi);
- int const nv = CCTK_NumVarsInGroupI(gi);
- for (int vi=v0; vi<v0+nv; ++vi) {
- reflevels_t& rls = vars.AT(vi);
- reflevels_t& old_rls = old_vars.AT(vi);
- assert(old_rls.empty());
- swap(rls, old_rls);
- // Delete (unused) old refinement levels
- int const old_reflevels = int(old_rls.size());
- for (int rl=reflevels; rl<old_reflevels; ++rl) {
- maps_t& old_ms = old_rls.AT(rl);
- if (verbose) {
- char* const fullname = CCTK_FullName(vi);
- CCTK_VInfo(CCTK_THORNSTRING,
- "Deleting unused refinement level %d of variable %s",
- rl, fullname);
- free(fullname);
- }
- old_ms.clear();
- }
- // Allocate new refinement levels
- rls.resize(reflevels);
- maps_t const& old_ms = old_rls.AT(0);
- int const old_maps = int(old_ms.size());
- int const maps = old_maps;
- for (int rl=old_reflevels; rl<reflevels; ++rl) {
- maps_t& ms = rls.AT(rl);
- if (verbose) {
- char* const fullname = CCTK_FullName(vi);
- CCTK_VInfo(CCTK_THORNSTRING,
- "Allocating new refinement level %d for variable %s",
- rl, fullname);
- free(fullname);
- }
- ms.resize(maps);
- for (maps_t::iterator im = ms.begin(); im != ms.end(); ++im) {
- int const crl = 0;
- int const m = &*im - &*ms.begin();
- timelevels_t& tls = *im;
- assert(tls.empty());
- int const ntls = int(old_rls.AT(crl).AT(m).size());
- // Allocate undefined timelevels
- tls.resize(ntls);
- }
- }
- }
- break;
- }
- default:
- assert(0);
- }
- }
- }
-
-
-
+
void Recompose(int const reflevel, valid::valid_t const where)
{
DECLARE_CCTK_PARAMETERS;
@@ -356,91 +119,7 @@ namespace Requirements {
"Aborting because schedule clauses were not satisfied");
}
}
-
- // Update internal data structures when Carpet recomposes
- void all_state_t::recompose(int const reflevel, valid::valid_t const where)
- {
- DECLARE_CCTK_PARAMETERS;
- int const ng = CCTK_NumGroups();
- location_t loc;
- loc.info = "recompose";
- loc.rl = reflevel;
- for (int gi=0; gi<ng; ++gi) {
- int const group_type = CCTK_GroupTypeI(gi);
- switch (group_type) {
- case CCTK_SCALAR:
- case CCTK_ARRAY:
- // Grid arrays remain unchanged
- break;
- case CCTK_GF: {
- // Only grid functions are regridded
- int const v0 = CCTK_FirstVarIndexI(gi);
- int const nv = CCTK_NumVarsInGroupI(gi);
- for (int vi=v0; vi<v0+nv; ++vi) {
- loc.vi = vi;
- reflevels_t& rls = vars.AT(vi);
- maps_t& ms = rls.AT(reflevel);
- reflevels_t& old_rls = old_vars.AT(vi);
- int const old_reflevels = int(old_rls.size());
- if (reflevel < old_reflevels) {
- // This refinement level is regridded
- maps_t& old_ms = old_rls.AT(reflevel);
- assert(not old_ms.empty());
- assert(ms.empty());
- swap(ms, old_ms);
- for (maps_t::iterator
- im = ms.begin(), old_im = old_ms.begin();
- im != ms.end(); ++im, ++old_im)
- {
- loc.m = &*im - &*ms.begin();
- timelevels_t& tls = *im;
- if (verbose) {
- char* const fullname = CCTK_FullName(vi);
- int const m = &*im - &*ms.begin();
- CCTK_VInfo(CCTK_THORNSTRING,
- "Recomposing variable %s(rl=%d,m=%d)",
- fullname, reflevel, m);
- free(fullname);
- }
- for (timelevels_t::iterator
- itl = tls.begin(); itl != tls.end(); ++itl)
- {
- gridpoint_t& gp = *itl;
- loc.tl = &*itl - &*tls.begin();
- switch (where) {
- case valid::nowhere:
- gp.set_interior(false, loc);
- // fall through
- case valid::interior:
- // Recomposing sets only the interior
- gp.set_boundary(false, loc);
- gp.set_ghostzones(false, loc);
- gp.set_boundary_ghostzones(false, loc);
- // fall through
- case valid::everywhere:
- // do nothing
- break;
- default:
- assert(0);
- }
- }
- }
- assert(old_ms.empty());
- } else {
- // This refinement level is new
- assert(where == valid::nowhere);
- }
- }
- break;
- }
- default:
- assert(0);
- }
- }
- }
-
-
-
+
void RegridFree()
{
DECLARE_CCTK_PARAMETERS;
@@ -457,25 +136,6 @@ namespace Requirements {
}
}
- void all_state_t::regrid_free()
- {
- // Ensure all old maps have been recomposed
- for (variables_t::const_iterator
- ivar = old_vars.begin(); ivar != old_vars.end(); ++ivar)
- {
- reflevels_t const& old_rls = *ivar;
- for (reflevels_t::const_iterator
- irl = old_rls.begin(); irl != old_rls.end(); ++irl)
- {
- maps_t const& old_ms = *irl;
- assert(old_ms.empty());
- }
- }
- old_vars.clear();
- }
-
-
-
void Cycle(int const reflevel)
{
DECLARE_CCTK_PARAMETERS;
@@ -491,55 +151,6 @@ namespace Requirements {
"Aborting because schedule clauses were not satisfied");
}
}
-
- // Update internal data structures when Carpet cycles timelevels
- void all_state_t::cycle(int const reflevel)
- {
- int const ng = CCTK_NumGroups();
- for (int gi=0; gi<ng; ++gi) {
- int const group_type = CCTK_GroupTypeI(gi);
- bool do_cycle;
- switch (group_type) {
- case CCTK_SCALAR:
- case CCTK_ARRAY:
- // Grid arrays are cycled in global mode
- do_cycle = reflevel == -1;
- break;
- case CCTK_GF:
- // Grid functions are cycled in level mode
- do_cycle = reflevel >= 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<v0+nv; ++vi) {
- reflevels_t& rls = vars.AT(vi);
- maps_t& ms = rls.AT(rl);
- for (maps_t::iterator im = ms.begin(); im != ms.end(); ++im) {
- timelevels_t& tls = *im;
- int const ntl = int(tls.size());
- if (ntl >= 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();
- }
- }
- }
- }
- }
- }
-
-
void BeforeRoutine(cFunctionData const* const function_data,
int const reflevel, int const map,
@@ -556,77 +167,6 @@ namespace Requirements {
}
}
- // 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,
- int const reflevel, int const map,
- int const timelevel,
- int const timelevel_offset)
- const
- {
- // Loop over all clauses
- clauses_t const& clauses = all_clauses.get_clauses(function_data);
- for (vector<clause_t>::const_iterator iclause = clauses.reads.begin();
- iclause != clauses.reads.end();
- ++iclause)
- {
- clause_t const& clause = *iclause;
- for (vector<int>::const_iterator ivar = clause.vars.begin();
- ivar != clause.vars.end();
- ++ivar)
- {
- int const vi = *ivar;
-
- 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<max_rl; ++rl) {
-
- maps_t const& ms = rls.AT(rl);
- int const maps = int(ms.size());
- int min_m, max_m;
- if (clause.all_maps or map==-1) {
- min_m = 0; max_m = maps;
- } else {
- min_m = map; max_m = min_m+1;
- }
- for (int m=min_m; m<max_m; ++m) {
-
- timelevels_t const& tls = ms.AT(m);
- int const timelevels = int(tls.size());
- assert(timelevel != -1);
- assert(timelevels >= clause.min_num_timelevels());
- // TODO: properly handle timelevels the way enter_local_mode() does
- const int mintl =
- timelevel == 0 || timelevels == 1 ? 0 : timelevel;
- const int maxtl =
- timelevel == 0 || timelevels == 1 ? timelevels-1 : timelevel;
- const int tloff = timelevel_offset;
- for (int tl=mintl; tl<=maxtl; ++tl) {
- if (timelevel==-1 or clause.active_on_timelevel(tl-tloff)) {
- gridpoint_t const& gp = tls.AT(tl);
- gp.check_state(clause, function_data, vi, rl, m, tl);
- }
- }
-
- }
- }
-
- }
- }
- }
-
-
-
void AfterRoutine(cFunctionData const* const function_data, CCTK_INT cctk_iteration,
int const reflevel, int const map,
int const timelevel, int const timelevel_offset)
@@ -642,90 +182,6 @@ namespace Requirements {
}
}
- // 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,
- CCTK_INT cctk_iteration,
- int const reflevel, int const map,
- int const timelevel,
- int const timelevel_offset)
- {
- location_t loc;
- std::string info = "after_routine ";
- info += function_data->thorn;
- info += "::";
- info += function_data->routine;
- info += " in ";
- info += function_data->where;
- loc.info = info.c_str();
- loc.it = cctk_iteration;
- // Loop over all clauses
- clauses_t const& clauses = all_clauses.get_clauses(function_data);
- for (vector<clause_t>::const_iterator iclause = clauses.writes.begin();
- iclause != clauses.writes.end();
- ++iclause)
- {
- clause_t const& clause = *iclause;
- for (vector<int>::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<max_rl; ++rl) {
-
- loc.rl = rl;
- maps_t& ms = rls.AT(rl);
- int const maps = int(ms.size());
- int min_m, max_m;
- if (clause.all_maps or map==-1) {
- min_m = 0; max_m = maps;
- } else {
- min_m = map; max_m = min_m+1;
- }
- for (int m=min_m; m<max_m; ++m) {
-
- loc.m = m;
- timelevels_t& tls = ms.AT(m);
- int const timelevels = int(tls.size());
- assert(timelevel != -1);
- assert(timelevels >= clause.min_num_timelevels());
- // TODO: properly handle timelevels the way enter_local_mode() does
- const int mintl =
- timelevel == 0 || timelevels == 1 ? 0 : timelevel;
- const int maxtl =
- timelevel == 0 || timelevels == 1 ? timelevels-1 : timelevel;
- const int tloff = timelevel_offset;
- for (int tl=mintl; tl<=maxtl; ++tl) {
- if (timelevel==-1 or clause.active_on_timelevel(tl-tloff)) {
- loc.tl = tl;
- 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);
- }
- }
-
- }
- }
-
- }
- }
- }
-
-
-
void Sync(cFunctionData const* const function_data,
CCTK_INT cctk_iteration,
vector<int> const& groups,
@@ -746,108 +202,6 @@ namespace Requirements {
}
}
- // Update internal data structures when Carpet syncs
- void all_state_t::sync(cFunctionData const* const function_data,
- CCTK_INT cctk_iteration,
- vector<int> const& groups,
- int const reflevel, int const timelevel)
- {
- location_t loc;
- loc.info = "sync";
- loc.rl = reflevel;
- loc.tl = timelevel;
- loc.it = cctk_iteration;
- // Loop over all variables
- for (vector<int>::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<v0+nv; ++vi) {
- if (ignored_variables.AT(vi))
- continue;
- loc.vi = vi;
-
- reflevels_t& rls = vars.AT(vi);
- maps_t& ms = rls.AT(rl);
- int const maps = int(ms.size());
- for (int m=0; m<maps; ++m) {
- timelevels_t& tls = ms.AT(m);
- int const tl = timelevel;
- gridpoint_t& gp = tls.AT(tl);
- loc.m = m;
-
- // Synchronising requires a valid interior
- if (not gp.interior()) {
- gp.report_error
- (function_data, vi, rl, m, tl, "synchronising", "interior");
- }
-
- // Synchronising (i.e. prolongating) requires valid data
- // on all time levels of the same map of the next
- // coarser refinement level
- if (rl > 0) {
- int const crl = rl-1;
- 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<ctimelevels; ++ctl) {
- gridpoint_t const& cgp = ctls.AT(ctl);
- if (not (cgp.interior() and cgp.boundary() and cgp.ghostzones() and
- cgp.boundary_ghostzones()))
- {
- cgp.report_error
- (function_data, vi, crl, m, ctl,
- "prolongating", "everywhere");
- }
- }
- }
-
- // Synchronising sets all ghost zones, and sets boundary
- // ghost zones if boundary zones are set
- if (gp.boundary() ) {
- if (gp.ghostzones() and gp.boundary_ghostzones()) {
- gp.report_warning
- (function_data, vi, rl, m, tl,
- "synchronising", "ghostzones+boundary_ghostzones");
- }
- } else {
- if (gp.ghostzones()) {
- gp.report_warning
- (function_data, vi, rl, m, tl,
- "synchronising", "ghostzones");
- }
- }
- gp.set_ghostzones(true, loc);
- gp.set_boundary_ghostzones(gp.boundary(), loc);
- }
- }
- }
- }
- }
-
-
-
void Restrict(vector<int> const& groups, CCTK_INT const cctk_iteration, int const reflevel)
{
DECLARE_CCTK_PARAMETERS;
@@ -865,111 +219,6 @@ namespace Requirements {
}
}
- // Update internal data structures when Carpet restricts
- void all_state_t::restrict1(vector<int> const& groups, CCTK_INT const cctk_iteration, int const reflevel)
- {
- location_t loc;
- loc.info = "restrict";
- loc.rl = reflevel;
- loc.it = cctk_iteration;
- // Loop over all variables
- for (vector<int>::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<v0+nv; ++vi) {
- if (ignored_variables.AT(vi))
- continue;
- loc.vi = vi;
-
- reflevels_t& rls = vars.AT(vi);
- int const reflevels = int(rls.size());
- maps_t& ms = rls.AT(rl);
- int const maps = int(ms.size());
- for (int m=0; m<maps; ++m) {
- loc.m = m;
- timelevels_t& tls = ms.AT(m);
- int const tl = 0;
- loc.tl = tl;
- gridpoint_t& gp = tls.AT(tl);
-
- // Restricting requires a valid interior (otherwise we
- // cannot be sure that all of the interior is valid
- // afterwards)
- if (not gp.interior()) {
- gp.report_error
- (NULL, vi, rl, m, tl, "restricting", "interior");
- }
-
- // Restricting requires valid data on the current time
- // level of the same map of the next finer refinement
- // level
- if (rl < reflevels-1) {
- int const frl = rl+1;
- maps_t const& fms = rls.AT(frl);
- timelevels_t const& ftls = fms.AT(m);
- int const ftl = 0;
- gridpoint_t const& fgp = ftls.AT(ftl);
- if (not (fgp.interior() and fgp.boundary() and fgp.ghostzones() and
- fgp.boundary_ghostzones()))
- {
- fgp.report_error
- (NULL, vi, frl, m, ftl, "restricting", "everywhere");
- }
- }
-
- // Restricting fills (part of) the interior, but leaves
- // ghost zones and boundary zones undefined
- gp.set_boundary(false, loc);
- gp.set_ghostzones(false, loc);
- gp.set_boundary_ghostzones(false, loc);
- }
- }
- }
- }
- }
-
- inline ostream& operator<< (ostream& os, const all_state_t& a) {
- a.output(os);
- return os;
- }
-
- void all_state_t::output(ostream& os) const
- {
- os << "all_state:" << std::endl;
- os << "vars:" << std::endl;
- os << vars << std::endl;
- os << "old_vars:" << std::endl;
- os << old_vars << std::endl;
- }
-
- template ostream& output (ostream& os, const vector<all_state_t::timelevels_t>& v);
- template ostream& output (ostream& os, const vector<all_state_t::maps_t>& v);
- template ostream& output (ostream& os, const vector<all_state_t::reflevels_t>& v);
- template ostream& output (ostream& os, const vector<all_state_t::variables_t>& v);
-
-
-
////////////////////////////////////////////////////////////////////////////
@@ -1075,23 +324,6 @@ namespace Requirements {
}
}
- void all_state_t::invalidate(vector<int> const& vars1,
- int const reflevel, int const map,
- int const timelevel)
- {
- // Loop over all variables
- for (vector<int>::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();
- }
- }
-
////////////////////////////////////////////////////////////////////////////
@@ -1165,6 +397,4 @@ namespace Requirements {
Requirements_NotifyWrites(cctkGH, num_vars, &vars[0], "boundary;boundary_ghostzones");
}
-
-
} // namespace Requirements
diff --git a/Carpet/Requirements/src/all_state.cc b/Carpet/Requirements/src/all_state.cc
new file mode 100644
index 000000000..192187944
--- /dev/null
+++ b/Carpet/Requirements/src/all_state.cc
@@ -0,0 +1,715 @@
+
+#include <cctk.h>
+#include <cctk_Parameters.h>
+
+#include <all_state.hh>
+#include <util.hh>
+#include <clauses.hh>
+#include <all_clauses.hh>
+
+using namespace std;
+
+namespace Requirements {
+
+ // Ignore requirements in these variables; these variables are
+ // always considered valid
+ std::vector<bool> ignored_variables;
+
+ extern all_clauses_t all_clauses;
+
+ static void add_ignored_variable(int const id, const char *const opstring,
+ void *const callback_arg)
+ {
+ std::vector<bool>& ivs = *static_cast<std::vector<bool>*>(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<int> const& groups,
+ vector<int> const& timelevels,
+ int const reflevel)
+ {
+ DECLARE_CCTK_PARAMETERS;
+ assert(groups.size() == timelevels.size());
+ for (vector<int>::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<v0+nv; ++vi) {
+ reflevels_t& rls = vars.AT(vi);
+ int const reflevels = int(rls.size());
+ bool const all_rl = reflevel==-1;
+ int const min_rl = is_array ? 0 : all_rl ? 0 : reflevel;
+ int const max_rl = is_array ? 1 : all_rl ? reflevels : reflevel+1;
+ assert(min_rl>=0 and max_rl<=reflevels);
+ for (int rl=min_rl; rl<max_rl; ++rl) {
+ maps_t& ms = rls.AT(rl);
+ for (maps_t::iterator im = ms.begin(); im != ms.end(); ++im) {
+ timelevels_t& tls = *im;
+ int const ntls = int(tls.size());
+ if (tl < ntls) {
+ // Free some storage
+ if (verbose) {
+ char* const fullname = CCTK_FullName(vi);
+ int const m = &*im - &*ms.begin();
+ CCTK_VInfo(CCTK_THORNSTRING,
+ "Decreasing storage to %d time levels for variable %s(rl=%d,m=%d)",
+ tl, fullname, rl, m);
+ free(fullname);
+ }
+ tls.resize(tl);
+ } else if (tl > 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<ng; ++gi) {
+ int const group_type = CCTK_GroupTypeI(gi);
+ switch (group_type) {
+ case CCTK_SCALAR:
+ case CCTK_ARRAY:
+ // Grid arrays remain unchanged
+ break;
+ case CCTK_GF: {
+ // Only grid functions are regridded
+ int const v0 = CCTK_FirstVarIndexI(gi);
+ int const nv = CCTK_NumVarsInGroupI(gi);
+ for (int vi=v0; vi<v0+nv; ++vi) {
+ reflevels_t& rls = vars.AT(vi);
+ reflevels_t& old_rls = old_vars.AT(vi);
+ assert(old_rls.empty());
+ swap(rls, old_rls);
+ // Delete (unused) old refinement levels
+ int const old_reflevels = int(old_rls.size());
+ for (int rl=reflevels; rl<old_reflevels; ++rl) {
+ maps_t& old_ms = old_rls.AT(rl);
+ if (verbose) {
+ char* const fullname = CCTK_FullName(vi);
+ CCTK_VInfo(CCTK_THORNSTRING,
+ "Deleting unused refinement level %d of variable %s",
+ rl, fullname);
+ free(fullname);
+ }
+ old_ms.clear();
+ }
+ // Allocate new refinement levels
+ rls.resize(reflevels);
+ maps_t const& old_ms = old_rls.AT(0);
+ int const old_maps = int(old_ms.size());
+ int const maps = old_maps;
+ for (int rl=old_reflevels; rl<reflevels; ++rl) {
+ maps_t& ms = rls.AT(rl);
+ if (verbose) {
+ char* const fullname = CCTK_FullName(vi);
+ CCTK_VInfo(CCTK_THORNSTRING,
+ "Allocating new refinement level %d for variable %s",
+ rl, fullname);
+ free(fullname);
+ }
+ ms.resize(maps);
+ for (maps_t::iterator im = ms.begin(); im != ms.end(); ++im) {
+ int const crl = 0;
+ int const m = &*im - &*ms.begin();
+ timelevels_t& tls = *im;
+ assert(tls.empty());
+ int const ntls = int(old_rls.AT(crl).AT(m).size());
+ // Allocate undefined timelevels
+ tls.resize(ntls);
+ }
+ }
+ }
+ break;
+ }
+ default:
+ assert(0);
+ }
+ }
+ }
+
+ // Update internal data structures when Carpet recomposes
+ void all_state_t::recompose(int const reflevel, valid::valid_t const where)
+ {
+ DECLARE_CCTK_PARAMETERS;
+ int const ng = CCTK_NumGroups();
+ location_t loc;
+ loc.info = "recompose";
+ loc.rl = reflevel;
+ for (int gi=0; gi<ng; ++gi) {
+ int const group_type = CCTK_GroupTypeI(gi);
+ switch (group_type) {
+ case CCTK_SCALAR:
+ case CCTK_ARRAY:
+ // Grid arrays remain unchanged
+ break;
+ case CCTK_GF: {
+ // Only grid functions are regridded
+ int const v0 = CCTK_FirstVarIndexI(gi);
+ int const nv = CCTK_NumVarsInGroupI(gi);
+ for (int vi=v0; vi<v0+nv; ++vi) {
+ loc.vi = vi;
+ reflevels_t& rls = vars.AT(vi);
+ maps_t& ms = rls.AT(reflevel);
+ reflevels_t& old_rls = old_vars.AT(vi);
+ int const old_reflevels = int(old_rls.size());
+ if (reflevel < old_reflevels) {
+ // This refinement level is regridded
+ maps_t& old_ms = old_rls.AT(reflevel);
+ assert(not old_ms.empty());
+ assert(ms.empty());
+ swap(ms, old_ms);
+ for (maps_t::iterator
+ im = ms.begin(), old_im = old_ms.begin();
+ im != ms.end(); ++im, ++old_im)
+ {
+ loc.m = &*im - &*ms.begin();
+ timelevels_t& tls = *im;
+ if (verbose) {
+ char* const fullname = CCTK_FullName(vi);
+ int const m = &*im - &*ms.begin();
+ CCTK_VInfo(CCTK_THORNSTRING,
+ "Recomposing variable %s(rl=%d,m=%d)",
+ fullname, reflevel, m);
+ free(fullname);
+ }
+ for (timelevels_t::iterator
+ itl = tls.begin(); itl != tls.end(); ++itl)
+ {
+ gridpoint_t& gp = *itl;
+ loc.tl = &*itl - &*tls.begin();
+ switch (where) {
+ case valid::nowhere:
+ gp.set_interior(false, loc);
+ // fall through
+ case valid::interior:
+ // Recomposing sets only the interior
+ gp.set_boundary(false, loc);
+ gp.set_ghostzones(false, loc);
+ gp.set_boundary_ghostzones(false, loc);
+ // fall through
+ case valid::everywhere:
+ // do nothing
+ break;
+ default:
+ assert(0);
+ }
+ }
+ }
+ assert(old_ms.empty());
+ } else {
+ // This refinement level is new
+ assert(where == valid::nowhere);
+ }
+ }
+ break;
+ }
+ default:
+ assert(0);
+ }
+ }
+ }
+
+ void all_state_t::regrid_free()
+ {
+ // Ensure all old maps have been recomposed
+ for (variables_t::const_iterator
+ ivar = old_vars.begin(); ivar != old_vars.end(); ++ivar)
+ {
+ reflevels_t const& old_rls = *ivar;
+ for (reflevels_t::const_iterator
+ irl = old_rls.begin(); irl != old_rls.end(); ++irl)
+ {
+ maps_t const& old_ms = *irl;
+ assert(old_ms.empty());
+ }
+ }
+ old_vars.clear();
+ }
+
+ // Update internal data structures when Carpet cycles timelevels
+ void all_state_t::cycle(int const reflevel)
+ {
+ int const ng = CCTK_NumGroups();
+ for (int gi=0; gi<ng; ++gi) {
+ int const group_type = CCTK_GroupTypeI(gi);
+ bool do_cycle;
+ switch (group_type) {
+ case CCTK_SCALAR:
+ case CCTK_ARRAY:
+ // Grid arrays are cycled in global mode
+ do_cycle = reflevel == -1;
+ break;
+ case CCTK_GF:
+ // Grid functions are cycled in level mode
+ do_cycle = reflevel >= 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<v0+nv; ++vi) {
+ reflevels_t& rls = vars.AT(vi);
+ maps_t& ms = rls.AT(rl);
+ for (maps_t::iterator im = ms.begin(); im != ms.end(); ++im) {
+ timelevels_t& tls = *im;
+ int const ntl = int(tls.size());
+ if (ntl >= 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,
+ int const reflevel, int const map,
+ int const timelevel,
+ int const timelevel_offset)
+ const
+ {
+ // Loop over all clauses
+ clauses_t const& clauses = all_clauses.get_clauses(function_data);
+ for (vector<clause_t>::const_iterator iclause = clauses.reads.begin();
+ iclause != clauses.reads.end();
+ ++iclause)
+ {
+ clause_t const& clause = *iclause;
+ for (vector<int>::const_iterator ivar = clause.vars.begin();
+ ivar != clause.vars.end();
+ ++ivar)
+ {
+ int const vi = *ivar;
+
+ 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<max_rl; ++rl) {
+
+ maps_t const& ms = rls.AT(rl);
+ int const maps = int(ms.size());
+ int min_m, max_m;
+ if (clause.all_maps or map==-1) {
+ min_m = 0; max_m = maps;
+ } else {
+ min_m = map; max_m = min_m+1;
+ }
+ for (int m=min_m; m<max_m; ++m) {
+
+ timelevels_t const& tls = ms.AT(m);
+ int const timelevels = int(tls.size());
+ assert(timelevel != -1);
+ assert(timelevels >= clause.min_num_timelevels());
+ // TODO: properly handle timelevels the way enter_local_mode() does
+ const int mintl =
+ timelevel == 0 || timelevels == 1 ? 0 : timelevel;
+ const int maxtl =
+ timelevel == 0 || timelevels == 1 ? timelevels-1 : timelevel;
+ const int tloff = timelevel_offset;
+ for (int tl=mintl; tl<=maxtl; ++tl) {
+ if (timelevel==-1 or clause.active_on_timelevel(tl-tloff)) {
+ gridpoint_t const& gp = tls.AT(tl);
+ gp.check_state(clause, function_data, vi, rl, m, tl);
+ }
+ }
+
+ }
+ }
+
+ }
+ }
+ }
+
+ // 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,
+ CCTK_INT cctk_iteration,
+ int const reflevel, int const map,
+ int const timelevel,
+ int const timelevel_offset)
+ {
+ location_t loc;
+ std::string info = "after_routine ";
+ info += function_data->thorn;
+ info += "::";
+ info += function_data->routine;
+ info += " in ";
+ info += function_data->where;
+ loc.info = info.c_str();
+ loc.it = cctk_iteration;
+ // Loop over all clauses
+ clauses_t const& clauses = all_clauses.get_clauses(function_data);
+ for (vector<clause_t>::const_iterator iclause = clauses.writes.begin();
+ iclause != clauses.writes.end();
+ ++iclause)
+ {
+ clause_t const& clause = *iclause;
+ for (vector<int>::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<max_rl; ++rl) {
+
+ loc.rl = rl;
+ maps_t& ms = rls.AT(rl);
+ int const maps = int(ms.size());
+ int min_m, max_m;
+ if (clause.all_maps or map==-1) {
+ min_m = 0; max_m = maps;
+ } else {
+ min_m = map; max_m = min_m+1;
+ }
+ for (int m=min_m; m<max_m; ++m) {
+
+ loc.m = m;
+ timelevels_t& tls = ms.AT(m);
+ int const timelevels = int(tls.size());
+ assert(timelevel != -1);
+ assert(timelevels >= clause.min_num_timelevels());
+ // TODO: properly handle timelevels the way enter_local_mode() does
+ const int mintl =
+ timelevel == 0 || timelevels == 1 ? 0 : timelevel;
+ const int maxtl =
+ timelevel == 0 || timelevels == 1 ? timelevels-1 : timelevel;
+ const int tloff = timelevel_offset;
+ for (int tl=mintl; tl<=maxtl; ++tl) {
+ if (timelevel==-1 or clause.active_on_timelevel(tl-tloff)) {
+ loc.tl = tl;
+ 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,
+ CCTK_INT cctk_iteration,
+ vector<int> const& groups,
+ int const reflevel, int const timelevel)
+ {
+ location_t loc;
+ loc.info = "sync";
+ loc.rl = reflevel;
+ loc.tl = timelevel;
+ loc.it = cctk_iteration;
+ // Loop over all variables
+ for (vector<int>::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<v0+nv; ++vi) {
+ if (ignored_variables.AT(vi))
+ continue;
+ loc.vi = vi;
+
+ reflevels_t& rls = vars.AT(vi);
+ maps_t& ms = rls.AT(rl);
+ int const maps = int(ms.size());
+ for (int m=0; m<maps; ++m) {
+ timelevels_t& tls = ms.AT(m);
+ int const tl = timelevel;
+ gridpoint_t& gp = tls.AT(tl);
+ loc.m = m;
+
+ // Synchronising requires a valid interior
+ if (not gp.interior()) {
+ gp.report_error
+ (function_data, vi, rl, m, tl, "synchronising", "interior");
+ }
+
+ // Synchronising (i.e. prolongating) requires valid data
+ // on all time levels of the same map of the next
+ // coarser refinement level
+ if (rl > 0) {
+ int const crl = rl-1;
+ 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<ctimelevels; ++ctl) {
+ gridpoint_t const& cgp = ctls.AT(ctl);
+ if (not (cgp.interior() and cgp.boundary() and cgp.ghostzones() and
+ cgp.boundary_ghostzones()))
+ {
+ cgp.report_error
+ (function_data, vi, crl, m, ctl,
+ "prolongating", "everywhere");
+ }
+ }
+ }
+
+ // Synchronising sets all ghost zones, and sets boundary
+ // ghost zones if boundary zones are set
+ if (gp.boundary() ) {
+ if (gp.ghostzones() and gp.boundary_ghostzones()) {
+ gp.report_warning
+ (function_data, vi, rl, m, tl,
+ "synchronising", "ghostzones+boundary_ghostzones");
+ }
+ } else {
+ if (gp.ghostzones()) {
+ gp.report_warning
+ (function_data, vi, rl, m, tl,
+ "synchronising", "ghostzones");
+ }
+ }
+ gp.set_ghostzones(true, loc);
+ gp.set_boundary_ghostzones(gp.boundary(), loc);
+ }
+ }
+ }
+ }
+ }
+
+
+ // Update internal data structures when Carpet restricts
+ void all_state_t::restrict1(vector<int> const& groups, CCTK_INT const cctk_iteration, int const reflevel)
+ {
+ location_t loc;
+ loc.info = "restrict";
+ loc.rl = reflevel;
+ loc.it = cctk_iteration;
+ // Loop over all variables
+ for (vector<int>::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<v0+nv; ++vi) {
+ if (ignored_variables.AT(vi))
+ continue;
+ loc.vi = vi;
+
+ reflevels_t& rls = vars.AT(vi);
+ int const reflevels = int(rls.size());
+ maps_t& ms = rls.AT(rl);
+ int const maps = int(ms.size());
+ for (int m=0; m<maps; ++m) {
+ loc.m = m;
+ timelevels_t& tls = ms.AT(m);
+ int const tl = 0;
+ loc.tl = tl;
+ gridpoint_t& gp = tls.AT(tl);
+
+ // Restricting requires a valid interior (otherwise we
+ // cannot be sure that all of the interior is valid
+ // afterwards)
+ if (not gp.interior()) {
+ gp.report_error
+ (NULL, vi, rl, m, tl, "restricting", "interior");
+ }
+
+ // Restricting requires valid data on the current time
+ // level of the same map of the next finer refinement
+ // level
+ if (rl < reflevels-1) {
+ int const frl = rl+1;
+ maps_t const& fms = rls.AT(frl);
+ timelevels_t const& ftls = fms.AT(m);
+ int const ftl = 0;
+ gridpoint_t const& fgp = ftls.AT(ftl);
+ if (not (fgp.interior() and fgp.boundary() and fgp.ghostzones() and
+ fgp.boundary_ghostzones()))
+ {
+ fgp.report_error
+ (NULL, vi, frl, m, ftl, "restricting", "everywhere");
+ }
+ }
+
+ // Restricting fills (part of) the interior, but leaves
+ // ghost zones and boundary zones undefined
+ gp.set_boundary(false, loc);
+ gp.set_ghostzones(false, loc);
+ gp.set_boundary_ghostzones(false, loc);
+ }
+ }
+ }
+ }
+ }
+
+ void all_state_t::output(ostream& os) const
+ {
+ os << "all_state:" << std::endl;
+ os << "vars:" << std::endl;
+ os << vars << std::endl;
+ os << "old_vars:" << std::endl;
+ os << old_vars << std::endl;
+ }
+
+ template ostream& output (ostream& os, const vector<all_state_t::timelevels_t>& v);
+ template ostream& output (ostream& os, const vector<all_state_t::maps_t>& v);
+ template ostream& output (ostream& os, const vector<all_state_t::reflevels_t>& v);
+ template ostream& output (ostream& os, const vector<all_state_t::variables_t>& v);
+
+ void all_state_t::invalidate(vector<int> const& vars1,
+ int const reflevel, int const map,
+ int const timelevel)
+ {
+ // Loop over all variables
+ for (vector<int>::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();
+ }
+ }
+
+}
diff --git a/Carpet/Requirements/src/all_state.hh b/Carpet/Requirements/src/all_state.hh
new file mode 100644
index 000000000..ae890fd86
--- /dev/null
+++ b/Carpet/Requirements/src/all_state.hh
@@ -0,0 +1,64 @@
+#ifndef ALL_STATE_HH
+#define ALL_STATE_HH
+
+#include <iostream>
+#include <vector>
+
+#include <cctk.h>
+#include <cctki_Schedule.h>
+
+#include <Requirements.hh>
+
+#include <gridpoint.hh>
+
+using namespace std;
+
+namespace Requirements {
+
+ // Keep track of which time levels contain good data; modify this
+ // while time level cycling; routines should specify how many time
+ // levels they require/provide
+
+ // The state (valid/invalid) of parts of the grid for all
+ // timelevels, maps, refinement levels and variables
+ class all_state_t {
+ typedef vector<gridpoint_t> timelevels_t;
+ typedef vector<timelevels_t> maps_t;
+ typedef vector<maps_t> reflevels_t;
+ typedef vector<reflevels_t> variables_t;
+ variables_t vars;
+ variables_t old_vars; // for regridding
+ public:
+ void setup(int maps);
+ void change_storage(vector<int> const& groups,
+ vector<int> const& timelevels,
+ int reflevel);
+ void regrid(int reflevels);
+ void recompose(int reflevel, valid::valid_t where);
+ void regrid_free();
+ void cycle(int reflevel);
+ void before_routine(cFunctionData const* function_data,
+ int reflevel, int map,
+ int timelevel, int timelevel_offset) const;
+ void after_routine(cFunctionData const* function_data,
+ CCTK_INT cctk_iteration,
+ int reflevel, int map,
+ int timelevel, int timelevel_offset);
+ void sync(cFunctionData const* function_data, CCTK_INT cctk_iteration,
+ vector<int> const& groups, int reflevel, int timelevel);
+ void restrict1(vector<int> const& groups, CCTK_INT cctk_iteration, int reflevel);
+ void invalidate(vector<int> const& vars,
+ int reflevel, int map, int timelevel);
+
+ // Input/Output helpers
+ void input (istream& is);
+ void output (ostream& os) const;
+ };
+
+ inline ostream& operator<< (ostream& os, const all_state_t& a) {
+ a.output(os);
+ return os;
+ }
+}
+
+#endif
diff --git a/Carpet/Requirements/src/make.code.defn b/Carpet/Requirements/src/make.code.defn
index 6a43416b3..2febb0a52 100644
--- a/Carpet/Requirements/src/make.code.defn
+++ b/Carpet/Requirements/src/make.code.defn
@@ -1,7 +1,7 @@
# Main make.code.defn file for thorn Requirements -*-Makefile-*-
# Source files in this directory
-SRCS = Requirements.cc clause.cc clauses.cc util.cc all_clauses.cc location.cc gridpoint.cc
+SRCS = Requirements.cc clause.cc clauses.cc util.cc all_clauses.cc location.cc gridpoint.cc all_state.cc
# Subdirectories containing source files
SUBDIRS =