Skip to content

mods⚓︎

Contains models included with DAPPER.

See the README section on test cases (models) for a table overview of the included models.

Defining your own model⚓︎

Below is a sugested structuring followed by most models already within DAPPER. However, you are free to organize your model as you see fit, as long as it culminates in the definition of one or more mods.HiddenMarkovModel. For the sake of modularity, try not to import stuff from DAPPER outside of mods and tools.liveplotting.

  • Make a directory: my_model. It does not have to reside within the dapper/mods folder, but make sure to look into some of the other dirs thereunder as examples, for example dapper/mods/DoublePendulum.
  • Make a file: my_model/__init__.py to hold the core workings of the model. Further details are given below, but the main work lies in defining a step(x, t, dt) function (you can name it however you like, but step is the convention), to implement the dynamical model/system mapping the state x from one time t to another t + dt.
  • Make a file: my_model/demo.py to run step and visually showcase a simulation of the model without any DA, and verify it's working.
  • Make a file: my_model/my_settings_1.py that defines (or "configures", since there is usually little programming logic and flow taking place) a complete mods.HiddenMarkovModel ready for a synthetic experiment (also called "twin experiment" or OSSE).
  • Once you've made some experiments you believe are noteworthy you should add a "suggested settings/tunings" section in comments at the bottom of my_model/my_settings_1.py, listing some of the relevant DA method configurations that you tested, along with the RMSE (or other stats) that you obtained for those methods. You will find plenty of examples already in DAPPER, used for cross-referenced with literature to verify the workings of DAPPER (and the reproducibility of publications).

Details on my_model/__init__.py⚓︎

  • The step function must support 2D-array (i.e. ensemble) and 1D-array (single realization) input, and return output of the same number of dimensions (as the input). See

    • mods.Lorenz63: use of ens_compatible.
    • mods.Lorenz96: use of relatively clever slice notation.
    • mods.LorenzUV: use of cleverer slice notation: ... (ellipsis). Consider pre-defining the slices like so:

      iiX = (..., slice(None, Nx))
      iiP = (..., slice(Nx, None))
      
      to abbreviate the indexing elsewhere.

    • mods.QG: use of parallelized for loop (map).

    Note

    To begin with, test whether the model works on 1 realization, before running it with several (simultaneously). Also, start with a small integration time step, before using more efficient/adventurous time steps. Note that the time step might need to be shorter in assimilation, because it may cause instabilities.

    Note

    Most models are defined using simple procedural style. However, mods.LorenzUV and mods.QG use OOP, which is perhaps more robust when different control-variable settings are to be investigated. The choice is yours.

    In parameter estimation problems, the parameters are treated as input variables to the "forward model". This does not necessarily require OOP. See docs/examples/param_estim.py.

  • Optional: define a suggested/example initial state, x0. This facilitates the specification of initial conditions for different synthetic experiments, as random variables centred on x0. It is also a convenient way just to specify the system size as len(x0). In many experiments, the specific value of x0 does not matter, because most systems are chaotic, and the average of the stats are computed only for time > BurnIn > 0, which will not depend on x0 if the experiment is long enough. Nevertheless, it's often convenient to pre-define a point on the attractor, or basin, or at least ensure "physicality", for quicker spin-up (burn-in).

  • Optional: define a number called Tplot which defines the (sliding) time window used by the liveplotting of diagnostics.

  • Optional: To use the (extended) Kalman filter, or 4D-Var, you will need to define the model linearization, typically called dstep_dx. Note: this only needs to support 1D input (single realization).

Modules:

Name Description
DoublePendulum

The motion of a pendulum with another pendulum attached to its end.

Id

The identity model (that does nothing, i.e. sets output = input).

Ikeda

The "Ikeda map" is a discrete-time dynamical system of size 2.

KS

Kuramoto-Sivashinsky (KS) system: the simplest (?) PDE admitting chaos.

LA

Linear advection (i.e. translation) in 1D.

Lorenz05

A multi-scale, smooth version of the classic Lorenz-96.

Lorenz63

The classic exhibitor of chaos, consisting of 3 coupled ODEs.

Lorenz84

A chaotic system of size 3, like Lorenz-63, but with +complex geometry.

Lorenz96

A 1D emulator of chaotic atmospheric behaviour.

Lorenz96s

A perfect-random version of Lorenz-96.

LorenzUV

The 2-scale/layer/speed coupled version of Lorenz-96.

LotkaVolterra

The generalized predator-prey model, with settings for chaotic dynamics.

QG

Quasi-geostraphic 2D flow. Described in detail by sakov2008b.

VL20

Single-scale Lorenz-96 with an added thermodynamic component.

explore_props

Estimtate the Lyapunov spectrum and other props. of the dynamics of the models.

integration

Time stepping (integration) tools.

pb

Make progbar (wrapper around tqdm) and read1.

utils

Utilities to help define hidden Markov models.

HiddenMarkovModel ⚓︎

Bases: NicePrint

Container class (with some embellishments) for a Hidden Markov Model (HMM).

Should contain the details necessary to run synthetic DA experiments, also known as "twin experiment", or OSSE (observing system simulation experiment). The synthetic truth and observations may then be obtained by running .simulate.

Note

Each model included with DAPPER comes with several examples of model settings from the literature. See, for example, mods.Lorenz63.sakov2012.

Warning

These example configs do not necessarily hold a high programming standard, as they may have been whipped up at short notice to replicate some experiments, and are not intended for re-use. Nevertheless, sometimes they are re-used by another configuration script, leading to a major gotcha/pitfall: changes made to the imported HMM (or the model's module itself) also impact the original object (since they are mutable and thereby referenced). This usually isn't an issue, since one rarely imports two/more separate configurations. However, the test suite imports all configurations, which might then unintentionally interact. To avoid this, you should use the copy method of the HMM before making any changes to it.

__init__(Dyn, Obs, tseq, X0, liveplotters=None, sectors=None, name=None, **kwargs) ⚓︎

Initialize.

Parameters:

Name Type Description Default
Dyn Operator or dict

Operator for the dynamics.

required
Obs Operator or TimeDependentOperator or dict

Operator for the observations Can also be time-dependent, ref TimeDependentOperator.

required
tseq Chronology

Time sequence of the HMM process.

required
X0 RV

Random distribution of initial condition

required
liveplotters list

A list of tuples. See example use in function LPs of mods.Lorenz63. - The first element of the tuple determines if the liveplotter is shown by default. If False, the liveplotter is only shown when included among the liveplots argument of assimilate - The second element in the tuple gives the corresponding liveplotter function/class.

None
sectors dict

Labelled indices referring to parts of the state vector. When defined, field-mean statistics are computed for each sector. Example use can be found in docs/examples/param_estim.py and dapper/mods/Lorenz96/miyoshi2011.py

None
name str

Label for the HMM.

None

simulate(desc='Truth & Obs') ⚓︎

Generate synthetic truth and observations.

Operator ⚓︎

Bases: NicePrint

Container for the dynamical and the observational maps.

Parameters:

Name Type Description Default
M int

Length of output vectors.

required
model function

The actual operator.

None
noise RV

The associated additive noise. The noise can also be a scalar or an array, producing GaussRV(C=noise).

None
Note

Any remaining keyword arguments are written to the object as attributes.

TimeDependentOperator ⚓︎

Wrapper for Operator that enables time dependence.

The time instance should be specified by ko, i.e. the index of an observation time.

Examples: docs/examples/time-dep-obs-operator.py and dapper/mods/QG/sakov2008.py.

__init__(**kwargs) ⚓︎

Can be initialized like Operator, in which case the resulting object will always return the same Operator nomatter the input time.

If initialized with 1 argument: dict(time_dependent=func) then func must return an Operator object.