The time stepper module is responsible for advancing the system in time. Three different time steppers are available, namely a fixed length stepper, a simple error estimating adaptive stepper, and an adaptive stepper which estimates and rescales the time step based on the current ionization time.
Page overview
The constant time stepper advances the system in time at a fixed rate \(\Delta t\) set by the user. The user always needs to specify the maximum simulation time, \(t_{\rm max}\), but can choose to either specify the step length \(\Delta t\) or the number of steps to take, \(N_t\). The options are set using the following code in the Python interface:
ds = DREAMSettings()
...
ds.timestep.setTmax(1e2)
ds.timestep.setDt(5e4)
# or, alternatively...
ds.timestep.setTmax(1e2)
ds.timestep.setNt(20)
By default, every time step taken is saved to the output file. For long
simulations with fine time resolution this may however require a significant
amount of memory and disk space. To reduce the amount of space needed, the
constant time stepper can instructed to only store a certain number of time
steps in the final output file. This is achieved using the
setNumberOfSaveSteps()
method as follows:
ds = DREAMSettings()
...
ds.timestep.setNt(6000)
ds.timestep.setNumberOfSaveSteps(1000)
This will cause the DREAM output file to only contain every 6th time step taken by the solver. Note that the solutions are unaffected by this downsampling—the finer time resolution is still used for evolving the system in time—and the only effect is that the output file contains fewer of the time steps actually taken.
A simple adaptive time stepper has been implemented for DREAM. Since DREAM uses an Euler backward method for time stepping, the adaptive scheme uses basic twopoint time step refinement to estimate the current error in the solution. The scheme consists of the following steps:
Evaluate the solution \(\boldsymbol{x}(t+\Delta t)\) from \(\boldsymbol{x}(t)\)
Evaluate the solution \(\boldsymbol{x}(t+\Delta t/2)\) from \(\boldsymbol{x}(t)\), and then the solution \(\boldsymbol{x}(t+\Delta t)\) from \(\boldsymbol{x}(t+\Delta t/2)\).
Estimate the error in each unknown quantity from the difference between the two solutions for \(t+\Delta t\) obtained in steps 1 and 2.
If the errors in all monitored unknown quantities are acceptably low, the solution is accepted and the optimal time step length for the next step is estimated. If the error in one or more of the monitored quantities is too large, however, a new optimal time step is estimated based on the error and the scheme is repeated for the same time \(t\) from step 1 above.
Warning
The adaptive time stepper is currently considered too unstable to be used in simulations.
Todo
Provide more details about the adaptive time stepper scheme.
Instabilities in DREAM primarily arise when the nonlinear system of equations is evolved with too large time steps, so that the initial guess of Newton’s method (which is that the solution is the same as in the previous time step) is too far from the true solution. These instabilities are therefore caused by physical processes which cause significant variation on time scales shorter than the resolved time scale.
One of the shortest time scales usually encountered in DREAM is that of the ionization of neutral and partially ionized atoms. As greater fractions of the plasma becomes ionized, however, the ionization time scale increases by several orders of magnitude. Therefore, if a simulation is started with a time step that respects the early ionization time scale, it is likely that after a while, the time step is much smaller than necessary, causing the simulation to take unnecessarily long time.
With the ionizationbased adaptive time stepper, we continuously update the time step length \(\Delta t\) as the ionization time scale evolves, by estimating the current ionization time scale from the variation in the cold electron density:
The user then provides the initial time step \(\Delta t_0\) at \(t=0\), after which the time stepper automatically rescales the time step throughout the simulation. A maximum time step can also be selected, since eventually other physical time scales will be shorter than the ionization time scale, making a constant time step suitable.
The time stepper can be instructed to automatically determine the first time step. This is achieved by taking a first very short time step, after which the ionization time scale can be estimated. Since the required time step length will depend also on the numerics (e.g. a kinetic simulation could require higher time resolution than a fluid simulation, since the ionization could induces “greater” variations in the distribution function), a safety factor can be used to adjust how the initial time step is determined.
To use the ionizationbased adaptive time stepper, one should call the
setIonization()
method on the time stepper object. If the user manually
specifies the initial time step length, the method takes the following
arguments:
Option 
Description 


Initial time step. 

Maximum time step allowed. 

Final time of simulation. 
If the time stepper should automatically determine the initial time step, the method takes the following arguments (should be given as keyword arguments):
Option 
Default value 
Description 


\(10^{12}\,\mathrm{s}\) 
Time step used first to estimate the initial ionization time scale. 

None 
Maximum time step allowed. 

50 
Factor giving the relation between the ionization time scale and initial time step. 

Final time of simulation. 
Final time of simulation. 
The number of time steps which are saved to the output file can also be limited
with the ionizationbased adaptive time stepper. However, since the total number
of time steps taken is not known until the simulation is completed, the limit is
based on a minimum requested time resolution instead of a maximum number of
saved steps. The user thus specifies the minimum time duration
\(\Delta t_{\mathrm{save}}\) between two saved time steps. This is done
using the setMinSaveTimestep()
function:
`python
ds = DREAMSettings()
...
ds.timestep.setIonization(dt0=1e10, dtmax=1e5, tmax=0.003)
ds.timestep.setMinSaveTimestep(1e6)
`
To manually specify the initial time step, the following call can be made:
ds = DREAMSettings()
...
ds.timestep.setIonization(dt0=1e10, dtmax=1e5, tmax=0.003)
Alternatively, tmax
can be set separately:
ds = DREAMSettings()
...
ds.timestep.setIonization(dt0=1e10, dtmax=1e5)
ds.timestep.setTmax(0.003)
If the time stepper should automatically determine the initial time step, the following call can be made:
ds = DREAMSettings()
...
ds.timestep.setIonization(dtmax=1e5, tmax=0.003)
Alternatively, if you want to explicitly set the time step used to determine the ionization time scale, or if you want to change the safety factor used to relate the ionization time scale to the initial time step, you can make the call:
ds = DREAMSettings()
...
ds.timestep.setIonization(automaticstep=1e12, safetyfactor=50, dtmax=1e5, tmax=0.003)
DREAM.Settings.TimeStepper.
TimeStepper
(ttype=1, checkevery=0, tmax=None, dt=None, nt=None, nSaveSteps=0, reltol=0.01, verbose=False, constantstep=False)¶Bases: object
__init__
(ttype=1, checkevery=0, tmax=None, dt=None, nt=None, nSaveSteps=0, reltol=0.01, verbose=False, constantstep=False)¶Constructor.
fromdict
(data)¶Load settings from the given dictionary.
set
(ttype=1, checkevery=0, tmax=None, dt=None, nt=None, nSaveSteps=0, reltol=0.01, verbose=False, constantstep=False, minsavedt=0)¶Set properties of the time stepper.
setCheckInterval
(checkevery)¶setConstantStep
(constantstep)¶setDt
(dt)¶setIonization
(dt0=0, dtmax=0, tmax=None, automaticstep=1e12, safetyfactor=50)¶Select and set parameters for the ionization time stepper.
setMinSaveTimestep
(dt)¶For the adapative ionizationbased time stepper, sets the minimum time which must elapse between two saved time steps.
setNt
(nt)¶setNumberOfSaveSteps
(nSaveSteps)¶Sets the number of time steps to save to the output file. This number must be <= Nt. If 0, all time steps are saved.
setRelTol
(reltol)¶setRelativeTolerance
(reltol)¶setTmax
(tmax)¶setType
(ttype, *args, **kwargs)¶setVerbose
(verbose=True)¶todict
(verify=True)¶Returns a Python dictionary containing all settings of this TimeStepper object.
verifySettings
()¶Verify that the TimeStepper settings are consistent.