FV3 Bundle
type_avg.F90
Go to the documentation of this file.
1 !----------------------------------------------------------------------
2 ! Module: type_avg
3 ! Purpose: average routines
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_avg
9 
10 use fckit_mpi_module, only: fckit_mpi_sum
11 !$ use omp_lib
12 use tools_const,only: reqkm
13 use tools_func, only: add,divide
14 use tools_kinds, only: kind_real
16 use tools_qsort, only: qsort
17 use type_avg_blk, only: avg_blk_type
18 use type_bpar, only: bpar_type
19 use type_geom, only: geom_type
20 use type_mom, only: mom_type
21 use type_mpl, only: mpl_type
22 use type_nam, only: nam_type
23 use type_samp, only: samp_type
24 
25 implicit none
26 
27 ! Averaged statistics derived type
29  integer :: ne ! Ensemble size
30  integer :: nsub ! Number of sub-ensembles
31  type(avg_blk_type),allocatable :: blk(:,:) ! Averaged statistics blocks
32 contains
33  procedure :: alloc => avg_alloc
34  procedure :: dealloc => avg_dealloc
35  procedure :: copy => avg_copy
36  procedure :: gather => avg_gather
37  procedure :: normalize => avg_normalize
38  procedure :: gather_lr => avg_gather_lr
39  procedure :: normalize_lr => avg_normalize_lr
40  procedure :: var_filter => avg_var_filter
41  procedure :: compute => avg_compute
42  procedure :: compute_hyb => avg_compute_hyb
43  procedure :: copy_wgt => avg_copy_wgt
44  procedure :: compute_bwavg => avg_compute_bwavg
45 end type avg_type
46 
47 private
48 public :: avg_type
49 
50 contains
51 
52 !----------------------------------------------------------------------
53 ! Subroutine: avg_alloc
54 ! Purpose: averaged statistics allocation
55 !----------------------------------------------------------------------
56 subroutine avg_alloc(avg,nam,geom,bpar,ne,nsub)
57 
58 implicit none
59 
60 ! Passed variables
61 class(avg_type),intent(inout) :: avg ! Averaged statistics
62 type(nam_type),intent(in) :: nam ! Namelist
63 type(geom_type),intent(in) :: geom ! Geometry
64 type(bpar_type),intent(in) :: bpar ! Block parameters
65 integer,intent(in) :: ne ! Ensemble size
66 integer,intent(in) :: nsub ! Number of sub-ensembles
67 
68 ! Local variables
69 integer :: ib,ic2
70 
71 ! Set attributes
72 avg%ne = ne
73 avg%nsub = nsub
74 
75 ! Allocation
76 allocate(avg%blk(0:nam%nc2,bpar%nbe))
77 do ib=1,bpar%nbe
78  if (bpar%diag_block(ib)) then
79  do ic2=0,nam%nc2
80  call avg%blk(ic2,ib)%alloc(nam,geom,bpar,ic2,ib,ne,nsub)
81  end do
82  end if
83 end do
84 
85 end subroutine avg_alloc
86 
87 !----------------------------------------------------------------------
88 ! Subroutine: avg_dealloc
89 ! Purpose: averaged statistics deallocation
90 !----------------------------------------------------------------------
91 subroutine avg_dealloc(avg,nam,bpar)
92 
93 implicit none
94 
95 ! Passed variables
96 class(avg_type),intent(inout) :: avg ! Averaged statistics
97 type(nam_type),intent(in) :: nam ! Namelist
98 type(bpar_type),intent(in) :: bpar ! Block parameters
99 
100 ! Local variables
101 integer :: ib,ic2
102 
103 ! Allocation
104 if (allocated(avg%blk)) then
105  do ib=1,bpar%nbe
106  if (bpar%diag_block(ib)) then
107  do ic2=0,nam%nc2
108  call avg%blk(ic2,ib)%dealloc
109  end do
110  end if
111  end do
112  deallocate(avg%blk)
113 end if
114 
115 end subroutine avg_dealloc
116 
117 !----------------------------------------------------------------------
118 ! Function: avg_copy
119 ! Purpose: averaged statistics copy
120 !----------------------------------------------------------------------
121 type(avg_type) function avg_copy(avg,nam,geom,bpar)
123 implicit none
124 
125 ! Passed variables
126 class(avg_type),intent(in) :: avg ! Averaged statistics
127 type(nam_type),intent(in) :: nam ! Namelist
128 type(geom_type),intent(in) :: geom ! Geometry
129 type(bpar_type),intent(in) :: bpar ! Block parameters
130 
131 ! Local variables
132 integer :: ib,ic2
133 
134 ! Deallocation
135 call avg_copy%dealloc(nam,bpar)
136 
137 ! Allocation
138 call avg_copy%alloc(nam,geom,bpar,avg%ne,avg%nsub)
139 
140 ! Copy
141 do ib=1,bpar%nbe
142  if (bpar%diag_block(ib)) then
143  do ic2=0,nam%nc2
144  avg_copy%blk(ic2,ib) = avg%blk(ic2,ib)%copy(nam,geom,bpar)
145  end do
146  end if
147 end do
148 
149 end function avg_copy
150 
151 !----------------------------------------------------------------------
152 ! Subroutine: avg_gather
153 ! Purpose: gather averaged statistics data
154 !----------------------------------------------------------------------
155 subroutine avg_gather(avg,mpl,nam,geom,bpar)
157 implicit none
158 
159 ! Passed variables
160 class(avg_type),intent(inout) :: avg ! Averaged statistics
161 type(mpl_type),intent(in) :: mpl ! MPI data
162 type(nam_type),intent(in) :: nam ! Namelist
163 type(geom_type),intent(in) :: geom ! Geometry
164 type(bpar_type),intent(in) :: bpar ! Block parameters
165 
166 ! Local variables
167 integer :: npack,offset,ib,ic2
168 real(kind_real),allocatable :: sbuf(:),rbuf(:)
169 logical,allocatable :: mask_0(:,:,:),mask_1(:,:,:,:),mask_2(:,:,:,:,:)
170 
171 ! Packing size
172 npack = 0
173 do ib=1,bpar%nb
174  if (bpar%diag_block(ib)) then
175  do ic2=0,nam%nc2
176  if ((ic2==0).or.(nam%var_diag)) then
177  npack = npack+geom%nl0
178  if (nam%var_filter.and.(.not.nam%gau_approx)) npack = npack+geom%nl0
179  end if
180  if ((ic2==0).or.(nam%local_diag)) then
181  npack = npack+(4+2*avg%blk(ic2,ib)%nsub**2)*bpar%nc3(ib)*bpar%nl0r(ib)*geom%nl0
182  if (.not.nam%gau_approx) npack = npack+avg%blk(ic2,ib)%nsub*bpar%nc3(ib)*bpar%nl0r(ib)*geom%nl0
183  end if
184  end do
185  end if
186 end do
187 
188 ! Allocation
189 allocate(sbuf(npack))
190 allocate(rbuf(npack))
191 
192 ! Pack data
193 offset = 0
194 sbuf = 0.0
195 do ib=1,bpar%nb
196  if (bpar%diag_block(ib)) then
197  do ic2=0,nam%nc2
198  if ((ic2==0).or.(nam%var_diag)) then
199  sbuf(offset+1:offset+geom%nl0) = pack(avg%blk(ic2,ib)%m2,.true.)
200  offset = offset+geom%nl0
201  if (nam%var_filter.and.(.not.nam%gau_approx)) then
202  sbuf(offset+1:offset+geom%nl0) = pack(avg%blk(ic2,ib)%m4,.true.)
203  offset = offset+geom%nl0
204  end if
205  end if
206  if ((ic2==0).or.(nam%local_diag)) then
207  sbuf(offset+1:offset+bpar%nc3(ib)*bpar%nl0r(ib)*geom%nl0) = pack(avg%blk(ic2,ib)%nc1a,.true.)
208  offset = offset+bpar%nc3(ib)*bpar%nl0r(ib)*geom%nl0
209  sbuf(offset+1:offset+bpar%nc3(ib)*bpar%nl0r(ib)*geom%nl0) = pack(avg%blk(ic2,ib)%m11,.true.)
210  offset = offset+bpar%nc3(ib)*bpar%nl0r(ib)*geom%nl0
211  sbuf(offset+1:offset+bpar%nc3(ib)*bpar%nl0r(ib)*geom%nl0*avg%blk(ic2,ib)%nsub**2) = pack(avg%blk(ic2,ib)%m11m11,.true.)
212  offset = offset+bpar%nc3(ib)*bpar%nl0r(ib)*geom%nl0*avg%blk(ic2,ib)%nsub**2
213  sbuf(offset+1:offset+bpar%nc3(ib)*bpar%nl0r(ib)*geom%nl0*avg%blk(ic2,ib)%nsub**2) = pack(avg%blk(ic2,ib)%m2m2,.true.)
214  offset = offset+bpar%nc3(ib)*bpar%nl0r(ib)*geom%nl0*avg%blk(ic2,ib)%nsub**2
215  if (.not.nam%gau_approx) then
216  sbuf(offset+1:offset+bpar%nc3(ib)*bpar%nl0r(ib)*geom%nl0*avg%blk(ic2,ib)%nsub) = pack(avg%blk(ic2,ib)%m22,.true.)
217  offset = offset+bpar%nc3(ib)*bpar%nl0r(ib)*geom%nl0*avg%blk(ic2,ib)%nsub
218  end if
219  sbuf(offset+1:offset+bpar%nc3(ib)*bpar%nl0r(ib)*geom%nl0) = pack(avg%blk(ic2,ib)%nc1a_cor,.true.)
220  offset = offset+bpar%nc3(ib)*bpar%nl0r(ib)*geom%nl0
221  sbuf(offset+1:offset+bpar%nc3(ib)*bpar%nl0r(ib)*geom%nl0) = pack(avg%blk(ic2,ib)%cor,.true.)
222  offset = offset+bpar%nc3(ib)*bpar%nl0r(ib)*geom%nl0
223  end if
224  end do
225  end if
226 end do
227 
228 ! Reduce data
229 call mpl%f_comm%allreduce(sbuf,rbuf,fckit_mpi_sum())
230 
231 ! Unpack data
232 offset = 0
233 do ib=1,bpar%nb
234  if (bpar%diag_block(ib)) then
235  ! Allocation
236  allocate(mask_0(bpar%nc3(ib),bpar%nl0r(ib),geom%nl0))
237  allocate(mask_1(bpar%nc3(ib),bpar%nl0r(ib),geom%nl0,avg%blk(0,ib)%nsub))
238  allocate(mask_2(bpar%nc3(ib),bpar%nl0r(ib),geom%nl0,avg%blk(0,ib)%nsub,avg%blk(0,ib)%nsub))
239 
240  ! Initialization
241  mask_0 = .true.
242  mask_1 = .true.
243  mask_2 = .true.
244 
245  do ic2=0,nam%nc2
246  ! Unpack
247  if ((ic2==0).or.(nam%var_diag)) then
248  avg%blk(ic2,ib)%m2 = unpack(rbuf(offset+1:offset+geom%nl0),mask_1(1,1,:,:),avg%blk(ic2,ib)%m2)
249  offset = offset+geom%nl0
250  if (nam%var_filter.and.(.not.nam%gau_approx)) then
251  avg%blk(ic2,ib)%m4 = unpack(rbuf(offset+1:offset+geom%nl0),mask_1(1,1,:,:),avg%blk(ic2,ib)%m4)
252  offset = offset+geom%nl0
253  end if
254  end if
255  if ((ic2==0).or.(nam%local_diag)) then
256  avg%blk(ic2,ib)%nc1a = unpack(rbuf(offset+1:offset+bpar%nc3(ib)*bpar%nl0r(ib)*geom%nl0),mask_0,avg%blk(ic2,ib)%m11)
257  offset = offset+bpar%nc3(ib)*bpar%nl0r(ib)*geom%nl0
258  avg%blk(ic2,ib)%m11 = unpack(rbuf(offset+1:offset+bpar%nc3(ib)*bpar%nl0r(ib)*geom%nl0),mask_0,avg%blk(ic2,ib)%m11)
259  offset = offset+bpar%nc3(ib)*bpar%nl0r(ib)*geom%nl0
260  avg%blk(ic2,ib)%m11m11 = unpack(rbuf(offset+1:offset+bpar%nc3(ib)*bpar%nl0r(ib)*geom%nl0*avg%blk(ic2,ib)%nsub**2), &
261  & mask_2,avg%blk(ic2,ib)%m11m11)
262  offset = offset+bpar%nc3(ib)*bpar%nl0r(ib)*geom%nl0*avg%blk(ic2,ib)%nsub**2
263  avg%blk(ic2,ib)%m2m2 = unpack(rbuf(offset+1:offset+bpar%nc3(ib)*bpar%nl0r(ib)*geom%nl0*avg%blk(ic2,ib)%nsub**2), &
264  & mask_2,avg%blk(ic2,ib)%m2m2)
265  offset = offset+bpar%nc3(ib)*bpar%nl0r(ib)*geom%nl0*avg%blk(ic2,ib)%nsub**2
266  if (.not.nam%gau_approx) then
267  avg%blk(ic2,ib)%m22 = unpack(rbuf(offset+1:offset+bpar%nc3(ib)*bpar%nl0r(ib)*geom%nl0*avg%blk(ic2,ib)%nsub), &
268  & mask_1,avg%blk(ic2,ib)%m22)
269  offset = offset+bpar%nc3(ib)*bpar%nl0r(ib)*geom%nl0*avg%blk(ic2,ib)%nsub
270  end if
271  avg%blk(ic2,ib)%nc1a_cor = unpack(rbuf(offset+1:offset+bpar%nc3(ib)*bpar%nl0r(ib)*geom%nl0), &
272  & mask_0,avg%blk(ic2,ib)%nc1a_cor)
273  offset = offset+bpar%nc3(ib)*bpar%nl0r(ib)*geom%nl0
274  avg%blk(ic2,ib)%cor = unpack(rbuf(offset+1:offset+bpar%nc3(ib)*bpar%nl0r(ib)*geom%nl0),mask_0,avg%blk(ic2,ib)%cor)
275  offset = offset+bpar%nc3(ib)*bpar%nl0r(ib)*geom%nl0
276  end if
277  end do
278 
279  ! Release memory
280  deallocate(mask_0)
281  deallocate(mask_1)
282  deallocate(mask_2)
283  end if
284 end do
285 
286 end subroutine avg_gather
287 
288 !----------------------------------------------------------------------
289 ! Subroutine: avg_normalize
290 ! Purpose: normalize averaged statistics data
291 !----------------------------------------------------------------------
292 subroutine avg_normalize(avg,nam,geom,bpar)
294 implicit none
295 
296 ! Passed variables
297 class(avg_type),intent(inout) :: avg ! Averaged statistics
298 type(nam_type),intent(in) :: nam ! Namelist
299 type(geom_type),intent(in) :: geom ! Geometry
300 type(bpar_type),intent(in) :: bpar ! Block parameters
301 
302 ! Local variables
303 integer :: ib,ic2,il0,jl0r,jc3,isub,jsub
304 real(kind_real) :: norm
305 
306 ! Normalize
307 do ib=1,bpar%nb
308  if (bpar%diag_block(ib)) then
309  do ic2=0,nam%nc2
310  if ((ic2==0).or.(nam%local_diag)) then
311  !$omp parallel do schedule(static) private(il0,jl0r,jc3,isub,jsub,norm)
312  do il0=1,geom%nl0
313  do jl0r=1,bpar%nl0r(ib)
314  do jc3=1,bpar%nc3(ib)
315  if (avg%blk(ic2,ib)%nc1a(jc3,jl0r,il0)>0.0) then
316  norm = 1.0/avg%blk(ic2,ib)%nc1a(jc3,jl0r,il0)
317  avg%blk(ic2,ib)%m11(jc3,jl0r,il0) = avg%blk(ic2,ib)%m11(jc3,jl0r,il0)*norm
318  do isub=1,avg%blk(ic2,ib)%nsub
319  do jsub=1,avg%blk(ic2,ib)%nsub
320  avg%blk(ic2,ib)%m11m11(jc3,jl0r,il0,jsub,isub) = avg%blk(ic2,ib)%m11m11(jc3,jl0r,il0,jsub,isub)*norm
321  avg%blk(ic2,ib)%m2m2(jc3,jl0r,il0,jsub,isub) = avg%blk(ic2,ib)%m2m2(jc3,jl0r,il0,jsub,isub)*norm
322  end do
323  if (.not.nam%gau_approx) avg%blk(ic2,ib)%m22(jc3,jl0r,il0,isub) &
324  & = avg%blk(ic2,ib)%m22(jc3,jl0r,il0,isub)*norm
325  end do
326  else
327  call msr(avg%blk(ic2,ib)%m11(jc3,jl0r,il0))
328  do isub=1,avg%blk(ic2,ib)%nsub
329  do jsub=1,avg%blk(ic2,ib)%nsub
330  call msr(avg%blk(ic2,ib)%m11m11(jc3,jl0r,il0,jsub,isub))
331  call msr(avg%blk(ic2,ib)%m2m2(jc3,jl0r,il0,jsub,isub))
332  end do
333  if (.not.nam%gau_approx) call msr(avg%blk(ic2,ib)%m22(jc3,jl0r,il0,isub))
334  end do
335  end if
336  if (avg%blk(ic2,ib)%nc1a_cor(jc3,jl0r,il0)>0.0) then
337  avg%blk(ic2,ib)%cor(jc3,jl0r,il0) = avg%blk(ic2,ib)%cor(jc3,jl0r,il0) &
338  & /avg%blk(ic2,ib)%nc1a_cor(jc3,jl0r,il0)
339  else
340  call msr(avg%blk(ic2,ib)%cor(jc3,jl0r,il0))
341  end if
342  end do
343  end do
344  end do
345  !$omp end parallel do
346  end if
347  end do
348  end if
349 end do
350 
351 end subroutine avg_normalize
352 
353 !----------------------------------------------------------------------
354 ! Subroutine: avg_gather_lr
355 ! Purpose: gather low-resolution averaged statistics data
356 !----------------------------------------------------------------------
357 subroutine avg_gather_lr(avg_lr,mpl,nam,geom,bpar)
359 implicit none
360 
361 ! Passed variables
362 class(avg_type),intent(inout) :: avg_lr ! Averaged statistics, low resolution
363 type(mpl_type),intent(in) :: mpl ! MPI data
364 type(nam_type),intent(in) :: nam ! Namelist
365 type(geom_type),intent(in) :: geom ! Geometry
366 type(bpar_type),intent(in) :: bpar ! Block parameters
367 
368 ! Local variables
369 integer :: npack,offset,ib,ic2
370 real(kind_real),allocatable :: sbuf(:),rbuf(:)
371 logical,allocatable :: mask_unpack(:,:,:,:,:)
372 
373 ! Packing size
374 npack = 0
375 do ib=1,bpar%nb
376  if (bpar%diag_block(ib)) then
377  do ic2=0,nam%nc2
378  if ((ic2==0).or.(nam%local_diag)) npack = npack+bpar%nc3(ib)*bpar%nl0r(ib)*geom%nl0*avg_lr%blk(ic2,ib)%nsub**2
379  end do
380  end if
381 end do
382 
383 ! Allocation
384 allocate(sbuf(npack))
385 allocate(rbuf(npack))
386 
387 ! Pack data
388 offset = 0
389 sbuf = 0.0
390 do ib=1,bpar%nb
391  if (bpar%diag_block(ib)) then
392  do ic2=0,nam%nc2
393  if ((ic2==0).or.(nam%local_diag)) then
394  sbuf(offset+1:offset+bpar%nc3(ib)*bpar%nl0r(ib)*geom%nl0*avg_lr%blk(ic2,ib)%nsub**2) = &
395  & pack(avg_lr%blk(ic2,ib)%m11lrm11sub,.true.)
396  offset = offset+bpar%nc3(ib)*bpar%nl0r(ib)*geom%nl0*avg_lr%blk(ic2,ib)%nsub**2
397  end if
398  end do
399  end if
400 end do
401 
402 ! Reduce data
403 call mpl%f_comm%allreduce(sbuf,rbuf,fckit_mpi_sum())
404 
405 ! Unpack data
406 offset = 0
407 do ib=1,bpar%nb
408  if (bpar%diag_block(ib)) then
409  ! Allocation
410  allocate(mask_unpack(bpar%nc3(ib),bpar%nl0r(ib),geom%nl0,avg_lr%nsub,avg_lr%nsub))
411 
412  ! Initialization
413  mask_unpack = .true.
414 
415  do ic2=0,nam%nc2
416  ! Unpack
417  if ((ic2==0).or.(nam%local_diag)) then
418  avg_lr%blk(ic2,ib)%m11lrm11sub = unpack(rbuf(offset+1:offset+bpar%nc3(ib)*bpar%nl0r(ib)* &
419  & geom%nl0*avg_lr%blk(ic2,ib)%nsub**2),mask_unpack,avg_lr%blk(ic2,ib)%m11lrm11sub)
420  offset = offset+bpar%nc3(ib)*bpar%nl0r(ib)*geom%nl0*avg_lr%blk(ic2,ib)%nsub**2
421  end if
422  end do
423 
424  ! Release memory
425  deallocate(mask_unpack)
426  end if
427 end do
428 
429 end subroutine avg_gather_lr
430 
431 !----------------------------------------------------------------------
432 ! Subroutine: avg_normalize_lr
433 ! Purpose: normalize low-resolution averaged statistics data
434 !----------------------------------------------------------------------
435 subroutine avg_normalize_lr(avg_lr,nam,geom,bpar)
437 implicit none
438 
439 ! Passed variables
440 class(avg_type),intent(inout) :: avg_lr ! Averaged statistics, low resolution
441 type(nam_type),intent(in) :: nam ! Namelist
442 type(geom_type),intent(in) :: geom ! Geometry
443 type(bpar_type),intent(in) :: bpar ! Block parameters
444 
445 ! Local variables
446 integer :: ib,ic2,il0,jl0r,jc3,isub,jsub
447 real(kind_real) :: norm
448 
449 ! Normalize
450 do ib=1,bpar%nb
451  if (bpar%diag_block(ib)) then
452  do ic2=0,nam%nc2
453  if ((ic2==0).or.(nam%local_diag)) then
454  !$omp parallel do schedule(static) private(il0,jl0r,jc3,isub,jsub,norm)
455  do il0=1,geom%nl0
456  do jl0r=1,bpar%nl0r(ib)
457  do jc3=1,bpar%nc3(ib)
458  if (avg_lr%blk(ic2,ib)%nc1a(jc3,jl0r,il0)>0.0) then
459  norm = 1.0/avg_lr%blk(ic2,ib)%nc1a(jc3,jl0r,il0)
460  do isub=1,avg_lr%blk(ic2,ib)%nsub
461  do jsub=1,avg_lr%blk(ic2,ib)%nsub
462  avg_lr%blk(ic2,ib)%m11lrm11sub(jc3,jl0r,il0,jsub,isub) &
463  & = avg_lr%blk(ic2,ib)%m11lrm11sub(jc3,jl0r,il0,jsub,isub)*norm
464  end do
465  end do
466  else
467  do isub=1,avg_lr%blk(ic2,ib)%nsub
468  do jsub=1,avg_lr%blk(ic2,ib)%nsub
469  call msr(avg_lr%blk(ic2,ib)%m11lrm11sub(jc3,jl0r,il0,jsub,isub))
470  end do
471  end do
472  end if
473  end do
474  end do
475  end do
476  !$omp end parallel do
477  end if
478  end do
479  end if
480 end do
481 
482 end subroutine avg_normalize_lr
483 
484 !----------------------------------------------------------------------
485 ! Subroutine: avg_var_filter
486 ! Purpose: filter variance
487 !----------------------------------------------------------------------
488 subroutine avg_var_filter(avg,mpl,nam,geom,bpar,samp)
490 implicit none
491 
492 ! Passed variables
493 class(avg_type),intent(inout) :: avg ! Averaged statistics
494 type(mpl_type),intent(inout) :: mpl ! MPI data
495 type(nam_type),intent(in) :: nam ! Namelist
496 type(geom_type),intent(in) :: geom ! Geometry
497 type(bpar_type),intent(in) :: bpar ! Block parameters
498 type(samp_type),intent(in) :: samp ! Sampling
499 
500 ! Local variables
501 integer :: n,ib,il0,ic2a,ic2,iter
502 real(kind_real) :: P9,P20,P21
503 real(kind_real) :: m2sq,m4,m2sqasy,rhflt,drhflt
504 real(kind_real) :: m2_ini(samp%nc2a),m2(samp%nc2a),m2prod,m2prod_tot
505 logical :: dichotomy,convergence
506 
507 ! Ensemble/sub-ensemble size-dependent coefficients
508 n = avg%ne/avg%nsub
509 p9 = -real(n,kind_real)/real((n-2)*(n-3),kind_real)
510 p20 = real((n-1)*(n**2-3*n+3),kind_real)/real(n*(n-2)*(n-3),kind_real)
511 p21 = real(n-1,kind_real)/real(n+1,kind_real)
512 
513 do ib=1,bpar%nb
514  if (bpar%diag_block(ib)) then
515  write(mpl%info,'(a13,a,a,a)') '','Block ',trim(bpar%blockname(ib)),':'
516  call flush(mpl%info)
517 
518  do il0=1,geom%nl0
519  write(mpl%info,'(a16,a,i3,a)') '','Level ',nam%levs(il0),':'
520  call flush(mpl%info)
521 
522  ! Global averages
523  m2sq = 0.0
524  m4 = 0.0
525  do ic2=1,nam%nc2
526  m2sq = m2sq+sum(avg%blk(ic2,ib)%m2(il0,:)**2)/real(avg%nsub,kind_real)
527  if (.not.nam%gau_approx) m4 = m4+sum(avg%blk(ic2,ib)%m4(il0,:))/real(avg%nsub,kind_real)
528  end do
529 
530  ! Asymptotic statistics
531  if (nam%gau_approx) then
532  ! Gaussian approximation
533  m2sqasy = p21*m2sq
534  else
535  ! General case
536  m2sqasy = p20*m2sq+p9*m4
537  end if
538 
539  ! Dichotomy initialization
540  do ic2a=1,samp%nc2a
541  ic2 = samp%c2a_to_c2(ic2a)
542  m2_ini(ic2a) = sum(avg%blk(ic2,ib)%m2(il0,:))/real(avg%nsub,kind_real)
543  end do
544  convergence = .true.
545  dichotomy = .false.
546  rhflt = nam%var_rhflt
547  drhflt = rhflt
548 
549  do iter=1,nam%var_niter
550  ! Copy initial value
551  m2 = m2_ini
552 
553  ! Median filter to remove extreme values
554  call samp%diag_filter(mpl,nam,geom,il0,'median',rhflt,m2)
555 
556  ! Average filter to smooth displacement
557  call samp%diag_filter(mpl,nam,geom,il0,'gc99',rhflt,m2)
558 
559  ! Compute product
560  m2prod = sum(m2*m2_ini)
561 
562  ! Reduce product
563  call mpl%f_comm%allreduce(m2prod,m2prod_tot,fckit_mpi_sum())
564 
565  ! Print result
566  write(mpl%info,'(a19,a,i2,a,f10.2,a,f10.2)') '','Iteration ',iter,': rhflt = ', &
567  & rhflt*reqkm,' km, difference = ',m2prod_tot-m2sqasy
568  call flush(mpl%info)
569 
570  ! Update support radius
571  if (m2prod_tot>m2sqasy) then
572  ! Increase filtering support radius
573  if (dichotomy) then
574  drhflt = 0.5*drhflt
575  rhflt = rhflt+drhflt
576  else
577  convergence = .false.
578  rhflt = rhflt+drhflt
579  drhflt = 2.0*drhflt
580  end if
581  else
582  ! Convergence
583  convergence = .true.
584 
585  ! Change dichotomy status
586  if (.not.dichotomy) then
587  dichotomy = .true.
588  drhflt = 0.5*drhflt
589  end if
590 
591  ! Decrease filtering support radius
592  drhflt = 0.5*drhflt
593  rhflt = rhflt-drhflt
594  end if
595  end do
596 
597  ! Copy final result
598  avg%blk(0,ib)%m2flt(il0) = sum(avg%blk(0,ib)%m2(il0,:))/real(avg%nsub,kind_real)
599  do ic2a=1,samp%nc2a
600  ic2 = samp%c2a_to_c2(ic2a)
601  avg%blk(ic2,ib)%m2flt(il0) = m2(ic2a)
602  end do
603  end do
604  end if
605 end do
606 
607 end subroutine avg_var_filter
608 
609 !----------------------------------------------------------------------
610 ! Subroutine: avg_compute
611 ! Purpose: compute averaged statistics
612 !----------------------------------------------------------------------
613 subroutine avg_compute(avg,mpl,nam,geom,bpar,samp,mom,ne)
615 implicit none
616 
617 ! Passed variables
618 class(avg_type),intent(inout) :: avg ! Averaged statistics
619 type(mpl_type),intent(inout) :: mpl ! MPI data
620 type(nam_type),intent(in) :: nam ! Namelist
621 type(geom_type),intent(in) :: geom ! Geometry
622 type(bpar_type),intent(in) :: bpar ! Block parameters
623 type(samp_type),intent(in) :: samp ! Sampling
624 type(mom_type),intent(in) :: mom ! Moments
625 integer,intent(in) :: ne ! Ensemble size
626 
627 ! Local variables
628 integer :: ib,ic2
629 
630 ! Allocation
631 call avg%alloc(nam,geom,bpar,mom%ne,mom%nsub)
632 
633 ! Compute averaged statistics
634 write(mpl%info,'(a10,a)') '','Compute averaged statistics'
635 call flush(mpl%info)
636 do ib=1,bpar%nb
637  if (bpar%diag_block(ib)) then
638  write(mpl%info,'(a13,a,a,a)',advance='no') '','Block ',trim(bpar%blockname(ib)),':'
639  call flush(mpl%info)
640  call mpl%prog_init(nam%nc2+1)
641  do ic2=0,nam%nc2
642  if ((ic2==0).or.nam%local_diag) call avg%blk(ic2,ib)%compute(nam,geom,bpar,samp,mom%blk(ib))
643  call mpl%prog_print(ic2+1)
644  end do
645  write(mpl%info,'(a)') '100%'
646  call flush(mpl%info)
647  end if
648 end do
649 
650 if (mpl%nproc>1) then
651  ! Gather averaged statistics
652  write(mpl%info,'(a10,a)') '','Gather averaged statistics'
653  call flush(mpl%info)
654  call avg%gather(mpl,nam,geom,bpar)
655 end if
656 
657 ! Normalize averaged statistics
658 write(mpl%info,'(a10,a)') '','Normalize averaged statistics'
659 call flush(mpl%info)
660 call avg%normalize(nam,geom,bpar)
661 
662 if (nam%var_filter) then
663  ! Filter variance
664  write(mpl%info,'(a10,a)') '','Filter variance'
665  call flush(mpl%info)
666  call avg%var_filter(mpl,nam,geom,bpar,samp)
667 end if
668 
669 ! Compute asymptotic statistics
670 write(mpl%info,'(a10,a)') '','Compute asymptotic statistics:'
671 call flush(mpl%info)
672 do ib=1,bpar%nb
673  if (bpar%diag_block(ib)) then
674  write(mpl%info,'(a13,a,a,a)',advance='no') '','Block ',trim(bpar%blockname(ib)),':'
675  call flush(mpl%info)
676  call mpl%prog_init(nam%nc2+1)
677  do ic2=0,nam%nc2
678  if ((ic2==0).or.nam%local_diag) call avg%blk(ic2,ib)%compute_asy(nam,geom,bpar,ne)
679  call mpl%prog_print(ic2+1)
680  end do
681  write(mpl%info,'(a)') '100%'
682  call flush(mpl%info)
683  end if
684 end do
685 
686 end subroutine avg_compute
687 
688 !----------------------------------------------------------------------
689 ! Subroutine: avg_compute_hyb
690 ! Purpose: compute hybrid averaged statistics
691 !----------------------------------------------------------------------
692 subroutine avg_compute_hyb(avg_2,mpl,nam,geom,bpar,samp,mom_1,mom_2,avg_1)
694 implicit none
695 
696 ! Passed variables
697 class(avg_type),intent(inout) :: avg_2 ! Ensemble 2 averaged statistics
698 type(mpl_type),intent(inout) :: mpl ! MPI data
699 type(nam_type),intent(in) :: nam ! Namelist
700 type(geom_type),intent(in) :: geom ! Geometry
701 type(bpar_type),intent(in) :: bpar ! Block parameters
702 type(samp_type),intent(in) :: samp ! Sampling
703 type(mom_type),intent(in) :: mom_1 ! Ensemble 2 moments
704 type(mom_type),intent(in) :: mom_2 ! Ensemble 1 moments
705 class(avg_type),intent(inout) :: avg_1 ! Ensemble 1 averaged statistics
706 
707 ! Local variables
708 integer :: ib,ic2
709 
710 ! Allocation
711 if (.not.allocated(avg_2%blk)) call avg_2%alloc(nam,geom,bpar,avg_2%ne,avg_2%nsub)
712 
713 do ib=1,bpar%nb
714  if (bpar%diag_block(ib)) then
715  write(mpl%info,'(a10,a,a,a)') '','Block ',trim(bpar%blockname(ib)),':'
716  call flush(mpl%info)
717 
718  ! Compute averaged statistics
719  write(mpl%info,'(a13,a)',advance='no') '','Compute averaged statistics:'
720  call flush(mpl%info)
721  call mpl%prog_init(nam%nc2+1)
722  do ic2=0,nam%nc2
723  if ((ic2==0).or.nam%local_diag) then
724  select case (trim(nam%method))
725  case ('hyb-avg')
726  ! Static covariance = ensemble covariance
727  avg_2%blk(ic2,ib)%m11sta = avg_1%blk(ic2,ib)%m11**2
728  avg_2%blk(ic2,ib)%stasq = avg_1%blk(ic2,ib)%m11**2
729  case ('hyb-rnd')
730  ! Static covariance = randomized covariance
731  avg_2%blk(ic2,ib)%m11sta = avg_1%blk(ic2,ib)%m11*avg_2%blk(ic2,ib)%m11
732  avg_2%blk(ic2,ib)%stasq = avg_2%blk(ic2,ib)%m11**2
733  case ('dual-ens')
734  ! LR covariance/HR covariance product average
735  call avg_2%blk(ic2,ib)%compute_lr(mpl,nam,geom,bpar,samp,mom_1%blk(ib),mom_2%blk(ib))
736  end select
737  end if
738  call mpl%prog_print(ic2+1)
739  end do
740  write(mpl%info,'(a)') '100%'
741  call flush(mpl%info)
742  end if
743 end do
744 
745 if (trim(nam%method)=='dual-ens') then
746  if (mpl%nproc>1) then
747  ! Gather averaged statistics
748  write(mpl%info,'(a13,a)') '','Gather averaged statistics'
749  call flush(mpl%info)
750  call avg_2%gather_lr(mpl,nam,geom,bpar)
751  end if
752 
753  ! Normalize averaged statistics
754  write(mpl%info,'(a10,a)') '','Normalize averaged statistics'
755  call flush(mpl%info)
756  call avg_2%normalize_lr(nam,geom,bpar)
757 
758  do ib=1,bpar%nb
759  if (bpar%diag_block(ib)) then
760  ! Compute asymptotic statistics
761  write(mpl%info,'(a13,a)',advance='no') '','Compute asymptotic statistics:'
762  call flush(mpl%info)
763  call mpl%prog_init(nam%nc2+1)
764  do ic2=0,nam%nc2
765  if ((ic2==0).or.nam%local_diag) call avg_2%blk(ic2,ib)%compute_asy_lr(nam,geom,bpar)
766  call mpl%prog_print(ic2+1)
767  end do
768  write(mpl%info,'(a)') '100%'
769  call flush(mpl%info)
770  end if
771  end do
772 end if
773 
774 end subroutine avg_compute_hyb
775 
776 !----------------------------------------------------------------------
777 ! Function: avg_copy_wgt
778 ! Purpose: averaged statistics data copy for weight definition
779 !----------------------------------------------------------------------
780 type(avg_type) function avg_copy_wgt(avg,geom,bpar)
782 implicit none
783 
784 ! Passed variables
785 type(geom_type),intent(in) :: geom ! Geometry
786 type(bpar_type),intent(in) :: bpar ! Block parameters
787 class(avg_type),intent(inout) :: avg ! Averaged statistics
788 
789 ! Local variables
790 integer :: ib
791 
792 if (bpar%diag_block(bpar%nbe)) then
793  ! Allocation
794  allocate(avg_copy_wgt%blk(0:0,bpar%nb))
795 
796  do ib=1,bpar%nb
797  if (bpar%diag_block(ib)) then
798  ! Restricted allocation
799  allocate(avg_copy_wgt%blk(0,ib)%m2m2asy(bpar%nc3(ib),bpar%nl0r(ib),geom%nl0))
800 
801  ! Restricted copy
802  avg_copy_wgt%blk(0,ib)%m2m2asy = avg%blk(0,ib)%m2m2asy
803  end if
804  end do
805 end if
806 
807 end function avg_copy_wgt
808 
809 !----------------------------------------------------------------------
810 ! Subroutine: avg_compute_bwavg
811 ! Purpose: compute block-averaged statistics
812 !----------------------------------------------------------------------
813 subroutine avg_compute_bwavg(avg,mpl,nam,geom,bpar,avg_wgt)
815 implicit none
816 
817 ! Passed variables
818 class(avg_type),intent(inout) :: avg ! Averaged statistics
819 type(mpl_type),intent(inout) :: mpl ! MPI data
820 type(nam_type),intent(in) :: nam ! Namelist
821 type(geom_type),intent(in) :: geom ! Geometry
822 type(bpar_type),intent(in) :: bpar ! Block parameters
823 type(avg_type),intent(in) :: avg_wgt ! Averaged statistics for weights
824 
825 ! Local variables
826 integer :: ib,ic2,il0,jl0r,jc3
827 real(kind_real) :: bwgtsq
828 real(kind_real),allocatable :: cor(:,:,:),m11asysq(:,:,:),m11sq(:,:,:)
829 real(kind_real),allocatable :: m11sta(:,:,:),stasq(:,:,:)
830 real(kind_real),allocatable :: m11lrm11(:,:,:),m11lrm11asy(:,:,:)
831 
832 ! Allocation
833 allocate(cor(nam%nc3,bpar%nl0rmax,geom%nl0))
834 allocate(m11asysq(nam%nc3,bpar%nl0rmax,geom%nl0))
835 allocate(m11sq(nam%nc3,bpar%nl0rmax,geom%nl0))
836 select case (trim(nam%method))
837 case ('hyb-avg','hyb-rnd')
838  allocate(m11sta(nam%nc3,bpar%nl0rmax,geom%nl0))
839  allocate(stasq(nam%nc3,bpar%nl0rmax,geom%nl0))
840 case ('dual-ens')
841  allocate(m11lrm11(nam%nc3,bpar%nl0rmax,geom%nl0))
842  allocate(m11lrm11asy(nam%nc3,bpar%nl0rmax,geom%nl0))
843 end select
844 
845 write(mpl%info,'(a10,a,a,a)',advance='no') '','Block ',trim(bpar%blockname(bpar%nbe)),':'
846 call flush(mpl%info)
847 
848 ! Initialization
849 call mpl%prog_init(nam%nc2+1)
850 
851 do ic2=0,nam%nc2
852  ! Copy ensemble size
853  avg%blk(ic2,bpar%nbe)%ne = avg%blk(ic2,1)%ne
854  avg%blk(ic2,bpar%nbe)%nsub = avg%blk(ic2,1)%nsub
855 
856  if ((ic2==0).or.(nam%local_diag)) then
857  ! Initialization
858  avg%blk(ic2,bpar%nbe)%cor = 0.0
859  cor = 0.0
860  avg%blk(ic2,bpar%nbe)%m11asysq = 0.0
861  m11asysq = 0.0
862  avg%blk(ic2,bpar%nbe)%m11sq = 0.0
863  m11sq = 0.0
864  select case (trim(nam%method))
865  case ('hyb-avg','hyb-rnd')
866  avg%blk(ic2,bpar%nbe)%m11sta = 0.0
867  m11sta = 0.0
868  avg%blk(ic2,bpar%nbe)%stasq = 0.0
869  stasq = 0.0
870  case ('dual-ens')
871  avg%blk(ic2,bpar%nbe)%m11lrm11 = 0.0
872  m11lrm11 = 0.0
873  avg%blk(ic2,bpar%nbe)%m11lrm11asy = 0.0
874  m11lrm11asy = 0.0
875  end select
876 
877  ! Block averages
878  do ib=1,bpar%nb
879  if (bpar%avg_block(ib)) then
880  !$omp parallel do schedule(static) private(il0,jl0r,bwgtsq,jc3)
881  do il0=1,geom%nl0
882  do jl0r=1,bpar%nl0r(ib)
883  ! Weight
884  if (avg_wgt%blk(0,ib)%m2m2asy(1,jl0r,il0)>0.0) then
885  bwgtsq = 1.0/avg_wgt%blk(0,ib)%m2m2asy(1,jl0r,il0)
886  else
887  bwgtsq = 0.0
888  end if
889 
890  ! Compute sum
891  do jc3=1,nam%nc3
892  call add(avg%blk(ic2,ib)%cor(jc3,jl0r,il0),avg%blk(ic2,bpar%nbe)%cor(jc3,jl0r,il0),cor(jc3,jl0r,il0))
893  call add(avg%blk(ic2,ib)%m11asysq(jc3,jl0r,il0),avg%blk(ic2,bpar%nbe)%m11asysq(jc3,jl0r,il0), &
894  & m11asysq(jc3,jl0r,il0),bwgtsq)
895  call add(avg%blk(ic2,ib)%m11sq(jc3,jl0r,il0),avg%blk(ic2,bpar%nbe)%m11sq(jc3,jl0r,il0), &
896  & m11sq(jc3,jl0r,il0),bwgtsq)
897  select case (trim(nam%method))
898  case ('hyb-avg','hyb-rnd')
899  call add(avg%blk(ic2,ib)%m11sta(jc3,jl0r,il0),avg%blk(ic2,bpar%nbe)%m11sta(jc3,jl0r,il0), &
900  & m11sta(jc3,jl0r,il0),bwgtsq)
901  call add(avg%blk(ic2,ib)%stasq(jc3,jl0r,il0),avg%blk(ic2,bpar%nbe)%stasq(jc3,jl0r,il0), &
902  & stasq(jc3,jl0r,il0),bwgtsq)
903  case ('dual-ens')
904  call add(avg%blk(ic2,ib)%m11lrm11(jc3,jl0r,il0),avg%blk(ic2,bpar%nbe)%m11lrm11(jc3,jl0r,il0), &
905  & m11lrm11(jc3,jl0r,il0),bwgtsq)
906  call add(avg%blk(ic2,ib)%m11lrm11asy(jc3,jl0r,il0),avg%blk(ic2,bpar%nbe)%m11lrm11asy(jc3,jl0r,il0), &
907  & m11lrm11asy(jc3,jl0r,il0),bwgtsq)
908  end select
909  end do
910  end do
911  end do
912  !$omp end parallel do
913  end if
914  end do
915 
916  ! Normalization
917  !$omp parallel do schedule(static) private(il0,jl0r,jc3)
918  do il0=1,geom%nl0
919  do jl0r=1,bpar%nl0r(ib)
920  do jc3=1,nam%nc3
921  call divide(avg%blk(ic2,bpar%nbe)%cor(jc3,jl0r,il0),cor(jc3,jl0r,il0))
922  call divide(avg%blk(ic2,bpar%nbe)%m11asysq(jc3,jl0r,il0),m11asysq(jc3,jl0r,il0))
923  call divide(avg%blk(ic2,bpar%nbe)%m11sq(jc3,jl0r,il0),m11sq(jc3,jl0r,il0))
924  select case (trim(nam%method))
925  case ('hyb-avg','hyb-rnd')
926  call divide(avg%blk(ic2,bpar%nbe)%m11sta(jc3,jl0r,il0),m11sta(jc3,jl0r,il0))
927  call divide(avg%blk(ic2,bpar%nbe)%stasq(jc3,jl0r,il0),stasq(jc3,jl0r,il0))
928  case ('dual-ens')
929  call divide(avg%blk(ic2,bpar%nbe)%m11lrm11(jc3,jl0r,il0),m11lrm11(jc3,jl0r,il0))
930  call divide(avg%blk(ic2,bpar%nbe)%m11lrm11asy(jc3,jl0r,il0),m11lrm11asy(jc3,jl0r,il0))
931  end select
932  end do
933  end do
934  end do
935  !$omp end parallel do
936  end if
937 
938  ! Update
939  call mpl%prog_print(ic2+1)
940 end do
941 write(mpl%info,'(a)') '100%'
942 call flush(mpl%info)
943 
944 end subroutine avg_compute_bwavg
945 
946 end module type_avg
subroutine, public add(value, cumul, num, wgt)
Definition: tools_func.F90:185
type(avg_type) function avg_copy_wgt(avg, geom, bpar)
Definition: type_avg.F90:781
subroutine, public copy(self, rhs)
Definition: qg_fields.F90:225
subroutine, public divide(value, num)
Definition: tools_func.F90:214
subroutine avg_normalize(avg, nam, geom, bpar)
Definition: type_avg.F90:293
subroutine avg_alloc(avg, nam, geom, bpar, ne, nsub)
Definition: type_avg.F90:57
subroutine avg_compute_bwavg(avg, mpl, nam, geom, bpar, avg_wgt)
Definition: type_avg.F90:814
subroutine avg_gather_lr(avg_lr, mpl, nam, geom, bpar)
Definition: type_avg.F90:358
subroutine avg_gather(avg, mpl, nam, geom, bpar)
Definition: type_avg.F90:156
subroutine avg_var_filter(avg, mpl, nam, geom, bpar, samp)
Definition: type_avg.F90:489
subroutine avg_compute_hyb(avg_2, mpl, nam, geom, bpar, samp, mom_1, mom_2, avg_1)
Definition: type_avg.F90:693
subroutine avg_normalize_lr(avg_lr, nam, geom, bpar)
Definition: type_avg.F90:436
type(avg_type) function avg_copy(avg, nam, geom, bpar)
Definition: type_avg.F90:122
integer, parameter, public kind_real
subroutine avg_dealloc(avg, nam, bpar)
Definition: type_avg.F90:92
subroutine avg_compute(avg, mpl, nam, geom, bpar, samp, mom, ne)
Definition: type_avg.F90:614
real(kind_real), parameter, public reqkm
Definition: tools_const.F90:19