3from .AbstractRKFD4ActionSet
import AbstractRKFD4ActionSet
11 Determine the time step size of the next Runge-Kutta step and advance
12 the solver's time stamp
14 The action set supports two modes:
16 - Fixed time step sizes: the next time step size is the one passed to
18 - Adaptive time step sizes: exahype2.api.rkfd4.actionsets.ComputeMaxEigenvalue
19 stores the maximum eigenvalue of every patch in the cell data
20 solver._max_eigenvalue. touchCellFirstTime() folds each cell's value
21 into the static _maxEigenvalue, and unprepareTraversal() derives the
22 next time step size from the global maximum through the CFL condition
23 @f$ \\Delta t = C h / (d \\lambda _{max}) @f$, with h the minimal grid
24 cell size, d the dimension and C the CFL constant.
26 In both modes, unprepareTraversal() feeds the next time step size into
27 ::exahype2::Solver's own time step bookkeeping
28 (updateCell()/finishTimeStep()/startTimeStep()). The time stamp
29 advances by the time step size the Runge-Kutta step has just used. The
30 last time step is not truncated: it may overshoot MaxTerminalTime, and
31 the simulation stops afterwards, i.e. MaxTerminalTime is a lower bound
32 on the final time. The solver starts with a time step size of zero, so
33 the very first Runge-Kutta step does not alter the solution: it only
34 yields the first time step size.
36 Global time stepping: all cells share one time stamp and time step size.
37 As getMinTimeStamp()==getMaxTimeStamp() and
38 getMinTimeStepSize()==getMaxTimeStepSize() always hold, a single
39 updateCell() call per time step is enough.
41 The class is derived from exahype2.api.fv.actionsets.ComputeGlobalCFLCondition,
42 as rkfd4 does not depend on the Finite Volume package. Consult the
43 latter for details on the reduction over threads and ranks.
48 self, solver, patch_size, guard, cfl_constant=None, time_step_size=None
52 @param solver: exahype2.api.Solver
53 With adaptive time stepping, solver._max_eigenvalue has to be set.
55 @param patch_size: int
56 Number of grid cells per patch and axis. The CFL condition is
57 evaluated over the grid cell size, i.e. the mesh cell size divided
61 C++ boolean expression, evaluated per cell in touchCellFirstTime,
62 guarding whether that cell contributes to the CFL condition. Has
63 to match the guard of exahype2.api.rkfd4.actionsets.ComputeMaxEigenvalue.
65 @param cfl_constant: float or None
66 CFL constant for adaptive time stepping.
68 @param time_step_size: float or None
69 Time step size for fixed time stepping. Exactly one of
70 cfl_constant and time_step_size has to be set.
73 AbstractRKFD4ActionSet.__init__(self, solver)
74 if (cfl_constant
is None) == (time_step_size
is None):
75 raise ValueError(
"Set exactly one of cfl_constant and time_step_size")
86 return " _maxEigenvalue = 0.0;\n" if self.
is_adaptive else ""
89 instance =
"repositories::" + self.
_solver.get_name_of_global_instance()
91 admissible_time_step_size = f
"""
92 const peano4::grid::GridStatistics globalStatistics = peano4::parallel::SpacetreeSet::getInstance().getGridStatistics();
93 const double globalMinGridCellH = tarch::la::max( globalStatistics.getMinH() ) / {self.patch_size};
95 // No semaphore required here, as it is only called once per rank
96 double localMaxEigenvalue = _maxEigenvalue;
97 double globalMaxEigenvalue = localMaxEigenvalue;
99 tarch::mpi::Rank::getInstance().allReduce(
100 &localMaxEigenvalue, &globalMaxEigenvalue, 1, MPI_DOUBLE, MPI_MAX,
101 [&]() -> void {{ tarch::services::ServiceRepository::getInstance().receiveDanglingMessages(); }}
104 const double admissibleTimeStepSize = {self.cfl_constant!r} * globalMinGridCellH / globalMaxEigenvalue / Dimensions;
107 admissible_time_step_size = f
"""
108 const double admissibleTimeStepSize = {self.time_step_size!r};
111 admissible_time_step_size
113 // The time stamp advances by the time step size the update used,
114 // newTimeStepSize is the one the next update will use
115 const double usedTimeStepSize = {instance}.getMaxTimeStepSize();
116 const double newTimeStamp = {instance}.getMaxTimeStamp() + usedTimeStepSize;
117 // The last time step is not truncated, i.e. it may overshoot MaxTerminalTime
118 const double newTimeStepSize = admissibleTimeStepSize;
120 {instance}.updateCell( newTimeStepSize, newTimeStamp );
121 {instance}.finishTimeStep();
122 {instance}.startTimeStep(
123 {instance}.getMinTimeStamp(),
124 {instance}.getMaxTimeStamp(),
125 {instance}.getMinTimeStepSize(),
126 {instance}.getMaxTimeStepSize()
128 logInfo( "unprepareTraversal()", "t=" << {instance}.getMaxTimeStamp() << ", new dt=" << newTimeStepSize );
136 static double _maxEigenvalue;
137 static tarch::multicore::BooleanSemaphore _semaphore;
145 + full_qualified_classname
146 +
"::_maxEigenvalue = 0.0;\n"
147 +
"tarch::multicore::BooleanSemaphore "
148 + full_qualified_classname
154 AbstractRKFD4ActionSet.get_includes(self)
157#include "tarch/multicore/BooleanSemaphore.h"
158#include "tarch/multicore/Lock.h"
159#include "tarch/mpi/Rank.h"
160#include "tarch/services/ServiceRepository.h"
161#include "tarch/la/VectorOperations.h"
162#include "peano4/parallel/SpacetreeSet.h"
163#include "peano4/grid/grid.h"
171 == peano4.api.solversteps.ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME
174 tarch::multicore::Lock lock(_semaphore);
175 _maxEigenvalue = std::max( fineGridCell{self._solver._max_eigenvalue.name}.getMaxEigenvalue(0), _maxEigenvalue );
182 == peano4.api.solversteps.ActionSet.OPERATION_TOUCH_CELL_FIRST_TIME
188 return __name__.replace(
".py",
"").replace(
".",
"_")
Base class of the action sets of exahype2.api.rkfd4 which work against the solver.
Determine the time step size of the next Runge-Kutta step and advance the solver's time stamp.
get_attributes(self)
Return attributes as copied and pasted into the generated class.
get_body_of_unprepareTraversal(self)
get_body_of_prepareTraversal(self)
get_action_set_name(self)
You should replicate this function in each subclass, so you get meaningful action set names (otherwis...
get_includes(self)
The includes cover the kernels the numerical scheme generates (exahype2.api.rkfd4....
get_static_initialisations(self, full_qualified_classname)
get_guard_of_operation(self, operation_name)
Return the guard of an operation.
get_body_of_operation(self, operation_name)
Return actual C++ code snippets to be inserted into C++ code.
__init__(self, solver, patch_size, guard, cfl_constant=None, time_step_size=None)