241 const creal DT_EPSILON=1e-12;
244 bool dtIsChanged {
false};
246 MPI_Comm_rank(MPI_COMM_WORLD,&
myRank);
248 phiprof::initialize();
250 double initialWtime = MPI_Wtime();
256 feenableexcept(FE_DIVBYZERO|FE_INVALID|FE_OVERFLOW);
258 signal(SIGFPE, fpehandler);
262 signal(SIGTERM, termhandler);
268 phiprof::Timer mainTimer {
"main"};
269 phiprof::Timer initTimer {
"Initialization"};
271 phiprof::Timer readParamsTimer {
"Read parameters"};
281 readparameters.
parse();
290 readparameters.
parse(
true,
false);
302 readParamsTimer.stop();
306 (VECL*VEC_PER_PLANE !=
WID2) ||
307 (VECL*VEC_PER_BLOCK !=
WID3) ||
309 (VECL != (
int)VECL) ||
310 (VPREC != (
int)VPREC) ||
311 (VEC_PER_PLANE != (
int)VEC_PER_PLANE) ||
312 (VEC_PER_BLOCK != (
int)VEC_PER_BLOCK) ) {
314 cerr <<
"(MAIN) ERROR: Vectorclass definition mismatch!" << endl;
315 cerr <<
"VECL " << VECL <<
" VEC_PER_PLANE " << VEC_PER_PLANE <<
" WID " <<
WID <<
" VEC_PER_BLOCK " << VEC_PER_BLOCK <<
" VPREC "<< VPREC<<endl;
323 double qnan = std::numeric_limits<double>::quiet_NaN();
324 double pinf = std::numeric_limits<double>::infinity();
325 double ninf = -std::numeric_limits<double>::infinity();
326 bool isnan1 = std::isnan(qnan);
327 bool isinf2 = std::isinf(pinf);
328 bool isinf3 = std::isinf(ninf);
329 bool isfinite1 = std::isfinite(qnan);
330 bool isfinite2 = std::isfinite(pinf);
331 bool isfinite3 = std::isfinite(ninf);
332 if (!isnan1||!isinf2||!isinf3||isfinite1||isfinite2||isfinite3) {
334 cerr <<
"(MAIN) ERROR: Floating point exceptions not being caught!" << endl;
350 phiprof::Timer openLoggerTimer {
"open logFile & diagnostic"};
354 if(
myRank ==
MASTER_RANK) cerr <<
"(MAIN) ERROR: Logger failed to open logfile!" << endl;
359 if (
logFile.open(MPI_COMM_WORLD,
MASTER_RANK,
"logfile_fullbgbio.txt",
false) ==
false) {
360 if(
myRank ==
MASTER_RANK) cerr <<
"(MAIN) ERROR: Logger failed to open logfile_fullbgbio!" << endl;
366 if(
myRank ==
MASTER_RANK) cerr <<
"(MAIN) ERROR: Logger failed to open diagnostic file!" << endl;
372 MPI_Comm_size(MPI_COMM_WORLD,&mpiProcs);
374 char nodename[MPI_MAX_PROCESSOR_NAME];
375 int namelength, nodehash;
376 int nodeRank, interRank;
384 MPI_Get_processor_name(nodename,&namelength);
385 nodehash=(int)(hasher(
string(nodename)) % std::numeric_limits<int>::max());
388 MPI_Comm_split(MPI_COMM_WORLD, nodehash,
myRank, &nodeComm);
389 MPI_Comm_rank(nodeComm,&nodeRank);
391 MPI_Comm_split(MPI_COMM_WORLD, nodeRank,
myRank, &interComm);
392 MPI_Comm_rank(interComm, &interRank);
393 MPI_Comm_size(interComm, &nNodes);
395 MPI_Comm_free(&interComm);
396 MPI_Comm_free(&nodeComm);
398 logFile <<
"(MAIN) Starting simulation with " << mpiProcs <<
" MPI processes ";
400 logFile <<
"and " << omp_get_max_threads();
404 logFile <<
" OpenMP threads per process on " << nNodes <<
" nodes" << endl <<
writeVerbose;
405 openLoggerTimer.stop();
408 phiprof::Timer initProjectimer {
"Init project"};
410 if(
myRank ==
MASTER_RANK) cerr <<
"(MAIN): Project did not initialize correctly!" << endl;
415 cerr <<
"(MAIN): Project base class was not initialized!" << endl;
416 cerr <<
"\t Call Project::initialize() in your project's initialize()-function." << endl;
420 initProjectimer.stop();
424 phiprof::Timer initFsTimer {
"Init fieldsolver grids"};
426 const std::array<fsgrid::FsSize_t, 3> fsGridDimensions = {
431 const std::array<bool, 3> periodicity{sysBoundaryContainer.
isPeriodic(0),
442 constexpr Real uniformTolerance = 1e-3;
443 if ((
abs((gridSpacing[0] - gridSpacing[1]) / gridSpacing[0]) > uniformTolerance) ||
444 (
abs((gridSpacing[0] - gridSpacing[2]) / gridSpacing[0]) > uniformTolerance) ||
445 (
abs((gridSpacing[1] - gridSpacing[2]) / gridSpacing[1]) > uniformTolerance)) {
447 std::cerr <<
"WARNING: Your spatial cells seem not to be cubic. The simulation will now abort!" << std::endl;
450 MPI_Abort(MPI_COMM_WORLD, -1);
453 MPI_Comm parentComm = MPI_COMM_WORLD;
454 const auto numFsProcs = [&]() {
455 auto parentCommSize = 0;
456 MPI_Comm_size(parentComm, &parentCommSize);
457 const auto envVar = getenv(
"FSGRID_PROCS");
458 const auto fsgridProcs = envVar != NULL ? atoi(envVar) : 0;
459 return parentCommSize > fsgridProcs && fsgridProcs > 0 ? fsgridProcs : parentCommSize;
463 physicalGlobalStart, decomposition);
465 const size_t fsgridNumElements =
fsgrid.getNumStorageCells();
466 fsgrid::FsData<fsgrids::technical> technical(fsgridNumElements);
467 fsgrid::FsData<std::array<Real, fsgrids::bfield::N_BFIELD>> perb(fsgridNumElements);
468 fsgrid::FsData<std::array<Real, fsgrids::efield::N_EFIELD>> e(fsgridNumElements);
469 fsgrid::FsData<std::array<Real, fsgrids::efield::N_EFIELD>> edt2(fsgridNumElements);
470 fsgrid::FsData<std::array<Real, fsgrids::ehall::N_EHALL>> ehall(fsgridNumElements);
471 fsgrid::FsData<std::array<Real, fsgrids::egradpe::N_EGRADPE>> egradpe(fsgridNumElements);
472 fsgrid::FsData<std::array<Real, fsgrids::egradpe::N_EGRADPE>> egradpedt2(fsgridNumElements);
473 fsgrid::FsData<std::array<Real, fsgrids::moments::N_MOMENTS>> moments(fsgridNumElements);
474 fsgrid::FsData<std::array<Real, fsgrids::moments::N_MOMENTS>> momentsdt2(fsgridNumElements);
475 fsgrid::FsData<std::array<Real, fsgrids::dperb::N_DPERB>> dperb(fsgridNumElements);
476 fsgrid::FsData<std::array<Real, fsgrids::dmoments::N_DMOMENTS>> dmoments(fsgridNumElements);
477 fsgrid::FsData<std::array<Real, fsgrids::dmoments::N_DMOMENTS>> dmomentsdt2(fsgridNumElements);
478 fsgrid::FsData<std::array<Real, fsgrids::bgbfield::N_BGB>> bgb(fsgridNumElements);
479 fsgrid::FsData<std::array<Real, fsgrids::volfields::N_VOL>> vol(fsgridNumElements);
488 phiprof::Timer initGridsTimer {
"Init grids"};
489 dccrg::Dccrg<SpatialCell,dccrg::Cartesian_Geometry> mpiGrid;
505 sysBoundaryContainer,
510 phiprof::Timer reportMemoryTimer {
"report-memory-consumption"};
512 cout <<
"(MAIN): Completed grid initialization." << endl;
516 reportMemoryTimer.stop();
523 fsgrid::FsData<std::array<Real, fsgrids::bfield::N_BFIELD>> perbdt2(perb.view());
545 initGridsTimer.stop();
549 phiprof::Timer initDROsTimer {
"Init DROs"};
559 initDROsTimer.stop();
565 logFile <<
"Writing out full BGB components and derivatives and exiting." << endl <<
writeVerbose;
582 const bool writeGhosts =
true;
594 cerr <<
"FAILED TO WRITE GRID AT " << __FILE__ <<
" " << __LINE__ << endl;
599 phiprof::print(MPI_COMM_WORLD,
"phiprof");
632 sysBoundaryContainer, 0.0, 1.0
636 phiprof::Timer getFieldsTimer {
"getFieldsFromFsGrid"};
637 fsgrid.updateGhostCells(vol.view());
639 getFieldsTimer.stop();
654 fsgrid.updateGhostCells(dperb.view());
669 phiprof::Timer dttimer {
"compute-dt"};
687 phiprof::Timer timer {
"write-initial-state"};
703 const bool writeGhosts =
true;
716 cerr <<
"FAILED TO WRITE GRID AT " << __FILE__ <<
" " << __LINE__ << endl;
730 phiprof::Timer computeDtTimer {
"compute-dt"};
738 computeDtTimer.stop();
742 phiprof::Timer propagateHalfTimer {
"propagate-velocity-space-dt/2"};
749 propagateHalfTimer.stop();
753 phiprof::Timer updateBoundariesTimer {(
"update system boundaries (Vlasov post-acceleration)")};
755 updateBoundariesTimer.stop();
759 phiprof::Timer computeMomentsTimer {
"Compute interp moments"};
774 computeMomentsTimer.stop();
785 cout <<
"(MAIN): Starting main simulation loop." << endl;
789 logFile<<
"Filtering Report: "<<endl;
797 phiprof::Timer reportMemTimer {
"report-memory-consumption"};
799 reportMemTimer.stop();
801 uint64_t computedCells=0;
822 uint wallTimeRestartCounter=1;
823 uint recoverCounter=0;
826 bool overrideRebalanceNow =
false;
827 bool refineNow =
false;
831 phiprof::Timer simulationTimer {
"Simulation"};
832 double startTime= MPI_Wtime();
833 double beforeTime = MPI_Wtime();
834 double beforeSimulationTime=
P::t_min;
836 Real compress_time=0.0;
844 phiprof::Timer ioTimer {
"IO"};
846 phiprof::Timer externalsTimer {
"checkExternalCommands"};
851 externalsTimer.stop();
855 phiprof::Timer loggingTimer {
"logfile-io"};
861 phiprof::print(MPI_COMM_WORLD,
"phiprof");
863 double currentTime=MPI_Wtime();
864 double timePerStep=double(currentTime - beforeTime) / (
P::tstep-beforeStep);
865 double timePerSecond=double(currentTime - beforeTime) / (
P::t-beforeSimulationTime + DT_EPSILON);
867 time_t finalWallTime=time(NULL)+(time_t)remainingTime;
868 struct tm *finalWallTimeInfo=localtime(&finalWallTime);
869 logFile <<
"(TIME) current " << nNodes*(currentTime - startTime)/3600 <<
" node-hours" << endl;
871 logFile <<
"(TIME) current " << omp_get_max_threads()*mpiProcs*(currentTime - startTime)/3600 <<
" thread-hours" << endl;
873 logFile <<
"(TIME) current walltime/step " << timePerStep<<
" s" <<endl;
874 logFile <<
"(TIME) current walltime/simusecond " << timePerSecond<<
" s" <<endl;
875 logFile <<
"(TIME) Estimated completion time is " <<asctime(finalWallTimeInfo)<<endl;
877 beforeTime = MPI_Wtime();
878 beforeSimulationTime=
P::t;
887 phiprof::Timer memTimer {
"memory-report"};
891 phiprof::Timer cellTimer {
"cell-count-report"};
896 phiprof::Timer diagnosticTimer {
"diagnostic-io"};
922 phiprof::Timer writeSysTimer {
"write-system"};
924 const bool writeGhosts =
true;
939 cerr <<
"FAILED TO WRITE GRID AT " << __FILE__ <<
" " << __LINE__ << endl;
950 phiprof::Timer bailoutReduceTimer {
"Bailout-allreduce"};
952 bailoutReduceTimer.stop();
956 phiprof::Timer restartCheckTimer {
"compute-is-restart-written-and-extra-LB"};
992 MPI_Bcast( &doNow, 4 , MPI_INT ,
MASTER_RANK ,MPI_COMM_WORLD);
999 restartCheckTimer.stop();
1002 phiprof::Timer timer {
"write-restart"};
1004 wallTimeRestartCounter++;
1027 cerr <<
"FAILED TO WRITE RESTART" << endl;
1036 phiprof::Timer timer {
"write-recover"};
1058 cerr <<
"FAILED TO WRITE RECOVER" << endl;
1086 phiprof::Timer shrinkTimer {
"Shrink_to_fit"};
1096 logFile <<
"(LB) AMR rebalancing with heavier refinement weights." << endl;
1098 for (
auto id : mpiGrid.get_local_cells_to_refine()) {
1103 for (
auto id : mpiGrid.get_local_cells_to_refine()) {
1110 mpiGrid.cancel_refining();
1112 for (
auto id : mpiGrid.get_local_cells_to_refine()) {
1122 phiprof::Timer computeDtimer {
"compute-dt-amr"};
1132 overrideRebalanceNow =
false;
1144 for(
size_t i=0;
i<cells.size();
i++) {
1146 computedCells += (uint64_t)mpiGrid[cells[
i]]->get_number_of_velocity_blocks(popID)*
WID3;
1157 phiprof::Timer updateDtimer {
"update-dt"};
1170 logFile <<
" dt changed to "<<
P::dt <<
"s, distribution function was half-stepped to real-time and back"<<endl<<
writeVerbose;
1171 updateDtimer.stop();
1179 overrideRebalanceNow =
true;
1183 #pragma omp parallel for
1184 for (
size_t c=0;
c<cells.size(); ++
c) {
1189 phiprof::Timer propagateTimer {
"Propagate"};
1194 phiprof::Timer timer {
"Update system boundaries (Vlasov pre-translation)"};
1218 phiprof::Timer spatialSpaceTimer {
"Spatial-space"};
1224 spatialSpaceTimer.stop(computedCells,
"Cells");
1228 phiprof::Timer timer {
"Update system boundaries (Vlasov post-translation)"};
1234 phiprof::Timer momentsTimer {
"Compute interp moments"};
1249 momentsTimer.stop();
1254 phiprof::Timer propagateTimer {
"Propagate Fields"};
1256 phiprof::Timer couplingInTimer {
"fsgrid-coupling-in"};
1262 fieldSolverData.
moments = moments.view();
1263 fieldSolverData.
momentsDt2 = momentsdt2.view();
1265 couplingInTimer.stop();
1284 sysBoundaryContainer,
1289 phiprof::Timer getFieldsTimer {
"getFieldsFromFsGrid"};
1291 fsgrid.updateGhostCells(vol.view());
1292 fsgrid.updateGhostCells(technical.view());
1294 getFieldsTimer.stop();
1295 propagateTimer.stop(cells.size(),
"SpatialCells");
1313 int nIterations, nRestarts;
1314 Real residual, minPotentialN, maxPotentialN, minPotentialS, maxPotentialS;
1315 SBC::ionosphereGrid.solve(nIterations, nRestarts, residual, minPotentialN, maxPotentialN, minPotentialS, maxPotentialS);
1318 <<
" ionosphere iterations = " << nIterations
1319 <<
" restarts = " << nRestarts
1320 <<
" residual = " << std::scientific << residual << std::defaultfloat
1321 <<
" N potential min " << minPotentialN
1322 <<
" max " << maxPotentialN
1323 <<
" difference " << maxPotentialN - minPotentialN
1324 <<
" S potential min " << minPotentialS
1325 <<
" max " << maxPotentialS
1326 <<
" difference " << maxPotentialS - minPotentialS
1332 phiprof::Timer vspaceTimer {
"Velocity-space"};
1340 vspaceTimer.stop(computedCells,
"Cells");
1344 phiprof::Timer diffusionTimer {
"Pitch-angle diffusion"};
1348 diffusionTimer.stop(computedCells,
"Cells");
1352 phiprof::Timer timer {
"Update system boundaries (Vlasov post-acceleration)"};
1358 momentsTimer.start();
1375 momentsTimer.stop();
1377 propagateTimer.stop(computedCells,
"Cells");
1379 phiprof::Timer endStepTimer {
"Project endTimeStep"};
1381 endStepTimer.stop();
1386 s <<
"The timestep dt=" <<
P::dt <<
" went below bailout.min_dt (" << to_string(
P::bailout_min_dt) <<
")." << endl;
1387 bailout(
true, s.str(), __FILE__, __LINE__);
1395 compress_time+=
P::dt;
1398 double after = MPI_Wtime();
1400 simulationTimer.stop();
1401 phiprof::Timer finalizationTimer {
"Finalization"};
1403 if (doBailout > 0) {
1404 logFile <<
"(BAILOUT): Bailing out, see error log for details." << endl;
1414 double timePerSecond=double(after - startTime) / (
P::t-
P::t_min+DT_EPSILON);
1415 logFile <<
"(MAIN): All timesteps calculated." << endl;
1416 logFile <<
"\t (TIME) total run time " << after - startTime <<
" s, total simulated time " <<
P::t -
P::t_min<<
" s" << endl;
1417 logFile <<
"\t (TIME) total " << nNodes*(after - startTime)/3600 <<
" node-hours" << endl;
1419 logFile <<
"\t (TIME) total " << omp_get_max_threads()*mpiProcs*(after - startTime)/3600 <<
" thread-hours" << endl;
1423 logFile <<
"\t (TIME) seconds per timestep " << timePerStep <<
1424 ", seconds per simulated second " << timePerSecond << endl;
1429 finalizationTimer.stop();
1434 vmesh::deallocateMeshWrapper();
1439 phiprof::print(MPI_COMM_WORLD,
"phiprof");
1443 cout <<
"(MAIN): Completed requested simulation. Exiting." << endl;