Skip to content

Commit f4296be

Browse files
System AdministratorSystem Administrator
authored andcommitted
in flight changes
1 parent 4536a16 commit f4296be

19 files changed

Lines changed: 656 additions & 378 deletions

class_da_system.py

Lines changed: 44 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
class da_system:
99

10-
def __init__(self,x0=[0],yo=[0],t0=0,dt=0,alpha=0.5,state_vector=[0],obs_data=[0]):
10+
def __init__(self,x0=[],yo=[],t0=0,dt=0,alpha=0.5,state_vector=[],obs_data=[],acyc_step=10):
1111
self.xdim = np.size(x0)
1212
self.ydim = np.size(yo)
1313
self.edim = 1
@@ -16,15 +16,19 @@ def __init__(self,x0=[0],yo=[0],t0=0,dt=0,alpha=0.5,state_vector=[0],obs_data=[0
1616
self.dt = dt
1717
self.X0 = x0
1818
self.t = t0
19-
self.ainc = 1
19+
self.acyc_step = acyc_step
20+
self.dtau = dt*acyc_step
21+
self.fcst_step = acyc_step
22+
self.fcst_dt = dt
23+
self.maxit = 0
2024
self.B = np.matrix(np.identity(self.xdim))
2125
self.R = np.matrix(np.identity(self.ydim))
2226
self.H = np.matrix(np.identity(self.xdim))
2327
self.Ht = (self.H).transpose()
2428
self.alpha = alpha
25-
self.SqrtB = sp.linalg.sqrtm(self.B)
26-
self.obs_data = obs_data
29+
self.SqrtB = []
2730
self.state_vector = state_vector
31+
self.obs_data = obs_data
2832

2933
def __str__(self):
3034
print('xdim = ', self.xdim)
@@ -33,10 +37,20 @@ def __str__(self):
3337
print('t0 = ', self.t0)
3438
print('dt = ', self.dt)
3539
print('t = ', self.t)
40+
print('acyc_step = ', self.acyc_step)
41+
print('dtau = ', self.dtau)
42+
print('fcst_step = ', self.fcst_step)
43+
print('fcst_dt = ', self.fcst_dt)
3644
print('B = ')
3745
print(self.B)
3846
print('R = ')
3947
print(self.R)
48+
print('H = ')
49+
print(self.H)
50+
print('state_vector = ')
51+
print(self.state_vector)
52+
print('obs_data = ')
53+
print(obs_data)
4054
return 'type::da_system'
4155

4256
def setMethod(self,method):
@@ -113,42 +127,56 @@ def reduceYdim(self,yp):
113127
self.setR(self.R[yp,yp])
114128

115129
def compute_analysis(self,xb,yo,params=[0]):
130+
# (params needed for 4D-Var)
116131
method = self.method
117132
if method == 'skip':
118133
xa = xb
134+
KH = np.identity(self.xdim)
119135
elif method == 'nudging':
120-
xa = self.nudging(xb,yo)
136+
xa,KH = self.nudging(xb,yo)
121137
elif method == 'OI':
122-
xa = self.OI(xb,yo)
138+
xa,KH = self.OI(xb,yo)
123139
elif method == '3DVar' or method == '3D-Var':
124-
xa = self._3DVar(xb,yo)
140+
xa,KH = self._3DVar(xb,yo)
125141
elif method == 'ETKF' or method == 'EnKF':
126-
xa = self.ETKF(xb,yo)
142+
xa,KH = self.ETKF(xb,yo)
127143
elif method == 'PF':
128-
xa = self.PF(xb,yo)
144+
xa,KH = self.PF(xb,yo)
129145
elif method == 'Hybrid':
130-
xa = self.HybridGain(xb,yo)
146+
xa,KH = self.HybridGain(xb,yo)
131147
# elif method == '4DVar' or method == '4D-Var':
132-
# xa = self._4DVar(xb,yo)
148+
# xa,KH = self._4DVar(xb,yo)
133149
# elif method == '4DEnVar':
134-
# xa = self._4DEnVar(xb,yo)
150+
# xa,KH = self._4DEnVar(xb,yo)
135151
# elif method == '4DETKF':
136-
# xa = self._4DETKF(xb,yo)
152+
# xa,KH = self._4DETKF(xb,yo)
137153
else:
138154
print('compute_analysis:: Unrecognized DA method.')
139155
raise SystemExit
140-
return xa
156+
return xa,KH
141157

142158
def initEns(self,x0,mu=0,sigma=0.1,edim=4):
143159
xdim = len(x0)
144160
x0 = np.matrix(x0).flatten().T
145-
xrand = np.random.normal(mu,sigma,(xdim,edim))
161+
mu = np.matrix(mu).flatten().T
162+
Xrand = np.random.normal(0,sigma,(xdim,edim))
163+
Xrand = np.matrix(Xrand)
164+
# print('Xrand = ')
165+
# print(Xrand)
166+
# Remove mean to make sure it is properly centered at 0
167+
# (add bias if included)
168+
rand_mean = np.mean(Xrand,axis=1) + mu
169+
# print('rand_mean = ')
170+
# print(rand_mean)
171+
rmat = np.matlib.repmat(rand_mean,1,edim)
172+
Xrand = Xrand - rmat
146173
# print('xrand = ')
147174
# print(xrand)
175+
# add perturbations to x0
148176
rmat = np.matlib.repmat(x0, 1, edim)
149177
# print('rmat = ')
150178
# print(rmat)
151-
X0 = np.matrix(rmat + xrand)
179+
X0 = np.matrix(rmat + Xrand)
152180
return X0
153181

154182
# def init4D(self):

class_lorenz63.py

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import plotly.offline as py
44
import plotly.graph_objs as go
55
from plotly import tools
6-
#from copy import deepcopy
6+
from copy import deepcopy
77

88
#------------------------------------------------------------------
99
# Define functions
@@ -14,9 +14,10 @@ def f(state, t, sigma, rho, beta):
1414

1515
def Ja(state, t, sigma, rho, beta):
1616
x, y, z = state # unpack the state vector
17-
J = [[-sigma, sigma, 0 ]
18-
[ rho-z, -1, -x ]
17+
J = [[-sigma, sigma, 0 ],
18+
[ rho-z, -1, -x ],
1919
[ y, x, -beta]]
20+
J = np.matrix(J)
2021
return J
2122

2223
def Jfd(state0,state1,params):
@@ -125,6 +126,44 @@ def run(self, state0, t):
125126
states = odeint(f, state0, t, args=(self.sigma, self.rho, self.beta))
126127
return states
127128

129+
#------------------------------------------------------------------
130+
# Compute approximate TLM with I + Df(x0)*dt
131+
#------------------------------------------------------------------
132+
def compute_TLMa(self, states, t):
133+
134+
print('states = ')
135+
print(states)
136+
137+
print('times = ')
138+
print(t)
139+
140+
nr,nc = np.shape(states)
141+
I = np.identity(nc)
142+
143+
# Compute Jacobian / linear propagator for each timestep
144+
sigma,rho,beta = self.params
145+
maxit = len(t)
146+
Mhist=[]
147+
for i in range(maxit):
148+
if (i < maxit-1):
149+
dt = t[i+1] - t[i]
150+
else:
151+
dt = t[-1] - t[-2]
152+
153+
# Evaluate Jacobian
154+
Df = Ja(states[i,:], t[i], sigma, rho, beta)
155+
156+
# print('Df = ')
157+
# print(Df)
158+
159+
# Compute approximate linear propagator
160+
# (Note this is a poor approximation of the matrix integral,
161+
# we would prefer a geometric integrator, e.g. the Magnus expansion)
162+
M = I + Df*dt
163+
Mhist.append(deepcopy(M))
164+
165+
return Mhist
166+
128167
#------------------------------------------------------------------
129168
# Compute approximate Jacobian with finite differences
130169
#------------------------------------------------------------------
@@ -188,10 +227,10 @@ def plot(self, states,cvec,outfile='l63-3d',plot_title='Lorenz 63 attractor'):
188227
data = [trace]
189228

190229
layout = dict(
191-
width=800,
230+
width=1200,
192231
height=700,
193232
autosize=False,
194-
title=self.title,
233+
title=plot_title,
195234
scene=dict(
196235
xaxis=dict(
197236
gridcolor='rgb(255, 255, 255)',

class_obs_data.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ def __str__(self):
2323
print(self.err)
2424
print('Positions:')
2525
print(self.pos)
26-
print('Time interval:')
27-
print(self.t)
26+
# print('Time interval:')
27+
# print(self.t)
2828
print('Values:')
2929
print(self.val)
3030
return self.name

class_state_vector.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ def __init__(self,params=[0],x0=[0],t=[0],name='uninitialized'):
1616
self.Mhist = []
1717
self.Qhist = []
1818
self.Rhist = []
19+
self.hist_ainc = 0
20+
self.hist_dtau = 0
1921
self.hist_idx = []
2022
self.rescale_interval = 1
2123
self.TLM = []
@@ -36,6 +38,9 @@ def __str__(self):
3638
print(self.clim_std)
3739
return self.name
3840

41+
def setName(self,name):
42+
self.name = name
43+
3944
def getTrajectory(self):
4045
return self.trajectory
4146

@@ -75,6 +80,12 @@ def getMhist(self):
7580
def setMhist(self,Mhist):
7681
self.Mhist = Mhist
7782

83+
def getM2hist(self):
84+
return self.M2hist
85+
86+
def setM2hist(self,M2hist):
87+
self.M2hist = M2hist
88+
7889
def getQhist(self):
7990
return self.Qhist
8091

generate_analysis_3dDet.py

Lines changed: 49 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,30 +6,48 @@
66
from class_state_vector import state_vector
77
from class_obs_data import obs_data
88
from class_da_system import da_system
9+
from copy import deepcopy
910

1011
#-----------------------------------------------------------------------
1112
# Read the da system object
1213
#-----------------------------------------------------------------------
13-
name = 'x_analysis_init'
14-
infile = name+'.pkl'
14+
name = 'x_analysis'
15+
infile = name+'_init.pkl'
16+
das = da_system()
17+
das = das.load(infile)
18+
19+
print(das)
20+
21+
#-----------------------------------------------------------------------
22+
# Get the nature run trajectory
23+
#-----------------------------------------------------------------------
1524
sv = das.getStateVector()
1625
x_nature = sv.getTrajectory()
1726

27+
#-----------------------------------------------------------------------
28+
# Get the L63 observations via the obs_data object
29+
#-----------------------------------------------------------------------
30+
obs = das.getObsData()
31+
y_obs = obs.getVal()
32+
y_pts = obs.getPos()
33+
y_err = obs.getErr()
34+
print('y_obs = ')
35+
print(y_obs[0,:])
36+
print('y_pts = ')
37+
print(y_pts[0,:])
38+
1839
#-----------------------------------------------------------------------
1940
# Initialize the timesteps
2041
#-----------------------------------------------------------------------
2142
t_nature = sv.getTimes()
22-
ainc_step = das.ainc # (how frequently to perform an analysis)
43+
acyc_step = das.acyc_step # (how frequently to perform an analysis)
2344
dtau = das.dtau
24-
tsteps= das.tsteps
2545
dt = das.dt
46+
fcst_step= das.fcst_step
47+
fcst_dt = das.fcst_dt
2648
maxit = das.maxit
2749
xdim = das.xdim
28-
29-
#-----------------------------------------------------------------------
30-
# Get the L63 observations via the obs_data object
31-
#-----------------------------------------------------------------------
32-
obs = das.getObsData()
50+
ydim = das.ydim
3351

3452
#-----------------------------------------------------------------------
3553
# Initialize the model
@@ -43,23 +61,21 @@
4361
method = das.getMethod() # (use default)
4462

4563
#-----------
46-
# Session 0:
4764
# Test basic functionality
4865
#-----------
4966
#method='skip'
5067

5168
#-----------
52-
# Session 2:
5369
# 3D methods
5470
#-----------
5571
# Nudging
5672
#method='nudging'
5773
# OI
58-
method='OI'
74+
#method='OI'
5975
# 3D-Var
6076
#method='3DVar'
6177

62-
das.setMethod(method)
78+
#das.setMethod(method)
6379

6480
#-----------------------------------------------------------------------
6581
# Conduct data assimilation process
@@ -68,31 +84,28 @@
6884
xa = sv.x0
6985
xa_history = np.zeros_like(x_nature)
7086
KH_history = []
71-
for i in range(0,maxit,ainc_step):
87+
for i in range(0,maxit-acyc_step,acyc_step):
7288

7389
#----------------------------------------------
7490
# Run forecast model for this analysis cycle:
7591
#----------------------------------------------
76-
t = np.arange(t_nature[i],t_nature[i]+dtau+dt,dt)
92+
t = np.arange(t_nature[i],t_nature[i+acyc_step]+dt,dt)
7793
# print('t = ', t)
94+
# print('t_nature[i+acyc_step] = ', t_nature[i+acyc_step])
95+
7896
# Run the model
79-
xf_4D = l63.run(xa,t)
97+
xf_4d = l63.run(xa,t)
8098
# Get last timestep of the forecast
81-
xf = xf_4D[-1,:]
99+
xf = xf_4d[-1,:]
82100

83101
#----------------------------------------------
84102
# Get the observations for this analysis cycle
85103
#----------------------------------------------
86-
yo = y_obs[i,:]
87-
yp = y_pts[i,:]
104+
yo = y_obs[i+acyc_step,:]
105+
yp = y_pts[i+acyc_step,:]
88106

89-
#----------------------------------------------
90-
# Update the error covariances
91-
#----------------------------------------------
92-
das.setB(sigma_b**2*I)
93-
das.setR(sigma_r**2*I)
94-
das.setH(I)
95-
das.reduceYdim(yp)
107+
# if (len(yp) < xdim):
108+
# das.reduceYdim(yp)
96109

97110
#----------------------------------------------
98111
# Compute analysis
@@ -104,10 +117,14 @@
104117
# print(KH)
105118

106119
# Archive the analysis
107-
xa_history[i,:] = xa
120+
xa_history[i+acyc_step,:] = xa
121+
# Fill in the missing timesteps with the forecast from the previous analysis IC's
122+
xa_history[i:i+acyc_step,:] = xf_4d[0:acyc_step,:]
123+
124+
# print('xa_history[i:i+acyc_step+1,:] = ', xa_history[i:i+acyc_step+1,:])
108125

109126
# Archive the KH matrix
110-
KH_history.append(KH)
127+
KH_history.append(deepcopy(KH))
111128

112129
#--------------------------------------------------------------------------------
113130
# Fill in unobserved dimensions (for plotting)
@@ -117,7 +134,10 @@
117134
#das.setObsData(obs)
118135

119136
sv.setTrajectory(xa_history)
137+
sv.setName(name)
120138
das.setStateVector(sv)
121139

122-
outfile='x_analysis_'+method+'.pkl'
140+
outfile=name+'_'+method+'.pkl'
123141
das.save(outfile)
142+
143+
print(das)

0 commit comments

Comments
 (0)