SURFEX  V8_0
Surfex V8_0 release
 All Classes Files Functions Variables
assim_nature_isba_ekf.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_ekf (I, &
6  hprogram, ki, pt2m, phu2m, htest)
7 
8 ! -----------------------------------------------------------------------------
9 !
10 ! Land Data Assimilation System based on an Extended Kalman Filter
11 !
12 ! Revised version : JFM (15 September 2008)
13 !
14 ! The control vector can be any element of (TG1,TG2,WG1,WG2) - Choice in namelist
15 !
16 ! The observations can be any element of (T2M,HU2M,WG1) - Choice in namelist
17 !
18 ! Possibility to evolve the B matrix in the cycling - otherwise SEKF
19 !
20 ! First version including patches (15 October 2008)
21 ! Trygve Aspelien, Separating IO 06/2013
22 ! Alina Barbu: bug correction of B matrix, otherwise understimation of the gain matrix (11/2013)
23 ! Alina Barbu: equivalent analysis of B matrix to ensure its symetric and positiv definiteness properties (11/2013)
24 
25 ! -----------------------------------------------------------------------------
26 !
27 !
28 USE modd_isba_n, ONLY : isba_t
29 !
30 USE modd_surfex_mpi, ONLY : nrank, npio
31 !
32 USE modd_assim, ONLY : lbev, lbfixed, nobstype, xerrobs, xqcobs, nnco, nvar, nncv, &
33  xscale_q, nprintlev, cvar, xsigma, cbio, xi, &
34  xf_patch, xf, cobs, xscale_qlai,cfile_format_obs, &
35  xalph,nechgu, nboutput, xtprt, xlai_pass, xbio_pass,&
36  nobs, xyo
37 !
38 USE modd_surf_par, ONLY : xundef
39 !
40 !
41 #ifdef SFX_ARO
42 USE yommp0, ONLY : myproc
43 #endif
44 !
45 USE yomhook, ONLY : lhook,dr_hook
46 USE parkind1, ONLY : jprb
47 !
48 USE modi_abor1_sfx
49 USE modi_add_forecast_to_date_surf
50 !
51 USE mode_ekf
52 !
53 ! -----------------------------------------------------------
54 !
55 IMPLICIT NONE
56 !
57 !
58 TYPE(isba_t), INTENT(INOUT) :: i
59 !
60  CHARACTER(LEN=6), INTENT(IN) :: hprogram ! program calling surf. schemes
61 INTEGER, INTENT(IN) :: ki
62 REAL, DIMENSION(:), INTENT(IN) :: pt2m
63 REAL, DIMENSION(:), INTENT(IN) :: phu2m
64  CHARACTER(LEN=2), INTENT(IN) :: htest ! must be equal to 'OK'
65 !
66 ! Declarations of local variables
67 !
68  CHARACTER(LEN=30) :: ybgfile
69  CHARACTER(LEN=19) :: ylfname
70  CHARACTER(LEN=9) :: yfname
71  CHARACTER(LEN=7) :: ymyproc
72  CHARACTER(LEN=1) :: ychar
73 !
74 ! Local Matrix for Analysis calculation
75 !
76 ! Allocation
77 ! Perturbed simulations
78 !
79 ! Initial values (to be analysed)
80 ! Observations
81 !
82 ! Temporary vectors used by the EKF approach
83 REAL,DIMENSION(KI) :: zcofswi ! dynamic range (Wfc - Wwilt)
84 !REAL,DIMENSION(KI) :: ZSMSAT ! saturation
85 !REAL,DIMENSION(KI) :: ZWILT
86 !
87 REAL,DIMENSION(KI,I%NPATCH,NVAR) :: zcoef
88 REAL,DIMENSION(KI,I%NPATCH,NVAR) :: zeps ! The perturbation amplitude
89 !
90 REAL,DIMENSION(NVAR+1,NOBSTYPE) :: zyf ! Vector of model observations (averaged)
91 !
92 REAL,DIMENSION(KI*I%NPATCH*NVAR*I%NPATCH*NVAR) :: zblong
93 REAL,DIMENSION(KI,I%NPATCH*NVAR,I%NPATCH*NVAR) :: zb ! background error covariance matrix
94 !
95 REAL,DIMENSION(I%NPATCH*NVAR,I%NPATCH*NVAR) :: zltm ! linear tangent matrix for the f'ward model
96 REAL,DIMENSION(I%NPATCH*NVAR,I%NPATCH*NVAR) :: zq ! model error matrix
97 !
98 REAL,DIMENSION(NOBSTYPE*NBOUTPUT,I%NPATCH*NVAR) :: zho, zhowr ! Jacobian of observation operator
99 REAL,DIMENSION(I%NPATCH*NVAR,NOBSTYPE*NBOUTPUT) :: zhot ! Transpose of HO
100 REAL,DIMENSION(I%NPATCH*NVAR,NOBSTYPE*NBOUTPUT) :: zgain ! Kalman gain (used explicitly for Ba)
101 !
102 REAL,DIMENSION(NOBSTYPE*NBOUTPUT,NOBSTYPE*NBOUTPUT) :: zr ! covariance matrix of observation errors
103 REAL,DIMENSION(NOBSTYPE*NBOUTPUT,NOBSTYPE*NBOUTPUT) :: zk1
104 REAL,DIMENSION(NOBSTYPE*NBOUTPUT) :: zx,zb2,zp
105 !
106 REAL,DIMENSION(I%NPATCH*NVAR,I%NPATCH*NVAR) :: zkrk
107 REAL,DIMENSION(I%NPATCH*NVAR,I%NPATCH*NVAR) :: zidkh
108 REAL,DIMENSION(I%NPATCH*NVAR,I%NPATCH*NVAR) :: zident ! identitiy matrix, used for Ba
109 !
110 REAL,DIMENSION(I%NPATCH) :: zvlaimin
111 !
112 REAL :: ztime ! current time since start of the run (s)
113 
114 INTEGER :: iobscount
115 INTEGER :: iyear ! current year (UTC)
116 INTEGER :: imonth ! current month (UTC)
117 INTEGER :: iday ! current day (UTC)
118 INTEGER :: ihour
119 INTEGER :: iresp ! return code
120 INTEGER :: istep !
121 INTEGER :: imyproc
122 INTEGER :: iobs
123 INTEGER :: istat, icpt, iunit
124 !
125 INTEGER :: ji,jj,jk,jjj,jl,k1,l1
126 !
127 LOGICAL :: gbexists
128 !
129 REAL(KIND=JPRB) :: zhook_handle
130 !
131 !
132 IF (lhook) CALL dr_hook('ASSIM_NATURE_ISBA_EKF',0,zhook_handle)
133 
134 #ifdef USE_SODA
135 
136 !
137 !############################# BEGINNING ###############################
138 !
139 IF (htest/='OK') THEN
140  CALL abor1_sfx('ASSIM_NATURE_ISBA_EKF: FATAL ERROR DURING ARGUMENT TRANSFER')
141 END IF
142 !
143 IF ( nprintlev>0 .AND. nrank==npio ) THEN
144  WRITE(*,*)
145  WRITE(*,*) ' --------------------------'
146  WRITE(*,*) ' | ENTERING VARASSIM |'
147  WRITE(*,*) ' --------------------------'
148  WRITE(*,*)
149 ENDIF
150 !
151 #ifdef SFX_ARO
152 IF ( myproc > 0 ) THEN
153  imyproc = myproc
154 ELSE
155  imyproc = 1
156 ENDIF
157 #else
158 imyproc = nrank+1
159 #endif
160 !
161 WRITE(ymyproc(1:7),'(I7.7)') imyproc
162 !
163 IF ( nprintlev > 0 .AND. nrank==npio ) WRITE(*,*) 'number of patches =',i%NPATCH
164 !
165 !############################# INITIALISATIONS ###############################
166 !
167 ! Read CLAY fraction to compute the SWI range (Wfc - Wwilt)
168 ! (XSIGMA is defined in terms of SWI), need to convert to equivalent v/v
169 ! using same clay fraction in both layers
170 ! Read SAND fraction to compute the saturation for conversion of ERS SWI
171 !
172  CALL cofswi(i%XCLAY(:,1),zcofswi)
173  !
174 !DO JI=1,KI
175  !ZSMSAT (I) = 0.001 * (-1.08*100.*XSAND(I,1) + 494.305)
176  !ZWILT (I) = 0.001 * 37.1342 * ((100.*XCLAY(I,1))**0.5)
177 !ENDDO
178 !
179 ! Set control variables
180 zident(:,:) = 0. ! identity matrix
181 DO jl = 1,nvar
182  !
183  DO jj = 1,i%NPATCH
184  zident(jj+i%NPATCH*(jl-1),jj+i%NPATCH*(jl-1)) = 1.0
185  ENDDO
186  !
187  WHERE ( xi(:,:,jl)/=xundef )
188  zeps(:,:,jl) = xtprt(jl) * xi(:,:,jl)
189  ELSEWHERE
190  zeps(:,:,jl) = 1.
191  ENDWHERE
192  !
193  IF ( trim(cvar(jl))=='WG2' .OR. trim(cvar(jl))=='WG1' ) THEN
194  !
195  DO ji = 1,ki
196  zcoef(ji,:,jl) = zcofswi(ji)*zcofswi(ji)
197  ENDDO
198  !
199  ELSEIF ( trim(cvar(jl))=='LAI' .AND. lbfixed ) THEN
200  !
201  DO ji = 1,ki
202  DO jj = 1,i%NPATCH
203  IF ( xlai_pass(ji,jj)/=xundef .AND. xlai_pass(ji,jj)>=2. ) THEN
204  zcoef(ji,jj,jl) = xlai_pass(ji,jj)*xlai_pass(ji,jj)
205  ELSE
206  zcoef(ji,jj,jl) = 0.4*0.4/(xsigma(jl)*xsigma(jl))
207  ENDIF
208  ENDDO
209  ENDDO
210  !
211  ELSE
212  !
213  zcoef(:,:,jl) = 1.
214  !
215  ENDIF
216  !
217 ENDDO
218 !
219 !############################# B CALCULATION ###############################
220 !
221 ! ----------------------
222 ! VARASSIM OPTION : LBEV
223 ! ----------------------
224 ! Calculate the LTM, and evolve B.
225 !
226 ! Set the B input file depending of an existing B was found or not
227 ybgfile = "BGROUNDin."//trim(ymyproc)
228 INQUIRE (file=trim(ybgfile),exist=gbexists)
229 !
230 IF ( lbev .AND. gbexists ) THEN
231  !
232  zb(:,:,:) = 0.
233  CALL b_big_loop(i, &
234  "READ",ybgfile,zb)
235  IF ( nprintlev > 0 ) WRITE(*,*) 'read previous B matrix ==>',zb(1,1,1),nvar
236  !
237 ELSEIF ( lbev .OR. lbfixed ) THEN
238  !
239  ! Initialization of B
240  zb(:,:,:) = 0.
241  DO ji = 1,ki
242  DO jl = 1,nvar
243  DO jj = 1,i%NPATCH
244  !
245  l1 = jj + i%NPATCH *(jl-1)
246  zb(ji,l1,l1) = xsigma(jl)*xsigma(jl) * zcoef(ji,jj,jl)
247  !
248  ENDDO
249  ENDDO
250  !
251  ENDDO
252  !
253  IF ( lbev ) THEN
254  !
255  zblong(:) = 0.
256  icpt = 0
257  !
258  DO ji = 1,ki
259  DO jj = 1,i%NPATCH
260  DO jjj = 1,i%NPATCH
261  DO jl = 1,nvar
262  DO jk = 1,nvar
263  !
264  l1 = jj + i%NPATCH * (jl-1)
265  !
266  icpt = icpt + 1
267  zblong(icpt) = zb(ji,l1,l1)
268  !
269  ENDDO
270  ENDDO
271  ENDDO
272  ENDDO
273  ENDDO
274  !
275  zb(:,:,:) = 0.
276  CALL b_big_loop(i, &
277  "BUIL","",zb,zblong)
278  IF ( nprintlev > 0 ) WRITE(*,*) 'Initialized B'
279  !
280  ENDIF
281  !
282 ELSE
283  !
284  CALL abor1_sfx("LBEV or LBFIXED should be .TRUE.!")
285  !
286 ENDIF
287 !
288 IF ( lbev ) THEN
289  !
290 !//////////////////////TO WRITE LTM/////////////////////////////////////
291  IF (nprintlev>0) THEN
292  iunit = 120
293  DO jl=1,nvar
294  DO jk=1,nvar
295  iunit = iunit + 1
296  WRITE(ychar,'(I1)') jk
297  ylfname='LTM_del'//trim(cvar(jk))//'_del'//trim(cvar(jl))//"."//trim(ymyproc)
298  OPEN(unit=iunit,file=ylfname,form='FORMATTED',status='UNKNOWN',position='APPEND')
299  ENDDO
300  ENDDO
301  ENDIF
302 !/////////////////////TO WRITE LTM////////////////////////////////////////
303  DO ji = 1,ki
304  !
305  ! calculate LTM
306  zltm(:,:) = 0.0
307  iunit = 120
308  DO jl = 1,nvar ! control variable (x at previous time step)
309  DO jk = 1,nvar
310  iunit = iunit + 1
311  DO jj = 1,i%NPATCH
312  !
313  l1 = jj + i%NPATCH*(jl-1)
314  k1 = jj + i%NPATCH*(jk-1)
315  !
316  IF ( i%XPATCH(ji,jj)>0.0 .AND. xf(ji,jj,jl+1,jk).NE.xundef .AND. xf(ji,jj,1,jk).NE.xundef ) THEN
317  !
318  ! Jacobian of fwd model
319  zltm(l1,k1) = ( xf(ji,jj,jl+1,jk) - xf(ji,jj,1,jk) ) / zeps(ji,jj,jl)
320  ! impose upper/lower limits
321  zltm(l1,k1) = max(-0.1, zltm(l1,k1))
322  zltm(l1,k1) = min( 1.0, zltm(l1,k1))
323  !
324  ENDIF
325  !
326  IF (nprintlev>0) WRITE (iunit,*) zltm(l1,k1)
327  !
328  ENDDO
329  ENDDO
330  ENDDO
331  !
332 !//////////////////////TO WRITE LTM/////////////////////////////////////
333  IF (nprintlev>0) THEN
334  iunit = 120
335  DO jl=1,nvar
336  DO jk=1,nvar
337  iunit = iunit + 1
338  CLOSE(iunit)
339  ENDDO
340  ENDDO
341  !//////////////////////TO WRITE LTM/////////////////////////////////////
342  WRITE(*,*) 'LTM d(wg2)/d(wg2)', zltm(1,1)
343  ENDIF
344  !
345  ! evolve B
346  zb(ji,:,:) = matmul(zltm(:,:),matmul(zb(ji,:,:),transpose(zltm(:,:))))
347  !
348  !
349  ! Adding model error to background error matrix
350  zq(:,:) = 0.0
351  DO jl=1,nvar
352  DO jj=1,i%NPATCH
353  !
354  l1 = jj+i%NPATCH*(jl-1)
355  !
356  zq(l1,l1) = xsigma(jl)*xsigma(jl)
357  !
358  IF (trim(cvar(jl)) == 'LAI') THEN
359  zq(l1,l1) = xscale_qlai*xscale_qlai * zq(l1,l1)
360  ELSE
361  zq(l1,l1) = xscale_q*xscale_q * zq(l1,l1) * zcoef(ji,jj,jl)
362  ENDIF
363  !
364  ENDDO
365  ENDDO
366  !
367  ! B is the forecast matrix - need to add Q
368  IF ( nprintlev > 0 ) THEN
369  WRITE(*,*) 'B before wg2 wg2 ==> ',zb(ji,1,1)/zcofswi(ji),zb(ji,1,1)
370  WRITE(*,*) 'Q value wg2 wg2 ==> ',zq(1,1)/zcofswi(ji),zq(1,1)
371  ENDIF
372  !
373  zb(ji,:,:) = zb(ji,:,:) + zq(:,:)
374  !
375  IF ( nprintlev > 0 ) WRITE(*,*) 'B after wg2 wg2 ==>',zb(ji,1,1)/zcofswi(1),zb(ji,1,1)
376  !
377  ENDDO
378  !
379  ! write out the LTM for the forward model
380  ! Write out current B
381  IF (nprintlev>0) THEN
382  ybgfile="BGROUNDout_LBEV."//trim(ymyproc)
383  CALL b_big_loop(i, &
384  "WRIT",ybgfile,zb)
385  WRITE(*,*) 'store B matrix after TL evolution ==>',zb(1,1,1)
386  WRITE(*,*) 'writing out B'
387  ENDIF
388  !
389 ENDIF
390 !
391 ! ====================================================================
392 !
393 ! Analysis
394 !
395 ! ====================================================================
396 !
397 ! Time reinitialization
398 iyear = i%TTIME%TDATE%YEAR
399 imonth = i%TTIME%TDATE%MONTH
400 iday = i%TTIME%TDATE%DAY
401 !
402 ihour = 0
403 ztime = float(nechgu) * 3600.
404 !
405 !############################# READS OBSERVATIONS ###############################
406 !
407 ! Map the variables in case we read them from CANARI inline/offline FA files
408 ! At the moment only T2M and HU2M can be used. If other variables should be used
409 ! they must be added to the interface or be read from file.
410 IF ( trim(cfile_format_obs) == "FA" ) THEN
411  !
412  DO iobs = 1,nobstype
413  SELECT CASE (trim(cobs(iobs)))
414  CASE("T2M")
415  xyo(:,iobs) = pt2m(:)
416  CASE("HU2M")
417  xyo(:,iobs) = phu2m(:)
418  CASE("WG1","LAI")
419  CALL abor1_sfx("Mapping of "//cobs(iobs)//" is not defined in ASSIM_NATURE_ISBA_EKF!")
420  END SELECT
421  ENDDO
422  !
423 ENDIF
424 !
425 !
426 !//////////////////////TO WRITE OBS/////////////////////////////////////
427 IF ( nprintlev > 0 ) OPEN (unit=111,file='OBSout.'//trim(ymyproc),status='unknown',iostat=istat)
428 DO ji = 1,ki
429  IF ( minval(i%XWGI(ji,1,:))>0. ) THEN
430  xyo(ji,:) = xundef
431  IF ( nprintlev > 0 ) WRITE(*,*) 'OBSERVATION FOR POINT ',ji,' REMOVED'
432  ENDIF
433  IF ( nprintlev > 0 ) WRITE (111,*) xyo(ji,:)
434 ENDDO
435 IF ( nprintlev > 0 ) CLOSE(111)
436 !//////////////////////TO WRITE OBS/////////////////////////////////////
437 !
438 !############################# ANALYSIS ###############################
439 !
440 IF ( nprintlev > 0 ) THEN
441  IF (nrank==npio) THEN
442  WRITE(*,*) 'calculating jacobians',nobs
443  WRITE(*,*) ' and then PERFORMING ANALYSIS'
444  ENDIF
445  !
446  !//////////////////////TO WRITE ANALYSIS ARRAYS/////////////////////////////////////
447  ! WRITE OUT OBS AND YERROR FOR DIAGNOSTIC PURPOSES
448  OPEN (unit=111,file='OBSERRORout.'//trim(ymyproc),status='unknown',iostat=istat)
449  ! *** Write innovations in ASCII file ***
450  OPEN (unit=112,file='INNOV.'//trim(ymyproc),status='unknown',iostat=istat)
451  ! Write analysis results and increments in ASCII file
452  OPEN (unit=113,file='ANAL_INCR.'//trim(ymyproc),status='unknown',iostat=istat)
453  ! **** Write out the observation operator + Gain matrix ****
454  iunit = 150
455  DO jl = 1,nvar
456  DO jk=1,nobstype
457  iunit = iunit + 1
458  WRITE(ychar,'(I1)') jk
459  yfname='HO_'//trim(cvar(jl))//'_v'//ychar
460  OPEN(unit=iunit,file=yfname,form='FORMATTED',status='UNKNOWN',iostat=istat)
461  ENDDO
462  ENDDO
463 ENDIF
464 !//////////////////////TO WRITE ANALYSIS ARRAYS/////////////////////////////////////
465 !
466 IF (i%NPATCH==12) THEN
467  zvlaimin = (/0.3,0.3,0.3,0.3,1.0,1.0,0.3,0.3,0.3,0.3,0.3,0.3/)
468 ELSE
469  zvlaimin = (/0.3/)
470 ENDIF
471 !
472 ALLOCATE(i%XINCR(ki,i%NPATCH*nvar))
473 i%XINCR(:,:) = 0.
474 !
475 iobscount = 0
476 DO ji=1,ki
477  !
478 !---------------- MEAN SIMULATED OBS AVERAGED OVER TILES-----------------------
479  zyf(:,:) = 0.
480  DO jj=1,i%NPATCH
481  IF (i%XPATCH(ji,jj) > 0.0) THEN
482  WHERE ( xf_patch(ji,jj,:,:)/=xundef )
483  zyf(:,:) = zyf(:,:) + i%XPATCH(ji,jj)*xf_patch(ji,jj,:,:)
484  ENDWHERE
485  ENDIF
486  ENDDO
487  IF ( nprintlev > 0 ) WRITE(*,*) 'read in sim obs yf', zyf(:,1)
488  !
489  !
490  zr(:,:) = 0. ! Observation error matrix
491  !
492  zho(:,:) = xundef ! Linearized observation matrix
493  zhowr(:,:) = xundef
494  zb2(:) = xundef ! Innovation vector
495 
496  DO istep=1,nboutput
497  !
498  DO jk = 1,nobstype
499  !
500  k1 = (istep-1)*nobstype + jk
501  !
502 !--------------------- SET OBSERVATION ERROR ------------------
503  zr(k1,k1) = xerrobs(jk)*xerrobs(jk)
504  IF ( cobs(jk) .EQ. "LAI" ) THEN
505  zr(k1,k1) = zr(k1,k1) * xyo(ji,k1)*xyo(ji,k1)
506  ELSEIF (cobs(jk) .EQ. "WG1") THEN
507  ! convert R for wg1 from SWI to abs value
508  zr(k1,k1) = zr(k1,k1) * zcofswi(ji)*zcofswi(ji)
509  ENDIF
510  !
511  ! Apply quality control
512  IF ( ( abs( xyo(ji,k1)-zyf(1,jk) ) > xqcobs(jk) ) .OR. (zr(k1,k1) .LT. 0 ) ) THEN
513  xyo(ji,k1) = 999.0
514  ENDIF
515  !
516 !--------------------- CALCULATE JACOBIANS ------------------
517  DO jl=1,nvar
518  DO jj=1,i%NPATCH
519  !
520  l1 = jj + i%NPATCH*(jl-1)
521  !
522  IF ( i%XPATCH(ji,jj)>0.0 .AND. xf_patch(ji,jj,jl+1,jk).NE.xundef .AND. xf_patch(ji,jj,1,jk).NE.xundef ) THEN
523  zhowr(k1,l1) = i%XPATCH(ji,jj)*(xf_patch(ji,jj,jl+1,jk) - xf_patch(ji,jj,1,jk))/zeps(ji,jj,jl)
524  ENDIF
525  !
526  IF( (xyo(ji,k1).NE.xundef) .AND. (xyo(ji,k1).NE.999.0) ) THEN !if obs available
527  ! Jacobian of obs operator
528  zho(k1,l1) = i%XPATCH(ji,jj)*(xf_patch(ji,jj,jl+1,jk) - xf_patch(ji,jj,1,jk))/zeps(ji,jj,jl)
529  ! impose limits
530  zho(k1,l1) = max(-0.1, zho(k1,l1))
531  zho(k1,l1) = min( 1.0, zho(k1,l1))
532  ! innovation vector
533  zb2(k1) = xyo(ji,k1) - zyf(1,jk)
534  iobscount = iobscount + 1
535  ELSE !if no obs available
536  ! set obs operator and innovation to zero if no obs available
537  zho(k1,l1) = 0.0
538  zb2(k1) = 0.0
539  ENDIF
540  !
541  ENDDO
542  ENDDO
543  !
544  ENDDO
545  !
546  ENDDO
547  !
548  IF ( nprintlev > 0 ) THEN
549  WRITE(111,*) zr(:,:)
550  WRITE(112,*) zb2(:)
551  ENDIF
552 
553 !---------------****** SOIL ANALYSIS *******--------------------------
554  zhot(:,:) = 0.
555  zk1(:,:) = 0.
556  zp(:) = 0.
557  zx(:) = 0.
558  !
559  zhot(:,:) = transpose(zho(:,:))
560  zk1(:,:) = matmul(zho(:,:),matmul(zb(ji,:,:),zhot(:,:))) + zr(:,:)
561  CALL choldc(nobstype,zk1(:,:),zp(:)) ! Cholesky decomposition (1)
562  CALL cholsl(nobstype,zk1(:,:),zp(:),zb2(:),zx(:)) ! Cholesky decomposition (2)
563  i%XINCR(ji,:) = matmul(zb(ji,:,:),matmul(zhot(:,:),zx(:)))
564  DO jl=1,nvar
565  DO jj=1,i%NPATCH
566  !
567  l1 = jj+i%NPATCH*(jl-1)
568  !
569  ! Update the modified values
570  IF ( trim(cvar(jl))=="LAI" ) THEN
571  i%XINCR(ji,l1) = max( i%XINCR(ji,l1), zvlaimin(jj)-xf(ji,jj,1,jl) )
572  xbio_pass(ji,jj) = xbio_pass(ji,jj) + i%XINCR(ji,l1)*xalph(jj)
573  ELSEIF ( xf(ji,jj,1,jl)+i%XINCR(ji,l1)<0. ) THEN
574  i%XINCR(ji,l1) = 0.
575  ENDIF
576  !
577  xf(ji,jj,1,jl) = xf(ji,jj,1,jl) + i%XINCR(ji,l1)
578  !
579  ! For no only warn if we have negative values.
580  IF ( nprintlev > 0 ) THEN
581  IF ( xf(ji,jj,1,jl) < 0. ) WRITE(*,*) "WARNING X<0. for ",ji,jj," for variable ",trim(cvar(jl))
582  ENDIF
583  !
584  ENDDO
585  ENDDO
586  !
587  IF ( nprintlev > 0 ) THEN
588  DO jj=1,i%NPATCH
589  WRITE(113,*) (xf(ji,jj,1,jl),jl=1,nvar), (i%XINCR(ji,jj+i%NPATCH*(jl-1)),jl=1,nvar)
590  ENDDO
591  ENDIF
592 
593 !--------------------ANALYSIS OF B (FOR USE IN NEXT CYCLE)-------------------
594  ! Ba = (I-KH)Bf(I-KH)t+KRKt
595  ! K = BfHt{K1}**-1
596  ! K1 needs PATCH dim added
597 
598  zgain(:,:) = 0.
599  zidkh(:,:) = 0.
600  zkrk(:,:) = 0.
601  !
602  ! K1 = (R+H.B.HT) (calculate inverse -> output goes to K1)
603  CALL inverse_matrix(nobs,zk1(:,:),zp(:))
604  zgain(:,:) = matmul(zb(ji,:,:),matmul(zhot(:,:),zk1(:,:)))
605  zidkh(:,:) = zident(:,:) - matmul(zgain(:,:),zho(:,:))
606  zkrk(:,:) = matmul(zgain(:,:),matmul(zr(:,:),transpose(zgain(:,:))))
607  IF (.NOT.lbfixed) zb(ji,:,:) = matmul(zidkh(:,:),matmul(zb(ji,:,:),transpose(zidkh(:,:)))) + zkrk(:,:)
608 
609  IF ( nprintlev > 0 ) THEN
610  iunit = 150
611  DO jl = 1,nvar
612  DO jk = 1,nobstype
613  iunit = iunit + 1
614  DO jj=1,i%NPATCH
615  WRITE(iunit,*) zhowr(jk,jj+i%NPATCH*(jl-1)),zgain(jj+i%NPATCH*(jl-1),jk)
616  ENDDO
617  ENDDO
618  ENDDO
619  ENDIF
620  !
621 ENDDO
622 !
623 !
624 !//////////////////////TO WRITE ANALYSIS ARRAYS/////////////////////////////////////
625 IF ( nprintlev > 0 ) THEN
626  CLOSE(111)
627  CLOSE(112)
628  CLOSE(113)
629  iunit = 150
630  DO jl = 1,nvar
631  DO jk = 1,nobstype
632  iunit = iunit + 1
633  CLOSE(iunit)
634  ENDDO
635  ENDDO
636 ENDIF
637 !//////////////////////TO WRITE ANALYSIS ARRAYS/////////////////////////////////////
638 !
639 IF (lbev .OR. nprintlev>0) THEN
640  ! Write out analysed B (for use in next cycle)
641  ybgfile = "BGROUNDout_ASSIM."//trim(ymyproc)
642  CALL b_big_loop(i, &
643  "WRIT",ybgfile,zb)
644 ENDIF
645 !
646 IF ( nprintlev > 0 ) THEN
647  iobscount = iobscount / i%NPATCH / nvar
648  IF (nrank==npio) THEN
649  WRITE(*,*)
650  WRITE(*,*) ' ---------------------------------------'
651  WRITE(*,*) ' | EXITING VARASSIM AFTER ANALYSIS |'
652  WRITE(*,*) ' ---------------------------------------'
653  WRITE(*,*)
654  ENDIF
655  WRITE(*,*) 'Number of assimilated observations =',iobscount
656  WRITE(*,*)
657 ENDIF
658 !
659 !############################# GET VARIABLES FOR OUTPUT WRITING ###############################
660 DO jl=1,nvar
661  !
662  ! Update the modified values
663  SELECT CASE (trim(cvar(jl)))
664  CASE("TG1")
665  i%XTG(:,1,:) = xf(:,:,1,jl)
666  CASE("TG2")
667  i%XTG(:,2,:) = xf(:,:,1,jl)
668  CASE("WG1")
669  i%XWG(:,1,:) = xf(:,:,1,jl)
670  CASE("WG2")
671  i%XWG(:,2,:) = xf(:,:,1,jl)
672  CASE("LAI")
673  i%XLAI(:,:) = xf(:,:,1,jl)
674  SELECT CASE (trim(cbio))
675  CASE("BIOMA1","BIOMASS1")
676  i%XBIOMASS(:,1,:) = xbio_pass(:,:)
677  CASE("BIOMA2","BIOMASS2")
678  i%XBIOMASS(:,2,:) = xbio_pass(:,:)
679  CASE("RESPI1","RESP_BIOM1")
680  i%XRESP_BIOMASS(:,1,:) = xbio_pass(:,:)
681  CASE("RESPI2","RESP_BIOM2")
682  i%XRESP_BIOMASS(:,2,:) = xbio_pass(:,:)
683  CASE("LAI")
684  i%XLAI(:,:) = xbio_pass(:,:)
685  CASE default
686  CALL abor1_sfx("Mapping of "//cbio//" is not defined in EKF!")
687  END SELECT
688  CASE default
689  CALL abor1_sfx("Mapping of "//trim(cvar(jl))//" is not defined in EKF!")
690  END SELECT
691 ENDDO
692 !
693 #endif
694 !
695 IF (lhook) CALL dr_hook('ASSIM_NATURE_ISBA_EKF',1,zhook_handle)
696 !
697 END SUBROUTINE assim_nature_isba_ekf
subroutine assim_nature_isba_ekf(I, HPROGRAM, KI, PT2M, PHU2M, HTEST)
subroutine abor1_sfx(YTEXT)
Definition: abor1_sfx.F90:6