Skip to content

TimeSteppers

jacklinzoho edited this page Feb 8, 2018 · 11 revisions

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.

ReturnMapIterDT

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.

How to use it?

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
[../]

Using PostProcessors

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
[../]

Making a new timestep function

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.