@@ -165,7 +165,7 @@ def initEns(self,x0,mu=0,sigma=0.1,edim=4):
165165# print(Xrand)
166166 # Remove mean to make sure it is properly centered at 0
167167 # (add bias if included)
168- rand_mean = np .mean (Xrand ,axis = 1 ) + mu
168+ rand_mean = np .mean (Xrand ,axis = 1 ) - mu
169169# print('rand_mean = ')
170170# print(rand_mean)
171171 rmat = np .matlib .repmat (rand_mean ,1 ,edim )
@@ -176,7 +176,7 @@ def initEns(self,x0,mu=0,sigma=0.1,edim=4):
176176 rmat = np .matlib .repmat (x0 , 1 , edim )
177177# print('rmat = ')
178178# print(rmat)
179- X0 = np .matrix (rmat + Xrand )
179+ X0 = np .matrix (Xrand + rmat )
180180 return X0
181181
182182# def init4D(self):
@@ -276,6 +276,7 @@ def _3DVar(self,xb,yo):
276276 def ETKF (self ,Xb ,yo ):
277277#---------------------------------------------------------------------------------------------------
278278# Use ensemble of states to estimate background error covariance
279+ verbose = False
279280
280281 # Make sure inputs are matrix and column vector types
281282 Xb = np .matrix (Xb )
@@ -291,47 +292,140 @@ def ETKF(self,Xb,yo):
291292 Hl = self .H
292293 Yb = np .matrix (np .zeros ([ydim ,edim ]))
293294 for i in range (edim ):
294- Yb [:,i ] = Hl * Xb [:,i ]
295+ Yb [:,i ] = np . dot ( Hl , Xb [:,i ])
295296
296297 # Convert ensemble members to perturbations
297298 xm = np .mean (Xb ,axis = 1 )
298- Xb = Xb - np .matlib .repmat (xm , 1 , edim )
299299 ym = np .mean (Yb ,axis = 1 )
300+ Xb = Xb - np .matlib .repmat (xm , 1 , edim )
300301 Yb = Yb - np .matlib .repmat (ym , 1 , edim )
301302
302303 # Compute R^{-1}
303304 R = self .R
304305 Rinv = np .linalg .inv (R )
305306
306307 # Compute the weights
307- Ybt = Yb .T
308- C = Ybt * Rinv
309308
309+ #----
310+ # stage(4) Now do computations for lxk Yb matrix
311+ # Compute Yb^T*R^(-1)
312+ #----
313+ Ybt = np .transpose (Yb )
314+ C = np .dot (Ybt ,Rinv )
315+
316+ if verbose :
317+ print ('C = ' )
318+ print (C )
319+
320+ #----
321+ # stage(5) Compute eigenvalue decomposition for Pa
322+ # Pa = [(k-1)I/rho + C*Yb]^(-1)
323+ #----
310324 I = np .identity (edim )
311- rho = 1.0
312- eigArg = (edim - 1 )* I / rho + C * Yb
325+ rho = 1.05 #1.0
326+ eigArg = (edim - 1 )* I / rho + np .dot (C ,Yb )
327+
313328 lamda ,P = np .linalg .eigh (eigArg )
329+
330+ if verbose :
331+ print ('lamda = ' )
332+ print (lamda )
333+ print ('P = ' )
334+ print (P )
335+
314336 Linv = np .diag (1.0 / lamda )
315- PLinv = P * Linv
316- Pt = P .T
317- Pa = PLinv * Pt
318337
338+ if verbose :
339+ print ('Linv = ' )
340+ print (Linv )
341+
342+ PLinv = np .dot (P ,Linv )
343+
344+ if verbose :
345+ print ('PLinv = ' )
346+ print (PLinv )
347+
348+ Pt = np .transpose (P )
349+
350+ if verbose :
351+ print ('Pt = ' )
352+ print (Pt )
353+
354+ Pa = np .dot (PLinv , Pt )
355+
356+ if verbose :
357+ print ('Pa = ' )
358+ print (Pa )
359+
360+ #----
361+ # stage(6) Compute matrix square root
362+ # Wa = [(k-1)Pa]1/2
363+ #----
319364 Linvsqrt = np .diag (1 / np .sqrt (lamda ))
320- PLinvsqrt = P * Linvsqrt
321- Wa = np .sqrt (edim - 1 ) * PLinvsqrt * Pt
322365
323- d = yo - ym
324- wm = Pa * (C * d )
366+ if verbose :
367+ print ('Linvsqrt = ' )
368+ print (Linvsqrt )
369+
370+ PLinvsqrt = np .dot (P ,Linvsqrt )
371+
372+ if verbose :
373+ print ('PLinvsqrt = ' )
374+ print (PLinvsqrt )
375+
376+ Wa = np .sqrt ((edim - 1 )) * np .dot (PLinvsqrt ,Pt )
377+
378+ if verbose :
379+ print ('Wa = ' )
380+ print (Wa )
381+
382+ #----
383+ # stage(7) Transform back
384+ # Compute the mean update
385+ # Compute wabar = Pa*C*(yo-ybbar) and add it to each column of Wa
386+ #----
387+ d = yo - ym
388+ Cd = np .dot (C ,d )
389+
390+ if verbose :
391+ print ('Cd = ' )
392+ print (Cd )
393+
394+ wm = np .dot (Pa ,Cd ) #k x 1
395+
396+ if verbose :
397+ print ('wm = ' )
398+ print (wm )
399+
400+ # Add the same mean vector wm to each column
401+ # Wa = Wa + wm[:,np.newaxis] #STEVE: make use of python broadcasting to add same vector to each column
325402 Wa = Wa + np .matlib .repmat (wm , 1 , edim )
326403
404+ if verbose :
405+ print ('Wa = ' )
406+ print (Wa )
407+
408+ #----
409+ # stage(8)
410+ # Compute the perturbation update
411+ # Multiply Xb (perturbations) by each wa(i) and add xbbar
412+ #----
413+
327414 # Add the same mean vector wm to each column
328- Xa = Xb * Wa + np .matlib .repmat (xm , 1 , edim )
415+ # Xa = np.dot(Xb,Wa) + xm[:,np.newaxis]
416+ Xa = np .dot (Xb ,Wa ) + np .matlib .repmat (xm , 1 , edim )
417+
418+ if verbose :
419+ print ('Xa = ' )
420+ print (Xa )
329421
330422 # Compute KH:
331- IpYbtRinvYb = ((edim - 1 )/ rho )* I + Ybt * Rinv * Yb
332- IpYbtRinvYb_inv = IpYbtRinvYb .I
333- K = Xb * IpYbtRinvYb_inv * Ybt * Rinv
334- KH = K * Hl
423+ RinvYb = np .dot (Rinv ,Yb )
424+ IpYbtRinvYb = ((edim - 1 )/ rho )* I + np .dot (Ybt ,RinvYb )
425+ IpYbtRinvYb_inv = np .linalg .inv (IpYbtRinvYb )
426+ YbtRinv = np .dot (Ybt ,Rinv )
427+ K = np .dot ( Xb , np .dot (IpYbtRinvYb_inv ,YbtRinv ) )
428+ KH = np .dot (K ,Hl )
335429
336430 return Xa , KH
337431
@@ -350,19 +444,23 @@ def ETKF(self,Xb,yo):
350444# R_4d = self.R ! may need list of R matrices if observations are non-uniform over time
351445# H_4d = self.H ! may need list of H matrices if observations are non-uniform over time
352446# M_4d = self.M ! input list of TLMs for each timestep
447+ #
448+ # (work in progress)
353449
354450
355451#---------------------------------------------------------------------------------------------------
356452# def _4DEnVar(self,Xb_4d,yo_4d):
357453#---------------------------------------------------------------------------------------------------
358454# Use ensemble of states over a time window to estimate temporal correlations
359-
455+ #
456+ # (work in progress)
360457
361458#---------------------------------------------------------------------------------------------------
362459# def _4DETKF(self,Xb_4d,yo_4d):
363460#---------------------------------------------------------------------------------------------------
364461# Use ensemble of states over a time window to estimate temporal correlations
365-
462+ #
463+ # (work in progress)
366464
367465#---------------------------------------------------------------------------------------------------
368466 def PF (self ,Xb ,yo ):
@@ -429,7 +527,7 @@ def PF(self,Xb,yo):
429527 if (Neff < edim / 2 ):
430528 # Apply additive inflation (remove sample mean)
431529 const = 1.0
432- rmat = np .rand .randn (xdim ,edim ) * np .matlib .repmat (np .std (Xa ,axis = 1 ),1 ,edim ) * const ;
530+ rmat = np .random .randn (xdim ,edim ) * np .matlib .repmat (np .std (Xa ,axis = 1 ),1 ,edim ) * const ;
433531 Xa = Xa + rmat - np .matlib .repmat (np .mean (rmat ,axis = 1 ),1 ,edim );
434532
435533 KH = [0 ] # dummy output
0 commit comments