33from class_state_vector import state_vector
44from class_obs_data import obs_data
55import numpy .matlib
6+ import pickle
67
78class da_system :
89
9- def __init__ (self ,x0 = [0 ],yo = [0 ],t0 = 0 ,dt = 0 ,alpha = 0.5 ):
10+ def __init__ (self ,x0 = [0 ],yo = [0 ],t0 = 0 ,dt = 0 ,alpha = 0.5 , state_vector = [ 0 ], obs_data = [ 0 ] ):
1011 self .xdim = np .size (x0 )
1112 self .ydim = np .size (yo )
1213 self .edim = 1
@@ -15,12 +16,15 @@ def __init__(self,x0=[0],yo=[0],t0=0,dt=0,alpha=0.5):
1516 self .dt = dt
1617 self .X0 = x0
1718 self .t = t0
19+ self .ainc = 1
1820 self .B = np .matrix (np .identity (self .xdim ))
1921 self .R = np .matrix (np .identity (self .ydim ))
2022 self .H = np .matrix (np .identity (self .xdim ))
2123 self .Ht = (self .H ).transpose ()
2224 self .alpha = alpha
2325 self .SqrtB = sp .linalg .sqrtm (self .B )
26+ self .obs_data = obs_data
27+ self .state_vector = state_vector
2428
2529 def __str__ (self ):
2630 print ('xdim = ' , self .xdim )
@@ -38,6 +42,21 @@ def __str__(self):
3842 def setMethod (self ,method ):
3943 self .method = method
4044
45+ def getMethod (self ):
46+ return self .method
47+
48+ def setStateVector (self ,sv ):
49+ self .state_vector = sv
50+
51+ def setObsData (self ,obs ):
52+ self .obs_data = obs
53+
54+ def getStateVector (self ):
55+ return self .state_vector
56+
57+ def getObsData (self ):
58+ return self .obs_data
59+
4160 def update (self ,B = [0 ],R = [0 ],H = [0 ],t = [0 ],x0 = [0 ]):
4261 # Update the state of the DA system for a new cycle
4362 self .B = B
@@ -68,8 +87,8 @@ def getR(self):
6887
6988 def setR (self ,R ):
7089 self .R = np .matrix (R )
71- nr ,nc = np .shape (R )
72- self .ydim = nr
90+ # nr,nc = np.shape(R)
91+ # self.ydim = nr
7392 self .Rinv = np .linalg .inv (R )
7493
7594 def getH (self ):
@@ -78,13 +97,20 @@ def getH(self):
7897 def setH (self ,H ):
7998 self .H = np .matrix (H )
8099 self .Ht = np .transpose (self .H )
81- nr ,nc = np .shape (H )
100+ # nr,nc = np.shape(H)
82101
83102 # Verify that H is ydim x xdim
84- if (nr != self .ydim ):
85- error ('H must be ydim x xdim, but instead H is %d x %d' % (nr ,nc ))
86- if (nc != self .xdim ):
87- error ('H must be ydim x xdim, but instead H is %d x %d' % (nr ,nc ))
103+ # if (nr != self.ydim):
104+ # error('H must be ydim x xdim, but instead H is %d x %d'%(nr,nc))
105+ # if (nc != self.xdim):
106+ # error('H must be ydim x xdim, but instead H is %d x %d'%(nr,nc))
107+
108+ def reduceYdim (self ,yp ):
109+ # print('reduceYdim:')
110+ # print('yp = ', yp)
111+ self .ydim = len (yp )
112+ self .setH (self .H [yp ,:])
113+ self .setR (self .R [yp ,yp ])
88114
89115 def compute_analysis (self ,xb ,yo ,params = [0 ]):
90116 method = self .method
@@ -125,10 +151,10 @@ def initEns(self,x0,mu=0,sigma=0.1,edim=4):
125151 X0 = np .matrix (rmat + xrand )
126152 return X0
127153
128- # def init_4D (self):
154+ # def init4D (self):
129155# xdim = size(self.x0)
130156
131- # def init_4DEns (self):
157+ # def init4DEns (self):
132158# xdim = size(self.x0)
133159
134160#---------------------------------------------------------------------------------------------------
@@ -157,19 +183,27 @@ def OI(self,xb,yo):
157183 yo = np .matrix (yo ).flatten ().T
158184
159185 # Use explicit expression to solve for the analysis
160- print (self )
186+ # print(self)
161187 Hl = self .H
162188 Ht = self .Ht
163189 B = self .B
164190 R = self .R
165191
166- KH = B * Ht * np .linalg .inv (H * B * Ht + R )* Hl
192+ # print('H = ')
193+ # print(Hl)
194+
195+ # print('R = ')
196+ # print(R)
197+
198+ # Should be dimensioned: xdim * xdim
199+ K = B * Ht * np .linalg .inv (Hl * B * Ht + R )
200+ KH = K * Hl
167201
168- print ('KH = ' )
169- print (KH )
202+ # print('KH = ')
203+ # print(KH)
170204
171205 Hxb = Hl * xb
172- xa = xb + KH * (yo - Hxb )
206+ xa = xb + K * (yo - Hxb )
173207
174208 return xa .A1 , KH
175209
@@ -179,20 +213,18 @@ def _3DVar(self,xb,yo):
179213#---------------------------------------------------------------------------------------------------
180214# Use minimization algorithm to solve for the analysis
181215
216+ # make inputs column vectors
182217 xb = np .matrix (xb ).flatten ().T
183218 yo = np .matrix (yo ).flatten ().T
184219
220+ # Set parameters
185221 xdim = self .xdim
186222 Hl = self .H
187223 Ht = self .Ht
188224 B = self .B
189225 R = self .R
190226 Rinv = np .linalg .inv (R )
191227
192- # make inputs column vectors
193- xb = np .matrix (xb ).flatten ().T
194- yo = np .matrix (yo ).flatten ().T
195-
196228 # 'preconditioning with B'
197229 I = np .identity (xdim )
198230 BHt = B * Ht
@@ -204,13 +236,12 @@ def _3DVar(self,xb,yo):
204236 xa ,ierr = sp .sparse .linalg .cg (A ,b1 ,x0 = xb ,tol = 1e-05 ,maxiter = 1000 )
205237# xa,ierr = sp.sparse.linalg.bicgstab(A,b1,x0=np.zeros_like(b1),tol=1e-05,maxiter=1000)
206238# try: gmres,
207- # xa = sp.optimize.minimize(fun, x0, args=(), method=None, jac=None, hess=None, hessp=None, bounds=None, constraints=(), tol=None, callback=None, options=None)
208239
209240 # Compute KH:
210241 HBHtPlusR_inv = np .linalg .inv (Hl * BHt + R )
211242 KH = BHt * HBHtPlusR_inv * Hl
212243
213- return xa . A1 , KH
244+ return xa , KH
214245
215246
216247#---------------------------------------------------------------------------------------------------
@@ -282,27 +313,27 @@ def ETKF(self,Xb,yo):
282313#---------------------------------------------------------------------------------------------------
283314# Use minimization over a time window to solve for the analysis
284315#
316+ # xb_4d = np.matrix(np.atleast_2d(xb_4d))
317+ # yo_4d = np.matrix(np.atleast_2d(yo_4d))
318+ # nr,nc = np.shape(xb_4d) ! columns are state vectors at consecutive timesteps
319+ # xdim = nr
320+ # tdim = nc
285321# B = self.B
286- # R = self.R
287- # xdim = self.xdim
288- # Xb = np.matrix(np.atleast_2d(Xb))
289- # Yo = np.matrix(np.atleast_2d(Yo))
290- # Yp = np.matrix(np.atleast_2d(Yp))
291-
322+ # R_4d = self.R ! may need list of R matrices if observations are non-uniform over time
323+ # H_4d = self.H ! may need list of H matrices if observations are non-uniform over time
324+ # M_4d = self.M ! input list of TLMs for each timestep
292325
293326
294327#---------------------------------------------------------------------------------------------------
295328# def _4DEnVar(self,Xb_4d,yo_4d):
296329#---------------------------------------------------------------------------------------------------
297330# Use ensemble of states over a time window to estimate temporal correlations
298- # xdim = size(self.x0)
299331
300332
301333#---------------------------------------------------------------------------------------------------
302334# def _4DETKF(self,Xb_4d,yo_4d):
303335#---------------------------------------------------------------------------------------------------
304336# Use ensemble of states over a time window to estimate temporal correlations
305- # xdim = size(self.x0)
306337
307338
308339#---------------------------------------------------------------------------------------------------
@@ -370,8 +401,8 @@ def PF(self,Xb,yo):
370401 if (Neff < edim / 2 ):
371402 # Apply additive inflation (remove sample mean)
372403 const = 1.0
373- rmat = np .rand .randn (xdim ,edim ) * np .matlib .repmat (np .std (Xa ,axis = 1 ),0 ,edim ) * const ;
374- Xa = Xa + rmat - np .matlib .repmat (np .mean (rmat ,axis = 1 ),0 ,edim );
404+ rmat = np .rand .randn (xdim ,edim ) * np .matlib .repmat (np .std (Xa ,axis = 1 ),1 ,edim ) * const ;
405+ Xa = Xa + rmat - np .matlib .repmat (np .mean (rmat ,axis = 1 ),1 ,edim );
375406
376407 KH = [0 ] # dummy output
377408
@@ -386,17 +417,53 @@ def HybridGain(self,Xb,yo):
386417 Xb = np .matrix (Xb )
387418 yo = np .matrix (yo ).flatten ().T
388419
420+ # Get parameters
421+ alpha = self .alpha
422+ nr ,nc = np .shape (Xb )
423+ xdim = nr
424+ edim = nc
425+ ydim = len (yo )
426+
389427 # Compute ETKF analysis
390428 Xa_ETKF , KH_ETKF = self .ETKF (Xb ,yo )
429+ print ('Xa_ETKF = ' )
430+ print (Xa_ETKF )
391431
392432 # Compute 3DVar analysis
393433 xa_ETKF = np .mean (Xa_ETKF ,axis = 1 )
434+ print ('xa_ETKF = ' )
435+ print (xa_ETKF )
394436 xa_3DVar , KH_3DVar = self ._3DVar (xa_ETKF ,yo )
437+ print ('xa_3DVar = ' )
438+ print (xa_3DVar )
439+
440+ xa_ETKF = np .matrix (xa_ETKF ).flatten ().T
441+ xa_3DVar = np .matrix (xa_3DVar ).flatten ().T
442+
443+ # Recover ensemble perturbations
444+ Xa_ETKF = Xa_ETKF - np .matlib .repmat (xa_ETKF ,1 ,edim )
395445
396- # Form hybrid combination
446+ # Form hybrid combination to update the mean state
397447 xa_hybrid = (1 - alpha )* xa_ETKF + alpha * xa_3DVar
398- Xa = Xa_ETKF + xa_hybrid [:,np .newaxis ]
448+ Xa = Xa_ETKF + np .matlib .repmat (xa_hybrid ,1 ,edim )
449+
450+ print ('xa_hybrid = ' )
451+ print (xa_hybrid )
399452
400453 KH = (1 - alpha )* KH_ETKF + alpha * KH_3DVar
401454
402455 return Xa , KH
456+
457+
458+ #---------------------------------------------------------------------------------------------------
459+ def save (self ,outfile ):
460+ #---------------------------------------------------------------------------------------------------
461+ with open (outfile ,'wb' ) as output :
462+ pickle .dump (self ,output ,pickle .HIGHEST_PROTOCOL )
463+
464+ #---------------------------------------------------------------------------------------------------
465+ def load (self ,infile ):
466+ #---------------------------------------------------------------------------------------------------
467+ with open (infile ,'rb' ) as input :
468+ das = pickle .load (input )
469+ return das
0 commit comments