SURFEX  V8_0
Surfex V8_0 release
 All Classes Files Functions Variables
assim_nature_isba_enkf.F90
Go to the documentation of this file.
1 !SFX_LIC Copyright 1994-2014 CNRS, Meteo-France and Universite Paul Sabatier
2 !SFX_LIC This is part of the SURFEX software governed by the CeCILL-C licence
3 !SFX_LIC version 1. See LICENSE, CeCILL-C_V1-en.txt and CeCILL-C_V1-fr.txt
4 !SFX_LIC for details. version 1.
5 SUBROUTINE assim_nature_isba_enkf(I, HPROGRAM, KI, PT2M, PHU2M, HTEST)
6 
7 ! -----------------------------------------------------------------------------
8 !
9 ! Land Data Assimilation System based on an Extended Kalman Filter
10 !
11 ! Revised version : JFM (15 September 2008)
12 !
13 ! The control vector can be any element of (TG1,TG2,WG1,WG2) - Choice in namelist
14 !
15 ! The observations can be any element of (T2M,HU2M,WG1) - Choice in namelist
16 !
17 ! Possibility to evolve the B matrix in the cycling - otherwise SEKF
18 !
19 ! First version including patches (15 October 2008)
20 ! Trygve Aspelien, Separating IO 06/2013
21 ! Alina Barbu: bug correction of B matrix, otherwise understimation of the gain matrix (11/2013)
22 ! Alina Barbu: equivalent analysis of B matrix to ensure its symetric and positiv definiteness properties (11/2013)
23 
24 ! -----------------------------------------------------------------------------
25 !
26 USE modd_surfex_mpi, ONLY : nrank, npio
27 USE modd_assim, ONLY : nobstype, xerrobs, nvar, nprintlev, cvar, &
28  xf_patch, xf,cobs,cfile_format_obs,nens, &
29  nechgu, nboutput, nobs, xyo, lenkf, ldenkf, &
30  lpb_correlations, lperturbation_run, &
31  lbias_correction, xinfl
32 !
33 USE modd_surf_par, ONLY : xundef
34 !
35 USE modd_isba_n, ONLY : isba_t
36 !
37 #ifdef SFX_ARO
38 USE yommp0, ONLY : myproc
39 #endif
40 !
41 USE yomhook, ONLY : lhook,dr_hook
42 USE parkind1, ONLY : jprb
43 !
44 USE modi_abor1_sfx
45 USE modi_add_forecast_to_date_surf
46 !
47 USE modi_outer_product
48 USE mode_ekf
49 USE mode_random
50 !
51 ! -----------------------------------------------------------
52 !
53 IMPLICIT NONE
54 !
55 TYPE(isba_t), INTENT(INOUT) :: i
56 !
57  CHARACTER(LEN=6), INTENT(IN) :: hprogram ! program calling surf. schemes
58 INTEGER, INTENT(IN) :: ki
59 REAL, DIMENSION(:), INTENT(IN) :: pt2m
60 REAL, DIMENSION(:), INTENT(IN) :: phu2m
61  CHARACTER(LEN=2), INTENT(IN) :: htest ! must be equal to 'OK'
62 !
63 ! Declarations of local variables
64 !
65  CHARACTER(LEN=30) :: ybgfile
66  CHARACTER(LEN=17) :: ylfname
67  CHARACTER(LEN=9) :: yfname
68  CHARACTER(LEN=7) :: ymyproc
69  CHARACTER(LEN=1) :: ychar
70 !
71 ! Local Matrix for Analysis calculation
72 !
73 ! Allocation
74 ! Perturbed simulations
75 !
76 ! Initial values (to be analysed)
77 ! Observations
78 !
79 ! Temporary vectors used by the EKF approach
80 REAL,DIMENSION(KI) :: zcofswi ! dynamic range (Wfc - Wwilt)
81 !
82 REAL,DIMENSION(NENS+1,NOBSTYPE*NBOUTPUT) :: zyf ! Vector of model observations (averaged)
83 !
84 REAL,DIMENSION(NOBSTYPE*NBOUTPUT,NENS) :: zinnov
85 !
86 REAL,DIMENSION(NVAR,NOBSTYPE*NBOUTPUT) :: zbht
87 REAL,DIMENSION(NOBSTYPE*NBOUTPUT,NOBSTYPE*NBOUTPUT) :: zr ! covariance matrix of observation errors
88 REAL,DIMENSION(NOBSTYPE*NBOUTPUT,NOBSTYPE*NBOUTPUT) :: zk1, zk2, zhbht
89 REAL,DIMENSION(NOBSTYPE*NBOUTPUT) :: zp, zx
90 !
91 REAL, DIMENSION(I%NPATCH,NVAR,NENS) :: zxincr
92 REAL, DIMENSION(I%NPATCH,NVAR,NENS) :: za, zf
93 REAL, DIMENSION(I%NPATCH,NOBSTYPE*NBOUTPUT,NENS) :: zf_patch
94 REAL, DIMENSION(I%NPATCH,NVAR) :: zf_mean, za_mean
95 REAL, DIMENSION(NVAR) :: zf_agg, za_agg
96 !
97 REAL,DIMENSION(:,:,:),ALLOCATABLE :: zf_mean0, zf_patch_mean
98 !
99 REAL :: ztime, zalpha ! current time since start of the run (s)
100 
101 INTEGER :: iobscount
102 INTEGER :: iyear ! current year (UTC)
103 INTEGER :: imonth ! current month (UTC)
104 INTEGER :: iday ! current day (UTC)
105 INTEGER :: ihour
106 INTEGER :: iresp ! return code
107 INTEGER :: istep !
108 INTEGER :: imyproc
109 INTEGER :: iobs, iens
110 INTEGER :: istat, icpt, iunit
111 !
112 INTEGER :: ii,j,k,jj,l,k1,l1
113 !
114 LOGICAL :: gbexists
115 !
116 REAL(KIND=JPRB) :: zhook_handle
117 !
118 !
119 IF (lhook) CALL dr_hook('ASSIM_NATURE_ISBA_ENKF',0,zhook_handle)
120 
121 #ifdef USE_SODA
122 
123 !
124 !############################# BEGINNING ###############################
125 !
126 IF (htest/='OK') THEN
127  CALL abor1_sfx('ASSIM_NATURE_ISBA_ENKF: FATAL ERROR DURING ARGUMENT TRANSFER')
128 END IF
129 !
130 IF ( nprintlev>0 .AND. nrank==npio) THEN
131  WRITE(*,*)
132  WRITE(*,*) ' --------------------------'
133  WRITE(*,*) ' | ENTERING VARASSIM |'
134  WRITE(*,*) ' --------------------------'
135  WRITE(*,*)
136 ENDIF
137 !
138 #ifdef SFX_ARO
139 IF ( myproc > 0 ) THEN
140  imyproc = myproc
141 ELSE
142  imyproc = 1
143 ENDIF
144 #else
145 imyproc = nrank+1
146 #endif
147 !
148 WRITE(ymyproc(1:7),'(I7.7)') imyproc
149 !
150 IF ( nprintlev > 0 .AND. nrank==npio ) WRITE(*,*) 'number of patches =',i%NPATCH
151 !
152 !############################# INITIALISATIONS ###############################
153 !
154 ! Read CLAY fraction to compute the SWI range (Wfc - Wwilt)
155 ! (XSIGMA is defined in terms of SWI), need to convert to equivalent v/v
156 ! using same clay fraction in both layers
157 ! Read SAND fraction to compute the saturation for conversion of ERS SWI
158 !
159  CALL cofswi(i%XCLAY(:,1),zcofswi)
160 !DO I=1,KI
161  !ZSMSAT (I) = 0.001 * (-1.08*100.*XSAND(I,1) + 494.305)
162  !ZWILT (I) = 0.001 * 37.1342 * ((100.*XCLAY(I,1))**0.5)
163 !ENDDO
164 !
165 ! ====================================================================
166 !
167 ! Analysis
168 !
169 ! ====================================================================
170 !
171 ! Time reinitialization
172 iyear = i%TTIME%TDATE%YEAR
173 imonth = i%TTIME%TDATE%MONTH
174 iday = i%TTIME%TDATE%DAY
175 !
176 ihour = 0
177 ztime = float(nechgu) * 3600.
178 !
179 !############################# READS OBSERVATIONS ###############################
180 !
181 ! Map the variables in case we read them from CANARI inline/offline FA files
182 ! At the moment only T2M and HU2M can be used. If other variables should be used
183 ! they must be added to the interface or be read from file.
184 IF ( trim(cfile_format_obs) == "FA" ) THEN
185  !
186  DO iobs = 1,nobstype
187  SELECT CASE (trim(cobs(iobs)))
188  CASE("T2M")
189  xyo(:,iobs) = pt2m(:)
190  CASE("HU2M")
191  xyo(:,iobs) = phu2m(:)
192  CASE("WG1","LAI")
193  CALL abor1_sfx("Mapping of "//cobs(iobs)//" is not defined in ASSIM_NATURE_ISBA_EKF!")
194  END SELECT
195  ENDDO
196  !
197 ENDIF
198 !
199 !//////////////////////TO WRITE OBS/////////////////////////////////////
200 IF ( nprintlev > 0 ) OPEN (unit=111,file='OBSout.'//ymyproc,status='unknown',iostat=istat)
201 DO ii = 1,ki
202  IF ( minval(i%XWGI(ii,1,:))>0. ) THEN
203  xyo(ii,:) = xundef
204  IF ( nprintlev > 1 ) WRITE(*,*) 'OBSERVATION FOR POINT ',ii,' REMOVED'
205  ENDIF
206  IF ( nprintlev > 0 ) WRITE (111,*) xyo(ii,:)
207 ENDDO
208 IF ( nprintlev > 0 ) CLOSE(111)
209 !//////////////////////TO WRITE OBS/////////////////////////////////////
210 !
211 ! Recentering THE FORECAST ENSEMBLE MEMBERS
212 IF ( lbias_correction ) THEN
213  !
214  ALLOCATE(zf_mean0(ki,i%NPATCH,nvar))
215  ALLOCATE(zf_patch_mean(ki,i%NPATCH,nobs))
216  !
217  DO ii = 1,ki
218  DO j=1,i%NPATCH
219  DO l = 1,nvar
220  zf_mean0(ii,j,l) = sum(xf(ii,j,1:nens,l))/REAL(nens)
221  ENDDO
222  DO k = 1,nobs
223  zf_patch_mean(ii,j,k) = sum(xf_patch(ii,j,1:nens,k))/REAL(nens)
224  ENDDO
225  ENDDO
226  ENDDO
227  !
228  DO ii = 1,ki
229  DO j = 1,i%NPATCH
230  DO iens = 1,nens
231  !
232  DO l = 1,nvar
233  IF ( xf(ii,j,iens,l) - zf_mean0(ii,j,l) + xf(ii,j,nens+1,l)>0.0 ) THEN
234  xf(ii,j,iens,l) = xf(ii,j,iens,l) - zf_mean0(ii,j,l) + xf(ii,j,nens+1,l)
235  ENDIF
236  ENDDO
237  !
238  DO k = 1,nobs
239  IF ( xf_patch(ii,j,iens,k) - zf_patch_mean(ii,j,k) + xf_patch(ii,j,nens+1,k)>0.0 ) THEN
240  xf_patch(ii,j,iens,k) = xf_patch(ii,j,iens,k) - zf_patch_mean(ii,j,k) + xf_patch(ii,j,nens+1,k)
241  ENDIF
242  ENDDO
243  !
244  ENDDO
245  ENDDO
246  ENDDO
247  !
248  DEALLOCATE(zf_mean0,zf_patch_mean)
249  !
250 ENDIF
251 !
252 !############################# ANALYSIS ###############################
253 !
254 IF ( nprintlev > 0 ) THEN
255  IF (nrank==npio) THEN
256  WRITE(*,*) 'calculating jacobians',nobs
257  WRITE(*,*) ' and then PERFORMING ANALYSIS'
258  ENDIF
259  !
260  !//////////////////////TO WRITE ANALYSIS ARRAYS/////////////////////////////////////
261  ! WRITE OUT OBS AND YERROR FOR DIAGNOSTIC PURPOSES
262  OPEN (unit=111,file='OBSERRORout.'//ymyproc,status='unknown',iostat=istat)
263  ! *** Write innovations in ASCII file ***
264  OPEN (unit=112,file='INNOV.'//ymyproc,status='unknown',iostat=istat)
265  ! Write analysis results and increments in ASCII file
266  OPEN (unit=113,file='ANAL_INCR.'//ymyproc,status='unknown',iostat=istat)
267  ! **** Write out the observation operator + Gain matrix ****
268  OPEN (unit=114,file='K1.'//ymyproc,status='unknown',iostat=istat)
269  OPEN (unit=115,file='F_AGG.'//ymyproc,status='unknown',iostat=istat)
270  OPEN (unit=116,file='A_AGG.'//ymyproc,status='unknown',iostat=istat)
271 ENDIF
272 !//////////////////////TO WRITE ANALYSIS ARRAYS/////////////////////////////////////
273 !
274 iobscount = 0
275 !
276  CALL init_random_seed()
277 !
278 DO ii=1,ki
279  !
280  !---------------- MEAN SIMULATED OBS AVERAGED OVER TILES-----------------------
281  zyf(:,:) = 0.
282  DO j=1,i%NPATCH
283  IF (i%XPATCH(ii,j) > 0.0) THEN
284  WHERE ( xf_patch(ii,j,:,:)/=xundef )
285  zyf(:,:) = zyf(:,:) + i%XPATCH(ii,j)*xf_patch(ii,j,:,:)
286  ENDWHERE
287  ENDIF
288  ENDDO
289  IF ( nprintlev > 1 ) WRITE(*,*) 'read in sim obs yf', zyf(:,1)
290  !
291  !
292  zr(:,:) = 0. ! Observation error matrix
293  zinnov(:,:) = 0.
294  !
295  zxincr(:,:,:) = 0.0
296  zk1(:,:) = 0.0
297  zk2(:,:) = 0.0
298  zp(:) = 0.0
299  zx(:) = 0.0
300  zbht(:,:) = 0.0
301  zhbht(:,:) = 0.0
302 
303  DO istep=1,nboutput
304  !
305  DO k = 1,nobstype
306  !
307  k1 = (istep-1)*nobstype + k
308  !
309 !--------------------- SET OBSERVATION ERROR ------------------
310  zr(k1,k1) = xerrobs(k)*xerrobs(k)
311  IF ( cobs(k) .EQ. "LAI" ) THEN
312  zr(k1,k1) = zr(k1,k1) * xyo(ii,k1)*xyo(ii,k1)
313  ELSEIF (cobs(k) .EQ. "WG1") THEN
314  ! convert R for wg1 from SWI to abs value
315  zr(k1,k1) = zr(k1,k1) * zcofswi(ii)*zcofswi(ii)
316  ENDIF
317  !
318  ! Apply quality control
319  IF ( abs(xyo(ii,k1)-zyf(nens+1,k1)) > 0.5 .OR. zr(k1,k1) < 0. ) xyo(ii,k1) = xundef
320  !
321  IF( xyo(ii,k1).NE.xundef .AND. xyo(ii,k1).NE.999.0 ) THEN !if obs available
322  !
323  DO iens = 1,nens
324  !
325  zinnov(k1,iens) = xyo(ii,k1) - zyf(iens,k1)
326  IF (lenkf) THEN
327  zinnov(k1,iens) = zinnov(k1,iens) + random_normal() * (xerrobs(k)*zcofswi(ii))
328  ENDIF
329  !
330  ENDDO
331  !
332  iobscount = iobscount + 1
333  !
334  ENDIF
335  !
336  ENDDO
337  !
338  IF ( nprintlev > 0 ) THEN
339  WRITE(111,*) zr(:,:)
340  DO k = 1,nobs
341  WRITE(112,*) (sum(zinnov(k,:))/(nens*1.0)), xyo(ii,k)
342  ENDDO
343  ENDIF
344  !
345  ENDDO
346  !
347  IF (nprintlev > 0) WRITE(*,*) 'PERFORMING ANALYSIS'
348  !
349  !---------------****** SOIL ANALYSIS *******--------------------------
350  !
351  DO iens = 1,nens
352  zf(:,:,iens) = xf(ii,:,iens,:)
353  zf_patch(:,:,iens) = xf_patch(ii,:,iens,:)
354  ENDDO
355 
356  !
357  zf_mean(:,:) = sum(zf(:,:,:),dim=3)/REAL(nens)
358  !
359  IF (.NOT.lperturbation_run) THEN
360  !
361  DO j = 1,i%NPATCH
362  !
363  CALL outer_product(nens,nvar,nobs,zf(j,:,:),i%XPATCH(ii,j)*zf_patch(j,:,:),&
364  zbht(:,:),zhbht(:,:),lpb_correlations,cvar,cobs)
365  !
366  zk1(:,:) = zhbht(:,:) + zr(:,:)
367  zk2(:,:) = zk2(:,:) + zhbht(:,:)
368  CALL choldc(nobs,zk1(:,:),zp(:))
369  !
370  DO iens = 1,nens ! Cholesky decomposition (1)
371  !
372  CALL cholsl(nobs,zk1(:,:),zp(:),zinnov(:,iens),zx(:)) ! Cholesky decomposition (2)
373  zxincr(j,:,iens) = matmul(zbht(:,:),zx(:))
374  !
375  DO l = 1,nvar
376  za(j,l,iens) = zf(j,l,iens)
377  IF (cvar(l)/="WG3" .AND. cvar(l)/="TG3") THEN
378  za(j,l,iens) = za(j,l,iens) + zxincr(j,l,iens)
379  ENDIF
380  ENDDO
381  !
382  ENDDO
383  !
384  ENDDO
385  !
386  za_mean(:,:) = sum(za(:,:,:),dim=3)/REAL(nens)
387  !
388  IF (nprintlev>1) WRITE(114,*) (zk2(:,:) + zr(:,:))
389  !
390  DO iens = 1,nens
391  !
392  DO l = 1,nvar
393  !
394  DO j = 1,i%NPATCH
395  !
396  IF ( ldenkf .AND. cvar(l)/="WG3" .AND. cvar(l)/="TG3" ) THEN
397  !
398  DO k = 1,nobs
399  zalpha = 1.0 / ( 1.0 + sqrt( zr(k,k)/(zk2(k,k) + zr(k,k)) ) )
400  za(j,l,iens) = za_mean(j,l) + (1.0-zalpha) * ( zf(j,l,iens)-zf_mean(j,l) ) &
401  + zalpha * ( za(j,l,iens)-za_mean(j,l))
402  ENDDO
403  !
404  ENDIF
405  !apply inflation factor to the ensemble spread
406  za(j,l,iens) = za_mean(j,l) + xinfl(l) * (za(j,l,iens) - za_mean(j,l))
407  !
408  ENDDO
409  !
410  ENDDO
411  !
412  ENDDO
413  !
414  WHERE (za(:,:,:)<0.0)
415  za(:,:,:) = zf(:,:,:)
416  END WHERE
417  !
418  !
419  ELSE
420  !
421  za(:,:,:) = zf(:,:,:)
422  !
423  ENDIF
424  !
425  za_mean(:,:) = sum(za(:,:,:),dim=3)/REAL(nens)
426  !
427  zf_agg(:) = 0.
428  za_agg(:) = 0.
429  DO l = 1,nvar
430  DO j = 1,i%NPATCH
431  IF (za_mean(j,l)/=xundef .AND. zf_mean(j,l)/=xundef) THEN
432  zf_agg(l) = zf_agg(l) + i%XPATCH(ii,j) * zf_mean(j,l)
433  za_agg(l) = za_agg(l) + i%XPATCH(ii,j) * za_mean(j,l)
434  ENDIF
435  ENDDO
436  ENDDO
437  !
438  IF (nprintlev>1) THEN
439  WRITE(115,*) (zf_agg(l), l=1,nvar)
440  WRITE(116,*) (za_agg(l), l=1,nvar)
441  ENDIF
442  !
443  !############################# GET VARIABLES FOR OUTPUT WRITING ###############################
444  !
445  DO iens = 1,nens
446  xf(ii,:,iens,:) = za(:,:,iens)
447  ENDDO
448  !
449  IF (lbias_correction) xf(ii,:,nens+1,:) = za_mean(:,:)
450  !
451 ENDDO
452 !
453 IF ( nprintlev > 0 ) THEN
454  CLOSE(111)
455  CLOSE(112)
456  CLOSE(113)
457  CLOSE(114)
458  CLOSE(115)
459  CLOSE(116)
460 ENDIF
461 !
462 IF (lhook) CALL dr_hook('ASSIM_NATURE_ISBA_ENKF',1,zhook_handle)
463 
464 #endif
465 
466 !
467 END SUBROUTINE assim_nature_isba_enkf
real function random_normal()
subroutine abor1_sfx(YTEXT)
Definition: abor1_sfx.F90:6
subroutine assim_nature_isba_enkf(I, HPROGRAM, KI, PT2M, PHU2M, HTEST)
subroutine outer_product(KENS, KX, KY, PX, PY, PA, PC, OPB_CORRELATIONS, HVAR, HOBS)
subroutine init_random_seed()