TimeStepper

TimeStepper represents the EB+AMR equation solving class in chombo-discharge. It owns the various numerical solvers and is responsible for setting up solvers and advancing the equations of motion. Because TimeStepper and not Driver owns the solvers as class members, it will also coordinate I/O (together with Driver).

Basic functions

Since it is necessary to implement different solvers for different types of physics, TimeStepper is an abstract class with the following pure functions:

// Setup routines
virtual void setupSolvers() = 0;
virtual void allocate() = 0;
virtual void initialData() = 0;
virtual void postInitialize() = 0;
virtual void postCheckpointSetup() = 0;
virtual void registerRealms() = 0;
virtual void registerOperators() = 0;
virtual void parseRuntimeOptions();

// IO routines
virtual void writeCheckpointData(HDF5Handle& a_handle, const int a_lvl) const = 0;
virtual void readCheckpointData(HDF5Handle& a_handle, const int a_lvl) = 0;
virtual void writePlotData(EBAMRCellData& a_output, Vector<std::string>& a_plotVariableNames, int& a_icomp) const = 0;
virtual int  getNumberOfPlotVariables() const = 0;
virtual Vector<long int> getCheckpointLoads(const std::string a_realm, const int a_level) const;

// Advance routines
virtual Real computeDt() = 0;
virtual Real advance(const Real a_dt) = 0;
virtual void synchronizeSolverTimes(const int a_step, const Real a_time, const Real a_dt) = 0;
virtual void printStepReport() = 0;

// Regrid routines
virtual void preRegrid(const int a_lmin, const int a_oldFinestLevel) = 0;
virtual void postRegrid() = 0;
virtual void regrid(const int a_lmin, const int a_oldFinestLevel, const int a_newFinestLevel) = 0;
virtual bool needToRegrid();
virtual bool loadBalanceThisRealm(const std::string a_realm) const;
virtual void loadBalanceBoxes(Vector<Vector<int> >&            a_procs,
                              Vector<Vector<Box> >&            a_boxes,
                              const std::string                a_realm,
                              const Vector<DisjointBoxLayout>& a_grids,
                              const int                        a_lmin,
                              const int                        a_finestLevel);

These functions are all used by Driver class at various stages.

Setup routines

Here, we consider the various setup routines in TimeStepper. The routines are used by Driver in the simulation setup step.

registerRealms

TimeStepper permits solvers to run on different realms (see Realm) for individual load balancing of various components. To register a Realm, users will have TimeStepper register realms in the registerRealms(), as follows:

void myTimeStepper::registerRealms(){
   m_amr->registerRealm(Realm::Primal);
   m_amr->registerRealm("particleRealm");
   m_amr->registerRealm("otherParticleRealm");
}

Since at least one realm is required, Driver will always register the realm "Primal". Fundamentally, there is no limitation to the number of realms that can be allocated.

registerOperators

Internally, an instantiation of Realm contains the grids and the geometric information (e.g. EBISLayout), as well as any operators that the user has seen fit to register. Various operators are available for e.g. gradient stencils, conservative coarsening, ghost cell interpolation, filling a patch with interpolation data, redistribution, and so on. Since operators always incur overhead and not all applications require all operators, they must be registered. If a solver needs an operator for, say, piecewise linear ghost cell interpolation, the solver needs to register that operator through the AmrMesh public interface:

m_amr->registerOperator(s_eb_pwl_interp, m_realm, m_phase);

Once an operator has been registered, Realm will define those operators during initialization e.g. regrids. Run-time error messages are issued if an AMR operator is used, but has not been registered.

More commonly, chombo-discharge solvers will contain a routine that registers the operators that the solver needs. A valid TimeStepper implementation must register all required operators in the function registerOperators().

Currently available operators are:

  1. Gradient s_eb_gradient.

  2. Irregular cell centroid interpolation, s_eb_irreg_interp.

  3. Coarse grid conservative coarsening, s_eb_coar_ave.

  4. Piecewise linear interpolation (with slope limiters), s_eb_fill_patch.

  5. Linear ghost cell interpolation, s_eb_fine_interp.

  6. Flux registers, s_eb_flux_reg.

  7. Redistribution registers, s_eb_redist.

  8. Non-conservative divergence stencils, s_eb_noncons_div.

  9. Multigrid interpolators, s_eb_multigrid (used for multigrid).

  10. Signed distance function defined on grid, s_levelset.

  11. Particle-mesh support, s_eb_particle_mesh.

Solvers will typically allocate a subset of these operators, but for multiphysics code that use both fluid and particles, most of these will probably be in use.

setupSolvers

setupSolvers is used for setting up solvers. This step is done prior to setting up the grids, so it is not possible to allocate mesh data inside this routine.

allocate

allocate is used for allocating particle and mesh data for the solvers and TimeStepper. This step is done after the grids have been initialized by AmrMesh and during regrids.

initialData

initialData is called by Driver setup routines after the allocate step. This routine must fill solvers with initial data.

postInitialize

postInitialize is called after Driver has filled the solvers with initial data. Most data initialization steps can, however, be done in initialData.

postCheckpointSetup

During simulation restarts, Driver will open an HDF5 file and have TimeStepper fill solvers with data from that file. postCheckpointSetup is a routine which is called immediately after the solvers have been filled with data.

I/O routines

The TimeStepper I/O routines serves two purposes:

  1. To add solver data to HDF5 plot files.

  2. To write and read data for checkpoint/restart files.

In general, plot and checkpoint data do not contain the same data.

getNumberOfPlotVariables

getNumberOfPlotVariables must return the number of components that will be plotted by TimeStepper. Note that if TimeStepper will plot a single scalar, it must return a value of one. If it plots a single vector, it must return a value of SpaceDim.

The existence of getNumberOfPlotVariables is due to pre-allocation of memory that will be written to the plot file.

writePlotData

writePlotData will write the plot data to the provided data holder. The signature is

virtual void writePlotData(EBAMRCellData& a_output, Vector<std::string>& a_plotVariableNames, int& a_icomp) const = 0;

Here, a_output is pre-allocate block of memory that TimeStepper will write its components to, and a_plotVariable are the associated plot variable names. a_icomp is the starting component in a_output where we start writing data.

writeCheckpointData

writeCheckpointData will write solver data to the provided HDF5 file handle. This data is used when restarting simulations from a checkpoint file. Note that checkpoint data is written on a level-by-level basis.

readCheckpointData

readCheckpointData will read data from the provided HDF5 file handle and back into the solvers. Note that the data is read on a level-by-level basis.

Advance routines

computeDt

computeDt will compute a time step for Driver to use when calling the advance method.

advance

advance is called by Driver when advancing the equation of motion one time step. Note that advancpe takes a trial time step as input argument and returns the actual time step that was used. These do not need to be the same.

synchronizeSolverTimes

synchronizeSolverTimes is called after the advance method and is used to update the simulation time for all solvers.

printStepReport

printStepReport called after the advance method – it can be left empty but is otherwise used to print some information about the time step that was taken.

Regrid routines

For an explanation to how regridding occurs in chombo-discharge, see Regridding.

preRegrid

preRegrid should any necessary pre-regrid operation. Note that when solvers regrid their data, solution is allocated on new grids and the previously defined data is lost. For this reason most solvers have the option of putting the old grid data into temporary storage that permits us to interpolate to the new grids.

regrid

regrid will perform the actual regrid operation.

postRegrid

postRegrid is called after regrid can be used to perform any post-regrid operations.

Load balancing routines

During the regrid step, Driver will check if any of the realms should be load balanced. If a realm should be load balanced then TimeStepper take a DisjointBoxLayout which originally load balanced using the patch volume, and generate a new set of grids.

loadBalanceThisRealm

Return true if a Realm should be load balanced and false otherwise.

loadBalanceBoxes

This is called if loadBalanceThisRealm evaluates to true, and in this case the TimeStepper should compute a new set of rank ownership for the input grid boxes.