FV3 Bundle
type_cmat.F90
Go to the documentation of this file.
1 !----------------------------------------------------------------------
2 ! Module: type_cmat
3 ! Purpose: C matrix derived type
4 ! Author: Benjamin Menetrier
5 ! Licensing: this code is distributed under the CeCILL-C license
6 ! Copyright © 2015-... UCAR, CERFACS, METEO-FRANCE and IRIT
7 !----------------------------------------------------------------------
8 module type_cmat
9 
10 use fckit_mpi_module, only: fckit_mpi_sum
11 use netcdf
12 use tools_const, only: rad2deg,reqkm,req
13 use tools_func, only: gau2gc
14 use tools_kinds, only: kind_real
16 use type_avg, only: avg_type
17 use type_bpar, only: bpar_type
19 use type_diag, only: diag_type
20 use type_displ, only: displ_type
21 use type_ens, only: ens_type
22 use type_geom, only: geom_type
23 use type_hdiag, only: hdiag_type
24 use type_io, only: io_type
25 use type_lct, only: lct_type
26 use type_mom, only: mom_type
27 use type_mpl, only: mpl_type
28 use type_nam, only: nam_type
29 use type_rng, only: rng_type
30 use type_samp, only: samp_type
31 
32 implicit none
33 
34 ! C matrix derived type
36  character(len=1024) :: prefix ! Prefix
37  type(cmat_blk_type),allocatable :: blk(:) ! C matrix blocks
38  logical :: allocated ! Allocation flag
39 contains
40  procedure :: cmat_alloc
41  procedure :: cmat_alloc_blk
42  generic :: alloc => cmat_alloc,cmat_alloc_blk
43  procedure :: dealloc => cmat_dealloc
44  procedure :: copy => cmat_copy
45  procedure :: read => cmat_read
46  procedure :: write => cmat_write
47  procedure :: from_hdiag => cmat_from_hdiag
48  procedure :: from_lct => cmat_from_lct
49  procedure :: from_nam => cmat_from_nam
50  procedure :: from_oops => cmat_from_oops
51  procedure :: setup_sampling => cmat_setup_sampling
52 end type cmat_type
53 
54 private
55 public :: cmat_type
56 
57 contains
58 
59 !----------------------------------------------------------------------
60 ! Subroutine: cmat_alloc
61 ! Purpose: C matrix allocation
62 !----------------------------------------------------------------------
63 subroutine cmat_alloc(cmat,bpar,prefix)
64 
65 implicit none
66 
67 ! Passed variables
68 class(cmat_type),intent(inout) :: cmat ! C matrix
69 type(bpar_type),intent(in) :: bpar ! Block parameters
70 character(len=*),intent(in) :: prefix ! Prefix
71 
72 ! Local variables
73 integer :: ib
74 
75 ! Copy prefix
76 cmat%prefix = prefix
77 
78 ! Allocation
79 if (.not.allocated(cmat%blk)) allocate(cmat%blk(bpar%nbe))
80 
81 ! Set block name
82 do ib=1,bpar%nbe
83  cmat%blk(ib)%name = trim(prefix)//'_'//trim(bpar%blockname(ib))
84 end do
85 
86 end subroutine cmat_alloc
87 
88 !----------------------------------------------------------------------
89 ! Subroutine: cmat_alloc_blk
90 ! Purpose: C matrix block allocation
91 !----------------------------------------------------------------------
92 subroutine cmat_alloc_blk(cmat,nam,geom,bpar)
93 
94 implicit none
95 
96 ! Passed variables
97 class(cmat_type),intent(inout) :: cmat ! C matrix
98 type(nam_type),target,intent(in) :: nam ! Namelist
99 type(geom_type),target,intent(in) :: geom ! Geometry
100 type(bpar_type),intent(in) :: bpar ! Block parameters
101 
102 ! Local variables
103 integer :: ib
104 
105 ! Allocation
106 do ib=1,bpar%nbe
107  cmat%blk(ib)%ib = ib
108  call cmat%blk(ib)%alloc(nam,geom,bpar)
109 end do
110 
111 ! Update allocation flag
112 cmat%allocated = .true.
113 
114 end subroutine cmat_alloc_blk
115 
116 !----------------------------------------------------------------------
117 ! Subroutine: cmat_dealloc
118 ! Purpose: C matrix allocation
119 !----------------------------------------------------------------------
120 subroutine cmat_dealloc(cmat,bpar)
122 implicit none
123 
124 ! Passed variables
125 class(cmat_type),intent(inout) :: cmat ! C matrix
126 type(bpar_type),intent(in) :: bpar ! Block parameters
127 
128 ! Local variables
129 integer :: ib
130 
131 ! Release memory
132 if (allocated(cmat%blk)) then
133  do ib=1,bpar%nbe
134  call cmat%blk(ib)%dealloc
135  end do
136  deallocate(cmat%blk)
137 end if
138 
139 ! Update allocation flag
140 cmat%allocated = .false.
141 
142 end subroutine cmat_dealloc
143 
144 !----------------------------------------------------------------------
145 ! Function: cmat_copy
146 ! Purpose: C matrix copy
147 !----------------------------------------------------------------------
148 type(cmat_type) function cmat_copy(cmat,nam,geom,bpar)
150 implicit none
151 
152 ! Passed variables
153 class(cmat_type),intent(in) :: cmat ! C matrix
154 type(nam_type),target,intent(in) :: nam ! Namelist
155 type(geom_type),target,intent(in) :: geom ! Geometry
156 type(bpar_type),intent(in) :: bpar ! Block parameters
157 
158 ! Local variables
159 integer :: ib
160 
161 ! Allocation
162 call cmat_copy%alloc(bpar,trim(cmat%prefix))
163 
164 ! Copy attributes
165 do ib=1,bpar%nbe
166  if (bpar%B_block(ib).and.bpar%nicas_block(ib)) then
167  cmat_copy%blk(ib)%double_fit = cmat%blk(ib)%double_fit
168  cmat_copy%blk(ib)%anisotropic = cmat%blk(ib)%anisotropic
169  end if
170 end do
171 
172 ! Allocation
173 call cmat_copy%alloc(nam,geom,bpar)
174 
175 ! Copy
176 do ib=1,bpar%nbe
177  if (allocated(cmat%blk(ib)%coef_ens)) cmat_copy%blk(ib)%coef_ens = cmat%blk(ib)%coef_ens
178  if (allocated(cmat%blk(ib)%coef_sta)) cmat_copy%blk(ib)%coef_sta = cmat%blk(ib)%coef_sta
179  if (allocated(cmat%blk(ib)%rh)) cmat_copy%blk(ib)%rh = cmat%blk(ib)%rh
180  if (allocated(cmat%blk(ib)%rv)) cmat_copy%blk(ib)%rv = cmat%blk(ib)%rv
181  if (allocated(cmat%blk(ib)%rv_rfac)) cmat_copy%blk(ib)%rv_rfac = cmat%blk(ib)%rv_rfac
182  if (allocated(cmat%blk(ib)%rv_coef)) cmat_copy%blk(ib)%rv_coef = cmat%blk(ib)%rv_coef
183  if (allocated(cmat%blk(ib)%rhs)) cmat_copy%blk(ib)%rhs = cmat%blk(ib)%rhs
184  if (allocated(cmat%blk(ib)%rvs)) cmat_copy%blk(ib)%rvs = cmat%blk(ib)%rvs
185  if (allocated(cmat%blk(ib)%H11)) cmat_copy%blk(ib)%H11 = cmat%blk(ib)%H11
186  if (allocated(cmat%blk(ib)%H22)) cmat_copy%blk(ib)%H22 = cmat%blk(ib)%H22
187  if (allocated(cmat%blk(ib)%H33)) cmat_copy%blk(ib)%H33 = cmat%blk(ib)%H33
188  if (allocated(cmat%blk(ib)%H12)) cmat_copy%blk(ib)%H12 = cmat%blk(ib)%H12
189  if (allocated(cmat%blk(ib)%Hcoef)) cmat_copy%blk(ib)%Hcoef = cmat%blk(ib)%Hcoef
190  if (allocated(cmat%blk(ib)%displ_lon)) cmat_copy%blk(ib)%displ_lon = cmat%blk(ib)%displ_lon
191  if (allocated(cmat%blk(ib)%displ_lat)) cmat_copy%blk(ib)%displ_lat = cmat%blk(ib)%displ_lat
192 end do
193 
194 end function cmat_copy
195 
196 !----------------------------------------------------------------------
197 ! Subroutine: cmat_read
198 ! Purpose: read C matrix
199 !----------------------------------------------------------------------
200 subroutine cmat_read(cmat,mpl,nam,geom,bpar,io)
202 implicit none
203 
204 ! Passed variables
205 class(cmat_type),intent(inout) :: cmat ! C matrix
206 type(mpl_type),intent(inout) :: mpl ! MPI data
207 type(nam_type),intent(in) :: nam ! Namelist
208 type(geom_type),intent(in) :: geom ! Geometry
209 type(bpar_type),intent(in) :: bpar ! Block parameters
210 type(io_type),intent(in) :: io ! I/O
211 
212 ! Local variables
213 integer :: ib,ncid,double_fit,anisotropic
214 character(len=1024) :: filename
215 character(len=1024) :: subr = 'cmat_read'
216 
217 ! Allocation
218 call cmat%alloc(bpar,'cmat')
219 
220 do ib=1,bpar%nbe
221  if (bpar%B_block(ib).and.bpar%nicas_block(ib)) then
222  if (mpl%main) then
223  ! Set filename
224  filename = trim(nam%prefix)//'_'//trim(cmat%blk(ib)%name)
225 
226  ! Read attributes
227  call mpl%ncerr(subr,nf90_open(trim(nam%datadir)//'/'//trim(filename)//'.nc',nf90_nowrite,ncid))
228  call mpl%ncerr(subr,nf90_get_att(ncid,nf90_global,'double_fit',double_fit))
229  if (double_fit==1) then
230  cmat%blk(ib)%double_fit = .true.
231  else
232  cmat%blk(ib)%double_fit = .false.
233  end if
234  call mpl%ncerr(subr,nf90_get_att(ncid,nf90_global,'anisotropic',anisotropic))
235  if (anisotropic==1) then
236  cmat%blk(ib)%anisotropic = .true.
237  else
238  cmat%blk(ib)%anisotropic = .false.
239  end if
240  call mpl%ncerr(subr,nf90_close(ncid))
241  end if
242 
243  ! Broadcast
244  call mpl%f_comm%broadcast(cmat%blk(ib)%double_fit,mpl%ioproc-1)
245  call mpl%f_comm%broadcast(cmat%blk(ib)%anisotropic,mpl%ioproc-1)
246  end if
247 end do
248 
249 ! Allocation
250 call cmat%alloc(nam,geom,bpar)
251 
252 do ib=1,bpar%nbe
253  if (bpar%B_block(ib).and.bpar%nicas_block(ib)) then
254  ! Set filename
255  filename = trim(nam%prefix)//'_'//trim(cmat%blk(ib)%name)
256 
257  ! Read fields
258  if (bpar%nicas_block(ib)) then
259  call io%fld_read(mpl,nam,geom,filename,'coef_ens',cmat%blk(ib)%coef_ens)
260  call io%fld_read(mpl,nam,geom,filename,'coef_sta',cmat%blk(ib)%coef_sta)
261  call io%fld_read(mpl,nam,geom,filename,'rh',cmat%blk(ib)%rh)
262  call io%fld_read(mpl,nam,geom,filename,'rv',cmat%blk(ib)%rv)
263  if (cmat%blk(ib)%double_fit) then
264  call io%fld_read(mpl,nam,geom,filename,'rv_rfac',cmat%blk(ib)%rv_rfac)
265  call io%fld_read(mpl,nam,geom,filename,'rv_coef',cmat%blk(ib)%rv_coef)
266  end if
267  call io%fld_read(mpl,nam,geom,filename,'rhs',cmat%blk(ib)%rhs)
268  call io%fld_read(mpl,nam,geom,filename,'rvs',cmat%blk(ib)%rvs)
269  if (cmat%blk(ib)%anisotropic) then
270  call io%fld_read(mpl,nam,geom,filename,'H11',cmat%blk(ib)%H11)
271  call io%fld_read(mpl,nam,geom,filename,'H22',cmat%blk(ib)%H22)
272  call io%fld_read(mpl,nam,geom,filename,'H33',cmat%blk(ib)%H33)
273  call io%fld_read(mpl,nam,geom,filename,'H12',cmat%blk(ib)%H12)
274  end if
275  end if
276  if ((ib==bpar%nbe).and.nam%displ_diag) then
277  call io%fld_read(mpl,nam,geom,filename,'displ_lon',cmat%blk(ib)%displ_lon)
278  call io%fld_read(mpl,nam,geom,filename,'displ_lat',cmat%blk(ib)%displ_lat)
279  end if
280  end if
281 end do
282 
283 end subroutine cmat_read
284 
285 !----------------------------------------------------------------------
286 ! Subroutine: cmat_write
287 ! Purpose: write C matrix
288 !----------------------------------------------------------------------
289 subroutine cmat_write(cmat,mpl,nam,geom,bpar,io)
291 implicit none
292 
293 ! Passed variables
294 class(cmat_type),intent(in) :: cmat ! C matrix
295 type(mpl_type),intent(inout) :: mpl ! MPI data
296 type(nam_type),intent(in) :: nam ! Namelist
297 type(geom_type),intent(in) :: geom ! Geometry
298 type(bpar_type),intent(in) :: bpar ! Block parameters
299 type(io_type),intent(in) :: io ! I/O
300 
301 ! Local variables
302 integer :: ib,ncid
303 character(len=1024) :: filename
304 character(len=1024) :: subr = 'cmat_write'
305 
306 do ib=1,bpar%nbe
307  if (bpar%B_block(ib).and.bpar%nicas_block(ib)) then
308  ! Set filename
309  filename = trim(nam%prefix)//'_'//trim(cmat%blk(ib)%name)
310 
311  ! Write fields
312  if (bpar%nicas_block(ib)) then
313  call io%fld_write(mpl,nam,geom,filename,'coef_ens',cmat%blk(ib)%coef_ens)
314  call io%fld_write(mpl,nam,geom,filename,'coef_sta',cmat%blk(ib)%coef_sta)
315  call io%fld_write(mpl,nam,geom,filename,'rh',cmat%blk(ib)%rh)
316  call io%fld_write(mpl,nam,geom,filename,'rv',cmat%blk(ib)%rv)
317  if (cmat%blk(ib)%double_fit) then
318  call io%fld_write(mpl,nam,geom,filename,'rv_rfac',cmat%blk(ib)%rv_rfac)
319  call io%fld_write(mpl,nam,geom,filename,'rv_coef',cmat%blk(ib)%rv_coef)
320  end if
321  call io%fld_write(mpl,nam,geom,filename,'rhs',cmat%blk(ib)%rhs)
322  call io%fld_write(mpl,nam,geom,filename,'rvs',cmat%blk(ib)%rvs)
323  if (cmat%blk(ib)%anisotropic) then
324  call io%fld_write(mpl,nam,geom,filename,'H11',cmat%blk(ib)%H11)
325  call io%fld_write(mpl,nam,geom,filename,'H22',cmat%blk(ib)%H22)
326  call io%fld_write(mpl,nam,geom,filename,'H33',cmat%blk(ib)%H33)
327  call io%fld_write(mpl,nam,geom,filename,'H12',cmat%blk(ib)%H12)
328  end if
329  end if
330  if ((ib==bpar%nbe).and.nam%displ_diag) then
331  call io%fld_write(mpl,nam,geom,filename,'displ_lon',cmat%blk(ib)%displ_lon)
332  call io%fld_write(mpl,nam,geom,filename,'displ_lat',cmat%blk(ib)%displ_lat)
333  end if
334 
335  if (mpl%main) then
336  ! Write attributes
337  call mpl%ncerr(subr,nf90_open(trim(nam%datadir)//'/'//trim(filename)//'.nc',nf90_write,ncid))
338  call mpl%ncerr(subr,nf90_redef(ncid))
339  if (cmat%blk(ib)%double_fit) then
340  call mpl%ncerr(subr,nf90_put_att(ncid,nf90_global,'double_fit',1))
341  else
342  call mpl%ncerr(subr,nf90_put_att(ncid,nf90_global,'double_fit',0))
343  end if
344  if (cmat%blk(ib)%anisotropic) then
345  call mpl%ncerr(subr,nf90_put_att(ncid,nf90_global,'anisotropic',1))
346  else
347  call mpl%ncerr(subr,nf90_put_att(ncid,nf90_global,'anisotropic',0))
348  end if
349  call mpl%ncerr(subr,nf90_close(ncid))
350  end if
351  end if
352 end do
353 
354 end subroutine cmat_write
355 
356 !----------------------------------------------------------------------
357 ! Subroutine: cmat_from_hdiag
358 ! Purpose: transform HDIAG into C matrix
359 !----------------------------------------------------------------------
360 subroutine cmat_from_hdiag(cmat,mpl,nam,geom,bpar,hdiag)
362 implicit none
363 
364 ! Passed variables
365 class(cmat_type),intent(inout) :: cmat ! C matrix
366 type(mpl_type),intent(inout) :: mpl ! MPI data
367 type(nam_type),intent(in) :: nam ! Namelist
368 type(geom_type),intent(in) :: geom ! Geometry
369 type(bpar_type),intent(in) :: bpar ! Block parameters
370 type(hdiag_type),intent(in) :: hdiag ! Hybrid diagnostics
371 
372 ! Local variables
373 integer :: ib,n,i,il0,il0i,ic2a,its
374 real(kind_real) :: fld_c2a(hdiag%samp%nc2a,geom%nl0,6),fld_c2b(hdiag%samp%nc2b,geom%nl0),fld_c0a(geom%nc0a,geom%nl0,6)
375 
376 ! Allocation
377 call cmat%alloc(bpar,'cmat')
378 
379 ! Copy attributes
380 do ib=1,bpar%nbe
381  if (bpar%B_block(ib).and.bpar%nicas_block(ib)) then
382  select case (trim(nam%method))
383  case ('cor')
384  cmat%blk(ib)%double_fit = hdiag%cor_1%blk(0,ib)%double_fit
385  case ('loc_norm','loc')
386  cmat%blk(ib)%double_fit = hdiag%loc_1%blk(0,ib)%double_fit
387  case ('hyb-avg','hyb-rnd')
388  cmat%blk(ib)%double_fit = hdiag%loc_2%blk(0,ib)%double_fit
389  case ('dual-ens')
390  call mpl%abort('dual-ens not ready yet for C matrix')
391  case default
392  call mpl%abort('cmat not implemented yet for this method')
393  end select
394  cmat%blk(ib)%anisotropic = .false.
395  end if
396 end do
397 
398 ! Allocation
399 call cmat%alloc(nam,geom,bpar)
400 
401 ! Convolution parameters
402 do ib=1,bpar%nbe
403  if (bpar%B_block(ib)) then
404  if (bpar%nicas_block(ib)) then
405  if (nam%local_diag) then
406  ! Copy data
407  n = 4
408  if (cmat%blk(ib)%double_fit) n = n+2
409  do ic2a=1,hdiag%samp%nc2a
410  select case (trim(nam%method))
411  case ('cor')
412  fld_c2a(ic2a,:,1) = hdiag%cor_1%blk(ic2a,ib)%raw_coef_ens
413  fld_c2a(ic2a,:,2) = 0.0
414  fld_c2a(ic2a,:,3) = hdiag%cor_1%blk(ic2a,ib)%fit_rh
415  fld_c2a(ic2a,:,4) = hdiag%cor_1%blk(ic2a,ib)%fit_rv
416  if (cmat%blk(ib)%double_fit) then
417  fld_c2a(ic2a,:,5) = hdiag%cor_1%blk(ic2a,ib)%fit_rv_rfac
418  fld_c2a(ic2a,:,6) = hdiag%cor_1%blk(ic2a,ib)%fit_rv_coef
419  end if
420  case ('loc_norm','loc')
421  fld_c2a(ic2a,:,1) = hdiag%loc_1%blk(ic2a,ib)%raw_coef_ens
422  fld_c2a(ic2a,:,2) = 0.0
423  fld_c2a(ic2a,:,3) = hdiag%loc_1%blk(ic2a,ib)%fit_rh
424  fld_c2a(ic2a,:,4) = hdiag%loc_1%blk(ic2a,ib)%fit_rv
425  if (cmat%blk(ib)%double_fit) then
426  fld_c2a(ic2a,:,5) = hdiag%loc_1%blk(ic2a,ib)%fit_rv_rfac
427  fld_c2a(ic2a,:,6) = hdiag%loc_1%blk(ic2a,ib)%fit_rv_coef
428  end if
429  case ('hyb-avg','hyb-rnd')
430  fld_c2a(ic2a,:,1) = hdiag%loc_2%blk(ic2a,ib)%raw_coef_ens
431  fld_c2a(ic2a,:,2) = hdiag%loc_2%blk(ic2a,ib)%raw_coef_sta
432  fld_c2a(ic2a,:,3) = hdiag%loc_2%blk(ic2a,ib)%fit_rh
433  fld_c2a(ic2a,:,4) = hdiag%loc_2%blk(ic2a,ib)%fit_rv
434  if (cmat%blk(ib)%double_fit) then
435  fld_c2a(ic2a,:,5) = hdiag%loc_2%blk(ic2a,ib)%fit_rv_rfac
436  fld_c2a(ic2a,:,6) = hdiag%loc_2%blk(ic2a,ib)%fit_rv_coef
437  end if
438  case ('dual-ens')
439  call mpl%abort('dual-ens not ready yet for C matrix')
440  case default
441  call mpl%abort('cmat not implemented yet for this method')
442  end select
443  end do
444 
445  do i=1,n
446  ! Fill missing values
447  do il0=1,geom%nl0
448  call hdiag%samp%diag_fill(mpl,nam,geom,il0,fld_c2a(:,il0,i))
449  end do
450 
451  ! Interpolate
452  call hdiag%samp%com_AB%ext(mpl,geom%nl0,fld_c2a(:,:,i),fld_c2b)
453  do il0=1,geom%nl0
454  il0i = min(il0,geom%nl0i)
455  call hdiag%samp%h(il0i)%apply(mpl,fld_c2b(:,il0),fld_c0a(:,il0,i))
456  end do
457  end do
458 
459  ! Copy to C matrix
460  cmat%blk(ib)%coef_ens = fld_c0a(:,:,1)
461  call mpl%f_comm%allreduce(sum(cmat%blk(ib)%coef_ens,mask=geom%mask_c0a),cmat%blk(ib)%wgt,fckit_mpi_sum())
462  cmat%blk(ib)%wgt = cmat%blk(ib)%wgt/real(count(geom%mask_c0),kind_real)
463  cmat%blk(ib)%coef_sta = fld_c0a(:,:,2)
464  cmat%blk(ib)%rh = fld_c0a(:,:,3)
465  cmat%blk(ib)%rv = fld_c0a(:,:,4)
466  if (cmat%blk(ib)%double_fit) then
467  cmat%blk(ib)%rv_rfac = fld_c0a(:,:,5)
468  cmat%blk(ib)%rv_coef = fld_c0a(:,:,6)
469  end if
470  else
471  ! Copy to C matrix
472  do il0=1,geom%nl0
473  ! Copy data
474  select case (trim(nam%method))
475  case ('cor')
476  cmat%blk(ib)%coef_ens(:,il0) = hdiag%cor_1%blk(0,ib)%raw_coef_ens(il0)
477  cmat%blk(ib)%wgt = sum(hdiag%cor_1%blk(0,ib)%raw_coef_ens)/real(geom%nl0,kind_real)
478  cmat%blk(ib)%coef_sta(:,il0) = 0.0
479  cmat%blk(ib)%rh(:,il0) = hdiag%cor_1%blk(0,ib)%fit_rh(il0)
480  cmat%blk(ib)%rv(:,il0) = hdiag%cor_1%blk(0,ib)%fit_rv(il0)
481  if (cmat%blk(ib)%double_fit) then
482  cmat%blk(ib)%rv_rfac(:,il0) = hdiag%cor_1%blk(0,ib)%fit_rv_rfac(il0)
483  cmat%blk(ib)%rv_coef(:,il0) = hdiag%cor_1%blk(0,ib)%fit_rv_coef(il0)
484  end if
485  case ('loc_norm','loc')
486  cmat%blk(ib)%coef_ens(:,il0) = hdiag%loc_1%blk(0,ib)%raw_coef_ens(il0)
487  cmat%blk(ib)%wgt = sum(hdiag%loc_1%blk(0,ib)%raw_coef_ens)/real(geom%nl0,kind_real)
488  cmat%blk(ib)%coef_sta(:,il0) = 0.0
489  cmat%blk(ib)%rh(:,il0) = hdiag%loc_1%blk(0,ib)%fit_rh(il0)
490  cmat%blk(ib)%rv(:,il0) = hdiag%loc_1%blk(0,ib)%fit_rv(il0)
491  if (cmat%blk(ib)%double_fit) then
492  cmat%blk(ib)%rv_rfac(:,il0) = hdiag%loc_1%blk(0,ib)%fit_rv_rfac(il0)
493  cmat%blk(ib)%rv_coef(:,il0) = hdiag%loc_1%blk(0,ib)%fit_rv_coef(il0)
494  end if
495  case ('hyb-avg','hyb-rnd')
496  cmat%blk(ib)%coef_ens(:,il0) = hdiag%loc_2%blk(0,ib)%raw_coef_ens(il0)
497  cmat%blk(ib)%wgt = sum(hdiag%loc_2%blk(0,ib)%raw_coef_ens)/real(geom%nl0,kind_real)
498  cmat%blk(ib)%coef_sta(:,il0) = hdiag%loc_2%blk(0,ib)%raw_coef_sta
499  cmat%blk(ib)%rh(:,il0) = hdiag%loc_2%blk(0,ib)%fit_rh(il0)
500  cmat%blk(ib)%rv(:,il0) = hdiag%loc_2%blk(0,ib)%fit_rv(il0)
501  if (cmat%blk(ib)%double_fit) then
502  cmat%blk(ib)%rv_rfac(:,il0) = hdiag%loc_2%blk(0,ib)%fit_rv_rfac(il0)
503  cmat%blk(ib)%rv_coef(:,il0) = hdiag%loc_2%blk(0,ib)%fit_rv_coef(il0)
504  end if
505  case ('dual-ens')
506  call mpl%abort('dual-ens not ready yet for C matrix')
507  case default
508  call mpl%abort('cmat not implemented yet for this method')
509  end select
510  end do
511  end if
512  else
513  ! Define weight only
514  select case (trim(nam%method))
515  case ('cor')
516  cmat%blk(ib)%wgt = sum(hdiag%cor_1%blk(0,ib)%raw_coef_ens)/real(geom%nl0,kind_real)
517  case ('loc_norm','loc')
518  cmat%blk(ib)%wgt = sum(hdiag%loc_1%blk(0,ib)%raw_coef_ens)/real(geom%nl0,kind_real)
519  case ('hyb-avg','hyb-rnd')
520  cmat%blk(ib)%wgt = sum(hdiag%loc_2%blk(0,ib)%raw_coef_ens)/real(geom%nl0,kind_real)
521  case ('dual-ens')
522  call mpl%abort('dual-ens not ready yet for C matrix')
523  case default
524  call mpl%abort('cmat not implemented yet for this method')
525  end select
526  end if
527  end if
528 end do
529 
530 ! Displacement
531 if (nam%displ_diag) then
532  do its=2,nam%nts
533  cmat%blk(bpar%nbe)%displ_lon(:,:,its) = hdiag%samp%displ_lon(:,:,its)
534  cmat%blk(bpar%nbe)%displ_lat(:,:,its) = hdiag%samp%displ_lat(:,:,its)
535  end do
536 end if
537 
538 end subroutine cmat_from_hdiag
539 
540 !----------------------------------------------------------------------
541 ! Subroutine: cmat_from_lct
542 ! Purpose: copy LCT into C matrix
543 !----------------------------------------------------------------------
544 subroutine cmat_from_lct(cmat,mpl,nam,geom,bpar,lct)
546 implicit none
547 
548 ! Passed variables
549 class(cmat_type),intent(inout) :: cmat ! C matrix
550 type(mpl_type),intent(inout) :: mpl ! MPI data
551 type(nam_type),intent(in) :: nam ! Namelist
552 type(geom_type),intent(in) :: geom ! Geometry
553 type(bpar_type),intent(in) :: bpar ! Block parameters
554 type(lct_type),intent(in) :: lct ! LCT
555 
556 ! Local variables
557 integer :: ib,iv,jv,its,jts,iscales,il0,ic0a
558 real(kind_real) :: tr,det,diff
559 
560 ! Allocation
561 call cmat%alloc(bpar,'cmat')
562 
563 ! Copy attributes
564 do ib=1,bpar%nbe
565  if (bpar%B_block(ib).and.bpar%nicas_block(ib)) then
566  cmat%blk(ib)%double_fit = .false.
567  cmat%blk(ib)%anisotropic = .true.
568  end if
569 end do
570 
571 ! Allocation
572 call cmat%alloc(nam,geom,bpar)
573 
574 ! Convolution parameters
575 do ib=1,bpar%nbe
576  if (bpar%B_block(ib).and.bpar%nicas_block(ib)) then
577  ! Indices
578  iv = bpar%b_to_v1(ib)
579  jv = bpar%b_to_v2(ib)
580  its = bpar%b_to_ts1(ib)
581  jts = bpar%b_to_ts2(ib)
582  if ((iv/=jv).or.(its/=jts)) call mpl%abort('only diagonal blocks for cmat_from_lct')
583 
584  if (lct%blk(ib)%nscales>1) call mpl%warning('only the first scale is used to define cmat from LCT')
585  iscales = 1
586 
587  do il0=1,geom%nl0
588  do ic0a=1,geom%nc0a
589  if (geom%mask_c0a(ic0a,il0)) then
590  ! Copy LCT
591  cmat%blk(ib)%H11(ic0a,il0) = lct%blk(ib)%H11(ic0a,il0,iscales)
592  cmat%blk(ib)%H22(ic0a,il0) = lct%blk(ib)%H22(ic0a,il0,iscales)
593  cmat%blk(ib)%H33(ic0a,il0) = lct%blk(ib)%H33(ic0a,il0,iscales)
594  cmat%blk(ib)%H12(ic0a,il0) = lct%blk(ib)%H12(ic0a,il0,iscales)
595 
596  ! Copy scale coefficient
597  cmat%blk(ib)%Hcoef(ic0a,il0) = lct%blk(ib)%Dcoef(ic0a,il0,iscales)
598 
599  ! Compute support radii from the largest scale
600  tr = cmat%blk(ib)%H11(ic0a,il0)+cmat%blk(ib)%H22(ic0a,il0)
601  det = cmat%blk(ib)%H11(ic0a,il0)*cmat%blk(ib)%H22(ic0a,il0)-cmat%blk(ib)%H12(ic0a,il0)**2
602  diff = 0.25*(cmat%blk(ib)%H11(ic0a,il0)-cmat%blk(ib)%H22(ic0a,il0))**2+cmat%blk(ib)%H12(ic0a,il0)**2
603  if ((det>0.0).and..not.(diff<0.0)) then
604  if (0.5*tr>sqrt(diff)) then
605  cmat%blk(ib)%rh(ic0a,il0) = gau2gc/(sqrt(0.5*tr-sqrt(diff)))
606  else
607  write(mpl%info,*) 0.5*tr,sqrt(diff)
608  call mpl%abort('non positive-definite LCT in cmat_from_lct (eigenvalue)')
609  end if
610  else
611  write(mpl%info,*) cmat%blk(ib)%H11(ic0a,il0),cmat%blk(ib)%H22(ic0a,il0), &
612  & cmat%blk(ib)%H12(ic0a,il0)
613  call mpl%abort('non positive-definite LCT in cmat_from_lct (determinant)')
614  end if
615  if (cmat%blk(ib)%H33(ic0a,il0)>0.0) then
616  cmat%blk(ib)%rv(ic0a,il0) = gau2gc/(sqrt(cmat%blk(ib)%H33(ic0a,il0)))
617  else
618  cmat%blk(ib)%rv(ic0a,il0) = 0.0
619  end if
620  end if
621  end do
622  end do
623 
624  ! Set coefficients
625  cmat%blk(ib)%coef_ens = 1.0
626  cmat%blk(ib)%coef_sta = 0.0
627  cmat%blk(ib)%wgt = 1.0
628  end if
629 end do
630 
631 end subroutine cmat_from_lct
632 
633 !----------------------------------------------------------------------
634 ! Subroutine: cmat_from_nam
635 ! Purpose: copy radii into C matrix
636 !----------------------------------------------------------------------
637 subroutine cmat_from_nam(cmat,mpl,nam,geom,bpar)
639 implicit none
640 
641 ! Passed variables
642 class(cmat_type),intent(inout) :: cmat ! C matrix
643 type(mpl_type),intent(in) :: mpl ! MPI data
644 type(nam_type),intent(in) :: nam ! Namelist
645 type(geom_type),intent(in) :: geom ! Geometry
646 type(bpar_type),intent(in) :: bpar ! Block parameters
647 
648 ! Local variables
649 integer :: ib,iv,jv,its,jts
650 
651 write(mpl%info,'(a)') '-------------------------------------------------------------------'
652 write(mpl%info,'(a)') '--- Copy namelist radii into C matrix'
653 call flush(mpl%info)
654 
655 ! Allocation
656 call cmat%alloc(bpar,'cmat')
657 
658 ! Copy attributes
659 do ib=1,bpar%nbe
660  if (bpar%B_block(ib).and.bpar%nicas_block(ib)) then
661  cmat%blk(ib)%double_fit = .false.
662  cmat%blk(ib)%anisotropic = .false.
663  end if
664 end do
665 
666 ! Allocation
667 call cmat%alloc(nam,geom,bpar)
668 
669 ! Convolution parameters
670 do ib=1,bpar%nbe
671  if (bpar%B_block(ib).and.bpar%nicas_block(ib)) then
672  ! Indices
673  iv = bpar%b_to_v1(ib)
674  jv = bpar%b_to_v2(ib)
675  its = bpar%b_to_ts1(ib)
676  jts = bpar%b_to_ts2(ib)
677  if ((iv/=jv).or.(its/=jts)) call mpl%abort('only diagonal blocks for cmat_from_nam')
678 
679  ! Copy support radii
680  cmat%blk(ib)%rh = nam%rh
681  cmat%blk(ib)%rhs = nam%rh
682  cmat%blk(ib)%rv = nam%rv
683  cmat%blk(ib)%rvs = nam%rv
684 
685  ! Set coefficients
686  cmat%blk(ib)%coef_ens = 1.0
687  cmat%blk(ib)%coef_sta = 0.0
688  cmat%blk(ib)%wgt = 1.0
689  end if
690 end do
691 
692 end subroutine cmat_from_nam
693 
694 !----------------------------------------------------------------------
695 ! Subroutine: cmat_from_oops
696 ! Purpose: copy C matrix from OOPS
697 !----------------------------------------------------------------------
698 subroutine cmat_from_oops(cmat,mpl,geom,bpar)
700 implicit none
701 
702 ! Passed variables
703 class(cmat_type),intent(inout) :: cmat ! C matrix
704 type(mpl_type),intent(in) :: mpl ! MPI data
705 type(geom_type),intent(in) :: geom ! Geometry
706 type(bpar_type),intent(in) :: bpar ! Block parameters
707 
708 ! Local variables
709 integer :: ib
710 
711 do ib=1,bpar%nbe
712  if (bpar%B_block(ib).and.bpar%nicas_block(ib)) then
713  if (allocated(cmat%blk(ib)%oops_coef_ens)) then
714  write(mpl%info,'(a7,a,a)') '','Ensemble coefficient copied from OOPS for block ',trim(bpar%blockname(ib))
715  cmat%blk(ib)%coef_ens = cmat%blk(ib)%oops_coef_ens
716  call mpl%f_comm%allreduce(sum(cmat%blk(ib)%coef_ens,mask=geom%mask_c0a),cmat%blk(ib)%wgt,fckit_mpi_sum())
717  cmat%blk(ib)%wgt = cmat%blk(ib)%wgt/real(count(geom%mask_c0),kind_real)
718  end if
719  if (allocated(cmat%blk(ib)%oops_coef_sta)) then
720  write(mpl%info,'(a7,a,a)') '','Static coefficient copied from OOPS for block ',trim(bpar%blockname(ib))
721  cmat%blk(ib)%coef_sta = cmat%blk(ib)%oops_coef_sta
722  end if
723  if (allocated(cmat%blk(ib)%oops_rh)) then
724  write(mpl%info,'(a7,a,a)') '','Horizontal fit support radius copied from OOPS for block ',trim(bpar%blockname(ib))
725  cmat%blk(ib)%rh = cmat%blk(ib)%oops_rh
726  end if
727  if (allocated(cmat%blk(ib)%oops_rv)) then
728  write(mpl%info,'(a7,a,a)') '','Vertical fit support radius copied from OOPS for block ',trim(bpar%blockname(ib))
729  cmat%blk(ib)%rv = cmat%blk(ib)%oops_rv
730  end if
731  if (allocated(cmat%blk(ib)%oops_rv_rfac)) then
732  write(mpl%info,'(a7,a,a)') '','Vertical fit factor copied from OOPS for block ',trim(bpar%blockname(ib))
733  cmat%blk(ib)%rv_rfac = cmat%blk(ib)%oops_rv_rfac
734  end if
735  if (allocated(cmat%blk(ib)%oops_rv_coef)) then
736  write(mpl%info,'(a7,a,a)') '','Vertical fit coefficient copied from OOPS for block ',trim(bpar%blockname(ib))
737  cmat%blk(ib)%rv_coef = cmat%blk(ib)%oops_rv_coef
738  end if
739  end if
740 end do
741 
742 end subroutine cmat_from_oops
743 
744 !----------------------------------------------------------------------
745 ! Subroutine: cmat_setup_sampling
746 ! Purpose: setup C matrix sampling
747 !----------------------------------------------------------------------
748 subroutine cmat_setup_sampling(cmat,nam,geom,bpar)
750 implicit none
751 
752 ! Passed variables
753 class(cmat_type),intent(inout) :: cmat ! C matrix
754 type(nam_type),target,intent(in) :: nam ! Namelist
755 type(geom_type),target,intent(in) :: geom ! Geometry
756 type(bpar_type),intent(in) :: bpar ! Block parameters
757 
758 ! Local variables
759 integer :: ib,il0,ic0a
760 
761 ! Sampling parameters
762 if (trim(nam%strategy)=='specific_multivariate') then
763  ! Initialization
764  cmat%blk(bpar%nbe)%rhs = huge(1.0)
765  cmat%blk(bpar%nbe)%rvs = huge(1.0)
766  do ib=1,bpar%nb
767  if (bpar%B_block(ib).and.bpar%nicas_block(ib)) then
768  ! Get minimum
769  do il0=1,geom%nl0
770  do ic0a=1,geom%nc0a
771  cmat%blk(bpar%nbe)%rhs(ic0a,il0) = min(cmat%blk(bpar%nbe)%rhs(ic0a,il0),cmat%blk(ib)%rh(ic0a,il0))
772  cmat%blk(bpar%nbe)%rvs(ic0a,il0) = min(cmat%blk(bpar%nbe)%rvs(ic0a,il0),cmat%blk(ib)%rv(ic0a,il0))
773  end do
774  end do
775  end if
776  end do
777 else
778  ! Copy
779  do ib=1,bpar%nbe
780  if (bpar%B_block(ib).and.bpar%nicas_block(ib)) then
781  cmat%blk(ib)%rhs = cmat%blk(ib)%rh
782  cmat%blk(ib)%rvs = cmat%blk(ib)%rv
783  end if
784  end do
785 end if
786 
787 end subroutine cmat_setup_sampling
788 
789 end module type_cmat
subroutine cmat_from_hdiag(cmat, mpl, nam, geom, bpar, hdiag)
Definition: type_cmat.F90:361
real(kind_real), parameter, public rad2deg
Definition: tools_const.F90:17
subroutine cmat_alloc(cmat, bpar, prefix)
Definition: type_cmat.F90:64
subroutine, public copy(self, rhs)
Definition: qg_fields.F90:225
subroutine cmat_dealloc(cmat, bpar)
Definition: type_cmat.F90:121
subroutine cmat_read(cmat, mpl, nam, geom, bpar, io)
Definition: type_cmat.F90:201
subroutine cmat_write(cmat, mpl, nam, geom, bpar, io)
Definition: type_cmat.F90:290
real(kind_real), parameter, public gau2gc
Definition: tools_func.F90:20
subroutine cmat_from_nam(cmat, mpl, nam, geom, bpar)
Definition: type_cmat.F90:638
type(cmat_type) function cmat_copy(cmat, nam, geom, bpar)
Definition: type_cmat.F90:149
real(kind=kind_real), parameter req
Earth radius at equator (m)
subroutine cmat_from_lct(cmat, mpl, nam, geom, bpar, lct)
Definition: type_cmat.F90:545
subroutine cmat_alloc_blk(cmat, nam, geom, bpar)
Definition: type_cmat.F90:93
subroutine cmat_from_oops(cmat, mpl, geom, bpar)
Definition: type_cmat.F90:699
integer, parameter, public kind_real
#define min(a, b)
Definition: mosaic_util.h:32
subroutine cmat_setup_sampling(cmat, nam, geom, bpar)
Definition: type_cmat.F90:749
real(kind_real), parameter, public reqkm
Definition: tools_const.F90:19