FV3 Bundle
type_lct_blk.F90
Go to the documentation of this file.
1 !----------------------------------------------------------------------
2 ! Module: type_lct_blk
3 ! Purpose: LCT data 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 !----------------------------------------------------------------------
9 
10 !$ use omp_lib
12 use tools_kinds, only: kind_real
13 use tools_missing, only: msr,isnotmsr
14 use type_bpar, only: bpar_type
15 use type_geom, only: geom_type
16 use type_minim, only: minim_type
17 use type_mom_blk, only: mom_blk_type
18 use type_mpl, only: mpl_type
19 use type_nam, only: nam_type
20 use type_samp, only: samp_type
21 
22 implicit none
23 
24 real(kind_real),parameter :: cor_min = 0.5_kind_real ! Minimum relevant correlation for first guess
25 real(kind_real),parameter :: dscale = 10.0_kind_real ! Typical factor between diffusion scales
26 logical,parameter :: lprt = .false. ! Optimization print
27 
28 ! LCT block data derived type
30  ! Attributes
31  integer :: ib ! Block index
32  integer :: nscales ! Number of LCT scales
33 
34  ! Correlation
35  real(kind_real),allocatable :: raw(:,:,:,:) ! Raw correlations
36 
37  ! Diffusion data
38  real(kind_real),allocatable :: d(:,:,:,:) ! Diffusion components
39  real(kind_real),allocatable :: coef(:,:,:) ! Multi-scale coefficients
40  real(kind_real),allocatable :: fit(:,:,:,:) ! Fitted correlations
41 
42  ! Filtered diffusion data
43  real(kind_real),allocatable :: d_filt(:,:,:,:) ! Diffusion components
44  real(kind_real),allocatable :: coef_filt(:,:,:) ! Multi-scale coefficients
45  real(kind_real),allocatable :: fit_filt(:,:,:,:) ! Fitted correlations
46 
47  ! Output data
48  real(kind_real),allocatable :: d11(:,:,:) ! Daley tensor, component 11
49  real(kind_real),allocatable :: d22(:,:,:) ! Daley tensor, component 22
50  real(kind_real),allocatable :: d33(:,:,:) ! Daley tensor, component 33
51  real(kind_real),allocatable :: d12(:,:,:) ! Daley tensor, component 12
52  real(kind_real),allocatable :: h11(:,:,:) ! Local correlation tensor, component 11
53  real(kind_real),allocatable :: h22(:,:,:) ! Local correlation tensor, component 22
54  real(kind_real),allocatable :: h33(:,:,:) ! Local correlation tensor, component 33
55  real(kind_real),allocatable :: h12(:,:,:) ! Local correlation tensor, component 12
56  real(kind_real),allocatable :: dcoef(:,:,:) ! Tensor coefficient
57  real(kind_real),allocatable :: dlh(:,:,:) ! Tensor length-scale
58 contains
59  procedure :: alloc => lct_blk_alloc
60  procedure :: dealloc => lct_blk_dealloc
61  procedure :: correlation => lct_blk_correlation
62  procedure :: fitting => lct_blk_fitting
63 end type lct_blk_type
64 
65 private
66 public :: lct_blk_type
67 
68 contains
69 
70 !----------------------------------------------------------------------
71 ! Subroutine: lct_blk_alloc
72 ! Purpose: LCT block data allocation
73 !----------------------------------------------------------------------
74 subroutine lct_blk_alloc(lct_blk,nam,geom,bpar,samp,ib)
75 
76 implicit none
77 
78 ! Passed variables
79 class(lct_blk_type),intent(inout) :: lct_blk ! LCT block
80 type(nam_type),intent(in) :: nam ! Namelist
81 type(geom_type),intent(in) :: geom ! Geometry
82 type(bpar_type),intent(in) :: bpar ! Block parameters
83 type(samp_type),intent(in) :: samp ! Sampling
84 integer,intent(in) :: ib ! Block index
85 
86 ! Attributes
87 lct_blk%ib = ib
88 lct_blk%nscales = nam%lct_nscales
89 
90 ! Allocation
91 allocate(lct_blk%raw(nam%nc3,bpar%nl0r(ib),samp%nc1a,geom%nl0))
92 allocate(lct_blk%D(4,lct_blk%nscales,samp%nc1a,geom%nl0))
93 allocate(lct_blk%coef(lct_blk%nscales,samp%nc1a,geom%nl0))
94 allocate(lct_blk%fit(nam%nc3,bpar%nl0r(ib),samp%nc1a,geom%nl0))
95 if (nam%diag_rhflt>0) then
96  allocate(lct_blk%D_filt(4,lct_blk%nscales,samp%nc1a,geom%nl0))
97  allocate(lct_blk%coef_filt(lct_blk%nscales,samp%nc1a,geom%nl0))
98  allocate(lct_blk%fit_filt(nam%nc3,bpar%nl0r(ib),samp%nc1a,geom%nl0))
99 end if
100 allocate(lct_blk%D11(geom%nc0a,geom%nl0,lct_blk%nscales))
101 allocate(lct_blk%D22(geom%nc0a,geom%nl0,lct_blk%nscales))
102 allocate(lct_blk%D33(geom%nc0a,geom%nl0,lct_blk%nscales))
103 allocate(lct_blk%D12(geom%nc0a,geom%nl0,lct_blk%nscales))
104 allocate(lct_blk%H11(geom%nc0a,geom%nl0,lct_blk%nscales))
105 allocate(lct_blk%H22(geom%nc0a,geom%nl0,lct_blk%nscales))
106 allocate(lct_blk%H33(geom%nc0a,geom%nl0,lct_blk%nscales))
107 allocate(lct_blk%H12(geom%nc0a,geom%nl0,lct_blk%nscales))
108 allocate(lct_blk%Dcoef(geom%nc0a,geom%nl0,lct_blk%nscales))
109 allocate(lct_blk%DLh(geom%nc0a,geom%nl0,lct_blk%nscales))
110 
111 ! Initialization
112 call msr(lct_blk%raw)
113 call msr(lct_blk%D)
114 call msr(lct_blk%coef)
115 call msr(lct_blk%fit)
116 if (nam%diag_rhflt>0) then
117  call msr(lct_blk%D)
118  call msr(lct_blk%coef)
119  call msr(lct_blk%fit)
120 end if
121 call msr(lct_blk%D11)
122 call msr(lct_blk%D22)
123 call msr(lct_blk%D33)
124 call msr(lct_blk%D12)
125 call msr(lct_blk%H11)
126 call msr(lct_blk%H22)
127 call msr(lct_blk%H33)
128 call msr(lct_blk%H12)
129 call msr(lct_blk%Dcoef)
130 call msr(lct_blk%DLh)
131 
132 end subroutine lct_blk_alloc
133 
134 !----------------------------------------------------------------------
135 ! Subroutine: lct_blk_dealloc
136 ! Purpose: LCT block data deallocation
137 !----------------------------------------------------------------------
138 subroutine lct_blk_dealloc(lct_blk)
140 implicit none
141 
142 ! Passed variables
143 class(lct_blk_type),intent(inout) :: lct_blk ! LCT block
144 
145 ! Release memory
146 if (allocated(lct_blk%raw)) deallocate(lct_blk%raw)
147 if (allocated(lct_blk%D)) deallocate(lct_blk%D)
148 if (allocated(lct_blk%coef)) deallocate(lct_blk%coef)
149 if (allocated(lct_blk%fit)) deallocate(lct_blk%fit)
150 if (allocated(lct_blk%D_filt)) deallocate(lct_blk%D_filt)
151 if (allocated(lct_blk%coef_filt)) deallocate(lct_blk%coef_filt)
152 if (allocated(lct_blk%fit_filt)) deallocate(lct_blk%fit_filt)
153 if (allocated(lct_blk%D11)) deallocate(lct_blk%D11)
154 if (allocated(lct_blk%D22)) deallocate(lct_blk%D22)
155 if (allocated(lct_blk%D33)) deallocate(lct_blk%D33)
156 if (allocated(lct_blk%D12)) deallocate(lct_blk%D12)
157 if (allocated(lct_blk%H11)) deallocate(lct_blk%H11)
158 if (allocated(lct_blk%H22)) deallocate(lct_blk%H22)
159 if (allocated(lct_blk%H33)) deallocate(lct_blk%H33)
160 if (allocated(lct_blk%H12)) deallocate(lct_blk%H12)
161 if (allocated(lct_blk%Dcoef)) deallocate(lct_blk%Dcoef)
162 if (allocated(lct_blk%DLh)) deallocate(lct_blk%DLh)
163 
164 end subroutine lct_blk_dealloc
165 
166 !----------------------------------------------------------------------
167 ! Subroutine: lct_blk_correlation
168 ! Purpose: compute raw correlation
169 !----------------------------------------------------------------------
170 subroutine lct_blk_correlation(lct_blk,nam,geom,bpar,samp,mom_blk)
172 implicit none
173 
174 ! Passed variables
175 class(lct_blk_type),intent(inout) :: lct_blk ! LCT block
176 type(nam_type),intent(in) :: nam ! Namelist
177 type(geom_type),intent(in) :: geom ! Geometry
178 type(bpar_type),intent(in) :: bpar ! Block parameters
179 type(samp_type),intent(in) :: samp ! Sampling
180 type(mom_blk_type),intent(in) :: mom_blk ! Moments block
181 
182 ! Local variables
183 integer :: jsub,il0,jl0r,jl0,jc3,ic1a,ic1
184 real(kind_real) :: den
185 real(kind_real),allocatable :: norm(:,:,:,:)
186 
187 ! Associate
188 associate(ib=>lct_blk%ib)
189 
190 ! Allocation
191 allocate(norm(nam%nc3,bpar%nl0r(ib),samp%nc1a,geom%nl0))
192 
193 ! Initialize
194 lct_blk%raw = 0.0
195 norm = 0.0
196 
197 ! Sum over jsub
198 do jsub=1,mom_blk%nsub
199  do il0=1,geom%nl0
200  do jl0r=1,bpar%nl0r(ib)
201  jl0 = bpar%l0rl0b_to_l0(jl0r,il0,ib)
202  do jc3=1,nam%nc3
203  do ic1a=1,samp%nc1a
204  ic1 = samp%c1a_to_c1(ic1a)
205  if (samp%c1l0_log(ic1,il0)) then
206  den = mom_blk%m2_1(ic1a,jc3,il0,jsub)*mom_blk%m2_2(ic1a,jc3,jl0,jsub)
207  if (den>0.0) then
208  lct_blk%raw(jc3,jl0r,ic1a,il0) = lct_blk%raw(jc3,jl0r,ic1a,il0)+mom_blk%m11(ic1a,jc3,jl0r,il0,jsub)/sqrt(den)
209  norm(jc3,jl0r,ic1a,il0) = norm(jc3,jl0r,ic1a,il0)+1.0
210  end if
211  end if
212  end do
213  end do
214  end do
215  end do
216 end do
217 
218 ! Normalize
219 do il0=1,geom%nl0
220  do jl0r=1,bpar%nl0r(ib)
221  do jc3=1,nam%nc3
222  do ic1a=1,samp%nc1a
223  ic1 = samp%c1a_to_c1(ic1a)
224  if (samp%c1l0_log(ic1,il0)) then
225  if (norm(jc3,jl0r,ic1a,il0)>0.0) lct_blk%raw(jc3,jl0r,ic1a,il0) = lct_blk%raw(jc3,jl0r,ic1a,il0) &
226  & /norm(jc3,jl0r,ic1a,il0)
227  end if
228  end do
229  end do
230  end do
231 end do
232 
233 ! End associate
234 end associate
235 
236 end subroutine lct_blk_correlation
237 
238 !----------------------------------------------------------------------
239 ! Subroutine: lct_blk_fitting
240 ! Purpose: fitting LCT
241 !----------------------------------------------------------------------
242 subroutine lct_blk_fitting(lct_blk,mpl,nam,geom,bpar,samp)
244 implicit none
245 
246 ! Passed variables
247 class(lct_blk_type),intent(inout) :: lct_blk ! LCT block
248 type(mpl_type),intent(inout) :: mpl ! MPI data
249 type(nam_type),intent(in) :: nam ! Namelist
250 type(geom_type),intent(in) :: geom ! Geometry
251 type(bpar_type),intent(in) :: bpar ! Block parameters
252 type(samp_type),intent(in) :: samp ! Sampling
253 
254 ! Local variables
255 integer :: il0,jl0r,jl0,ic1a,ic1,ic0,jc3,jc0,iscales,icomp
256 real(kind_real) :: distsq,Dhbar,Dvbar,diag_rescale
257 real(kind_real),allocatable :: Dh(:),Dv(:),dx(:,:),dy(:,:),dz(:,:)
258 logical :: valid
259 logical,allocatable :: dmask(:,:)
260 type(minim_type) :: minim
261 
262 ! Associate
263 associate(ib=>lct_blk%ib)
264 
265 ! Allocation
266 allocate(dh(nam%nc3))
267 allocate(dv(bpar%nl0r(ib)))
268 allocate(dx(nam%nc3,bpar%nl0r(ib)))
269 allocate(dy(nam%nc3,bpar%nl0r(ib)))
270 allocate(dz(nam%nc3,bpar%nl0r(ib)))
271 allocate(dmask(nam%nc3,bpar%nl0r(ib)))
272 minim%nx = lct_blk%nscales*4
273 if (lct_blk%nscales>1) minim%nx = minim%nx+lct_blk%nscales-1
274 minim%ny = nam%nc3*bpar%nl0r(ib)
275 allocate(minim%x(minim%nx))
276 allocate(minim%guess(minim%nx))
277 allocate(minim%binf(minim%nx))
278 allocate(minim%bsup(minim%nx))
279 allocate(minim%obs(minim%ny))
280 allocate(minim%dx(nam%nc3,bpar%nl0r(ib)))
281 allocate(minim%dy(nam%nc3,bpar%nl0r(ib)))
282 allocate(minim%dz(nam%nc3,bpar%nl0r(ib)))
283 allocate(minim%dmask(nam%nc3,bpar%nl0r(ib)))
284 
285 do il0=1,geom%nl0
286  write(mpl%info,'(a13,a,i3,a)',advance='no') '','Level ',nam%levs(il0),':'
287  call flush(mpl%info)
288 
289  ! Initialization
290  call mpl%prog_init(samp%nc1a)
291 
292  do ic1a=1,samp%nc1a
293  ! Global index
294  ic1 = samp%c1a_to_c1(ic1a)
295 
296  if (samp%c1l0_log(ic1,il0)) then
297  ! Compute deltas
298  ic0 = samp%c1_to_c0(ic1)
299  do jl0r=1,bpar%nl0r(ib)
300  jl0 = bpar%l0rl0b_to_l0(jl0r,il0,ib)
301  do jc3=1,nam%nc3
302  dmask(jc3,jl0r) = samp%c1l0_log(ic1,il0).and.samp%c1c3l0_log(ic1,jc3,jl0)
303  if (dmask(jc3,jl0r)) then
304  jc0 = samp%c1c3_to_c0(ic1,jc3)
305  call geom%compute_deltas(ic0,il0,jc0,jl0,dx(jc3,jl0r),dy(jc3,jl0r),dz(jc3,jl0r))
306  end if
307  end do
308  end do
309 
310  ! Approximate homogeneous horizontal length-scale
311  call msr(dh)
312  do jl0r=1,bpar%nl0r(ib)
313  jl0 = bpar%l0rl0b_to_l0(jl0r,il0,ib)
314  if (il0==jl0) then
315  do jc3=1,nam%nc3
316  if (dmask(jc3,jl0r)) then
317  distsq = dx(jc3,jl0r)**2+dy(jc3,jl0r)**2
318  if ((lct_blk%raw(jc3,jl0r,ic1a,il0)>cor_min).and.(lct_blk%raw(jc3,jl0r,ic1a,il0)<1.0).and.(distsq>0.0)) &
319  & dh(jc3) = -distsq/(2.0*log(lct_blk%raw(jc3,jl0r,ic1a,il0)))
320  end if
321  end do
322  end if
323  end do
324  call msr(dhbar)
325  if (count(isnotmsr(dh))>0) dhbar = sum(dh,mask=isnotmsr(dh))/real(count(isnotmsr(Dh)),kind_real)
326 
327  ! Approximate homogeneous vertical length-scale
328  call msr(dv)
329  jc3 = 1
330  do jl0r=1,bpar%nl0r(ib)
331  if (dmask(jc3,jl0r)) then
332  distsq = dz(jc3,jl0r)**2
333  if ((lct_blk%raw(jc3,jl0r,ic1a,il0)>cor_min).and.(lct_blk%raw(jc3,jl0r,ic1a,il0)<1.0).and.(distsq>0.0)) &
334  & dv(jl0r) = -distsq/(2.0*log(lct_blk%raw(jc3,jl0r,ic1a,il0)))
335  end if
336  end do
337  if (bpar%nl0r(ib)>1) then
338  if (count(isnotmsr(dv))>0) dvbar = sum(dv,mask=isnotmsr(dv))/real(count(isnotmsr(Dv)),kind_real)
339  else
340  dvbar = 0.0
341  end if
342 
343  if (isnotmsr(dhbar).and.(isnotmsr(dvbar))) then
344  ! Define norm and bounds
345  do iscales=1,lct_blk%nscales
346  minim%guess((iscales-1)*4+1:(iscales-1)*4+3) = (/dhbar,dhbar,dvbar/)*dscale**(iscales-1)
347  if (lct_blk%nscales==1) then
348  minim%binf((iscales-1)*4+1:(iscales-1)*4+3) = (/1.0/dscale,1.0/dscale,1.0/dscale/)*minim%guess(1:3)
349  minim%bsup((iscales-1)*4+1:(iscales-1)*4+3) = (/dscale,dscale,dscale/)*minim%guess(1:3)
350  else
351  minim%binf((iscales-1)*4+1:(iscales-1)*4+3) = (/1.0/sqrt(dscale),1.0/sqrt(dscale),1.0/sqrt(dscale)/) &
352  & *minim%guess(1:3)*dscale**(iscales-1)
353  minim%bsup((iscales-1)*4+1:(iscales-1)*4+3) = (/sqrt(dscale),sqrt(dscale),sqrt(dscale)/)*minim%guess(1:3) &
354  & *dscale**(iscales-1)
355  end if
356  minim%guess((iscales-1)*4+4) = 0.0
357  minim%binf((iscales-1)*4+4) = -1.0
358  minim%bsup((iscales-1)*4+4) = 1.0
359  end do
360  do iscales=1,lct_blk%nscales-1
361  minim%guess(lct_blk%nscales*4+1) = 1.0/real(lct_blk%nscales,kind_real)
362  minim%binf(lct_blk%nscales*4+1) = 0.1
363  minim%bsup(lct_blk%nscales*4+1) = 1.0
364  end do
365 
366  ! Fill minim
367  minim%obs = pack(lct_blk%raw(:,:,ic1a,il0),.true.)
368  minim%cost_function = 'fit_lct'
369  minim%algo = trim(nam%minim_algo)
370  minim%nc3 = nam%nc3
371  minim%nl0 = bpar%nl0r(ib)
372  minim%dx = dx
373  minim%dy = dy
374  minim%dz = dz
375  minim%dmask = dmask
376  minim%nscales = lct_blk%nscales
377 
378  ! Compute fit
379  call minim%compute(mpl,lprt)
380 
381  ! Copy parameters
382  do iscales=1,lct_blk%nscales
383  do icomp=1,4
384  lct_blk%D(icomp,iscales,ic1a,il0) = minim%x((iscales-1)*4+icomp)
385  end do
386  end do
387  if (lct_blk%nscales>1) then
388  lct_blk%coef(1:lct_blk%nscales-1,ic1a,il0) = minim%x(lct_blk%nscales*4+1:lct_blk%nscales*4+lct_blk%nscales-1)
389  lct_blk%coef(lct_blk%nscales,ic1a,il0) = 1.0-sum(lct_blk%coef(1:lct_blk%nscales-1,ic1a,il0))
390  else
391  lct_blk%coef(1,ic1a,il0) = 1.0
392  end if
393 
394  ! Set vertical value at zero for the 2D case
395  if (bpar%nl0r(ib)==1) lct_blk%D(3,:,ic1a,il0) = 0.0
396 
397  ! Check tensor validity
398  valid = .true.
399  do iscales=1,lct_blk%nscales
400  if (valid) then
401  call check_cond(lct_blk%D(1,iscales,ic1a,il0),lct_blk%D(2,iscales,ic1a,il0),lct_blk%D(4,iscales,ic1a,il0),valid)
402  if (bpar%nl0r(ib)>1) valid = valid.and.(lct_blk%D(3,iscales,ic1a,il0)>0.0)
403  valid = valid.and.(lct_blk%coef(iscales,ic1a,il0)>0.0)
404  if (lct_blk%nscales>1) valid = valid.and.(lct_blk%coef(iscales,ic1a,il0)<1.0)
405  end if
406  end do
407  if (valid) then
408  do iscales=1,lct_blk%nscales
409  if (nam%lct_diag(iscales)) then
410  ! Rescale diagonal tensor
411  diag_rescale = sqrt(1.0-lct_blk%D(4,iscales,ic1a,il0)**2)
412  lct_blk%D(1,iscales,ic1a,il0) = lct_blk%D(1,iscales,ic1a,il0)*diag_rescale
413  lct_blk%D(2,iscales,ic1a,il0) = lct_blk%D(2,iscales,ic1a,il0)*diag_rescale
414  lct_blk%D(4,iscales,ic1a,il0) = 0.0
415  end if
416  end do
417 
418  ! Rebuild fit
419  call fit_lct(mpl,nam%nc3,bpar%nl0r(ib),dx,dy,dz,dmask,lct_blk%nscales, &
420  & lct_blk%D(:,:,ic1a,il0),lct_blk%coef(:,ic1a,il0),lct_blk%fit(:,:,ic1a,il0))
421  else
422  ! Missing values
423  call msr(lct_blk%D(:,:,ic1a,il0))
424  call msr(lct_blk%coef(:,ic1a,il0))
425  call msr(lct_blk%fit(:,:,ic1a,il0))
426  end if
427  else
428  ! Missing values
429  call msr(lct_blk%D(:,:,ic1a,il0))
430  call msr(lct_blk%coef(:,ic1a,il0))
431  call msr(lct_blk%fit(:,:,ic1a,il0))
432  end if
433  end if
434 
435  ! Update
436  call mpl%prog_print(ic1a)
437  end do
438  write(mpl%info,'(a)') '100%'
439  call flush(mpl%info)
440 end do
441 
442 ! End associate
443 end associate
444 
445 end subroutine lct_blk_fitting
446 
447 end module type_lct_blk
subroutine lct_blk_alloc(lct_blk, nam, geom, bpar, samp, ib)
logical, parameter lprt
subroutine lct_blk_correlation(lct_blk, nam, geom, bpar, samp, mom_blk)
subroutine, public lonlatmod(lon, lat)
Definition: tools_func.F90:37
subroutine, public check_cond(d1, d2, nod, valid)
Definition: tools_func.F90:661
subroutine lct_blk_fitting(lct_blk, mpl, nam, geom, bpar, samp)
subroutine lct_blk_dealloc(lct_blk)
real(kind_real), parameter cor_min
real(kind_real), parameter dscale
integer, parameter, public kind_real
subroutine, public fit_lct(mpl, nc, nl0, dx, dy, dz, dmask, nscales, D, coef, fit)
Definition: tools_func.F90:548