It is somewhat inevitable in land modeling that different processes operate at vastly different time scales; e.g. soil energy and hydrology dynamics in the vadose zone typically have characteristic time scales of seconds to minutes, while vegetation and carbon processes often have characteristic time scales of days, months, or even years.
There are two practical solutions to this: one is to force all processes in the model onto the a shared, intermediate time scale, e.g. daily time steps. This is simpler from a software engineering point of view but physically harder and requires more sophisticated (e.g. implicit) timestepping for some components. The other (also more common) solution is to allow for multi-scale, or nested, time steps. In principle, we would like to support both options in Terrarium.
The proposed design for multi-scale timestepping is as follows:
- Each process implementation will declare one or more
timescales with a new API:
timescale(::Process) = Second
where the returned value is a Dates.Period type. Note that this is only the type corresponding to an order of magnitude; it does not prescribe specific values or timestep sizes.
AbstractModel implementations collect timescales from all processes and return a Tuple of Period types from timescale(::AbstractModel)
- The
ModelIntegrator will collect all of the time scales and sort them in descending order.
- A new
MultiClock type will be added that composes multiple Clocks each corresponding to a particular time scale.
- The
timestep! API will be changed to accept only Dates.Period types, converted internally to NF only when the tendencies are actually applied.
- Within each integrator
timestep!, the integrator will check the status of the MultiClock and determine which timescales need to be stepped based on the requested timestep size; e.g. if the elapsed time on the Year clock is only 1 month since the last update, multiple Day(1) timesteps could be made before updating it.
- The integrator will then loop over each "active" time scale within the requested step in descending order (i.e. shortest time scale on the innermost loop).
- Each
AbstractModel implementation will optionally be able to provide a timestep! dispatch for dt values of the relevant timescale type (e.g. timestep!(integrator, model::LandModel, dt::Year)).
For simplicity, all model components regardless of scale will still only have access to the transient prognostic state; i.e. we will not accumulate past prognostic states anywhere in the integrator. This is to avoid (for now) the problem of formally or informally supporting delay differentiation equations. This means that any necessary time-averages will need to be directly accumulated as prognostic variables.
This issue is directly related to #137 since it will be required to make the existing daily vegetation model components work in parallel with subdaily components.
It is somewhat inevitable in land modeling that different processes operate at vastly different time scales; e.g. soil energy and hydrology dynamics in the vadose zone typically have characteristic time scales of seconds to minutes, while vegetation and carbon processes often have characteristic time scales of days, months, or even years.
There are two practical solutions to this: one is to force all processes in the model onto the a shared, intermediate time scale, e.g. daily time steps. This is simpler from a software engineering point of view but physically harder and requires more sophisticated (e.g. implicit) timestepping for some components. The other (also more common) solution is to allow for multi-scale, or nested, time steps. In principle, we would like to support both options in Terrarium.
The proposed design for multi-scale timestepping is as follows:
timescales with a new API:where the returned value is a
Dates.Periodtype. Note that this is only the type corresponding to an order of magnitude; it does not prescribe specific values or timestep sizes.AbstractModelimplementations collect timescales from all processes and return aTupleofPeriodtypes fromtimescale(::AbstractModel)ModelIntegratorwill collect all of the time scales and sort them in descending order.MultiClocktype will be added that composes multipleClocks each corresponding to a particular time scale.timestep!API will be changed to accept onlyDates.Periodtypes, converted internally toNFonly when the tendencies are actually applied.timestep!, the integrator will check the status of theMultiClockand determine which timescales need to be stepped based on the requested timestep size; e.g. if the elapsed time on theYearclock is only 1 month since the last update, multipleDay(1)timesteps could be made before updating it.AbstractModelimplementation will optionally be able to provide atimestep!dispatch for dt values of the relevant timescale type (e.g.timestep!(integrator, model::LandModel, dt::Year)).For simplicity, all model components regardless of scale will still only have access to the transient prognostic state; i.e. we will not accumulate past prognostic states anywhere in the integrator. This is to avoid (for now) the problem of formally or informally supporting delay differentiation equations. This means that any necessary time-averages will need to be directly accumulated as prognostic variables.
This issue is directly related to #137 since it will be required to make the existing daily vegetation model components work in parallel with subdaily components.