Vlasiator ebf0dd394 on dev (v5.4.0 + 1054 commits)
Loading...
Searching...
No Matches
vlasiator.cpp
Go to the documentation of this file.
1/*
2 * This file is part of Vlasiator.
3 * Copyright 2010-2016 Finnish Meteorological Institute
4 * Copyright 2024 CSC - IT Center for Science
5 *
6 * For details of usage, see the COPYING file and read the "Rules of the Road"
7 * at http://www.physics.helsinki.fi/vlasiator/
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 */
23#include "common.h"
24#include <cstdlib>
25#include <iostream>
26#include <cmath>
27#include <vector>
28#include <sstream>
29#include <ctime>
30#include <cstdlib>
31#include <iostream>
32#include <chrono>
33
34#ifdef _OPENMP
35 #include <omp.h>
36#endif
37
38#ifdef USE_GPU
39#include "arch/gpu_base.hpp"
40#endif
41
42#include <fsgrid.hpp>
43
45#include "vlasovsolver/vec.h"
46#include "definitions.h"
47#include "mpiconversion.h"
48#include "logger.h"
49#include "parameters.h"
50#include "readparameters.h"
53
56
58
60#include "projects/project.h"
61#include "grid.h"
62#include "iowrite.h"
63#include "ioread.h"
64#include "memory_report.h"
65
66#include "object_wrapper.h"
71
72#include <signal.h>
73
74#ifdef CATCH_FPE
75#include <fenv.h>
78void fpehandler(int sig_num)
79{
80 signal(SIGFPE, fpehandler);
81 printf("SIGFPE: floating point exception occured, exiting.\n");
82 abort();
83}
84#endif
85
86#include "phiprof.hpp"
87
89
90using namespace std;
91
93bool globalflags::writeRestart = false;
94bool globalflags::writeRecover = false;
95bool globalflags::balanceLoad = false;
96bool globalflags::doRefine = false;
98
99#ifdef CATCH_SIGTERM
100// The normal behaviour on SIGTERM is to simply abort the simulation in place.
101// This implementation instead attempts to write a restart file and then quit,
102// to work nicely with slurm's job preemption mechanism.
103void termhandler(int sig_num) {
104 logFile << "Caught SIGTERM. Writing recover and initiating bailout." << endl << flush;
107}
108#endif
109
111
115
120const std::vector<CellID>& getLocalCells() {
122}
123
124void addTimedBarrier(string name){
125#ifndef DEBUG_VLASIATOR
126//let's not do a barrier
127 return;
128#endif
129 phiprof::Timer btimer {name, {"Barriers", "MPI"}};
130 MPI_Barrier(MPI_COMM_WORLD);
131}
132
133void computeNewTimeStep(dccrg::Dccrg<SpatialCell, dccrg::Cartesian_Geometry>& mpiGrid,
135 bool& isChanged) {
136 phiprof::Timer computeTimestepTimer {"compute-timestep"};
137 // Compute maximum time step. This cannot be done at the first step as the solvers compute the limits for each cell.
138
139 isChanged = false;
140
141 const vector<CellID>& cells = getLocalCells();
142 /* Arrays for storing local (per process) and global max dt
143 0th position stores ordinary space propagation dt
144 1st position stores velocity space propagation dt
145 2nd position stores field propagation dt
146 */
147 Real dtMaxLocal[3];
148 Real dtMaxGlobal[3];
149
150 dtMaxLocal[0] = numeric_limits<Real>::max();
151 dtMaxLocal[1] = numeric_limits<Real>::max();
152 dtMaxLocal[2] = numeric_limits<Real>::max();
153
154 // Compute max dt for Vlasov solver
155 reduce_vlasov_dt(mpiGrid, cells, dtMaxLocal);
156
157 // compute max dt for fieldsolver
158 dtMaxLocal[2] = fsgrid.parallel_reduction([](int timerId) -> phiprof::Timer { return phiprof::Timer{timerId}; },
159 phiprof::initializeTimer("compute-dt-reduction-loop"), technical,
160 [](Real a, Real b) { return std::min<Real>(a, b); },
161 std::numeric_limits<Real>::max(),
162 [=](const fsgrid::Coordinates &coordinates, const fsgrid::FsStencil& stencil, cuint sysBoundaryFlag, cuint sysBoundaryLayer, creal maximum) {
163 if (sysBoundaryFlag == sysboundarytype::NOT_SYSBOUNDARY ||
164 (sysBoundaryLayer == 1 && sysBoundaryFlag != sysboundarytype::NOT_SYSBOUNDARY)) {
165 return technical[stencil.ooo()].maxFsDt;
166 } else {
167 return maximum;
168 }
169 });
170
171 MPI_Allreduce(&(dtMaxLocal[0]), &(dtMaxGlobal[0]), 3, MPI_Type<Real>(), MPI_MIN, MPI_COMM_WORLD);
172
173 // If any of the solvers are disabled there should be no limits in timespace from it
175 dtMaxGlobal[0] = numeric_limits<Real>::max();
177 dtMaxGlobal[1] = numeric_limits<Real>::max();
179 dtMaxGlobal[2] = numeric_limits<Real>::max();
180
181 creal meanVlasovCFL = 0.5 * (P::vlasovSolverMaxCFL + P::vlasovSolverMinCFL);
182 creal meanFieldsCFL = 0.5 * (P::fieldSolverMaxCFL + P::fieldSolverMinCFL);
183 Real subcycleDt;
184
185 // reduce/increase dt if it is too high for any of the three propagators or too low for all propagators
186 if ((P::dt > dtMaxGlobal[0] * P::vlasovSolverMaxCFL ||
189 (P::dt < dtMaxGlobal[0] * P::vlasovSolverMinCFL &&
192
193 // new dt computed
194 isChanged = true;
195
196 // set new timestep to the lowest one of all interval-midpoints
197 newDt = meanVlasovCFL * dtMaxGlobal[0];
198 newDt = min(newDt, meanVlasovCFL * dtMaxGlobal[1] * P::maxSlAccelerationSubcycles);
199 newDt = min(newDt, meanFieldsCFL * dtMaxGlobal[2] * P::maxFieldSolverSubcycles);
200
201 logFile << "(TIMESTEP) New dt = " << newDt << " computed on step " << P::tstep << " at " << P::t
202 << "s Maximum possible dt (not including vlasovsolver CFL " << P::vlasovSolverMinCFL << "-"
203 << P::vlasovSolverMaxCFL << " or fieldsolver CFL " << P::fieldSolverMinCFL << "-" << P::fieldSolverMaxCFL
204 << ") in {r, v, BE} was " << dtMaxGlobal[0] << " " << dtMaxGlobal[1] << " " << dtMaxGlobal[2] << " "
205 << " Including subcycling { v, BE} was " << dtMaxGlobal[1] * P::maxSlAccelerationSubcycles << " "
206 << dtMaxGlobal[2] * P::maxFieldSolverSubcycles << " " << endl
207 << writeVerbose;
208
209 if (P::dynamicTimestep) {
210 // Check if the calculated value was and continues to be above the ceiling
211 if (P::dt_ceil > 0.0 && newDt >= P::dt_ceil && P::dt == P::dt_ceil) {
212 isChanged = false;
213 newDt = P::dt_ceil;
214 return;
215 }
216 // Check if we at this time exceeded the ceiling
217 if (P::dt_ceil > 0.0 && newDt > P::dt_ceil) {
218 newDt = P::dt_ceil;
219 logFile << "(TIMESTEP) However, ceiling timestep in config overrides larger dynamic and dt = " << P::dt_ceil << endl << writeVerbose;
220 }
221 subcycleDt = newDt;
222 } else {
223 logFile << "(TIMESTEP) However, fixed timestep in config overrides and dt = " << P::dt << endl << writeVerbose;
224 subcycleDt = P::dt;
225 }
226 } else {
227 subcycleDt = P::dt;
228 }
229
230 // Subcycle if field solver dt < global dt (including CFL) (new or old dt hence the hassle with subcycleDt
231 if (meanFieldsCFL * dtMaxGlobal[2] < subcycleDt && P::propagateField) {
233 min(convert<uint>(ceil(subcycleDt / (meanFieldsCFL * dtMaxGlobal[2]))), P::maxFieldSolverSubcycles);
234 } else {
236 }
237}
238
239int simulate(int argn,char* args[]) {
240 int myRank, doBailout=0;
241 const creal DT_EPSILON=1e-12;
242 typedef Parameters P;
243 Real newDt;
244 bool dtIsChanged {false};
245
246 MPI_Comm_rank(MPI_COMM_WORLD,&myRank);
247
248 phiprof::initialize();
249
250 double initialWtime = MPI_Wtime();
251 SysBoundary& sysBoundaryContainer = getObjectWrapper().sysBoundaryContainer;
252
253 #ifdef CATCH_FPE
254 // WARNING FE_INEXACT is too sensitive to be used. See man fenv.
255 //feenableexcept(FE_DIVBYZERO|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW);
256 feenableexcept(FE_DIVBYZERO|FE_INVALID|FE_OVERFLOW);
257 //feenableexcept(FE_DIVBYZERO|FE_INVALID);
258 signal(SIGFPE, fpehandler);
259 #endif
260
261 #ifdef CATCH_SIGTERM
262 signal(SIGTERM, termhandler);
263 #endif
264
265 // Initialize memory allocator configuration.
267
268 phiprof::Timer mainTimer {"main"};
269 phiprof::Timer initTimer {"Initialization"};
270
271 phiprof::Timer readParamsTimer {"Read parameters"};
272 // Allocate host-side velocity mesh wrapper
274 // init parameter file reader
275 Readparameters readparameters(argn,args);
276
278
279 // Add parameters for number of populations
281 readparameters.parse();
283
285 sysBoundaryContainer.addParameters();
287
288 Project* project = projects::createProject();
289 getObjectWrapper().project = project;
290 readparameters.parse(true, false); // 2nd parsing for specific population parameters
291 readparameters.helpMessage(); // Call after last parse, exits after printing help if help requested
293 sysBoundaryContainer.getParameters();
294 project->getParameters();
295
296 #ifdef USE_GPU
297 // Activate device, create streams
299 #endif
300 // Fill in rest of velocity meshes data, upload GPU version
301 vmesh::getMeshWrapper()->initVelocityMeshes(getObjectWrapper().particleSpecies.size());
302 readParamsTimer.stop();
303
304 // Check for correct application of vectorclass values:
305 if ( (VECL<WID) ||
306 (VECL*VEC_PER_PLANE != WID2) ||
307 (VECL*VEC_PER_BLOCK != WID3) ||
308 //(VPREC > VECL) ||
309 (VECL != (int)VECL) ||
310 (VPREC != (int)VPREC) ||
311 (VEC_PER_PLANE != (int)VEC_PER_PLANE) ||
312 (VEC_PER_BLOCK != (int)VEC_PER_BLOCK) ) {
313 if (myRank == MASTER_RANK) {
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;
316 }
317 exit(1);
318 }
319
320 // Verify correct handling of floating point exceptions
321 // see https://github.com/fmihpc/vlasiator/pull/845
322 {
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) {
333 if (myRank == MASTER_RANK) {
334 cerr << "(MAIN) ERROR: Floating point exceptions not being caught!" << endl;
335 }
336 exit(1);
337 }
338 }
339 //Get version and config info here
340 std::string version;
341 std::string config;
342 //Only master needs the info
343 if (myRank==MASTER_RANK){
344 version=readparameters.versionInfo();
345 config=readparameters.configInfo();
346 }
347
348 // Init parallel logger:
349
350 phiprof::Timer openLoggerTimer {"open logFile & diagnostic"};
351 //if restarting we will append to logfiles
352 if(!P::writeFullBGB) {
353 if (logFile.open(MPI_COMM_WORLD,MASTER_RANK,"logfile.txt",P::isRestart) == false) {
354 if(myRank == MASTER_RANK) cerr << "(MAIN) ERROR: Logger failed to open logfile!" << endl;
355 exit(1);
356 }
357 } else {
358 // If we are out to write the full background field and derivatives, we don't want to overwrite the existing run's logfile.
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;
361 exit(1);
362 }
363 }
364 if (P::diagnosticInterval != 0) {
365 if (diagnostic.open(MPI_COMM_WORLD,MASTER_RANK,"diagnostic.txt",P::isRestart) == false) {
366 if(myRank == MASTER_RANK) cerr << "(MAIN) ERROR: Logger failed to open diagnostic file!" << endl;
367 exit(1);
368 }
369 }
370
371 int mpiProcs;
372 MPI_Comm_size(MPI_COMM_WORLD,&mpiProcs);
373
374 char nodename[MPI_MAX_PROCESSOR_NAME];
375 int namelength, nodehash;
376 int nodeRank, interRank;
377 int nNodes;
378
379 hash<string> hasher;
380 MPI_Comm nodeComm;
381 MPI_Comm interComm;
382
383 //get name of this node
384 MPI_Get_processor_name(nodename,&namelength);
385 nodehash=(int)(hasher(string(nodename)) % std::numeric_limits<int>::max());
386
387 //intra-node communicator
388 MPI_Comm_split(MPI_COMM_WORLD, nodehash, myRank, &nodeComm);
389 MPI_Comm_rank(nodeComm,&nodeRank);
390 //create communicator for inter-node communication
391 MPI_Comm_split(MPI_COMM_WORLD, nodeRank, myRank, &interComm);
392 MPI_Comm_rank(interComm, &interRank);
393 MPI_Comm_size(interComm, &nNodes);
394
395 MPI_Comm_free(&interComm);
396 MPI_Comm_free(&nodeComm);
397
398 logFile << "(MAIN) Starting simulation with " << mpiProcs << " MPI processes ";
399 #ifdef _OPENMP
400 logFile << "and " << omp_get_max_threads();
401 #else
402 logFile << "and 0";
403 #endif
404 logFile << " OpenMP threads per process on " << nNodes << " nodes" << endl << writeVerbose;
405 openLoggerTimer.stop();
406
407 // Init project
408 phiprof::Timer initProjectimer {"Init project"};
409 if (project->initialize() == false) {
410 if(myRank == MASTER_RANK) cerr << "(MAIN): Project did not initialize correctly!" << endl;
411 exit(1);
412 }
413 if (project->initialized() == false) {
414 if (myRank == MASTER_RANK) {
415 cerr << "(MAIN): Project base class was not initialized!" << endl;
416 cerr << "\t Call Project::initialize() in your project's initialize()-function." << endl;
417 exit(1);
418 }
419 }
420 initProjectimer.stop();
421
422 // Initialize simplified Fieldsolver grids.
423 // Needs to be done here already ad the background field will be set right away, before going to initializeGrid even
424 phiprof::Timer initFsTimer {"Init fieldsolver grids"};
425
426 const std::array<fsgrid::FsSize_t, 3> fsGridDimensions = {
430
431 const std::array<bool, 3> periodicity{sysBoundaryContainer.isPeriodic(0),
432 sysBoundaryContainer.isPeriodic(1),
433 sysBoundaryContainer.isPeriodic(2)};
434
435 const std::array gridSpacing{P::dx_ini / pow(2, P::amrMaxSpatialRefLevel),
438 const std::array physicalGlobalStart{P::xmin, P::ymin, P::zmin};
439 const auto decomposition = P::manualFsGridDecomposition;
440
441 // Checking that spatial cells are cubic, otherwise field solver is incorrect (cf. derivatives in E, Hall term)
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)) {
446 if (myRank == MASTER_RANK) {
447 std::cerr << "WARNING: Your spatial cells seem not to be cubic. The simulation will now abort!" << std::endl;
448 }
449 // just abort sending SIGTERM to all tasks
450 MPI_Abort(MPI_COMM_WORLD, -1);
451 }
452
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;
460 }();
461
462 FieldSolverGrid fsgrid(fsGridDimensions, parentComm, numFsProcs, periodicity, gridSpacing,
463 physicalGlobalStart, decomposition);
464
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);
480
481
482 // Initialize grid. After initializeGrid local cells have dist
483 // functions, and B fields set. Cells have also been classified for
484 // the various sys boundary conditions. All remote cells have been
485 // created. All spatial date computed this far is up to date for
486 // FULL_NEIGHBORHOOD. Block lists up to date for
487 // VLASOV_SOLVER_NEIGHBORHOOD (but dist function has not been communicated)
488 phiprof::Timer initGridsTimer {"Init grids"};
489 dccrg::Dccrg<SpatialCell,dccrg::Cartesian_Geometry> mpiGrid;
490
492 argn,
493 args,
494 mpiGrid,
495 perb,
496 bgb,
497 moments,
498 momentsdt2,
499 dmoments,
500 e,
501 egradpe,
502 vol,
503 technical,
504 fsgrid,
505 sysBoundaryContainer,
506 *project
507 );
508 const std::vector<CellID>& cells = getLocalCells();
509
510 phiprof::Timer reportMemoryTimer {"report-memory-consumption"};
511 if (myRank == MASTER_RANK){
512 cout << "(MAIN): Completed grid initialization." << endl;
513 logFile << "(MAIN): Completed grid initialization." << endl << writeVerbose;
514 }
516 reportMemoryTimer.stop();
517
518 // There are projects that have non-uniform and non-zero perturbed B, e.g. Magnetosphere with dipole type 4.
519 // For inflow cells (e.g. maxwellian), we cannot take a FSgrid perturbed B value from the templateCell,
520 // because we need a copy of the value from initialization in both perBGrid and perBDt2Grid and it isn't
521 // touched as we are in boundary cells for components that aren't solved. We do a straight full copy instead
522 // of looping and detecting boundary types here.
523 fsgrid::FsData<std::array<Real, fsgrids::bfield::N_BFIELD>> perbdt2(perb.view());
524 // fieldSolverData not const as we need to update the spans for moments and momentsdt2 when filtering
525 FieldSolverData fieldSolverData(
526 perb,
527 perbdt2,
528 e,
529 edt2,
530 ehall,
531 egradpe,
532 egradpedt2,
533 moments,
534 momentsdt2,
535 dperb,
536 dmoments,
537 dmomentsdt2,
538 bgb,
539 vol,
540 technical,
541 fsgrid
542 );
543 initFsTimer.stop();
544
545 initGridsTimer.stop();
546
547 // Initialize data reduction operators. This should be done elsewhere in order to initialize
548 // user-defined operators:
549 phiprof::Timer initDROsTimer {"Init DROs"};
550 DataReducer outputReducer, diagnosticReducer;
551
552 if(P::writeFullBGB) {
553 // We need the following variables for this, let's just erase and replace the entries in the list
554 P::outputVariableList.clear();
555 P::outputVariableList= {"fg_b_background", "fg_b_background_vol", "fg_derivs_b_background"};
556 }
557
558 initializeDataReducers(&outputReducer, &diagnosticReducer);
559 initDROsTimer.stop();
560
561 // Free up memory:
562 readparameters.~Readparameters();
563
564 if(P::writeFullBGB) {
565 logFile << "Writing out full BGB components and derivatives and exiting." << endl << writeVerbose;
566
567 // initialize the communicators so we can write out ionosphere grid metadata.
568 SBC::ionosphereGrid.updateIonosphereCommunicator(mpiGrid, technical.view(), fsgrid);
569
571 P::systemWriteName.push_back("bgb");
575 P::systemWritePath.push_back("./");
576 P::systemWriteFsGrid.push_back(true);
577
578 for(uint si=0; si<P::systemWriteName.size(); si++) {
579 P::systemWrites.push_back(0);
580 }
581
582 const bool writeGhosts = true;
583 if (writeGrid(mpiGrid,
584 fieldSolverData,
585 technical.view(),
586 version,
587 config,
588 &outputReducer,
589 P::systemWriteName.size()-1,
591 writeGhosts
592 ) == false
593 ) {
594 cerr << "FAILED TO WRITE GRID AT " << __FILE__ << " " << __LINE__ << endl;
595 }
596 initTimer.stop();
597 mainTimer.stop();
598
599 phiprof::print(MPI_COMM_WORLD,"phiprof");
600
601 if (myRank == MASTER_RANK) logFile << "(MAIN): Exiting." << endl << writeVerbose;
602 logFile.close();
603 if (P::diagnosticInterval != 0) diagnostic.close();
604
605 fsgrid.finalize();
606
607 MPI_Finalize();
608 return 0;
609 }
610
611 // Run the field solver once with zero dt. This will initialize
612 // Fieldsolver dt limits, and also calculate volumetric B-fields.
613 // At restart, all we need at this stage has been read from the restart, the rest will be recomputed in due time.
614 if(P::isRestart == false) {
616 perb.view(),
617 perbdt2.view(),
618 e.view(),
619 edt2.view(),
620 ehall.view(),
621 egradpe.view(),
622 egradpedt2.view(),
623 moments.view(),
624 momentsdt2.view(),
625 dperb.view(),
626 dmoments.view(),
627 dmomentsdt2.view(),
628 bgb.view(),
629 vol.view(),
630 technical.view(),
631 fsgrid,
632 sysBoundaryContainer, 0.0, 1.0
633 );
634 }
635
636 phiprof::Timer getFieldsTimer {"getFieldsFromFsGrid"};
637 fsgrid.updateGhostCells(vol.view());
638 getFieldsFromFsGrid(vol.view(), bgb.view(), egradpe.view(), dmoments.view(), technical.view(), fsgrid, mpiGrid, cells);
639 getFieldsTimer.stop();
640
641 // Build communicator for ionosphere solving
642 SBC::ionosphereGrid.updateIonosphereCommunicator(mpiGrid, technical.view(), fsgrid);
643 // If not a restart, perBGrid and dPerBGrid are up to date after propagateFields just above. Otherwise, we should compute them.
644 if(P::isRestart) {
646 perb.view(),
647 moments.view(),
648 dperb.view(),
649 dmoments.view(),
650 technical.view(),
651 fsgrid,
652 false // Don't communicate moments, they are not needed here.
653 );
654 fsgrid.updateGhostCells(dperb.view());
655 }
657 SBC::ionosphereGrid.initSolver(!P::isRestart); // If it is a restart we do not want to zero out everything
660 } else {
662 }
663
664 if(P::isRestart) {
665 // If it is a restart, we want to regenerate proper ig_inplanecurrent as well in case there's IO before the next solver step.
667 }
668
669 phiprof::Timer dttimer {"compute-dt"};
670 // Run Vlasov solver once with zero dt to initialize
671 // per-cell dt limits. Also compute initial _R and _V moments at restart.
672 calculateSpatialTranslation(mpiGrid,0.0);
673 calculateAcceleration(mpiGrid,0.0);
674
675 sysBoundaryContainer.setupL2OutflowAtRestart(mpiGrid);
676
677 dttimer.stop();
678
679 // Save restart data
681 // Calculate these so refinement parameters can be tuned based on the vlsv
683
684 // Call the reductions (e.g. field tracing)
685 FieldTracing::reduceData(technical.view(), fsgrid, perb.view(), dperb.view(), mpiGrid, SBC::ionosphereGrid.nodes);
686
687 phiprof::Timer timer {"write-initial-state"};
688
689 if (myRank == MASTER_RANK)
690 logFile << "(IO): Writing initial state to disk, tstep = " << endl << writeVerbose;
692 P::systemWriteName.push_back("initial-grid");
696 P::systemWritePath.push_back("./");
697 P::systemWriteFsGrid.push_back(true);
698
699 for(uint si=0; si<P::systemWriteName.size(); si++) {
700 P::systemWrites.push_back(0);
701 }
702
703 const bool writeGhosts = true;
704 if (writeGrid(
705 mpiGrid,
706 fieldSolverData,
707 technical.view(),
708 version,
709 config,
710 &outputReducer,
711 P::systemWriteName.size()-1,
713 writeGhosts
714 ) == false
715 ) {
716 cerr << "FAILED TO WRITE GRID AT " << __FILE__ << " " << __LINE__ << endl;
717 }
718
720 P::systemWriteName.pop_back();
724 P::systemWritePath.pop_back();
725 P::systemWriteFsGrid.pop_back();
726 }
727
728 if (P::isRestart == false) {
729 //compute new dt
730 phiprof::Timer computeDtTimer {"compute-dt"};
731 computeNewTimeStep(mpiGrid, technical.view(), fsgrid, newDt, dtIsChanged);
732 if (P::dynamicTimestep == true && dtIsChanged == true) {
733 // Only actually update the timestep if dynamicTimestep is on
734 P::dt=newDt;
735 } else {
736 dtIsChanged = false;
737 }
738 computeDtTimer.stop();
739
740 //go forward by dt/2 in V, initializes leapfrog split. In restarts the
741 //the distribution function is already propagated forward in time by dt/2
742 phiprof::Timer propagateHalfTimer {"propagate-velocity-space-dt/2"};
744 calculateAcceleration(mpiGrid, 0.5*P::dt);
745 } else {
746 //zero step to set up moments _v
747 calculateAcceleration(mpiGrid, 0.0);
748 }
749 propagateHalfTimer.stop();
750
751 // Apply boundary conditions
753 phiprof::Timer updateBoundariesTimer {("update system boundaries (Vlasov post-acceleration)")};
754 sysBoundaryContainer.applySysBoundaryVlasovConditions(mpiGrid, 0.5*P::dt, true);
755 updateBoundariesTimer.stop();
756 addTimedBarrier("barrier-boundary-conditions");
757 }
758 // Also update all moments. They won't be transmitted to FSgrid until the field solver is called, though.
759 phiprof::Timer computeMomentsTimer {"Compute interp moments"};
761 mpiGrid,
773 );
774 computeMomentsTimer.stop();
775 }
776
777 initTimer.stop();
778
779 // ***********************************
780 // ***** INITIALIZATION COMPLETE *****
781 // ***********************************
782
783 // Main simulation loop:
784 if (myRank == MASTER_RANK){
785 cout << "(MAIN): Starting main simulation loop." << endl;
786 logFile << "(MAIN): Starting main simulation loop." << endl << writeVerbose;
787 //report filtering if we are in an AMR run
789 logFile<<"Filtering Report: "<<endl;
790 for (int refLevel=0 ; refLevel<= P::amrMaxSpatialRefLevel; refLevel++){
791 logFile<<"\tRefinement Level " <<refLevel<<"==> Passes "<<P::numPasses.at(refLevel)<<endl;
792 }
793 logFile<<endl;
794 }
795 }
796
797 phiprof::Timer reportMemTimer {"report-memory-consumption"};
799 reportMemTimer.stop();
800
801 uint64_t computedCells=0;
802 //Compute here based on time what the file intervals are
803 P::systemWrites.clear();
804 for(uint i=0;i< P::systemWriteTimeInterval.size();i++){
806 //if we are already over 1% further than the time interval time that
807 //is requested for writing, then jump to next writing index. This is to
808 //make sure that at restart we do not write in the middle of
809 //the interval.
811 index++;
812 // Special case for large timesteps
813 int index2=(int)((P::t_min+P::dt)/P::systemWriteTimeInterval[i]);
814 if (index2>index) index=index2;
815 }
816 P::systemWrites.push_back(index);
817 }
818
819 // Invalidate cached cell lists just to be sure (might not be needed)
821
822 uint wallTimeRestartCounter=1;
823 uint recoverCounter=0;
824
825 int doNow[donow::N_DONOW] = {0}; // 0: writeRestartNow, 1: writeRecoverNow, 2: balanceLoadNow, 3: refineNow ; declared outside main loop
826 bool overrideRebalanceNow = false; // declared outside main loop
827 bool refineNow = false; // declared outside main loop
828
829 addTimedBarrier("barrier-end-initialization");
830
831 phiprof::Timer simulationTimer {"Simulation"};
832 double startTime= MPI_Wtime();
833 double beforeTime = MPI_Wtime();
834 double beforeSimulationTime=P::t_min;
835 double beforeStep=P::tstep_min;
836 Real compress_time=0.0;
837
838 while(P::tstep <= P::tstep_max &&
839 P::t-P::dt <= P::t_max+DT_EPSILON &&
840 wallTimeRestartCounter <= P::exitAfterRestarts) {
841
842 addTimedBarrier("barrier-loop-start");
843
844 phiprof::Timer ioTimer {"IO"};
845
846 phiprof::Timer externalsTimer {"checkExternalCommands"};
847 if(myRank == MASTER_RANK) {
848 // check whether STOP or KILL or SAVE has been passed, should be done by MASTER_RANK only as it can reset P::bailout_write_restart
850 }
851 externalsTimer.stop();
852
853 //write out phiprof profiles and logs with a lower interval than normal
854 //diagnostic (every 10 diagnostic intervals).
855 phiprof::Timer loggingTimer {"logfile-io"};
856 logFile << "---------- tstep = " << P::tstep << " t = " << P::t <<" dt = " << P::dt << " FS cycles = " << P::fieldSolverSubcycles << " ----------" << endl;
857 if (P::diagnosticInterval != 0 &&
858 P::tstep % (P::diagnosticInterval*10) == 0 &&
860
861 phiprof::print(MPI_COMM_WORLD,"phiprof");
862
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);
866 double remainingTime=min(timePerStep*(P::tstep_max-P::tstep),timePerSecond*(P::t_max-P::t));
867 time_t finalWallTime=time(NULL)+(time_t)remainingTime; //assume time_t is in seconds, as it is almost always
868 struct tm *finalWallTimeInfo=localtime(&finalWallTime);
869 logFile << "(TIME) current " << nNodes*(currentTime - startTime)/3600 << " node-hours" << endl;
870 #if _OPENMP
871 logFile << "(TIME) current " << omp_get_max_threads()*mpiProcs*(currentTime - startTime)/3600 << " thread-hours" << endl;
872 #endif
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;
876 //reset before values, we want to report speed since last report of speed.
877 beforeTime = MPI_Wtime();
878 beforeSimulationTime=P::t;
879 beforeStep=P::tstep;
880
881 }
883 loggingTimer.stop();
884
885 // Check whether diagnostic output has to be produced
887 phiprof::Timer memTimer {"memory-report"};
888 memTimer.start();
890 memTimer.stop();
891 phiprof::Timer cellTimer {"cell-count-report"};
892 cellTimer.start();
894 cellTimer.stop();
895
896 phiprof::Timer diagnosticTimer {"diagnostic-io"};
897 if (writeDiagnostic(mpiGrid, diagnosticReducer) == false) {
898 if(myRank == MASTER_RANK) cerr << "ERROR with diagnostic computation" << endl;
899
900 }
901 }
902
903 // write system, loop through write classes
904 for (uint i = 0; i < P::systemWriteTimeInterval.size(); i++) {
905 if (P::systemWriteTimeInterval[i] >= 0.0 &&
906 P::t >= P::systemWrites[i] * P::systemWriteTimeInterval[i] - DT_EPSILON) {
907 // If we have only just restarted, the bulk file should already exist from the previous slot.
908 if ((P::tstep == P::tstep_min) && (P::tstep>0)) {
910 // Special case for large timesteps
911 int index2=(int)((P::t+P::dt)/P::systemWriteTimeInterval[i]);
912 if (index2>P::systemWrites[i]) P::systemWrites[i]=index2;
913 continue;
914 }
915
916 // Calculate these so refinement parameters can be tuned based on the vlsv
918
919 // Call the reductions (e.g. field tracing)
920 FieldTracing::reduceData(technical.view(), fsgrid, perb.view(), dperb.view(), mpiGrid, SBC::ionosphereGrid.nodes);
921
922 phiprof::Timer writeSysTimer {"write-system"};
923 logFile << "(IO): Writing spatial cell and reduced system data to disk, tstep = " << P::tstep << " t = " << P::t << endl << writeVerbose;
924 const bool writeGhosts = true;
925
926 if (writeGrid(
927 mpiGrid,
928 fieldSolverData,
929 technical.view(),
930 version,
931 config,
932 &outputReducer,
933 i,
935 writeGhosts,
937 ) == false
938 ) {
939 cerr << "FAILED TO WRITE GRID AT " << __FILE__ << " " << __LINE__ << endl;
940 }
942 // Special case for large timesteps
943 int index2=(int)((P::t+P::dt)/P::systemWriteTimeInterval[i]);
944 if (index2>P::systemWrites[i]) P::systemWrites[i]=index2;
945 logFile << "(IO): .... done!" << endl << writeVerbose;
946 }
947 }
948
949 // Reduce globalflags::bailingOut from all processes
950 phiprof::Timer bailoutReduceTimer {"Bailout-allreduce"};
951 MPI_Allreduce(&(globalflags::bailingOut), &(doBailout), 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
952 bailoutReduceTimer.stop();
953
954 // Write restart data if needed
955 // Combined with checking of additional load balancing to have only one collective call.
956 phiprof::Timer restartCheckTimer {"compute-is-restart-written-and-extra-LB"};
957 if (myRank == MASTER_RANK) {
958 doNow[donow::SAVE] = 0;
959 doNow[donow::DORC] = 0;
961 && (P::saveRestartWalltimeInterval*wallTimeRestartCounter <= MPI_Wtime()-initialWtime
963 || P::t >= P::t_max))
964 || (doBailout > 0 && P::bailout_write_restart)
966 ) {
967 doNow[donow::SAVE] = 1;
968 if (globalflags::writeRestart == true) {
969 doNow[donow::SAVE] = 2; // Setting to 2 so as to not increment the restart count below.
970 globalflags::writeRestart = false; // This flag is only used by MASTER_RANK here and it needs to be reset after a restart write has been issued.
971 }
972 }
977 ) {
978 doNow[donow::DORC] = 1;
979 if (globalflags::writeRecover == true) {
980 globalflags::writeRecover = false; // This flag is only used by MASTER_RANK here and it needs to be reset after a recover write has been issued.
981 }
982 }
984 doNow[donow::DOLB] = 1;
987 doNow[donow::DOMR] = 1;
988 globalflags::doRefine = false;
989 }
990 }
991 }
992 MPI_Bcast( &doNow, 4 , MPI_INT , MASTER_RANK ,MPI_COMM_WORLD);
993 if (doNow[donow::DOLB] == 1) {
995 }
996 if (doNow[donow::DOMR] == 1) {
997 refineNow = true;
998 }
999 restartCheckTimer.stop();
1000
1001 if (doNow[donow::SAVE] >= 1){ // write restart
1002 phiprof::Timer timer {"write-restart"};
1003 if (doNow[donow::SAVE] == 1) { // write restart
1004 wallTimeRestartCounter++;
1005 }
1006
1007 // Refinement params for restart refinement
1009
1010 if (myRank == MASTER_RANK)
1011 logFile << "(IO): Writing restart data to disk, tstep = " << P::tstep << " t = " << P::t << endl << writeVerbose;
1012 //Write the restart:
1013 if (writeRestart(
1014 mpiGrid,
1015 fieldSolverData,
1016 technical.view(),
1017 version,
1018 config,
1019 outputReducer,
1020 "restart",
1021 (uint)P::t,
1022 true, // add the date of the file to the name
1025 ) {
1026 logFile << "(IO): ERROR Failed to write restart!" << endl << writeVerbose;
1027 cerr << "FAILED TO WRITE RESTART" << endl;
1028 }
1029 if (myRank == MASTER_RANK) {
1030 logFile << "(IO): .... done!"<< endl << writeVerbose;
1031 }
1032 timer.stop();
1033 }
1034
1035 if (doNow[donow::DORC] == 1){ // write recover
1036 phiprof::Timer timer {"write-recover"};
1037
1038 // Refinement params for restart refinement
1040
1041 if (myRank == MASTER_RANK)
1042 logFile << "(IO): Writing recover data to disk, index = " << recoverCounter % P::recoverMaxFiles << ", tstep = " << P::tstep << " t = " << P::t << endl << writeVerbose;
1043 //Write the recover:
1044 if (writeRestart(
1045 mpiGrid,
1046 fieldSolverData,
1047 technical.view(),
1048 version,
1049 config,
1050 outputReducer,
1051 "recover",
1052 recoverCounter % P::recoverMaxFiles,
1053 false, // overwrite so do not put date in file name
1056 ) {
1057 logFile << "(IO): ERROR Failed to write recover!" << endl << writeVerbose;
1058 cerr << "FAILED TO WRITE RECOVER" << endl;
1059 }
1060 recoverCounter++;
1061 if (myRank == MASTER_RANK) {
1062 logFile << "(IO): .... done!"<< endl << writeVerbose;
1063 }
1064 timer.stop();
1065 }
1066
1067 ioTimer.stop();
1068 addTimedBarrier("barrier-end-io");
1069
1070 // reset these for next time around
1071 doNow[donow::SAVE] = doNow[donow::DORC] = doNow[donow::DOLB] = doNow[donow::DOMR] = 0;
1072
1073 //no need to propagate if we are on the final step, we just
1074 //wanted to make sure all IO is done even for final step
1075 if(P::tstep == P::tstep_max ||
1076 P::t >= P::t_max ||
1077 doBailout > 0) {
1078 break;
1079 }
1080
1081 //Re-loadbalance if needed
1082 //TODO - add LB measure and do LB if it exceeds threshold
1083 if(((P::tstep % P::rebalanceInterval == 0 && P::tstep > P::tstep_min) || overrideRebalanceNow)) {
1084 logFile << "(LB): Start load balance, tstep = " << P::tstep << " t = " << P::t << endl << writeVerbose;
1085
1086 phiprof::Timer shrinkTimer {"Shrink_to_fit"};
1087 // * shrink to fit before LB * //
1088 shrink_to_fit_grid_data(mpiGrid);
1089 shrinkTimer.stop();
1090
1091 if (refineNow || (!dtIsChanged && P::adaptRefinement && P::tstep % (P::rebalanceInterval * P::refineCadence) == 0 && P::t > P::refineAfter)) {
1092 logFile << "(AMR): Adapting refinement!" << endl << writeVerbose;
1093 refineNow = false;
1094 if (!adaptRefinement(mpiGrid, technical.view(), fsgrid, sysBoundaryContainer, *project)) {
1095 // OOM, rebalance and try again
1096 logFile << "(LB) AMR rebalancing with heavier refinement weights." << endl;
1097 globalflags::bailingOut = false; // Reset this
1098 for (auto id : mpiGrid.get_local_cells_to_refine()) {
1099 mpiGrid[id]->parameters[CellParams::LBWEIGHTCOUNTER] *= 8.0;
1100 }
1101 balanceLoad(mpiGrid, sysBoundaryContainer, technical.view(), fsgrid);
1102 // We can /= 8.0 now as cells have potentially migrated. Go back to block-based count for now.
1103 for (auto id : mpiGrid.get_local_cells_to_refine()) {
1104 mpiGrid[id]->parameters[CellParams::LBWEIGHTCOUNTER] = 0;
1105 for (uint popID=0; popID<getObjectWrapper().particleSpecies.size(); ++popID) {
1106 mpiGrid[id]->parameters[CellParams::LBWEIGHTCOUNTER] += mpiGrid[id]->get_number_of_velocity_blocks(popID);
1107 }
1108 }
1109
1110 mpiGrid.cancel_refining();
1111 if (!adaptRefinement(mpiGrid, technical.view(), fsgrid, sysBoundaryContainer, *project)) {
1112 for (auto id : mpiGrid.get_local_cells_to_refine()) {
1113 mpiGrid[id]->parameters[CellParams::LBWEIGHTCOUNTER] *= 8.0;
1114 }
1115 continue; // Refinement failed and we're bailing out
1116 } else {
1117 globalflags::bailingOut = false; // Reset this
1118 }
1119 }
1120
1121 // Calculate new dt limits since we might break CFL when refining
1122 phiprof::Timer computeDtimer {"compute-dt-amr"};
1123 calculateSpatialTranslation(mpiGrid,0.0);
1124 calculateAcceleration(mpiGrid,0.0);
1125 }
1126 // This now uses the block-based count just copied between the two refinement calls above.
1127 balanceLoad(mpiGrid, sysBoundaryContainer, technical.view(), fsgrid);
1128 addTimedBarrier("barrier-end-load-balance");
1129 logFile << "(LB): ... done!" << endl << writeVerbose;
1130 P::prepareForRebalance = false;
1131
1132 overrideRebalanceNow = false;
1133
1134 // Make sure the ionosphere communicator is up-to-date, in case inner boundary cells
1135 // moved.
1136 SBC::ionosphereGrid.updateIonosphereCommunicator(mpiGrid, technical.view(), fsgrid);
1137 }
1138
1139 //get local cells
1140 const vector<CellID>& cells = getLocalCells();
1141
1142 //compute how many spatial cells we solve for this step
1143 computedCells=0;
1144 for(size_t i=0; i<cells.size(); i++) {
1145 for (uint popID=0; popID<getObjectWrapper().particleSpecies.size(); ++popID)
1146 computedCells += (uint64_t)mpiGrid[cells[i]]->get_number_of_velocity_blocks(popID)*WID3;
1147 }
1148
1149 //Check if dt needs to be changed, and propagate V back a half-step to change dt and set up new situation
1150 //do not compute new dt on first step (in restarts dt comes from file, otherwise it was initialized before we entered
1151 //simulation loop
1152 // FIXME what if dt changes at a restart??
1154 computeNewTimeStep(mpiGrid, technical.view(), fsgrid, newDt, dtIsChanged);
1155 addTimedBarrier("barrier-check-dt");
1156 if(dtIsChanged) {
1157 phiprof::Timer updateDtimer {"update-dt"};
1158 //propagate velocity space back to real-time
1160 // Back half dt to real time, forward by new half dt
1161 calculateAcceleration(mpiGrid,-0.5*P::dt + 0.5*newDt);
1162 }
1163 else {
1164 //zero step to set up moments _v
1165 calculateAcceleration(mpiGrid, 0.0);
1166 }
1167
1168 P::dt=newDt;
1169
1170 logFile <<" dt changed to "<<P::dt <<"s, distribution function was half-stepped to real-time and back"<<endl<<writeVerbose;
1171 updateDtimer.stop();
1172 continue; //
1173 //addTimedBarrier("barrier-new-dt-set");
1174 }
1175 }
1176
1178 if(P::prepareForRebalance == true) {
1179 overrideRebalanceNow = true;
1180 } else {
1182 }
1183 #pragma omp parallel for
1184 for (size_t c=0; c<cells.size(); ++c) {
1185 mpiGrid[cells[c]]->get_cell_parameters()[CellParams::LBWEIGHTCOUNTER] = 0;
1186 }
1187 }
1188
1189 phiprof::Timer propagateTimer {"Propagate"};
1190 //Propagate the state of simulation forward in time by dt:
1191
1192 // Update boundary condition states (time-varying)
1194 phiprof::Timer timer {"Update system boundaries (Vlasov pre-translation)"};
1195
1196 sysBoundaryContainer.updateState(mpiGrid, technical.view(), fsgrid, perb.view(), bgb.view(), P::t + 0.5 * P::dt);
1197
1198 // updateState leaves mpiGrid and fsgrid in mismatching states, interpolated moments need to be recalculated
1199 // TODO: Check whether updated state is the same as previously so synchronization can be skipped when not needed?
1201 mpiGrid,
1213 );
1214 timer.stop();
1215 addTimedBarrier("barrier-boundary-conditions");
1216 }
1217
1218 phiprof::Timer spatialSpaceTimer {"Spatial-space"};
1221 } else {
1222 calculateSpatialTranslation(mpiGrid,0.0);
1223 }
1224 spatialSpaceTimer.stop(computedCells, "Cells");
1225
1226 // Apply boundary conditions
1228 phiprof::Timer timer {"Update system boundaries (Vlasov post-translation)"};
1229 sysBoundaryContainer.applySysBoundaryVlasovConditions(mpiGrid, P::t+0.5*P::dt, false);
1230 timer.stop();
1231 addTimedBarrier("barrier-boundary-conditions");
1232 }
1233
1234 phiprof::Timer momentsTimer {"Compute interp moments"};
1236 mpiGrid,
1248 );
1249 momentsTimer.stop();
1250
1251 // Propagate fields forward in time by dt. This needs to be done before the
1252 // moments for t + dt are computed (field uses t and t+0.5dt)
1253 if (P::propagateField) {
1254 phiprof::Timer propagateTimer {"Propagate Fields"};
1255
1256 phiprof::Timer couplingInTimer {"fsgrid-coupling-in"};
1257 // Copy moments over into the fsgrid.
1258 feedMomentsIntoFsGrid(mpiGrid, cells, moments, technical.view(), fsgrid, false);
1259 feedMomentsIntoFsGrid(mpiGrid, cells, momentsdt2, technical.view(), fsgrid, true);
1260 // Update the spans of the filtered grids that were swapped in filtering
1261 if (P::amrMaxSpatialRefLevel > 0) {
1262 fieldSolverData.moments = moments.view();
1263 fieldSolverData.momentsDt2 = momentsdt2.view();
1264 }
1265 couplingInTimer.stop();
1266
1268 perb.view(),
1269 perbdt2.view(),
1270 e.view(),
1271 edt2.view(),
1272 ehall.view(),
1273 egradpe.view(),
1274 egradpedt2.view(),
1275 moments.view(),
1276 momentsdt2.view(),
1277 dperb.view(),
1278 dmoments.view(),
1279 dmomentsdt2.view(),
1280 bgb.view(),
1281 vol.view(),
1282 technical.view(),
1283 fsgrid,
1284 sysBoundaryContainer,
1285 P::dt,
1287 );
1288
1289 phiprof::Timer getFieldsTimer {"getFieldsFromFsGrid"};
1290 // Copy results back from fsgrid.
1291 fsgrid.updateGhostCells(vol.view());
1292 fsgrid.updateGhostCells(technical.view());
1293 getFieldsFromFsGrid(vol.view(), bgb.view(), egradpe.view(), dmoments.view(), technical.view(), fsgrid, mpiGrid, cells);
1294 getFieldsTimer.stop();
1295 propagateTimer.stop(cells.size(),"SpatialCells");
1296 addTimedBarrier("barrier-after-field-solver");
1297 }
1298
1301 }
1302
1303 // Map current data down into the ionosphere
1304 // momentsGrid was ghost-updated in the field solver above, volGrid just after a few lines above.
1305 // perBGrid was ghost-updated before derivatives were computed in the field solver.
1306 // dPerBGrid was updated before the electric fields.
1308 FieldTracing::calculateIonosphereFsgridCoupling(technical.view(), fsgrid, perb.view(), dperb.view(), SBC::ionosphereGrid.nodes, SBC::Ionosphere::radius);
1309 SBC::ionosphereGrid.mapDownBoundaryData(perb.view(), dperb.view(), moments.view(), technical.view(), fsgrid);
1311
1312 // Solve ionosphere
1313 int nIterations, nRestarts;
1314 Real residual, minPotentialN, maxPotentialN, minPotentialS, maxPotentialS;
1315 SBC::ionosphereGrid.solve(nIterations, nRestarts, residual, minPotentialN, maxPotentialN, minPotentialS, maxPotentialS);
1316 logFile << "tstep = " << P::tstep
1317 << " t = " << P::t
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
1327 << endl;
1330 }
1331
1332 phiprof::Timer vspaceTimer {"Velocity-space"};
1335 addTimedBarrier("barrier-after-ad just-blocks");
1336 } else {
1337 //zero step to set up moments _v
1338 calculateAcceleration(mpiGrid, 0.0);
1339 }
1340 vspaceTimer.stop(computedCells, "Cells");
1341 addTimedBarrier("barrier-after-acceleration");
1342
1344 phiprof::Timer diffusionTimer {"Pitch-angle diffusion"};
1345 for (uint popID=0; popID<getObjectWrapper().particleSpecies.size(); ++popID) {
1346 pitchAngleDiffusion(mpiGrid,popID);
1347 }
1348 diffusionTimer.stop(computedCells, "Cells");
1349 }
1350
1352 phiprof::Timer timer {"Update system boundaries (Vlasov post-acceleration)"};
1353 sysBoundaryContainer.applySysBoundaryVlasovConditions(mpiGrid, P::t + 0.5 * P::dt, true);
1354 timer.stop();
1355 addTimedBarrier("barrier-boundary-conditions");
1356 }
1357
1358 momentsTimer.start();
1359 // *here we compute rho and rho_v for timestep t + dt, so next
1360 // timestep * //
1362 mpiGrid,
1374 );
1375 momentsTimer.stop();
1376
1377 propagateTimer.stop(computedCells,"Cells");
1378
1379 phiprof::Timer endStepTimer {"Project endTimeStep"};
1380 project->hook(hook::END_OF_TIME_STEP, mpiGrid, perb.view(), technical.view(), fsgrid);
1381 endStepTimer.stop();
1382
1383 // Check timestep
1384 if (P::dt < P::bailout_min_dt) {
1385 stringstream s;
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__);
1388 }
1389
1390 //Move forward in time
1391 P::meshRepartitioned = false;
1393 ++P::tstep;
1394 P::t += P::dt;
1395 compress_time+=P::dt;
1396 }//main while loop
1397
1398 double after = MPI_Wtime();
1399
1400 simulationTimer.stop();
1401 phiprof::Timer finalizationTimer {"Finalization"};
1402 if (myRank == MASTER_RANK) {
1403 if (doBailout > 0) {
1404 logFile << "(BAILOUT): Bailing out, see error log for details." << endl;
1405 }
1406
1407 double timePerStep;
1408
1409 if (P::tstep == P::tstep_min) {
1410 timePerStep=0.0;
1411 } else {
1412 timePerStep=double(after - startTime) / (P::tstep-P::tstep_min);
1413 }
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;
1418 #if _OPENMP
1419 logFile << "\t (TIME) total " << omp_get_max_threads()*mpiProcs*(after - startTime)/3600 << " thread-hours" << endl;
1420 #endif
1421
1422 if(P::t != 0.0) {
1423 logFile << "\t (TIME) seconds per timestep " << timePerStep <<
1424 ", seconds per simulated second " << timePerSecond << endl;
1425 }
1427 }
1428
1429 finalizationTimer.stop();
1430 mainTimer.stop();
1431
1432 #ifdef USE_GPU
1433 // Deallocate buffers, clear device
1434 vmesh::deallocateMeshWrapper();
1437 #endif
1438
1439 phiprof::print(MPI_COMM_WORLD,"phiprof");
1440
1441 if (myRank == MASTER_RANK) {
1442 logFile << "(MAIN): Completed requested simulation. Exiting." << endl << writeVerbose;
1443 cout << "(MAIN): Completed requested simulation. Exiting." << endl;
1444 }
1445 logFile.close();
1446 if (P::diagnosticInterval != 0) {
1447 diagnostic.close();
1448 }
1449
1450 return 0;
1451}
1452
1453int main(int argn, char* args[]) {
1454 // Before MPI_Init we hardwire some settings, if we are in OpenMPI
1455 int myRank;
1456 int required=MPI_THREAD_FUNNELED;
1457 int provided, resultlen;
1458 char mpiversion[MPI_MAX_LIBRARY_VERSION_STRING];
1459 bool overrideMCAompio = false;
1460
1461 MPI_Get_library_version(mpiversion, &resultlen);
1462 string versionstr = string(mpiversion);
1463 stringstream mpiioMessage;
1464
1465 if(versionstr.find("Open MPI") != std::string::npos) {
1466 #ifdef VLASIATOR_ALLOW_MCA_OMPIO
1467 mpiioMessage << "We detected OpenMPI but the compilation flag VLASIATOR_ALLOW_MCA_OMPIO was set so we do not override the default MCA io flag." << endl;
1468 #else
1469 overrideMCAompio = true;
1470 int index, count;
1471 char io_value[64];
1472 MPI_T_cvar_handle io_handle;
1473
1474 MPI_T_init_thread(required, &provided);
1475 MPI_T_cvar_get_index("io", &index);
1476 MPI_T_cvar_handle_alloc(index, NULL, &io_handle, &count);
1477 MPI_T_cvar_write(io_handle, "^ompio");
1478 MPI_T_cvar_read(io_handle, io_value);
1479 MPI_T_cvar_handle_free(&io_handle);
1480 mpiioMessage << "We detected OpenMPI so we set the cvars value to disable ompio, MCA io: " << io_value << endl;
1481 #endif
1482 }
1483
1484 // After the MPI_T settings we can init MPI all right.
1485 MPI_Init_thread(&argn,&args,required,&provided);
1486 MPI_Comm_rank(MPI_COMM_WORLD,&myRank);
1487 if (required > provided){
1488 if(myRank==MASTER_RANK) {
1489 cerr << "(MAIN): MPI_Init_thread failed! Got " << provided << ", need "<<required <<endl;
1490 }
1491 exit(1);
1492 }
1493 if (myRank == MASTER_RANK) {
1494 const char* mpiioenv = std::getenv("OMPI_MCA_io");
1495 if(mpiioenv != nullptr) {
1496 std::string mpiioenvstr(mpiioenv);
1497 if(mpiioenvstr.find("^ompio") == std::string::npos) {
1498 cout << mpiioMessage.str();
1499 }
1500 }
1501 }
1502
1503 int ret {simulate(argn, args)};
1504
1505 if(overrideMCAompio) {
1506 MPI_T_finalize();
1507 }
1508 MPI_Finalize();
1509
1510 return ret;
1511}
for i
Definition Dispersion.m:24
Constants c
Definition Dispersion.m:45
void reduce_vlasov_dt(dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, const vector< CellID > &cells, Real(&dtMaxLocal)[3])
Definition arch_dt.cpp:34
static std::string configInfo()
static void helpMessage()
static std::string versionInfo()
static bool parse(const bool needsRunConfig=true, const bool allowUnknown=true)
static int solveCount
Definition ionosphere.h:649
static Real couplingInterval
Definition ionosphere.h:648
static Real backgroundIonisation
Definition ionosphere.h:637
static Real recombAlpha
Definition ionosphere.h:635
static Real F10_7
Definition ionosphere.h:636
static Real radius
Definition ionosphere.h:618
SysBoundary contains the SysBoundaryConditions used in the simulation.
Definition sysboundary.h:54
bool isPeriodic(uint direction) const
void updateState(dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, fsgrids::technicalspan technical, FieldSolverGrid &fsgrid, fsgrids::perbspan perb, fsgrids::bgbspan bgb, creal t)
void getParameters()
Get this class' parameters.
void addParameters()
Add its own and all existing SysBoundaryConditions' parameters.
void clear()
Definition sysboundary.h:91
void setupL2OutflowAtRestart(dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid)
void applySysBoundaryVlasovConditions(dccrg::Dccrg< spatial_cell::SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, creal &t, const bool calculate_V_moments)
Apply the Vlasov system boundary conditions to all system boundary cells at time t.
virtual bool initialize()
Definition project.cpp:113
virtual void getParameters()
Definition project.cpp:103
static void addParameters()
Definition project.cpp:75
virtual void hook(cuint &stage, const dccrg::Dccrg< spatial_cell::SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, fsgrids::perbspan perb, fsgrids::technicalspan technical, FieldSolverGrid &fsgrid) const
Definition project.cpp:138
void bailout(const bool condition, const std::string &message, const char *const file, const int line)
A function to stop the simulation if the boolean condition is true. Raises a flag which gets MPI_Redu...
Definition common.cpp:36
#define WID
Definition common.h:514
#define MASTER_RANK
Definition common.h:67
const int WID3
Definition common.h:517
const int WID2
Definition common.h:516
void pitchAngleDiffusion(dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, const uint popID)
void initializeDataReducers(DataReducer *outputReducer, DataReducer *diagnosticReducer)
Parameters P
const uint32_t cuint
Definition definitions.h:50
float Real
Definition definitions.h:41
T convert(const T &number)
Definition definitions.h:56
fsgrid::FsGrid< FS_STENCIL_WIDTH > FieldSolverGrid
Definition definitions.h:78
const float creal
Definition definitions.h:42
void calculateDerivativesSimple(fsgrids::perbspan perb, fsgrids::momentsspan moments, fsgrids::dperbspan dperb, fsgrids::dmomentsspan dmoments, fsgrids::technicalspan technical, FieldSolverGrid &fsgrid, const bool doMoments)
High-level derivative calculation wrapper function.
void calculateScaledDeltasSimple(dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid)
High-level scaled gradient calculation wrapper function.
bool propagateFields(fsgrids::perbspan perb, fsgrids::perbspan perbdt2, fsgrids::efieldspan e, fsgrids::efieldspan edt2, fsgrids::ehallspan ehall, fsgrids::egradpespan egradpe, fsgrids::egradpespan egradpedt2, fsgrids::momentsspan moments, fsgrids::momentsspan momentsdt2, fsgrids::dperbspan dperb, fsgrids::dmomentsspan dmoments, fsgrids::dmomentsspan dmomentsdt2, fsgrids::bgbspan bgb, fsgrids::volspan vol, fsgrids::technicalspan technical, FieldSolverGrid &fsgrid, SysBoundary &sysBoundaries, creal &dt, cuint subcycles)
Top-level field propagation function.
Definition ldz_main.cpp:91
__host__ void gpu_clear_device()
Definition gpu_base.cpp:229
__host__ void gpu_init_device()
Definition gpu_base.cpp:103
int myRank
Definition gpu_base.cpp:48
Logger logFile
Definition main.cpp:25
bool adaptRefinement(dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, fsgrids::technicalspan technical, FieldSolverGrid &fsgrid, SysBoundary &sysBoundaries, Project &project, int useStatic)
Definition grid.cpp:1337
void shrink_to_fit_grid_data(dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid)
Definition grid.cpp:874
void initializeGrids(int argn, char **argc, dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, fsgrid::FsData< std::array< Real, fsgrids::bfield::N_BFIELD > > &perb, fsgrid::FsData< std::array< Real, fsgrids::bgbfield::N_BGB > > &bgb, fsgrid::FsData< std::array< Real, fsgrids::moments::N_MOMENTS > > &moments, fsgrid::FsData< std::array< Real, fsgrids::moments::N_MOMENTS > > &momentsdt2, fsgrid::FsData< std::array< Real, fsgrids::dmoments::N_DMOMENTS > > &dmoments, fsgrid::FsData< std::array< Real, fsgrids::efield::N_EFIELD > > &e, fsgrid::FsData< std::array< Real, fsgrids::egradpe::N_EGRADPE > > &egradpe, fsgrid::FsData< std::array< Real, fsgrids::volfields::N_VOL > > &vol, fsgrid::FsData< fsgrids::technical > &technical, FieldSolverGrid &fsgrid, SysBoundary &sysBoundaries, Project &project)
Initialize DCCRG and fsgrids.
Definition grid.cpp:92
void balanceLoad(dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, SysBoundary &sysBoundaries, fsgrids::technicalspan technical, FieldSolverGrid &fsgrid, bool doTranslationLists)
Balance load.
Definition grid.cpp:672
void feedMomentsIntoFsGrid(dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, const std::vector< CellID > &cells, fsgrid::FsData< std::array< Real, fsgrids::moments::N_MOMENTS > > &moments, fsgrids::technicalspan technical, FieldSolverGrid &fsgrid, bool dt2)
Definition gridGlue.cpp:165
void getFieldsFromFsGrid(fsgrids::constvolspan volumefields, fsgrids::constbgbspan bgb, fsgrids::constegradpespan egradpe, fsgrids::constdmomentsspan dmoments, fsgrids::consttechnicalspan technical, FieldSolverGrid &fsgrid, dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, const std::vector< CellID > &cells)
Definition gridGlue.cpp:257
ObjectWrapper objectWrapper
Definition main.cpp:32
void checkExternalCommands()
Checks for command files written to the local directory. If a file STOP was written and is readable,...
Definition ioread.cpp:72
Logger diagnostic
Definition ioread.cpp:59
bool writeGrid(dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, const FieldSolverData &fieldSolverData, fsgrids::consttechnicalspan technical, const std::string &versionInfo, const std::string &configInfo, DataReducer *dataReducer, const uint &outputFileTypeIndex, const int &stripe, const bool writeGhosts, bool compress_vdfs)
Write out system into a vlsv file.
Definition iowrite.cpp:1829
bool writeRestart(dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, const FieldSolverData &fieldSolverData, fsgrids::consttechnicalspan technical, const std::string &versionInfo, const std::string &configInfo, DataReducer &dataReducer, const string &name, const uint &fileIndex, const bool dateInFileName, const int &stripe, bool compress_vdfs)
Write out a restart of the simulation into a vlsv file. All block data in remote cells will be reset.
Definition iowrite.cpp:2048
bool writeDiagnostic(const dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, DataReducer &dataReducer)
Write out simulation diagnostics into diagnostic.txt.
Definition iowrite.cpp:2422
Logger & writeVerbose(Logger &logger)
Definition logger.cpp:177
#define index(i, j, k)
void report_memory_consumption(const dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, double extra_bytes)
void report_cell_and_block_counts(const dccrg::Dccrg< spatial_cell::SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid)
void memory_configurator()
MPI_Datatype MPI_Type()
@ LBWEIGHTCOUNTER
Definition common.h:198
void resetReconstructionCoefficientsCache()
void calculateIonosphereFsgridCoupling(fsgrids::technicalspan technical, FieldSolverGrid &fsgrid, fsgrids::perbspan perb, fsgrids::constdperbspan dperb, std::vector< SBC::SphericalTriGrid::Node > &nodes, creal couplingRadius)
void reduceData(fsgrids::technicalspan technical, FieldSolverGrid &fsgrid, fsgrids::perbspan perb, fsgrids::constdperbspan dperb, dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, std::vector< SBC::SphericalTriGrid::Node > &nodes)
FieldTracingParameters fieldTracingParameters
SphericalTriGrid ionosphereGrid
@ DORC
Definition common.h:549
@ SAVE
Definition common.h:548
@ DOMR
Definition common.h:551
@ N_DONOW
Definition common.h:552
@ DOLB
Definition common.h:550
std::span< technical > technicalspan
Definition common.h:452
@ END_OF_TIME_STEP
Definition common.h:562
Project * createProject()
Definition project.cpp:649
ARCH_HOSTDEV MeshWrapper * getMeshWrapper()
fsgrids::constmomentsspan moments
Definition grid.h:45
fsgrids::constmomentsspan momentsDt2
Definition grid.h:46
bool getPopulationParameters()
SysBoundary sysBoundaryContainer
projects::Project * project
std::vector< species::Species > particleSpecies
bool addPopulationParameters()
static Real t_min
Definition parameters.h:53
static bool systemWriteRestartCompressed
Definition parameters.h:88
static Real dz_ini
Definition parameters.h:46
static bool writeInitialState
Definition parameters.h:116
static Real dx_ini
Definition parameters.h:44
static std::vector< int > systemWriteDistributionWriteZlineStride
Definition parameters.h:97
static Real t_max
Definition parameters.h:54
static int restartStripeFactor
Definition parameters.h:124
static uint maxFieldSolverSubcycles
Definition parameters.h:140
static int systemStripeFactor
Definition parameters.h:125
static bool writeFullBGB
Definition parameters.h:118
static std::vector< CellID > localCells
Definition parameters.h:76
static uint zcells_ini
Definition parameters.h:50
static int amrMaxSpatialRefLevel
Definition parameters.h:190
static std::vector< std::string > outputVariableList
Definition parameters.h:171
static std::vector< bool > systemWriteFsGrid
Definition parameters.h:105
static std::vector< int > systemWriteDistributionWriteYlineStride
Definition parameters.h:94
static Real saveRestartWalltimeInterval
Definition parameters.h:119
static std::vector< int > systemWrites
Definition parameters.h:108
static void getParameters()
Get the global parameters.
static bool prepareForRebalance
Definition parameters.h:167
static bool addParameters()
Add the global parameters.
static Real ymin
Definition parameters.h:40
static std::vector< std::string > systemWritePath
Definition parameters.h:83
static int maxSlAccelerationSubcycles
Definition parameters.h:157
static bool meshRepartitioned
Definition parameters.h:75
static std::vector< int > systemWriteDistributionWriteXlineStride
Definition parameters.h:91
static bool dynamicTimestep
Definition parameters.h:180
static bool systemWriteRecoveryCompressed
Definition parameters.h:89
static uint ycells_ini
Definition parameters.h:49
static Real vlasovSolverMinCFL
Definition parameters.h:61
static uint xcells_ini
Definition parameters.h:48
static uint tstep_min
Definition parameters.h:71
static Real xmin
Definition parameters.h:38
static uint fieldSolverSubcycles
Definition parameters.h:69
static Real fieldSolverMinCFL
Definition parameters.h:65
static Real t
Definition parameters.h:52
static bool bailout_write_restart
Definition parameters.h:184
static uint tstep
Definition parameters.h:73
static uint recoverMaxFiles
Definition parameters.h:122
static bool isRestart
Definition parameters.h:176
static Real dt_ceil
Definition parameters.h:57
static bool propagateVlasovAcceleration
Definition parameters.h:134
static uint exitAfterRestarts
Definition parameters.h:121
static Real refineAfter
Definition parameters.h:211
static bool artificialPADiff
Definition parameters.h:237
static Real zmin
Definition parameters.h:42
static Real bailout_min_dt
Definition parameters.h:186
static std::vector< Real > systemWriteTimeInterval
Definition parameters.h:84
static Real dy_ini
Definition parameters.h:45
static std::array< fsgrid::Task_t, 3 > manualFsGridDecomposition
Definition parameters.h:245
static uint saveRecoverTstepInterval
Definition parameters.h:120
static std::vector< int > systemWriteDistributionWriteStride
Definition parameters.h:86
static Real vlasovSolverMaxCFL
Definition parameters.h:59
static uint rebalanceInterval
Definition parameters.h:166
static bool adaptRefinement
Definition parameters.h:192
static bool propagateVlasovTranslation
Definition parameters.h:136
static bool systemWriteDistributionCompressed
Definition parameters.h:87
static std::vector< std::string > systemWriteName
Definition parameters.h:82
static std::vector< int > numPasses
Definition parameters.h:236
static uint refineCadence
Definition parameters.h:210
static uint tstep_max
Definition parameters.h:72
static uint diagnosticInterval
Definition parameters.h:81
static Real fieldSolverMaxCFL
Definition parameters.h:67
static Real dt
Definition parameters.h:55
static bool propagateField
Definition parameters.h:133
static bool balanceLoad
Definition common.h:541
static bool ionosphereJustSolved
Definition common.h:543
static int bailingOut
Definition common.h:538
static bool doRefine
Definition common.h:542
static bool writeRecover
Definition common.h:540
static bool writeRestart
Definition common.h:539
void initVelocityMeshes(const uint nMeshes)
int main()
An interface to a type with floating point values.
static ARCH_HOSTDEV VecSimple< T > min(VecSimple< T > const &l, VecSimple< T > const &r)
static ARCH_HOSTDEV VecSimple< T > abs(const VecSimple< T > &l)
static ARCH_HOSTDEV VecSimple< T > floor(VecSimple< T > const &a)
const std::vector< CellID > & getLocalCells()
ObjectWrapper & getObjectWrapper()
void addTimedBarrier(string name)
int simulate(int argn, char *args[])
void computeNewTimeStep(dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, fsgrids::technicalspan technical, FieldSolverGrid &fsgrid, Real &newDt, bool &isChanged)
void calculateInterpolatedVelocityMoments(dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, const int cp_rhom, const int cp_vx, const int cp_vy, const int cp_vz, const int cp_rhoq, const int cp_p11, const int cp_p22, const int cp_p33, const int cp_p23, const int cp_p13, const int cp_p12)
Compute real-time 1st order accurate moments from the moments after propagation in velocity and spati...
void calculateAcceleration(const uint popID, const uint globalMaxSubcycles, const uint step, dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, const std::vector< CellID > &acceleratedCells, const Real dt)
void calculateSpatialTranslation(dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, const vector< CellID > &local_propagated_cells, const vector< CellID > &remoteTargetCellsx, const vector< CellID > &remoteTargetCellsy, const vector< CellID > &remoteTargetCellsz, vector< uint > &nPencils, const Realf dt, const uint popID, Real &time)