# Wilks2005 uses dt=1e-4 with RK4 for the full model, # and dt=5e-3 with RK2 for the forecast/truncated model. # As berry2014linear notes, this is possible coz # "numerical stiffness disappears when fast processes are removed". ################ # Full ################ # tseq = modelling.Chronology(dt=0.001,dto=0.05,T=4**3,BurnIn=6) # allows using rk2 tseq = modelling.Chronology(dt=0.005, dto=0.05, T=4**3, BurnIn=6) # requires rk4 Dyn = { 'M': LUV.M, 'model': modelling.with_rk4(LUV.dxdt, autonom=True), 'noise': 0, 'linear': LUV.dstep_dx, } X0 = modelling.GaussRV(mu=LUV.x0, C=0.01) R = 0.1 jj = np.arange(nU) Obs = modelling.partial_Id_Obs(LUV.M, jj) Obs['noise'] = R other = {'name': rel2mods(__file__) + '_full'} HMM_full = modelling.HiddenMarkovModel(Dyn, Obs, tseq,
import numpy as np import dapper.mods as modelling from .extras import LPs, d2x_dtdx, dstep_dx __pdoc__ = {"demo": False} # Constants sig = 10.0 rho = 28.0 beta = 8.0 / 3 @modelling.ens_compatible def dxdt(x): """Evolution equation (coupled ODEs) specifying the dynamics.""" d = np.zeros_like(x) x, y, z = x d[0] = sig * (y - x) d[1] = rho * x - y - x * z d[2] = x * y - beta * z return d step = modelling.with_rk4(dxdt, autonom=True) Tplot = 4.0 x0 = np.array([1.509, -1.531, 25.46])
import numpy as np from matplotlib import pyplot as plt import dapper.mods as modelling from dapper.mods.LorenzUV.lorenz96 import LUV # Setup sd0 = modelling.set_seed(4) # from dapper.mods.LorenzUV.wilks05 import LUV nU, J = LUV.nU, LUV.J dt = 0.005 t0 = np.nan K = int(10/dt) step_1 = modelling.with_rk4(LUV.dxdt, autonom=True) step_K = modelling.with_recursion(step_1, prog=1) x0 = 0.01*np.random.randn(LUV.M) x0 = step_K(x0, int(2/dt), t0, dt)[-1] # BurnIn xx = step_K(x0, K, t0, dt) # Grab parts of state vector ii = np.arange(nU+1) jj = np.arange(nU*J+1) circU = np.mod(ii, nU) circV = np.mod(jj, nU*J) + nU iU = np.hstack([0, 0.5+np.arange(nU), nU]) def Ui(xx): interp = (xx[0]+xx[-1])/2
# In unitless time (as used here), this means LyapExps ∈ ( −4.87, 1.66 ) . if mod == "L96": from dapper.mods.Lorenz96 import step Nx = 40 # State size (flexible). Usually 36 or 40 T = 1e3 # Length of experiment (unitless time). dt = 0.1 # Step length # dt = 0.0083 # Any dt<0.1 yield "almost correct" Lyapunov expos. x0 = randn(Nx) # Init condition. eps = 0.0002 # Ens rescaling factor. N = Nx # Num of perturbations used. # Lyapunov exponents with F=10: [9.47 9.3 8.72 ..., -33.02 -33.61 -34.79] => n0:64 if mod == "LUV": from dapper.mods.LorenzUV.lorenz96 import LUV ii = np.arange(LUV.nU) step = with_rk4(LUV.dxdt, autonom=True) Nx = LUV.M T = 1e2 dt = 0.005 LUV.F = 10 x0 = 0.01*randn(LUV.M) eps = 0.001 N = 66 # Don't need all Nx for a good approximation of upper spectrum. # Lyapunov exponents: [8.36, 7.58, 7.20, 6.91, ..., -4.18, -4.22, -4.19] => n0≈164 if mod == "L05": from dapper.mods.LorenzIII import Model model = Model() step = model.step x0 = model.x0 dt = 0.05/12
# `[x, Force]` as the state variable. # - enclosing `dxdt` in an outer function which binds the value of the Force # - creating `dxdt` in an outer "factory" function which determines the # shape and allocation of the input vector to dxdt. # - Do the latter using OOP. This would probably be more verbose, # but even more flexible. In particular, OOP excels at working with multiple # realisations of models at the same time. However, when using ensemble methods, # the number of realisations, and the required level of automation # (input vector/ensemble --> output vector/ensemble) is very high. # It is not immediately clear if OOP is then more convenient. # - There are also some intriguing possibilities relating to namedtuples. # TODO 4: revise the above text. # Turn dxdt into `step` such that `x_{k+1} = step(x_k, t, dt)` step = modelling.with_rk4(dxdt_augmented, autonom=True) # #### HMM # Define the sequence of the experiment # See `modelling.Chronology` for more details. t = modelling.Chronology( dt=0.05, # Integrational time step dkObs=1, # Steps of duration dt between obs KObs=10**3, # Total number of obs in experiment BurnIn=5, # Omit from averages the period t=0 --> BurnIn Tplot=7) # Default plot length # Define dynamical model Dyn = {
########################### PRMS = 'Lorenz' if PRMS == 'Wilks': from dapper.mods.LorenzUV.wilks05 import LUV else: from dapper.mods.LorenzUV.lorenz96 import LUV nU = LUV.nU K = 400 dt = 0.005 t0 = np.nan modelling.set_seed(30) # 3 5 7 13 15 30 x0 = np.random.randn(LUV.M) true_step = with_rk4(LUV.dxdt, autonom=True) model_step = with_rk4(LUV.dxdt_trunc, autonom=True) true_K = with_recursion(true_step, prog=1) ########################### # Compute truth trajectory ########################### x0 = true_K(x0, int(2 / dt), t0, dt)[-1] # BurnIn xx = true_K(x0, K, t0, dt) ########################### # Compute unresovled scales ########################### gg = np.zeros((K, nU)) # "Unresolved tendency" for k, x in enumerate(xx[:-1]): X = x[:nU]