Skip to content

Commit 3fea498

Browse files
System AdministratorSystem Administrator
authored andcommitted
initial implementation
1 parent 26296d0 commit 3fea498

14 files changed

Lines changed: 1177 additions & 0 deletions

class_da_system.py

Lines changed: 282 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,282 @@
1+
import numpy as np
2+
import scipy as sp
3+
from class_state_vector import state_vector
4+
from class_obs_data import obs_data
5+
6+
class da_system:
7+
8+
def __init__(self,x0=[0],yo=[0],t0=0,dt=0):
9+
self.xdim = np.size(x0)
10+
self.ydim = np.size(yo)
11+
self.x0 = x0
12+
self.t0 = t0
13+
self.dt = dt
14+
self.X0 = x0
15+
self.t = t0
16+
self.B = np.matrix(np.identity(self.xdim))
17+
self.R = np.matrix(np.identity(self.ydim))
18+
self.H = np.matrix(np.identity(self.xdim))
19+
self.Ht = (self.H).transpose()
20+
# self.SqrtB =
21+
22+
def __str__(self):
23+
print('xdim = ', self.xdim)
24+
print('ydim = ', self.ydim)
25+
print('x0 = ', self.x0)
26+
print('t0 = ', self.t0)
27+
print('dt = ', self.dt)
28+
print('t = ', self.t)
29+
print('B = ')
30+
print(self.B)
31+
print('R = ')
32+
print(self.R)
33+
return 'type::da_system'
34+
35+
def setMethod(self,method):
36+
self.method = method
37+
38+
def update(self,B=[0],R=[0],H=[0],t=[0],x0=[0]):
39+
# Update the state of the DA system for a new cycle
40+
self.B = B
41+
self.R = R
42+
self.H = H
43+
self.Ht = H.Transpose()
44+
self.t = t
45+
self.x0 = x0
46+
47+
def getB(self):
48+
return self.B
49+
50+
def setB(self,B):
51+
self.B = np.matrix(B)
52+
nr,nc = np.shape(B)
53+
self.xdim = nr
54+
55+
def getR(self):
56+
return self.R
57+
58+
def setR(self,R):
59+
self.R = np.matrix(R)
60+
nr,nc = np.shape(R)
61+
self.ydim = nr
62+
63+
def getH(self):
64+
return self.H
65+
66+
def setH(self,H):
67+
self.H = np.matrix(H)
68+
self.Ht = np.transpose(self.H)
69+
nr,nc = np.shape(H)
70+
71+
# Verify that H is ydim x xdim
72+
if (nr != self.ydim):
73+
error('H must be ydim x xdim, but instead H is %d x %d'%(nr,nc))
74+
if (nc != self.xdim):
75+
error('H must be ydim x xdim, but instead H is %d x %d'%(nr,nc))
76+
77+
def compute_analysis(self,xb,yo,params=[0]):
78+
method = self.method
79+
if method == 'skip':
80+
xa = xb
81+
elif method == 'nudging':
82+
xa = self.nudging(xb,yo)
83+
elif method == 'OI':
84+
xa = self.OI(xb,yo)
85+
elif method == '3DVar' or method == '3D-Var':
86+
xa = self._3DVar(xb,yo)
87+
# elif method == '4DVar' or method == '4D-Var':
88+
# xa = self._4DVar(xb,yo)
89+
# elif method == 'PF':
90+
# xa = self.PF(xb,yo)
91+
# elif method == 'ETKF' or method == 'EnKF':
92+
# xa = self.ETKF(xb,yo)
93+
# elif method == '4DEnVar':
94+
# xa = self._4DEnVar(xb,yo)
95+
# elif method == '4DETKF':
96+
# xa = self._4DETKF(xb,yo)
97+
else:
98+
print('compute_analysis:: Unrecognized DA method.')
99+
return xa
100+
101+
# def init_ens(self,sigma=0.1,nens=2):
102+
# xdim = size(self.x0)
103+
# self.X0 = np.matlib.repmat(self.x0, 1, nens) + np.random.normal(mu,sigma,(xdim,nens))
104+
105+
# def init_4D(self):
106+
# xdim = size(self.x0)
107+
108+
# def init_4DEns(self):
109+
# xdim = size(self.x0)
110+
111+
#---------------------------------------------------------------------------------------------------
112+
def nudging(self,xb,yo):
113+
#---------------------------------------------------------------------------------------------------
114+
# Use observations at predefined points to drive the model system to the observed nature system
115+
const = np.diagonal(self.B)
116+
xa = xb + const*(yo - xb)
117+
118+
C = np.diag(const)
119+
Hl = self.H
120+
Ht = self.Ht
121+
KH = Ht*C*Hl
122+
123+
return xa,KH
124+
125+
#---------------------------------------------------------------------------------------------------
126+
def OI(self,xb,yo):
127+
#---------------------------------------------------------------------------------------------------
128+
xb = np.matrix(xb).flatten().T
129+
yo = np.matrix(yo).flatten().T
130+
131+
# Use explicit expression to solve for the analysis
132+
print(self)
133+
H = self.H
134+
Ht = self.Ht
135+
B = self.B
136+
R = self.R
137+
138+
KH = B*Ht*np.linalg.inv(H*B*Ht + R)*H
139+
140+
print('KH = ')
141+
print(KH)
142+
143+
Hxb = H*xb.flatten().T
144+
xa = xb + KH*(yo - Hxb)
145+
146+
return xa.A1, KH
147+
148+
149+
#---------------------------------------------------------------------------------------------------
150+
def _3DVar(self,xb,yo):
151+
#---------------------------------------------------------------------------------------------------
152+
# Use minimization algorithm to solve for the analysis
153+
xdim = self.xdim
154+
Hl = self.H
155+
Ht = self.Ht
156+
B = self.B
157+
R = self.R
158+
Rinv = np.linalg.inv(R)
159+
160+
# make inputs column vectors
161+
xb = np.matrix(xb).flatten().T
162+
yo = np.matrix(yo).flatten().T
163+
164+
# 'preconditioning with B'
165+
I = np.identity(xdim)
166+
BHt = B*Ht
167+
BHtRinv = BHt*Rinv
168+
A = I + BHtRinv*Hl
169+
b1 = xb + BHtRinv*yo
170+
171+
# Use minimization algorithm to minimize cost function:
172+
xa,ierr = sp.sparse.linalg.cg(A,b1,x0=xb,tol=1e-05,maxiter=1000)
173+
# xa,ierr = sp.sparse.linalg.bicgstab(A,b1,x0=np.zeros_like(b1),tol=1e-05,maxiter=1000)
174+
# try: gmres,
175+
# xa = sp.optimize.minimize(fun, x0, args=(), method=None, jac=None, hess=None, hessp=None, bounds=None, constraints=(), tol=None, callback=None, options=None)
176+
177+
# Compute KH:
178+
HBHtPlusR_inv = np.linalg.inv(Hl*BHt + R)
179+
KH = BHt*HBHtPlusR_inv*Hl
180+
181+
return xa, KH
182+
183+
184+
#---------------------------------------------------------------------------------------------------
185+
# def ETKF(self,Xb,yo):
186+
#---------------------------------------------------------------------------------------------------
187+
# # Use ensemble of states to estimate background error covariance
188+
xdim = self.xdim
189+
Yf = self.H*Xb
190+
R = self.R
191+
Yb = np.zeros([nobs,kdim])
192+
for i in range(kdim):
193+
Yb[:,i] = H*Xb[:,i]
194+
195+
# Convert ensemble members to perturbations
196+
xm = np.mean(Xb,axis=1)
197+
ym = np.mean(Yb,axis=1)
198+
Xb = Xb - xm[:,np.newaxis]
199+
Yb = Yb - ym[:,np.newaxis]
200+
201+
# Compute R^{-1}
202+
Rinv = np.linalg.inv(R)
203+
204+
# Compute the weights
205+
Ybt = np.transpose(Yb)
206+
C = np.dot(Ybt,Rinv)
207+
208+
I = np.identity(kdim)
209+
rho = 1.0
210+
eigArg = (kdim-1)*I/rho + np.dot(C,Yb)
211+
lamda,P = np.linalg.eigh(eigArg)
212+
Linv = np.diag(1.0/lamda)
213+
PLinv = np.dor(P,Linv)
214+
Pt = np.transpose(P)
215+
Pa = np.dot(PLinv,Pt)
216+
217+
Linvsqrt = np.diag(1/np.sqrt(lamda))
218+
PLinvsqrt = np.dor(P,Linvsqrt)
219+
Wa = np.sqrt(kdim-1) * np.dot(PLinvsqrt,Pt)
220+
221+
d = yo - ym
222+
Cd = np.dot(C,d)
223+
wm = np.dot(Pa,Cd)
224+
225+
Wa = Wa + wm[:,np.newaxis]
226+
227+
# Add the same mean vector wm to each column
228+
Xa = np.dot(Xb,Wa) + xm[:,np.newaxis]
229+
230+
# Compute KH:
231+
Hl = self.H
232+
Pb = np.dot(Xb,np.transpose(Xb))
233+
Ht = np.transpose(H)
234+
PbHt = np.dot*(Pb,Ht)
235+
HPbHtPlusR_inv = np.linalg.inv(np.dot(Hl,PbHt) + R)
236+
K = np.dot(PbHt,HPbHtPlusR_inv)
237+
KH = np.dot(K,Hl)
238+
239+
240+
return Xa, KH
241+
242+
243+
#---------------------------------------------------------------------------------------------------
244+
# def _4DVar(self,xb_4d,yo_4d):
245+
#---------------------------------------------------------------------------------------------------
246+
# # Use minimization over a time window to solve for the analysis
247+
248+
B = self.B
249+
R = self.R
250+
xdim = self.xdim
251+
Xb = np.matrix(np.atleast_2d(Xb))
252+
Yo = np.matrix(np.atleast_2d(Yo))
253+
Yp = np.matrix(np.atleast_2d(Yp))
254+
255+
256+
257+
#---------------------------------------------------------------------------------------------------
258+
# def 4DEnVar(self,Xb_4d,yo_4d):
259+
#---------------------------------------------------------------------------------------------------
260+
# # Use ensemble of states over a time window to estimate temporal correlations
261+
# xdim = size(self.x0)
262+
263+
264+
#---------------------------------------------------------------------------------------------------
265+
# def 4DETKF(self,Xb_4d,yo_4d):
266+
#---------------------------------------------------------------------------------------------------
267+
# # Use ensemble of states over a time window to estimate temporal correlations
268+
# xdim = size(self.x0)
269+
270+
271+
#---------------------------------------------------------------------------------------------------
272+
# def PF(self,Xb,yo):
273+
#---------------------------------------------------------------------------------------------------
274+
# # Use an ensemble of states to estimate a multidimensional probability distribution
275+
# xdim = size(self.x0)
276+
277+
278+
#---------------------------------------------------------------------------------------------------
279+
# def Hybrid(self,Xb,yo):
280+
#---------------------------------------------------------------------------------------------------
281+
# # Use a hybrid method to compute the analysis
282+
# xdim = size(self.x0)

0 commit comments

Comments
 (0)