15#include "observers/CreateGrid.h"
16#include "observers/CreateGridAndConvergeLoadBalancing.h"
17#include "observers/CreateGridButPostponeRefinement.h"
18#include "observers/InitGrid.h"
19#include "observers/PlotSolution.h"
20#include "observers/TimeStep.h"
23#include "repositories/DataRepository.h"
24#include "repositories/SolverRepository.h"
25#include "repositories/StepRepository.h"
43#if defined(USE_ADDITIONAL_MESH_TRAVERSAL)
44 #include "observers/AdditionalMeshTraversal.h"
68 static bool gridConstructed =
false;
69 static bool gridInitialised =
false;
70 static bool gridBalanced =
false;
71 static double nextMaxPlotTimeStamp = FirstPlotTimeStamp;
72 static double nextMinPlotTimeStamp = FirstPlotTimeStamp;
73 static bool haveJustWrittenSnapshot =
false;
74 static bool haveReceivedNoncriticialAssertion =
false;
75 static bool addGridSweepWithoutGridRefinementNext =
false;
77 std::numeric_limits<double>::max()
79 static int globalNumberOfTrees = 0;
80 bool continueToSolve =
true;
84 repositories::StepRepository::toProgramStep(repositories::StepRepository::Steps::PlotSolution)
86 haveReceivedNoncriticialAssertion =
true;
88 "selectNextAlgorithmicStep()",
"non-critical assertion has been triggered in code. Dump final state and terminate"
91 continueToSolve =
false;
92 }
else if (gridConstructed and not gridBalanced) {
93 if (not repositories::loadBalancer.isEnabled(
true) and not repositories::loadBalancer.hasSplitRecently()) {
94 logInfo(
"selectNextAlgorithmicStep()",
"all ranks have switched off their load balancing");
98 "selectNextAlgorithmicStep()",
"wait for load balancing to become stable: " << repositories::loadBalancer
103 repositories::StepRepository::Steps::CreateGridAndConvergeLoadBalancing
105 }
else if (gridBalanced and not gridInitialised) {
107 repositories::StepRepository::toProgramStep(repositories::StepRepository::Steps::InitGrid)
110 gridInitialised =
true;
111 }
else if (not gridConstructed) {
115 "selectNextAlgorithmicStep()",
"mesh has refined, so reset minH=" << minH <<
" and postpone further refinement"
117 addGridSweepWithoutGridRefinementNext =
true;
118 }
else if (repositories::loadBalancer.getGlobalNumberOfTrees() > globalNumberOfTrees) {
119 logInfo(
"selectNextAlgorithmicStep()",
"mesh has rebalanced recently, so postpone further refinement)");
120 addGridSweepWithoutGridRefinementNext =
true;
121 globalNumberOfTrees = repositories::loadBalancer.getGlobalNumberOfTrees();
131 "selectNextAlgorithmicStep()",
"grid has been stationary for quite some time. Terminate grid construction"
133 addGridSweepWithoutGridRefinementNext =
false;
134 gridConstructed =
true;
137 "selectNextAlgorithmicStep()",
138 "mesh rebalancing seems to be stationary, so study whether to refine mesh further in next sweep: "
141 addGridSweepWithoutGridRefinementNext =
false;
142 globalNumberOfTrees = repositories::loadBalancer.getGlobalNumberOfTrees();
146 if (addGridSweepWithoutGridRefinementNext) {
148 repositories::StepRepository::Steps::CreateGridButPostponeRefinement
152 repositories::StepRepository::toProgramStep(repositories::StepRepository::Steps::CreateGrid)
156 continueToSolve =
true;
159 #if defined(USE_ADDITIONAL_MESH_TRAVERSAL)
161 repositories::isLastGridSweepOfTimeStep()
166 repositories::StepRepository::toProgramStep( repositories::StepRepository::Steps::AdditionalMeshTraversal )
168 continueToSolve =
true;
172 if (TimeInBetweenPlots > 0.0 and repositories::getMinTimeStamp() < MinTerminalTime and repositories::getMaxTimeStamp() < MaxTerminalTime and (repositories::getMinTimeStamp() >= nextMinPlotTimeStamp or repositories::getMaxTimeStamp() >= nextMaxPlotTimeStamp) and repositories::mayPlot()) {
173 if (repositories::getMinTimeStamp() >= nextMinPlotTimeStamp) {
174 nextMinPlotTimeStamp += TimeInBetweenPlots;
176 if (repositories::getMaxTimeStamp() >= nextMaxPlotTimeStamp) {
177 nextMaxPlotTimeStamp += TimeInBetweenPlots;
180 if (nextMinPlotTimeStamp < repositories::getMinTimeStamp()) {
182 "selectNextAlgorithmicStep()",
183 "code is asked to plot every dt="
184 << TimeInBetweenPlots <<
", but this seems to be less than the time step size of the solvers. "
185 <<
"So postpone next plot to t=" << (repositories::getMinTimeStamp() + TimeInBetweenPlots)
187 nextMinPlotTimeStamp = repositories::getMinTimeStamp() + TimeInBetweenPlots;
188 }
else if (nextMaxPlotTimeStamp < repositories::getMaxTimeStamp()) {
190 "selectNextAlgorithmicStep()",
191 "code is asked to plot every dt="
192 << TimeInBetweenPlots <<
", but this seems to be less than the time step size of the solvers. "
193 <<
"So postpone next plot to t=" << (repositories::getMaxTimeStamp() + TimeInBetweenPlots)
195 nextMaxPlotTimeStamp = repositories::getMaxTimeStamp() + TimeInBetweenPlots;
198 nextMaxPlotTimeStamp = std::max(nextMaxPlotTimeStamp, nextMinPlotTimeStamp);
201 repositories::StepRepository::toProgramStep(repositories::StepRepository::Steps::PlotSolution)
203 haveJustWrittenSnapshot =
true;
204 continueToSolve =
true;
205 }
else if (repositories::getMinTimeStamp() < MinTerminalTime and repositories::getMaxTimeStamp() < MaxTerminalTime) {
207 repositories::StepRepository::toProgramStep(repositories::StepRepository::Steps::TimeStep)
209 continueToSolve =
true;
210 haveJustWrittenSnapshot =
false;
212 if (not haveJustWrittenSnapshot and TimeInBetweenPlots > 0.0 and repositories::mayPlot()) {
214 repositories::StepRepository::toProgramStep(repositories::StepRepository::Steps::PlotSolution)
216 continueToSolve =
true;
217 haveJustWrittenSnapshot =
true;
218 nextMinPlotTimeStamp = std::numeric_limits<double>::max();
219 nextMaxPlotTimeStamp = std::numeric_limits<double>::max();
220 }
else if (not haveJustWrittenSnapshot and TimeInBetweenPlots > 0.0 and not repositories::mayPlot()) {
221 continueToSolve =
true;
223 continueToSolve =
false;
228 return continueToSolve;
234 auto stepName = repositories::StepRepository::toStepEnum(stepIdentifier);
241 logInfo(
"step()",
"run " << repositories::StepRepository::toString(stepName) <<
"\t" << applications::exahype2::ccz4::AbstractCCZ4::toString(repositories::instanceOfCCZ4.getSolverState()));
245 static int creepingNumberOfLocalCells = 0;
248 case repositories::StepRepository::Steps::CreateGridButPostponeRefinement: {
253 repositories::startGridConstructionStep();
258 observers::CreateGridButPostponeRefinement observer;
268 repositories::finishGridConstructionStep();
270 case repositories::StepRepository::Steps::CreateGrid: {
275 repositories::startGridConstructionStep();
280 observers::CreateGrid observer;
290 repositories::finishGridConstructionStep();
297 case repositories::StepRepository::Steps::CreateGridAndConvergeLoadBalancing: {
301 "it seems the grid has just refined before we switched to the phase where we make the load balancing converge. Wait for a few iterations more to give load balancing chance to catch up"
313 logInfo(
"step()",
"rank is degenerated so disable load balancing temporarily");
314 repositories::loadBalancer.enable(
false);
319 repositories::loadBalancer.isEnabled(
false)
323 "grid construction and decomposition on this rank seem to be stable as we have around "
324 << creepingNumberOfLocalCells <<
" local cells in the heaviest tree. Disable load balancing temporarily"
326 repositories::loadBalancer.enable(
false);
329 repositories::startGridConstructionStep();
334 observers::CreateGridButPostponeRefinement observer;
344 repositories::finishGridConstructionStep();
349 not repositories::loadBalancer.hasSplitRecently()
351 repositories::loadBalancer.isEnabled(
false)
355 "have to decrement local cell counter "
356 << creepingNumberOfLocalCells <<
" as maximum weight is "
359 creepingNumberOfLocalCells = (creepingNumberOfLocalCells
364 case repositories::StepRepository::Steps::InitGrid: {
366 repositories::loadBalancer.enable(
false);
370 repositories::startGridInitialisationStep();
375 observers::InitGrid observer;
385 repositories::finishGridInitialisationStep();
387 case repositories::StepRepository::Steps::PlotSolution: {
389 const double minTimeStamp = repositories::getMinTimeStamp();
390 const double maxTimeStamp = repositories::getMaxTimeStamp();
391 const double minTimeStepSize = repositories::getMinTimeStepSize();
392 const double maxTimeStepSize = repositories::getMaxTimeStepSize();
396 repositories::startPlottingStep(minTimeStamp, maxTimeStamp, minTimeStepSize, maxTimeStepSize);
401 observers::PlotSolution observer;
411 repositories::finishPlottingStep();
413 case repositories::StepRepository::Steps::TimeStep: {
415 if (repositories::loadBalancer.isEnabled(
false)) {
416 logInfo(
"step()",
"disable load balancing throughout initialisation (to be removed in later releases)");
417 repositories::loadBalancer.enable(
false);
420 const double minTimeStamp = repositories::getMinTimeStamp();
421 const double maxTimeStamp = repositories::getMaxTimeStamp();
422 const double minTimeStepSize = repositories::getMinTimeStepSize();
423 const double maxTimeStepSize = repositories::getMaxTimeStepSize();
424 const double minMeshSize = repositories::getMinMeshSize();
425 const double maxMeshSize = repositories::getMaxMeshSize();
429 repositories::startTimeStep(minTimeStamp, maxTimeStamp, minTimeStepSize, maxTimeStepSize);
434 observers::TimeStep observer;
444 repositories::finishTimeStep();
447 #if defined(USE_ADDITIONAL_MESH_TRAVERSAL)
448 case repositories::StepRepository::Steps::AdditionalMeshTraversal:
452 repositories::suspendSolversForOneGridSweep();
453 observers::AdditionalMeshTraversal observer;
459 case repositories::StepRepository::Steps::Undef:
465int main(
int argc,
char** argv) {
466 const int ExitCodeSuccess = 0;
467 const int ExitCodeUnitTestsFailed = 1;
468 const int ExitCodeInvalidArguments = 2;
469 const int ExitCodeInvalidBuild = 3;
476 repositories::initLogFilters();
484 repositories::initSharedMemoryAndGPUEnvironment();
487 logError(
"main()",
"MPI runs without multithreading are not supported currently.");
488 return ExitCodeInvalidBuild;
491 repositories::DataRepository::initDatatypes();
501 logError(
"main()",
"unit tests failed. Quit.");
507 repositories::startSimulation();
513#if defined(SharedOMP)
520#if defined(UseSmartMPI)
528 if (isGlobalMaster) {
538 logInfo(
"main()",
"terminated successfully");
557 }
else if (isPeanoComputeNode) {
562#if defined(UseSmartMPI)
564 while (smartmpi::continueToRun()) {
570#if defined(SharedOMP)
579 repositories::finishSimulation();
582 repositories::DataRepository::shutdownDatatypes();
587 return ExitCodeSuccess;
#define logError(methodName, logMacroMessageStream)
Wrapper macro around tarch::tarch::logging::Log to improve logging.
#define logDebug(methodName, logMacroMessageStream)
#define logWarning(methodName, logMacroMessageStream)
Wrapper macro around tarch::tarch::logging::Log to improve logging.
#define logInfo(methodName, logMacroMessageStream)
Wrapper macro around tarch::tarch::logging::Log to improve logging.
tarch::timing::Measurement gridConstructionMeasurement
tarch::logging::Log _log("::")
tarch::timing::Measurement timeStepMeasurement
bool selectNextAlgorithmicStep()
Decide which step to run next.
tarch::timing::Measurement plotMeasurement
tarch::timing::Measurement timePerMeshSwepMeasurement
int getCurrentProgramStep() const
void setNextProgramStep(int number)
The user tells the set which program step to use, i.e.
static Node & getInstance()
This operation returns the singleton instance.
peano4::grid::GridStatistics getGridStatistics() const
Return statistics object for primary spacetree.
static SpacetreeSet & getInstance()
void traverse(peano4::grid::TraversalObserver &observer)
Invoke traverse on all spacetrees in parallel.
void switchProgramPhase(const std::string &activeProgramPhase)
static LogFilter & getInstance()
void writeToCSV(std::string filename="statistics")
Write data to csv file.
static Statistics & getInstance()
This is not the canonical realisation of singletons as I use it usually for stats in Peano.
bool isGlobalMaster() const
Is this node the global master process, i.e.
static Rank & getInstance()
This operation returns the singleton instance.
static void abort(int errorCode)
A proper abort in an MPI context has to use MPI_Abort.
static Core & getInstance()
int getNumberOfThreads() const
Returns the number of threads that is used.
int getNumberOfErrors() const
void addTestCase(const std::string &fullQualifiedPath, TestCase *testCase)
Adds a new test case.
virtual void run()
Runs all test cases assigned.
double getAccumulatedValue() const
std::string toString() const
void setValue(const double &value)
Set the value.
A simple class that has to be included to measure the clock ticks required for an operation.
double getCalendarTime()
This method returns the elapsed calendar time between the start and stop command of the timer,...
void start()
(Re)Start the Timer
std::string toString(Filter filter)
tarch::tests::TestCase * getUnitTests()
Please destroy after usage.
static const char * create_grid
static const char * timestep
static const char * create_grid_converge
static const char * create_grid_no_refine
tarch::tests::TestCase * getUnitTests()
Please destroy after usage.
void shutdownSingletons()
The very first thing I have to do is to shut down Node.
void fillLookupTables()
Fill Lookup Tables.
int initParallelEnvironment(int *argc, char ***argv)
Init Parallel Environment.
void initSingletons(const tarch::la::Vector< Dimensions, double > &offset, const tarch::la::Vector< Dimensions, double > &width, const std::bitset< Dimensions > &periodicBC=0)
Fire up all the singletons.
void shutdownParallelEnvironment()
Shutdown all the parallel environment, i.e.
double max(double a, double b, double c)
I need the maximum of three values all the time, to I decided to write a function for this.
void initSmartMPI()
Switch on SmartMPI.
tarch::tests::TestCase * getUnitTests()
Please destroy after usage.
bool hasNonCriticalAssertionBeenViolated()
void shutdownNonCriticalAssertionEnvironment()
peano4::shutdownParallelEnvironment().
void initNonCriticalAssertionEnvironment()
Register the assertion tag from the global communicator.
#define OTTER_TASK_WAIT_IMPLICIT(...)
#define OTTER_TASK_END(...)
#define OTTER_INITIALISE()
#define OTTER_PHASE_SWITCH(...)
#define OTTER_TASK_START(...)
#define OTTER_DEFINE_TASK(...)
tarch::la::Vector< Dimensions, double > getMinH() const