diff options
Diffstat (limited to 'Carpet')
-rw-r--r-- | Carpet/Carpet/src/Initialise.cc | 2 | ||||
-rw-r--r-- | Carpet/Carpet/src/Requirements.cc | 314 | ||||
-rw-r--r-- | Carpet/Carpet/src/carpet.hh | 5 | ||||
-rw-r--r-- | Carpet/Carpet/src/make.code.defn | 1 |
4 files changed, 322 insertions, 0 deletions
diff --git a/Carpet/Carpet/src/Initialise.cc b/Carpet/Carpet/src/Initialise.cc index 0afecaa5b..8d7cffff5 100644 --- a/Carpet/Carpet/src/Initialise.cc +++ b/Carpet/Carpet/src/Initialise.cc @@ -158,6 +158,8 @@ namespace Carpet { ScheduleTraverse (where, "CCTK_PARAMCHECK", cctkGH); } END_MGLEVEL_LOOP; + Requirements::CheckRequirements (cctkGH); + CCTKi_FinaliseParamWarn(); timer.stop(); diff --git a/Carpet/Carpet/src/Requirements.cc b/Carpet/Carpet/src/Requirements.cc new file mode 100644 index 000000000..3b53dd313 --- /dev/null +++ b/Carpet/Carpet/src/Requirements.cc @@ -0,0 +1,314 @@ +#include <algorithm> +#include <set> +#include <string> + +#include <cctk.h> +#include <cctk_Schedule.h> + +#include <cctki_GHExtensions.h> +#include <cctki_Schedule.h> + +#include "carpet.hh" + +using namespace std; + + + +// Illegally copied from ScheduleInterface.c: + +typedef enum {sched_none, sched_group, sched_function} iSchedType; +typedef enum {schedpoint_misc, schedpoint_analysis} iSchedPoint; + +typedef struct +{ + /* Static data */ + char *description; + + /*char *thorn; MOVED TO FunctionData */ + char *implementation; + + iSchedType type; + + cFunctionData FunctionData; + + int n_mem_groups; + int *mem_groups; + int *timelevels; + + int n_comm_groups; + int *comm_groups; + + /* Timer data */ + + int timer_handle; + + /* Dynamic data */ + int *CommOnEntry; + int *StorageOnEntry; + + int done_entry; + int synchronised; + +} t_attribute; + + + +namespace Carpet { + namespace Requirements { + + + + // Rules: + // + // 1. Everything that is required by a routine must be provided by + // another routine which is scheduled earlier. + // + // 2. Things can be provided only once, not multiple times. + // Except when they are also provided. + + + + int CheckEntry (void * attribute, void * data); + int CheckExit (void * attribute, void * data); + int CheckWhile (int n_whiles, char ** whiles, void * attribute, void * data, int first); + int CheckIf (int n_ifs, char ** ifs, void * attribute, void * data); + int CheckCall (void * function, void * attribute, void * data); + + void CheckOneGroup (cGH const * cctkGH, char const * where); + + + + int + CheckEntry (void * const attribute, + void * const data) + { + if (not attribute) { + // Nothing to check + return 1; + } + + // Convert argument types + cFunctionData & function_data = + (static_cast <t_attribute *> (attribute))->FunctionData; + set <string> & active_provisions = * static_cast <set <string> *> (data); + + // Gather all required items + set <string> requires; +#ifdef CACTUS_HAS_REQUIRES_CLAUSES + for (int n = 0; n < function_data.n_RequiresClauses; ++ n) { + requires.insert (string (function_data.RequiresClauses[n])); + } +#endif + + // Check whether all required items have already been provided + set <string> required_but_not_provided; + set_difference + (requires.begin(), requires.end(), + active_provisions.begin(), active_provisions.end(), + insert_iterator <set <string> > + (required_but_not_provided, required_but_not_provided.begin())); + + // Are there unmet requirements? + if (not required_but_not_provided.empty()) { + for (set<string>::const_iterator ri = required_but_not_provided.begin(); + ri != required_but_not_provided.end(); ++ ri) + { + string const req = * ri; + CCTK_VParamWarn (CCTK_THORNSTRING, + "Requirement inconsistency:\n" + " Group %s, function %s::%s requires \"%s\" which has not been provided", + function_data.where, + function_data.thorn, function_data.routine, + req.c_str()); + } + } + + // Do traverse this schedule item + return 1; + } + + + + int + CheckExit (void * const attribute, + void * const data) + { + if (not attribute) { + // Nothing to check + return 1; + } + + // Convert argument types + cFunctionData & function_data = + (static_cast <t_attribute *> (attribute))->FunctionData; + set <string> & active_provisions = * static_cast <set <string> *> (data); + + // Gather all required and provided items + set <string> requires; +#ifdef CACTUS_HAS_REQUIRES_CLAUSES + for (int n = 0; n < function_data.n_RequiresClauses; ++ n) { + requires.insert (string (function_data.RequiresClauses[n])); + } +#endif + set <string> provides; +#ifdef CACTUS_HAS_REQUIRES_CLAUSES + for (int n = 0; n < function_data.n_ProvidesClauses; ++ n) { + provides.insert (string (function_data.ProvidesClauses[n])); + } +#endif + + // Check whether any of the providions have already been + // provided. (We disallow this as well, so that a routine + // cannot overwrite what another routine has already set up.) + set <string> provided_twice; + set_intersection + (provides.begin(), provides.end(), + active_provisions.begin(), active_provisions.end(), + insert_iterator <set <string> > + (provided_twice, provided_twice.begin())); + // But we do allow to provide things which are also required + set <string> provided_too_often; + set_difference + (provided_twice.begin(), provided_twice.end(), + requires.begin(), requires.end(), + insert_iterator <set <string> > + (provided_too_often, provided_too_often.begin())); + + // Are there things provided twice? + if (not provided_too_often.empty()) { + for (set<string>::const_iterator pi = provided_too_often.begin(); + pi != provided_too_often.end(); ++ pi) + { + string const prov = * pi; + CCTK_VParamWarn (CCTK_THORNSTRING, + "Requirement inconsistency:\n" + " Group %s, function %s::%s provides (and does not require) \"%s\" which has already been provided", + function_data.where, + function_data.thorn, function_data.routine, + prov.c_str()); + } + } + + // Add the new provisions + for (set<string>::const_iterator pi = + provides.begin(); pi != provides.end(); ++ pi) + { + string const prov = * pi; + active_provisions.insert (prov); + } + + // ??? + return 1; + } + + + + int + CheckWhile (int const n_whiles, char ** const whiles, + void * const attribute, + void * const data, + int const first) + { + // Execute item once + return first; + } + + + + int + CheckIf (int const n_ifs, char ** const ifs, + void * const attribute, + void * const data) + { + // Execute item + return 1; + } + + + + int CheckCall (void * const function, + void * const attribute, + void * const data) + { + // Do nothing + return 0; + } + + + + // Check one schedule bin + void + CheckOneGroup (cGH const * const cctkGH, + char const * const where) + { + CCTK_VInfo (CCTK_THORNSTRING, + "Checking requirements of schedule bin %s", where); + + // Set up initial provision (none at the moment) + set <string> active_provisions; + + // Output initial provisions + CCTK_VInfo (CCTK_THORNSTRING, + " Initial provisions:"); + for (set<string>::const_iterator pi = + active_provisions.begin(); pi != active_provisions.end(); ++ pi) + { + string const prov = * pi; + CCTK_VInfo (CCTK_THORNSTRING, + " %s", prov.c_str()); + } + + // Check the schedule bin + CCTKi_DoScheduleTraverse (where, + CheckEntry, CheckExit, + CheckWhile, CheckIf, + CheckCall, + & active_provisions); + + // Output the final provisions + CCTK_VInfo (CCTK_THORNSTRING, + " Final provisions:"); + for (set<string>::const_iterator pi = + active_provisions.begin(); pi != active_provisions.end(); ++ pi) + { + string const prov = * pi; + CCTK_VInfo (CCTK_THORNSTRING, + " %s", prov.c_str()); + } + } + + + + // Check everything + void + CheckRequirements (cGH const * const cctkGH) + { + Checkpoint ("Checking schedule requirements"); + + // Check some bins + CheckOneGroup (cctkGH, "CCTK_WRAGH"); + CheckOneGroup (cctkGH, "CCTK_BASEGRID"); + + CheckOneGroup (cctkGH, "CCTK_RECOVER_VARIABLES"); + CheckOneGroup (cctkGH, "CCTK_POST_RECOVER_VARIABLES"); + + CheckOneGroup (cctkGH, "CCTK_PREREGRIDINITIAL"); + CheckOneGroup (cctkGH, "CCTK_POSTREGRIDINITIAL"); + CheckOneGroup (cctkGH, "CCTK_INITIAL"); + CheckOneGroup (cctkGH, "CCTK_POSTRESTRICTINITIAL"); + CheckOneGroup (cctkGH, "CCTK_POSTINITIAL"); + CheckOneGroup (cctkGH, "CCTK_CPINITIAL"); + + CheckOneGroup (cctkGH, "CCTK_PREREGRID"); + CheckOneGroup (cctkGH, "CCTK_POSTREGRID"); + CheckOneGroup (cctkGH, "CCTK_PRESTEP"); + CheckOneGroup (cctkGH, "CCTK_EVOL"); + CheckOneGroup (cctkGH, "CCTK_POSTSTEP"); + CheckOneGroup (cctkGH, "CCTK_CHECKPOINT"); + CheckOneGroup (cctkGH, "CCTK_ANALYSIS"); + + CheckOneGroup (cctkGH, "CCTK_TERMINATE"); + } + + }; // namespace Carpet +}; // namespace Requirements diff --git a/Carpet/Carpet/src/carpet.hh b/Carpet/Carpet/src/carpet.hh index 16dca4228..9e53cfe5c 100644 --- a/Carpet/Carpet/src/carpet.hh +++ b/Carpet/Carpet/src/carpet.hh @@ -64,6 +64,11 @@ namespace Carpet { void CallBeforeRoutines (cGH const * restrict cctkGH); void CallAfterRoutines (cGH const * restrict cctkGH); + // Requirements + namespace Requirements { + void CheckRequirements (cGH const * cctkGH); + } + // Debugging output void Output (const char* fmt, ...); void Waypoint (const char* fmt, ...); diff --git a/Carpet/Carpet/src/make.code.defn b/Carpet/Carpet/src/make.code.defn index 1f70291cd..08caa1eff 100644 --- a/Carpet/Carpet/src/make.code.defn +++ b/Carpet/Carpet/src/make.code.defn @@ -15,6 +15,7 @@ SRCS = AllGatherString.cc \ MultiModel.cc \ Poison.cc \ Recompose.cc \ + Requirements.cc \ Restrict.cc \ ScheduleWrapper.cc \ SetupGH.cc \ |