Mesh ODE solver
The MeshODESolver<N> implements a solver for
where \(\vec{\phi}\) represents \(N\) unknowns on the mesh, and \(\vec{S}\) is the corresponding source term. The class is templated as
/*!
@brief Class for solving dy/dt = f on an AMR hierarchy.
@details The template parameter is the number of variables in y and f.
*/
template <size_t N = 1>
class MeshODESolver
where N indicates the number of variables stored on the mesh.
MeshODESolver<N> is designed to store N variables in each grid cell, without any cell-to-cell coupling.
To instantiate the solver, use the full constructor with reference to AmrMesh:
/*!
@brief Full constructor.
@param[in] a_amr AMR core.
*/
MeshODESolver(const RefCountedPtr<AmrMesh>& a_amr) noexcept;
Tip
Source code for the MeshODESolver<N> resides in Source/MeshODESolver.
See https://chombo-discharge.github.io/chombo-discharge/doxygen/html/classMeshODESolver.html for the full C++ API.
Setting \(\vec{\phi}\)
Mesh-based
To set \(\vec{\phi}\), one can fetch the \(N\) mesh components from
/*!
@brief Get the solution vector (left-hand side of equation).
*/
EBAMRCellData&
getPhi() noexcept;
This will return the data holder that holds the cell centered data \(\vec{\phi}\) which the user can iterate through. See Mesh data for examples.
Analytic function
One can set \(\vec{\phi}(\mathbf{x}) = \vec{f}\left(\mathbf{x}\right)\) through the following functions:
/*!
@brief Set phi for a specific component.
@param[in] a_phiFunc Phi function
@param[in] a_comp Component
*/
virtual void
setPhi(const std::function<Real(const RealVect& a_pos)>& a_phiFunc, const size_t a_comp) noexcept;
/*!
@brief Set phi everywhere.
@param[in] a_phiFunc Phi function.
*/
virtual void
setPhi(const std::function<std::array<Real, N>(const RealVect& a_pos)>& a_phiFunc) noexcept;
These differ only in that the first function sets a specific component, whereas the second version sets all \(N\) components.
Setting \(\vec{S}\)
Mesh-based
For a general method of setting the source term one can fetch \(\vec{S}\) through
/*!
@brief Get the solution vector (left-hand side of equation).
*/
EBAMRCellData&
getRHS() noexcept;
This returns a reference to \(\vec{S}\) which the user can iterate through and set the value in each cell. See Mesh data for explicit examples.
Spatially dependent
The source term can also be set on a component-by-component basis using
/*!
@brief Set right-hand side for specified component.
@param[in] a_srcFunc Source term function.
@param[in] a_comp Component
*/
virtual void
setRHS(const std::function<Real(const RealVect& a_pos)>& a_srcFunc, const size_t a_comp) noexcept;
As a function of \(\vec{\phi}\)
In order to compute the source term \(\vec{S}\) as a function of \(\vec{\phi}\), MeshOdeSolver<N> has a function
/*!
@brief Alias for right-hand side
*/
using RHSFunction = std::function<std::array<Real, N>(const std::array<Real, N>&, const Real)>;
/*!
@brief Compute right-hand side from left-hand side. I.e. compute f = f(y,t).
@param[in] a_rhsFunction Function for computing the right-hand side.
*/
virtual void
computeRHS(const RHSFunction& a_rhsFunction) noexcept;
which computes the source term \(\vec{S}\) as a function
An example which sets \(\vec{S} = \vec{\phi}\) is given below
auto f = [](const std::array<Real, N>& phi, const Real t) -> std::array<Real, N> {
const std::array<Real, N> S = phi;
return S;
};
solver.computeRHS(f);
Regridding
When regridding the MeshODESolver<N>, one must first ensure that the mesh data on the old mesh is stored before calling the regrid function:
/*!
@brief Perform pre-regrid operations.
@param[in] a_lbase Coarsest level that changed during regrid.
@param[in] a_oldFinestLevel Finest grid level before the regrid operation.
@note This copies m_phi onto m_cache
*/
virtual void
preRegrid(const int a_lbase, const int a_oldFinestLevel) noexcept;
This must be done before AmrMesh creates the new grids. This will store \(\vec{\phi}\) on the old mesh. After AmrMesh has generated the new grids, \(\vec{\phi}\) can be interpolated onto the new grids by calling
/*!
@brief Regrid this solver.
@param[in] a_lmin Coarsest level where grids did not change.
@param[in] a_oldFinestLevel Finest AMR level before the regrid.
@param[in] a_newFinestLevel Finest AMR level after the regrid.
@details This linearly interpolates (potentially with limiters) m_phi to the new grids.
*/
virtual void
regrid(const int a_lmin, const int a_oldFinestLevel, const int a_newFinestLevel) noexcept;
Users can also choose to turn on/off slope limiters when putting the solution on the new mesh.
Important
The source term \(\vec{S}\) is also allocated on the new mesh, but is not interpolated onto the new grids. It must therefore be set by the user after calling the regrid function.
Input options
Several input options are available for configuring the run-time configuration of MeshODESolver<N>, which are listed below
# ====================================================================================================
# MeshODESolver class options
# ====================================================================================================
MeshODESolver.verbosity = -1 ## Verbosity level
MeshODESolver.plt_vars = phi rhs ## Stuff that can be plotted. 'phi' and/or 'rhs
MeshODESolver.use_regrid_slopes = false ## Use or don't use slopes when regridding
I/O
The user can add \(\vec{\phi}\) and \(\vec{S}\) to output files by specifying these in the input script. These variables are named
MeshODESolver.plt_vars = phi rhs
Only phi and rhs are recognized as valid arguments.
If choosing to omit output variables for the solver, one can put e.g. MeshODESolver.plt_vars = -1.
Note
MeshODESolver<N> checkpoint files only contain \(\vec{\phi}\).