Peano
ccz4-main.cpp
Go to the documentation of this file.
1 // **********************************************************************************************
2 // This file is modifed from the original version generated by exahype2.
3 // You are free to change the content here, but do not delete it or the
4 // auto-generated main file will disable the additional step and causing compiling errors.
5 // in some circumstance.
6 // **********************************************************************************************
7 
8 #include <iomanip>
9 
10 #include "Constants.h"
11 #include "ccz4-main.h"
12 #include "exahype2/UnitTests.h"
13 #include "exahype2/UserInterface.h"
14 #include "observers/CreateGrid.h"
15 #include "observers/CreateGridAndConvergeLoadBalancing.h"
16 #include "observers/CreateGridButPostponeRefinement.h"
17 #include "observers/InitGrid.h"
18 #include "observers/PlotSolution.h"
19 #include "observers/CheckpointSolution.h"
20 #include "observers/TimeStep.h"
21 #include "peano4/peano4.h"
22 #include "peano4/UnitTests.h"
23 #include "repositories/DataRepository.h"
24 #include "repositories/SolverRepository.h"
25 #include "repositories/StepRepository.h"
26 #include "tarch/UnitTests.h"
27 #include "peano4/grid/Spacetree.h"
28 #include "peano4/parallel/SpacetreeSet.h"
29 #include "tarch/logging/Log.h"
30 #include "tarch/logging/LogFilter.h"
31 #include "tarch/logging/Statistics.h"
32 #include "tarch/multicore/Core.h"
33 #include "tarch/multicore/multicore.h"
34 #include "tarch/NonCriticalAssertions.h"
35 #include "tarch/tests/TreeTestCaseCollection.h"
36 #include "tarch/timing/Measurement.h"
37 #include "tarch/timing/Watch.h"
38 #include "toolbox/blockstructured/UnitTests.h"
39 #include "toolbox/loadbalancing/loadbalancing.h"
40 
42 #if defined(USE_ADDITIONAL_MESH_TRAVERSAL)
43  #include "observers/AdditionalMeshTraversal.h"
44 #endif
46 
47 using namespace applications::exahype2::ccz4;
48 
49 tarch::logging::Log _log("::");
50 
51 
52 tarch::timing::Measurement timePerMeshSweepMeasurement;
53 tarch::timing::Measurement gridConstructionMeasurement;
54 tarch::timing::Measurement timeStepMeasurement;
55 tarch::timing::Measurement plotMeasurement;
56 
57 
67  static bool gridConstructed = false;
68  static bool gridInitialised = false;
69  static bool gridBalanced = false;
70  static double nextMaxPlotTimeStamp = FirstPlotTimeStamp;
71  static double nextMinPlotTimeStamp = FirstPlotTimeStamp;
72  static double nextMaxCheckpointTimeStamp = FirstCheckpointTimeStamp;
73  static double nextMinCheckpointTimeStamp = FirstCheckpointTimeStamp;
74  static bool haveJustWrittenSnapshot = false;
75  static bool haveReceivedNoncriticialAssertion = false;
76  static bool addGridSweepWithoutGridRefinementNext = false;
77  static tarch::la::Vector<DIMENSIONS, double> minH = tarch::la::Vector<DIMENSIONS, double>(
78  std::numeric_limits<double>::max()
79  );
80  static int globalNumberOfTrees = 0;
81  bool continueToSolve = true;
82 
83  if (tarch::hasNonCriticalAssertionBeenViolated() and not haveReceivedNoncriticialAssertion) {
84  peano4::parallel::Node::getInstance().setNextProgramStep(
85  repositories::StepRepository::toProgramStep(repositories::StepRepository::Steps::PlotSolution)
86  );
87  haveReceivedNoncriticialAssertion = true;
88  logError(
89  "selectNextAlgorithmicStep()", "non-critical assertion has been triggered in code. Dump final state and terminate"
90  );
91  } else if (tarch::hasNonCriticalAssertionBeenViolated()) {
92  continueToSolve = false;
93  } else if (gridConstructed and not gridBalanced) {
94  if (not repositories::loadBalancer.isEnabled(true) and not repositories::loadBalancer.hasSplitRecently()) {
95  logInfo("selectNextAlgorithmicStep()", "all ranks have switched off their load balancing");
96  gridBalanced = true;
97  } else {
98  logInfo(
99  "selectNextAlgorithmicStep()", "wait for load balancing to become stable: " << repositories::loadBalancer
100  );
101  }
102 
103  peano4::parallel::Node::getInstance().setNextProgramStep(repositories::StepRepository::toProgramStep(
104  repositories::StepRepository::Steps::CreateGridAndConvergeLoadBalancing
105  ));
106  } else if (gridBalanced and not gridInitialised) {
107  peano4::parallel::Node::getInstance().setNextProgramStep(
108  repositories::StepRepository::toProgramStep(repositories::StepRepository::Steps::InitGrid)
109  );
110 
111  gridInitialised = true;
112  } else if (not gridConstructed) {
113  if (tarch::la::max(peano4::parallel::SpacetreeSet::getInstance().getGridStatistics().getMinH()) < tarch::la::max(minH)) {
114  minH = peano4::parallel::SpacetreeSet::getInstance().getGridStatistics().getMinH();
115  logDebug(
116  "selectNextAlgorithmicStep()", "mesh has refined, so reset minH=" << minH << " and postpone further refinement"
117  );
118  addGridSweepWithoutGridRefinementNext = true;
119  } else if (repositories::loadBalancer.getGlobalNumberOfTrees() > globalNumberOfTrees) {
120  logInfo("selectNextAlgorithmicStep()", "mesh has rebalanced recently, so postpone further refinement)");
121  addGridSweepWithoutGridRefinementNext = true;
122  globalNumberOfTrees = repositories::loadBalancer.getGlobalNumberOfTrees();
123  }
124  else if (
125  peano4::parallel::SpacetreeSet::getInstance().getGridStatistics().getStationarySweeps()>5
126  and
127  // ensure that a proper creation has been ran before, so the mesh had the opportunity
128  // to refine further if it has not done yet
129  repositories::StepRepository::toStepEnum( peano4::parallel::Node::getInstance().getCurrentProgramStep() ) == repositories::StepRepository::Steps::CreateGrid
130  ) {
131  logInfo(
132  "selectNextAlgorithmicStep()", "grid has been stationary for quite some time. Terminate grid construction"
133  );
134  addGridSweepWithoutGridRefinementNext = false;
135  gridConstructed = true;
136  } else {
137  logInfo(
138  "selectNextAlgorithmicStep()",
139  "mesh rebalancing seems to be stationary, so study whether to refine mesh further in next sweep: "
140  << peano4::parallel::SpacetreeSet::getInstance().getGridStatistics().toString()
141  );
142  addGridSweepWithoutGridRefinementNext = false;
143  globalNumberOfTrees = repositories::loadBalancer.getGlobalNumberOfTrees();
144  }
145 
146  // Actual grid traversal choice
147  if (addGridSweepWithoutGridRefinementNext) {
148  peano4::parallel::Node::getInstance().setNextProgramStep(repositories::StepRepository::toProgramStep(
149  repositories::StepRepository::Steps::CreateGridButPostponeRefinement
150  ));
151  } else {
152  peano4::parallel::Node::getInstance().setNextProgramStep(
153  repositories::StepRepository::toProgramStep(repositories::StepRepository::Steps::CreateGrid)
154  );
155  }
156 
157  continueToSolve = true;
158  } else {
159  if (TimeInBetweenPlots > 0.0 and repositories::getMinTimeStamp() < MinTerminalTime and repositories::getMaxTimeStamp() < MaxTerminalTime and (repositories::getMinTimeStamp() >= nextMinPlotTimeStamp or repositories::getMaxTimeStamp() >= nextMaxPlotTimeStamp) and repositories::mayPlot()) {
160  if (repositories::getMinTimeStamp() >= nextMinPlotTimeStamp) {
161  nextMinPlotTimeStamp += TimeInBetweenPlots;
162  }
163  if (repositories::getMaxTimeStamp() >= nextMaxPlotTimeStamp) {
164  nextMaxPlotTimeStamp += TimeInBetweenPlots;
165  }
166 
167  if (nextMinPlotTimeStamp < repositories::getMinTimeStamp()) {
168  logWarning(
169  "selectNextAlgorithmicStep()",
170  "code is asked to plot every dt="
171  << TimeInBetweenPlots << ", but this seems to be less than the time step size of the solvers. "
172  << "So postpone next plot to t=" << (repositories::getMinTimeStamp() + TimeInBetweenPlots)
173  );
174  nextMinPlotTimeStamp = repositories::getMinTimeStamp() + TimeInBetweenPlots;
175  } else if (nextMaxPlotTimeStamp < repositories::getMaxTimeStamp()) {
176  logWarning(
177  "selectNextAlgorithmicStep()",
178  "code is asked to plot every dt="
179  << TimeInBetweenPlots << ", but this seems to be less than the time step size of the solvers. "
180  << "So postpone next plot to t=" << (repositories::getMaxTimeStamp() + TimeInBetweenPlots)
181  );
182  nextMaxPlotTimeStamp = repositories::getMaxTimeStamp() + TimeInBetweenPlots;
183  }
184 
185  nextMaxPlotTimeStamp = std::max(nextMaxPlotTimeStamp, nextMinPlotTimeStamp);
186 
187  peano4::parallel::Node::getInstance().setNextProgramStep(
188  repositories::StepRepository::toProgramStep(repositories::StepRepository::Steps::PlotSolution)
189  );
190  haveJustWrittenSnapshot = true;
191  continueToSolve = true;
192  } else if (TimeInBetweenCheckpoints > 0.0 and repositories::getMinTimeStamp() < MinTerminalTime and repositories::getMaxTimeStamp() < MaxTerminalTime and (repositories::getMinTimeStamp() >= nextMinCheckpointTimeStamp or repositories::getMaxTimeStamp() >= nextMaxCheckpointTimeStamp) and repositories::mayPlot()) {
193  if (repositories::getMinTimeStamp() >= nextMinCheckpointTimeStamp) {
194  nextMinCheckpointTimeStamp += TimeInBetweenCheckpoints;
195  }
196  if (repositories::getMaxTimeStamp() >= nextMaxCheckpointTimeStamp) {
197  nextMaxCheckpointTimeStamp += TimeInBetweenCheckpoints;
198  }
199 
200  if (nextMinCheckpointTimeStamp < repositories::getMinTimeStamp()) {
201  logWarning(
202  "selectNextAlgorithmicStep()",
203  "code is asked to Checkpoint every dt="
204  << TimeInBetweenCheckpoints << ", but this seems to be less than the time step size of the solvers. "
205  << "So postpone next Checkpoint to t=" << (repositories::getMinTimeStamp() + TimeInBetweenCheckpoints)
206  );
207  nextMinCheckpointTimeStamp = repositories::getMinTimeStamp() + TimeInBetweenCheckpoints;
208  } else if (nextMaxCheckpointTimeStamp < repositories::getMaxTimeStamp()) {
209  logWarning(
210  "selectNextAlgorithmicStep()",
211  "code is asked to Checkpoint every dt="
212  << TimeInBetweenCheckpoints << ", but this seems to be less than the time step size of the solvers. "
213  << "So postpone next Checkpoint to t=" << (repositories::getMaxTimeStamp() + TimeInBetweenCheckpoints)
214  );
215  nextMaxCheckpointTimeStamp = repositories::getMaxTimeStamp() + TimeInBetweenCheckpoints;
216  }
217 
218  nextMaxCheckpointTimeStamp = std::max(nextMaxCheckpointTimeStamp, nextMinCheckpointTimeStamp);
219 
220  peano4::parallel::Node::getInstance().setNextProgramStep(
221  repositories::StepRepository::toProgramStep(repositories::StepRepository::Steps::CheckpointSolution)
222  );
223  haveJustWrittenSnapshot = true;
224  continueToSolve = true;
225  } else if (repositories::getMinTimeStamp() < MinTerminalTime and repositories::getMaxTimeStamp() < MaxTerminalTime) {
226  peano4::parallel::Node::getInstance().setNextProgramStep(
227  repositories::StepRepository::toProgramStep(repositories::StepRepository::Steps::TimeStep)
228  );
229  continueToSolve = true;
230  haveJustWrittenSnapshot = false;
231  } else {
232  if (not haveJustWrittenSnapshot and TimeInBetweenPlots > 0.0 and repositories::mayPlot()) {
233  peano4::parallel::Node::getInstance().setNextProgramStep(
234  repositories::StepRepository::toProgramStep(repositories::StepRepository::Steps::PlotSolution)
235  );
236  continueToSolve = true; // don't want to terminate immediately
237  haveJustWrittenSnapshot = true;
238  nextMinPlotTimeStamp = std::numeric_limits<double>::max();
239  nextMaxPlotTimeStamp = std::numeric_limits<double>::max();
240  } else if (not haveJustWrittenSnapshot and TimeInBetweenPlots > 0.0 and not repositories::mayPlot()) {
241  continueToSolve = true; // don't want to terminate immediately but to wait for incomplete time steps to complete
242  } else {
243  continueToSolve = false;
244  }
245  }
246  }
247 
248  return continueToSolve;
249 }
250 
251 
252 void step() {
253  int stepIdentifier = peano4::parallel::Node::getInstance().getCurrentProgramStep();
254  auto stepName = repositories::StepRepository::toStepEnum(stepIdentifier);
255 
256  static tarch::logging::Log _log("");
257 #if PEANO_DEBUG > 0
258 #else
259  if (tarch::mpi::Rank::getInstance().isGlobalMaster())
260 #endif
261  logInfo("step()", "Starting AlgorithmicStep [" << repositories::StepRepository::toString(stepName)<<"]" );
262 
263  static tarch::timing::Watch watch("::", "step()", false);
264 
265  static int creepingNumberOfLocalCells = 0;
266 
267  switch (stepName) {
268  case repositories::StepRepository::Steps::CreateGridButPostponeRefinement: {
269  tarch::logging::LogFilter::getInstance().switchProgramPhase("create-grid-but-postpone-refinement");
270 
271  repositories::startGridConstructionStep();
272 
273  observers::CreateGridButPostponeRefinement observer;
274  watch.start();
275  peano4::parallel::SpacetreeSet::getInstance().traverse(observer);
276  watch.stop();
277  gridConstructionMeasurement.setValue(watch.getCalendarTime());
278 
279  repositories::finishGridConstructionStep();
280  } break;
281  case repositories::StepRepository::Steps::CreateGrid: {
282  tarch::logging::LogFilter::getInstance().switchProgramPhase("create-grid");
283 
284  repositories::startGridConstructionStep();
285 
286  observers::CreateGrid observer;
287  watch.start();
288  peano4::parallel::SpacetreeSet::getInstance().traverse(observer);
289  watch.stop();
290  gridConstructionMeasurement.setValue(watch.getCalendarTime());
291 
292  repositories::finishGridConstructionStep();
293 
294  // We always overestimate so give the convergence the opportunity to catch up. The constant
295  // here is a magic one.
296  creepingNumberOfLocalCells = ::toolbox::loadbalancing::getWeightOfHeaviestLocalSpacetree()
297  + tarch::multicore::Core::getInstance().getNumberOfThreads() * 3;
298  } break;
299  case repositories::StepRepository::Steps::CreateGridAndConvergeLoadBalancing: {
300  if (creepingNumberOfLocalCells < ::toolbox::loadbalancing::getWeightOfHeaviestLocalSpacetree() - 1) {
301  logInfo(
302  "step()",
303  "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"
304  );
305  creepingNumberOfLocalCells = ::toolbox::loadbalancing::getWeightOfHeaviestLocalSpacetree()
306  + tarch::multicore::Core::getInstance().getNumberOfThreads() * 3;
307  }
308 
309  tarch::logging::LogFilter::getInstance().switchProgramPhase("create-grid-and-converge-load-balancing");
310 
311  // The smaller here corresponds to the -1 below
312  if (::toolbox::loadbalancing::getWeightOfHeaviestLocalSpacetree() < 0 and repositories::loadBalancer.isEnabled(false)) {
313  logInfo("step()", "rank is degenerated so disable load balancing temporarily");
314  repositories::loadBalancer.enable(false);
315  }
316  if (
317  ::toolbox::loadbalancing::getWeightOfHeaviestLocalSpacetree() >= creepingNumberOfLocalCells
318  and
319  repositories::loadBalancer.isEnabled(false)
320  ) {
321  logInfo(
322  "step()",
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"
325  );
326  repositories::loadBalancer.enable(false);
327  }
328 
329  repositories::startGridConstructionStep();
330 
331  observers::CreateGridButPostponeRefinement observer;
332  watch.start();
333  peano4::parallel::SpacetreeSet::getInstance().traverse(observer);
334  watch.stop();
335  gridConstructionMeasurement.setValue(watch.getCalendarTime());
336 
337  repositories::finishGridConstructionStep();
338 
339  if (
340  ::toolbox::loadbalancing::getWeightOfHeaviestLocalSpacetree() <= creepingNumberOfLocalCells
341  and
342  not repositories::loadBalancer.hasSplitRecently()
343  and
344  repositories::loadBalancer.isEnabled(false)
345  ) {
346  logInfo(
347  "step()",
348  "have to decrement local cell counter "
349  << creepingNumberOfLocalCells << " as maximum weight is "
350  << ::toolbox::loadbalancing::getWeightOfHeaviestLocalSpacetree()
351  );
352  creepingNumberOfLocalCells = (creepingNumberOfLocalCells
353  + ::toolbox::loadbalancing::getWeightOfHeaviestLocalSpacetree())
354  / 2;
355  }
356  } break;
357  case repositories::StepRepository::Steps::InitGrid: {
358  tarch::logging::LogFilter::getInstance().switchProgramPhase("init-grid");
359  repositories::loadBalancer.enable(false);
360 
361  repositories::startGridInitialisationStep();
362 
363  observers::InitGrid observer;
364  observers::InitGrid::prepareTraversal();
365  watch.start();
366  peano4::parallel::SpacetreeSet::getInstance().traverse(observer);
367  watch.stop();
368  observers::InitGrid::unprepareTraversal();
369  gridConstructionMeasurement.setValue(watch.getCalendarTime());
370 
371  repositories::finishGridInitialisationStep();
372  } break;
373  case repositories::StepRepository::Steps::PlotSolution: {
374  tarch::logging::LogFilter::getInstance().switchProgramPhase("plot-solution");
375  const double minTimeStamp = repositories::getMinTimeStamp();
376  const double maxTimeStamp = repositories::getMaxTimeStamp();
377  const double minTimeStepSize = repositories::getMinTimeStepSize();
378  const double maxTimeStepSize = repositories::getMaxTimeStepSize();
379 
380  repositories::startPlottingStep(minTimeStamp, maxTimeStamp, minTimeStepSize, maxTimeStepSize);
381 
382  observers::PlotSolution observer;
383  observers::PlotSolution::prepareTraversal();
384  watch.start();
385  peano4::parallel::SpacetreeSet::getInstance().traverse(observer);
386  watch.stop();
387  observers::PlotSolution::unprepareTraversal();
388  plotMeasurement.setValue(watch.getCalendarTime());
389 
390  repositories::finishPlottingStep();
391  } break;
392  case repositories::StepRepository::Steps::CheckpointSolution: {
393  tarch::logging::LogFilter::getInstance().switchProgramPhase("Checkpoint-solution");
394  const double minTimeStamp = repositories::getMinTimeStamp();
395  const double maxTimeStamp = repositories::getMaxTimeStamp();
396  const double minTimeStepSize = repositories::getMinTimeStepSize();
397  const double maxTimeStepSize = repositories::getMaxTimeStepSize();
398 
399  repositories::startPlottingStep(minTimeStamp, maxTimeStamp, minTimeStepSize, maxTimeStepSize);
400 
401  observers::CheckpointSolution observer;
402  observers::CheckpointSolution::prepareTraversal();
403  watch.start();
404  peano4::parallel::SpacetreeSet::getInstance().traverse(observer);
405  watch.stop();
406  observers::CheckpointSolution::unprepareTraversal();
407  plotMeasurement.setValue(watch.getCalendarTime());
408 
409  repositories::finishPlottingStep();
410  } break;
411  case repositories::StepRepository::Steps::TimeStep: {
412  tarch::logging::LogFilter::getInstance().switchProgramPhase("time-step");
413  if (repositories::loadBalancer.isEnabled(false)) {
414  logInfo("step()", "disable load balancing throughout initialisation (to be removed in later releases)");
415  repositories::loadBalancer.enable(false);
416  }
417 
418  const double minTimeStamp = repositories::getMinTimeStamp();
419  const double maxTimeStamp = repositories::getMaxTimeStamp();
420  const double minTimeStepSize = repositories::getMinTimeStepSize();
421  const double maxTimeStepSize = repositories::getMaxTimeStepSize();
422  const double minMeshSize = repositories::getMinMeshSize();
423  const double maxMeshSize = repositories::getMaxMeshSize();
424 
425  repositories::startTimeStep(minTimeStamp, maxTimeStamp, minTimeStepSize, maxTimeStepSize);
426 
427  observers::TimeStep observer;
428  observers::TimeStep::prepareTraversal();
429  watch.start();
430  peano4::parallel::SpacetreeSet::getInstance().traverse(observer);
431  watch.stop();
432  observers::TimeStep::unprepareTraversal();
433  timeStepMeasurement.setValue(watch.getCalendarTime());
434 
435  repositories::finishTimeStep();
436  } break;
438  #if defined(USE_ADDITIONAL_MESH_TRAVERSAL)
439  case repositories::StepRepository::Steps::AdditionalMeshTraversal:
440  {
441  tarch::logging::LogFilter::getInstance().switchProgramPhase( "additional-MeshTraversal" );
442 
443  repositories::suspendSolversForOneGridSweep();
444  observers::AdditionalMeshTraversal observer;
445  observers::AdditionalMeshTraversal::prepareTraversal();
446  peano4::parallel::SpacetreeSet::getInstance().traverse(observer);
447  observers::AdditionalMeshTraversal::unprepareTraversal();
448  }
449  break;
450  #endif
452  case repositories::StepRepository::Steps::Undef:
453  assertion(false);
454  break;
455  }
456 
457 #if PEANO_DEBUG > 0
458 #else
459  if (tarch::mpi::Rank::getInstance().isGlobalMaster())
460 #endif
461  logInfo("step()", "Finishing [" << repositories::StepRepository::toString(stepName) << "] Current SolverState [" << AbstractCCZ4::toString(repositories::instanceOfCCZ4.getSolverState())<<"]" );
462 }
463 
464 int main(int argc, char** argv) {
465  constexpr int ExitCodeSuccess = 0;
466  constexpr int ExitCodeUnitTestsFailed = 1;
467  constexpr int ExitCodeInvalidArguments = 2;
468  constexpr int ExitCodeInvalidBuild = 3;
469 
470  static tarch::timing::Watch watch("::", "main()", false);
471 
472  peano4::initParallelEnvironment(&argc, &argv);
473 
474  // Do this early, so people can use logInfo properly.
475  repositories::initLogFilters();
476 
477  tarch::initNonCriticalAssertionEnvironment();
478  peano4::fillLookupTables();
479 
480  peano4::initSingletons(DomainOffset, DomainSize, PeriodicBC);
481 
482  repositories::initSharedMemoryAndGPUEnvironment();
483 
484  if (tarch::mpi::Rank::getInstance().getNumberOfRanks() > 1 and tarch::multicore::Core::getInstance().getNumberOfThreads() <= 1) {
485  logError("main()", "MPI runs without multithreading are not supported currently.");
486  return ExitCodeInvalidBuild;
487  }
488 
489  repositories::DataRepository::initDatatypes();
490 
491  #if PEANO_DEBUG >= 2
492  tarch::tests::TreeTestCaseCollection* unitTests = new tarch::tests::TreeTestCaseCollection();
493  unitTests->addTestCase(peano4::getUnitTests());
494  unitTests->addTestCase(tarch::getUnitTests());
495  unitTests->addTestCase(toolbox::blockstructured::getUnitTests());
496  unitTests->addTestCase(exahype2::getUnitTests());
497  unitTests->run();
498  if (unitTests->getNumberOfErrors() != 0) {
499  logError("main()", "unit tests failed. Quit.");
500  tarch::mpi::Rank::abort(ExitCodeUnitTestsFailed);
501  }
502  delete unitTests;
503 #endif
504 
505  repositories::startSimulation();
506 
507  tarch::logging::Statistics::getInstance().clear();
508 
509 #if defined(WITH_OPENMP)
510 #pragma omp parallel
511  {
512 #pragma omp master
513  {
514 #endif
515 
516  const bool isGlobalMaster = tarch::mpi::Rank::getInstance().isGlobalMaster();
517  const bool isPeanoComputeNode = not tarch::mpi::Rank::getInstance().isGlobalMaster();
518 
519  if (isGlobalMaster) {
520  while (selectNextAlgorithmicStep()) {
521  watch.start();
522  step();
523  watch.stop();
524 
525  timePerMeshSweepMeasurement.setValue(watch.getCalendarTime());
526  logInfo("main()", "time per mesh sweep (current/average): " << std::fixed << std::setprecision(2) << watch.getCalendarTime() << " / " << timePerMeshSweepMeasurement.getValue() );
527  }
528 
529  logInfo("main()", "terminated successfully");
530  logInfo(
531  "main()",
532  "initial grid construction: " << gridConstructionMeasurement.getAccumulatedValue(
533  ) << "s\t" << gridConstructionMeasurement.toString()
534  );
535  logInfo(
536  "main()",
537  "plotting: " << plotMeasurement.getAccumulatedValue() << "s\t" << plotMeasurement.toString()
538  );
539  logInfo(
540  "main()",
541  "time stepping: " << timeStepMeasurement.getAccumulatedValue(
542  ) << "s\t" << timeStepMeasurement.toString()
543  );
544  logInfo(
545  "main()",
546  "average time per mesh sweep: " << timePerMeshSweepMeasurement.getValue() << "\t" << timePerMeshSweepMeasurement.toString()
547  );
548  } else if (isPeanoComputeNode) {
549  while (peano4::parallel::Node::getInstance().continueToRun()) {
550  step();
551  }
552  }
553 #if defined(WITH_OPENMP)
554  }
555  }
556 #endif
557 
558  tarch::logging::Statistics::getInstance().writeToCSV();
559 
560  repositories::finishSimulation();
561 
562  peano4::shutdownSingletons();
563  repositories::DataRepository::shutdownDatatypes();
564  tarch::shutdownNonCriticalAssertionEnvironment();
565  peano4::shutdownParallelEnvironment();
566 
567  return ExitCodeSuccess;
568 }
tarch::timing::Measurement gridConstructionMeasurement
Definition: ccz4-main.cpp:57
int main(int argc, char **argv)
Definition: ccz4-main.cpp:422
tarch::timing::Measurement timePerMeshSweepMeasurement
Definition: ccz4-main.cpp:56
tarch::timing::Measurement timeStepMeasurement
Definition: ccz4-main.cpp:58
bool selectNextAlgorithmicStep()
Decide which step to run next.
Definition: ccz4-main.cpp:70
tarch::timing::Measurement plotMeasurement
Definition: ccz4-main.cpp:59
void step()
Definition: ccz4-main.cpp:235
tarch::logging::Log _log("::")