-
Notifications
You must be signed in to change notification settings - Fork 21
TimeSteppers
Redback has an adaptive timestepper. This means it can dynamically vary timestep size depending on how difficult the solve is. Also, in the case where the sim crashes due to timestep being too large - "constitutive error" in the logs, it will automatically start back up with half the timestep size.
Even when a simulation doesn't crash, having too large/too small timestep impacts performance. You can wring a lot of speed out of large sims by tweaking the timestepper. This may be worth it if you have to run an exceptionally large problem, or run the same sim many hundreds of times. Alternatively, you can selectively lower the timestep size at critical points in the sim to prevent crashes.
At the moment we only have one custom time stepper, ReturnMapIterDT, which reduces the timestep based on the number of iterations taken by the returnMap algorithm (for mechanics). This is a pre-emptive way to avoid a simulation to crash when the maximum allowed number of returnMap iterations is reached. In time, MOOSE should/will propose a way to interact with libmesh and restart the iteration with a smaller timestep when that maximum number of iteration is reached, but for the moment the simulation crashes, hence the need for this custom time stepper.
This time stepper works with a postprocessor which monitors the maximum number of iteration of the returnMap algorithm over the whole mesh. It can then cut the time step by multiplying it by ratio (e.g. 0.5) if the maximum number of iteration is above max_iter or divide by that ratio if the maximum number of iteration is below min_iter.
For example, create an AuxVariable...
[./returnmap_iter]
order = CONSTANT
family = MONOMIAL
block = 0
[../]
... to use in an AuxKernel...
[./returnmap_iter]
type = MaterialRealAux
variable = returnmap_iter
property = returnmap_iter
block = 0
[../]
... which will define a PostProcessor...
[./max_returnmap_iter]
type = ElementExtremeValue
variable = returnmap_iter
[../]
... that is required by the TimeStepper:
[./TimeStepper]
type = ReturnMapIterDT
dt = 1e-3
min_iter = 10
ratio = 0.5
max_iter = 20
dt_max = 1e-3
postprocessor = max_returnmap_iter
dt_min = 1e-5
[../]
One good way to mix and match several time steppers is to use the PostprocessorDT TimeStepper.
First, define some PostProcessors that you'll need:
[./num_nli]
type = NumNonlinearIterations
[../]
[./timestep]
type = TimestepSize
[../]
Then, define a function with the formula you want, using other PostProcessors. For example, using the previous timestep and the number of non-linear iterations:
[./timestep_function]
type = ParsedFunction
value = 'max(1e-3, min(dt*max(1-0.1*(n-4), 0.2), 1.0))'
vals = 'num_nli timestep'
vars = 'n dt'
[../]
This function can be turned into a PostProcessor of type PlotFunction:
[./new_timestep]
type = PlotFunction
function = timestep_function
[../]
And that PostProcessor can then be used as a TimeStepper:
[./TimeStepper]
type = PostprocessorDT
dt = 0.5
postprocessor = new_timestep
[../]
The input file part looks something like this (from my sandstone sims):
[./timestep_function]
type = ParsedFunction
value = "if(m<1, 0.01,if(((m<4.5)+(n<4))>1,if(((m<4)+(n<3))>1, dt*1.05,dt),dt*0.9))"
vals = 'num_nli dt max_returnmap_iter'
vars = 'n dt m'
[../]
type = ParsedFunction
This tells Redback that you will use a user-supplied function.
vals = 'num_nli dt max_returnmap_iter' vars = 'n dt m'
assign the num_nli, dt, max_returnmap_iter postprocessors to variables n, dt, m respectively. These values should be visible in the csv file. Values are updated at each timestep.
num_nli
number of non-linear iterations
max_returnmap_iter
number of return map iterations (this is zero in elasticity and >0 in plasticity)
dt
last timestep size
value = "if(m<1, 0.01,if(((m<4.5)+(n<4))>1,if(((m<4)+(n<3))>1, dt*1.05,dt),dt*0.9))"
This is the equation that controls timestep size. Syntax is horrible because it all has to fit on one line. With proper formatting it's not so bad:
if(
m<1,
0.01,
if(
((m<4.5)+(n<4))>1,
if(
((m<4)+(n<3))>1,
dt*1.05,
dt
),
dt*0.9
)
)
Explanation:
if(x,y,z)
If condition-x, set timestep to y, otherwise set timestep to z.
(m<4.5)+(n<4))>1
(boolean_x+boolean_y)>1 is logical AND. Similarly, (boolean_x+boolean_y)>0 is logical OR. I can't find the proper syntax for logical operators anywhere so this will do.
if(m<1,0.01, ...)
If m<1 (i.e. we're in elastic regime), set timestep-size to 0.01, otherwise {do stuff}.
if(((m<4)+(n<3))>1, dt*1.05,dt)
If m<4.5 AND n<4, set next timestep size to 1.05 times current timestep size; otherwise no change.
The numbers in the above equation - 0.01, 4.5, 1.05, etc -- are obtained from trial and error. Most likely they will be different for a different problem.
REDBACK: Rock mEchanics with Dissipative feedBACKs