FV3 Bundle
type_samp.F90
Go to the documentation of this file.
1 !----------------------------------------------------------------------
2 ! Module: type_samp
3 ! Purpose: sampling 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_samp
9 
10 use fckit_mpi_module, only: fckit_mpi_sum,fckit_mpi_status
11 use netcdf
12 !$ use omp_lib
15 use tools_kinds, only: kind_real
17 use tools_nc, only: ncfloat
18 use tools_qsort, only: qsort
19 use tools_stripack, only: trans
20 use type_bpar, only: bpar_type
21 use type_com, only: com_type
22 use type_ens, only: ens_type
23 use type_geom, only: geom_type
24 use type_io, only: io_type
25 use type_kdtree, only: kdtree_type
26 use type_linop, only: linop_type
27 use type_mesh, only: mesh_type
28 use type_mpl, only: mpl_type
29 use type_nam, only: nam_type
30 use type_rng, only: rng_type
31 
32 implicit none
33 
34 integer,parameter :: irmax = 10000 ! Maximum number of random number draws
35 real(kind_real),parameter :: lcoast = 1000.0e3_kind_real/req ! Length-scale to increase sampling density along coasts
36 real(kind_real),parameter :: rcoast = 0.2_kind_real ! Minimum value to increase sampling density along coasts
37 
38 ! Sampling derived type
40  ! Sampling
41  real(kind_real),allocatable :: rh_c0(:,:) ! Sampling radius on subset Sc0
42  logical,allocatable :: mask_c0(:,:) ! Mask on subset Sc0
43  logical,allocatable :: mask_hor_c0(:) ! Union of horizontal masks on subset Sc0, global
44  integer,allocatable :: nc0_mask(:) ! Horizontal mask size on subset Sc0
45  integer,allocatable :: c1_to_c0(:) ! First sampling index
46  logical,allocatable :: c1l0_log(:,:) ! Log for the first sampling index
47  integer,allocatable :: c1c3_to_c0(:,:) ! Second horizontal sampling index
48  logical,allocatable :: c1c3l0_log(:,:,:) ! Log for the second horizontal sampling index
49  integer,allocatable :: c2_to_c1(:) ! Subgrid to diagnostic points
50  integer,allocatable :: c2_to_c0(:) ! Subgrid to grid
51 
52  ! Local data
53  logical,allocatable :: vbal_mask(:,:) ! Vertical balance mask
54  logical,allocatable :: local_mask(:,:) ! Local mask
55  logical,allocatable :: displ_mask(:,:) ! Displacement mask
56  integer,allocatable :: nn_c2_index(:,:,:) ! Nearest diagnostic neighbors from diagnostic points
57  real(kind_real),allocatable :: nn_c2_dist(:,:,:) ! Nearest diagnostic neighbors distance from diagnostic points
58  integer,allocatable :: nn_ldwv_index(:) ! Nearest diagnostic neighbors for local diagnostics profiles
59 
60  ! Sampling mesh
61  type(mesh_type) :: mesh ! Sampling mesh
62 
63  ! Displacement
64  real(kind_real),allocatable :: displ_lon(:,:,:) ! Interpolated displaced longitude
65  real(kind_real),allocatable :: displ_lat(:,:,:) ! Interpolated displaced latitude
66 
67  ! Interpolations
68  type(linop_type),allocatable :: hfull(:) ! Horizontal interpolation from Sc2 to Sc0 (global)
69  type(linop_type),allocatable :: h(:) ! Horizontal interpolation from Sc2 to Sc0 (local)
70  type(linop_type),allocatable :: d(:,:) ! Displacement interpolation
71 
72  ! MPI distribution
73  integer :: nc0c ! Number of points in subset Sc0, halo C
74  integer :: nc0d ! Number of points in subset Sc0, halo D
75  integer :: nc1a ! Number of points in subset Sc1, halo A
76  integer :: nc2a ! Number of points in subset Sc2, halo A
77  integer :: nc2b ! Number of points in subset Sc2, halo B
78  integer :: nc2f ! Number of points in subset Sc2, halo F
79  logical,allocatable :: lcheck_c0a(:) ! Detection of halo A on subset Sc0
80  logical,allocatable :: lcheck_c0c(:) ! Detection of halo C on subset Sc0
81  logical,allocatable :: lcheck_c0d(:) ! Detection of halo D on subset Sc0
82  logical,allocatable :: lcheck_c1a(:) ! Detection of halo A on subset Sc1
83  logical,allocatable :: lcheck_c2a(:) ! Detection of halo A on subset Sc2
84  logical,allocatable :: lcheck_c2b(:) ! Detection of halo B on subset Sc2
85  logical,allocatable :: lcheck_c2f(:) ! Detection of halo F on subset Sc2
86  logical,allocatable :: lcheck_h(:,:) ! Detection of horizontal interpolation coefficients
87  logical,allocatable :: lcheck_d(:,:,:) ! Detection of displacement interpolation coefficients
88  integer,allocatable :: c0c_to_c0(:) ! Subset Sc0, halo C to global
89  integer,allocatable :: c0_to_c0c(:) ! Subset Sc0, global to halo C
90  integer,allocatable :: c0a_to_c0c(:) ! Subset Sc0, halo A to halo C
91  integer,allocatable :: c0d_to_c0(:) ! Subset Sc0, halo D to global
92  integer,allocatable :: c0_to_c0d(:) ! Subset Sc0, global to halo D
93  integer,allocatable :: c0a_to_c0d(:) ! Subset Sc0, halo A to halo D
94  integer,allocatable :: c1a_to_c1(:) ! Subset Sc1, halo A to global
95  integer,allocatable :: c1_to_c1a(:) ! Subset Sc1, global to halo A
96  integer,allocatable :: c2a_to_c2(:) ! Subset Sc2, halo A to global
97  integer,allocatable :: c2_to_c2a(:) ! Subset Sc2, global to halo A
98  integer,allocatable :: c2b_to_c2(:) ! Subset Sc2, halo B to global
99  integer,allocatable :: c2_to_c2b(:) ! Subset Sc2, global to halo B
100  integer,allocatable :: c2a_to_c2b(:) ! Subset Sc2, halo A to halo B
101  integer,allocatable :: c2f_to_c2(:) ! Subset Sc2, halo B to global
102  integer,allocatable :: c2_to_c2f(:) ! Subset Sc2, global to halo B
103  integer,allocatable :: c2a_to_c2f(:) ! Subset Sc2, halo A to halo B
104  integer,allocatable :: c2_to_proc(:) ! Subset Sc2, global to processor
105  integer,allocatable :: proc_to_nc2a(:) ! Number of points in subset Sc2, halo A, for each processor
106  type(com_type) :: com_ac ! Communication between halos A and C
107  type(com_type) :: com_ab ! Communication between halos A and B
108  type(com_type) :: com_ad ! Communication between halos A and D
109  type(com_type) :: com_af ! Communication between halos A and F (filtering)
110 contains
111  procedure :: alloc => samp_alloc
112  procedure :: dealloc => samp_dealloc
113  procedure :: read => samp_read
114  procedure :: write => samp_write
115  procedure :: setup_sampling => samp_setup_sampling
116  procedure :: compute_mask => samp_compute_mask
117  procedure :: compute_sampling_zs => samp_compute_sampling_zs
118  procedure :: compute_sampling_ps => samp_compute_sampling_ps
119  procedure :: compute_sampling_lct => samp_compute_sampling_lct
120  procedure :: compute_sampling_mask => samp_compute_sampling_mask
121  procedure :: compute_mpi_a => samp_compute_mpi_a
122  procedure :: compute_mpi_ab => samp_compute_mpi_ab
123  procedure :: compute_mpi_d => samp_compute_mpi_d
124  procedure :: compute_mpi_c => samp_compute_mpi_c
125  procedure :: compute_mpi_f => samp_compute_mpi_f
126  procedure :: diag_filter => samp_diag_filter
127  procedure :: diag_fill => samp_diag_fill
128 end type samp_type
129 
130 private
131 public :: samp_type
132 
133 contains
134 
135 !----------------------------------------------------------------------
136 ! Subroutine: samp_alloc
137 ! Purpose: sampling allocation
138 !----------------------------------------------------------------------
139 subroutine samp_alloc(samp,nam,geom)
141 implicit none
142 
143 ! Passed variables
144 class(samp_type),intent(inout) :: samp ! Sampling
145 type(nam_type),intent(in) :: nam ! Namelist
146 type(geom_type),intent(in) :: geom ! Geometry
147 
148 ! Allocation
149 allocate(samp%rh_c0(geom%nc0,geom%nl0))
150 allocate(samp%mask_c0(geom%nc0,geom%nl0))
151 allocate(samp%mask_hor_c0(geom%nc0))
152 allocate(samp%nc0_mask(geom%nl0))
153 allocate(samp%c1_to_c0(nam%nc1))
154 allocate(samp%c1l0_log(nam%nc1,geom%nl0))
155 allocate(samp%c1c3_to_c0(nam%nc1,nam%nc3))
156 allocate(samp%c1c3l0_log(nam%nc1,nam%nc3,geom%nl0))
157 if (nam%new_vbal.or.nam%new_lct.or.(nam%new_hdiag.and.(nam%var_diag.or.nam%local_diag.or.nam%displ_diag))) then
158  allocate(samp%c2_to_c1(nam%nc2))
159  allocate(samp%c2_to_c0(nam%nc2))
160  allocate(samp%nn_c2_index(nam%nc2,nam%nc2,geom%nl0i))
161  allocate(samp%nn_c2_dist(nam%nc2,nam%nc2,geom%nl0i))
162  allocate(samp%hfull(geom%nl0i))
163 end if
164 if (nam%new_vbal) allocate(samp%vbal_mask(nam%nc1,nam%nc2))
165 if (nam%local_diag) allocate(samp%local_mask(nam%nc1,nam%nc2))
166 if (nam%displ_diag) then
167  allocate(samp%displ_mask(nam%nc1,nam%nc2))
168  allocate(samp%displ_lon(geom%nc0a,geom%nl0,nam%nts))
169  allocate(samp%displ_lat(geom%nc0a,geom%nl0,nam%nts))
170 end if
171 
172 ! Initialization
173 call msr(samp%rh_c0)
174 samp%mask_c0 = .false.
175 samp%mask_hor_c0 = .false.
176 call msi(samp%nc0_mask)
177 call msi(samp%c1_to_c0)
178 samp%c1l0_log = .false.
179 call msi(samp%c1c3_to_c0)
180 samp%c1c3l0_log = .false.
181 if (nam%new_vbal.or.nam%new_lct.or.(nam%new_hdiag.and.(nam%var_diag.or.nam%local_diag.or.nam%displ_diag))) then
182  call msi(samp%c2_to_c1)
183  call msi(samp%c2_to_c0)
184  call msi(samp%nn_c2_index)
185  call msr(samp%nn_c2_dist)
186 end if
187 if (nam%new_vbal) samp%vbal_mask = .false.
188 if (nam%local_diag) samp%local_mask = .false.
189 if (nam%displ_diag) then
190  samp%displ_mask = .false.
191  call msr(samp%displ_lon)
192  call msr(samp%displ_lat)
193 end if
194 
195 end subroutine samp_alloc
196 
197 !----------------------------------------------------------------------
198 ! Subroutine: samp_dealloc
199 ! Purpose: sampling deallocation
200 !----------------------------------------------------------------------
201 subroutine samp_dealloc(samp,geom)
203 implicit none
204 
205 ! Passed variables
206 class(samp_type),intent(inout) :: samp ! Sampling
207 type(geom_type),intent(in) :: geom ! Geometry
208 
209 ! Local variables
210 integer :: il0
211 
212 ! Release memory
213 if (allocated(samp%rh_c0)) deallocate(samp%rh_c0)
214 if (allocated(samp%mask_c0)) deallocate(samp%mask_c0)
215 if (allocated(samp%mask_hor_c0)) deallocate(samp%mask_hor_c0)
216 if (allocated(samp%nc0_mask)) deallocate(samp%nc0_mask)
217 if (allocated(samp%c1_to_c0)) deallocate(samp%c1_to_c0)
218 if (allocated(samp%c1l0_log)) deallocate(samp%c1l0_log)
219 if (allocated(samp%c1c3_to_c0)) deallocate(samp%c1c3_to_c0)
220 if (allocated(samp%c1c3l0_log)) deallocate(samp%c1c3l0_log)
221 if (allocated(samp%c2_to_c1)) deallocate(samp%c2_to_c1)
222 if (allocated(samp%c2_to_c0)) deallocate(samp%c2_to_c0)
223 if (allocated(samp%c2a_to_c2)) deallocate(samp%c2a_to_c2)
224 if (allocated(samp%c2_to_c2a)) deallocate(samp%c2_to_c2a)
225 if (allocated(samp%vbal_mask)) deallocate(samp%vbal_mask)
226 if (allocated(samp%local_mask)) deallocate(samp%local_mask)
227 if (allocated(samp%displ_mask)) deallocate(samp%displ_mask)
228 if (allocated(samp%nn_c2_index)) deallocate(samp%nn_c2_index)
229 if (allocated(samp%nn_c2_dist)) deallocate(samp%nn_c2_dist)
230 if (allocated(samp%hfull)) then
231  do il0=1,geom%nl0
232  call samp%hfull(il0)%dealloc
233  end do
234  deallocate(samp%hfull)
235 end if
236 if (allocated(samp%h)) then
237  do il0=1,geom%nl0
238  call samp%h(il0)%dealloc
239  end do
240  deallocate(samp%h)
241 end if
242 if (allocated(samp%nn_ldwv_index)) deallocate(samp%nn_ldwv_index)
243 if (allocated(samp%displ_lon)) deallocate(samp%displ_lon)
244 if (allocated(samp%displ_lat)) deallocate(samp%displ_lat)
245 
246 end subroutine samp_dealloc
247 
248 !----------------------------------------------------------------------
249 ! Subroutine: samp_read
250 ! Purpose: read sampling
251 !----------------------------------------------------------------------
252 subroutine samp_read(samp,mpl,nam,geom,bpar,ios)
254 implicit none
255 
256 ! Passed variables
257 class(samp_type),intent(inout) :: samp ! Sampling
258 type(mpl_type),intent(in) :: mpl ! MPI data
259 type(nam_type),intent(inout) :: nam ! Namelist
260 type(geom_type),intent(in) :: geom ! Geometry
261 type(bpar_type),intent(in) :: bpar ! Block parameters
262 integer,intent(out) :: ios ! Status flag
263 
264 ! Local variables
265 integer :: il0,il0i,ic1,jc3,ic2
266 integer :: nl0_test,nl0r_test,nc_test,nc1_test,nc2_test,nc2_1_test,nc2_2_test
267 integer :: info,ncid,nl0_id,nc3_id,nc1_id,nc2_id,nc2_1_id,nc2_2_id
268 integer :: c1_to_c0_id,c1l0_log_id,c1c3_to_c0_id,c1c3l0_log_id
269 integer :: c2_to_c1_id,c2_to_c0_id,vbal_mask_id,local_mask_id,displ_mask_id,nn_c2_index_id,nn_c2_dist_id
270 integer :: c1l0_logint(nam%nc1,geom%nl0),c1c3l0_logint(nam%nc1,nam%nc3,geom%nl0)
271 integer,allocatable :: vbal_maskint(:,:),local_maskint(:,:),displ_maskint(:,:)
272 character(len=3) :: il0ichar
273 character(len=1024) :: subr = 'samp_read'
274 
275 ! Initialization
276 ios = 0
277 
278 ! Open file
279 info = nf90_open(trim(nam%datadir)//'/'//trim(nam%prefix)//'_sampling.nc',nf90_nowrite,ncid)
280 if (info/=nf90_noerr) then
281  call mpl%warning('cannot find sampling to read, recomputing sampling')
282  nam%sam_write = .true.
283  ios = 1
284  return
285 end if
286 
287 ! Check dimensions
288 call mpl%ncerr(subr,nf90_inq_dimid(ncid,'nl0',nl0_id))
289 call mpl%ncerr(subr,nf90_inquire_dimension(ncid,nl0_id,len=nl0_test))
290 call mpl%ncerr(subr,nf90_get_att(ncid,nf90_global,'nl0r',nl0r_test))
291 call mpl%ncerr(subr,nf90_inq_dimid(ncid,'nc3',nc3_id))
292 call mpl%ncerr(subr,nf90_inquire_dimension(ncid,nc3_id,len=nc_test))
293 call mpl%ncerr(subr,nf90_inq_dimid(ncid,'nc1',nc1_id))
294 call mpl%ncerr(subr,nf90_inquire_dimension(ncid,nc1_id,len=nc1_test))
295 if (nam%new_lct.or.nam%var_diag.or.nam%local_diag.or.nam%displ_diag) then
296  info = nf90_inq_dimid(ncid,'nc2',nc2_id)
297  if (info==nf90_noerr) then
298  call mpl%ncerr(subr,nf90_inquire_dimension(ncid,nc2_id,len=nc2_test))
299  else
300  call mpl%warning('cannot find nc2 when reading sampling, recomputing sampling')
301  nam%sam_write = .true.
302  ios = 2
303  end if
304 end if
305 if ((geom%nl0/=nl0_test).or.(bpar%nl0rmax/=nl0r_test).or.(nam%nc3/=nc_test).or.(nam%nc1/=nc1_test)) then
306  call mpl%warning('wrong dimension when reading sampling, recomputing sampling')
307  nam%sam_write = .true.
308  call mpl%ncerr(subr,nf90_close(ncid))
309  ios = 1
310  return
311 end if
312 if (nam%new_lct.or.nam%var_diag.or.nam%local_diag.or.nam%displ_diag) then
313  if (nam%nc2/=nc2_test) then
314  call mpl%warning('wrong dimension when reading sampling, recomputing sampling')
315  nam%sam_write = .true.
316  ios = 2
317  end if
318 end if
319 
320 write(mpl%info,'(a7,a)') '','Read sampling'
321 call flush(mpl%info)
322 
323 ! Get arrays ID
324 call mpl%ncerr(subr,nf90_inq_varid(ncid,'c1_to_c0',c1_to_c0_id))
325 call mpl%ncerr(subr,nf90_inq_varid(ncid,'c1l0_log',c1l0_log_id))
326 call mpl%ncerr(subr,nf90_inq_varid(ncid,'c1c3_to_c0',c1c3_to_c0_id))
327 call mpl%ncerr(subr,nf90_inq_varid(ncid,'c1c3l0_log',c1c3l0_log_id))
328 if ((ios==0).and.(nam%new_lct.or.nam%var_diag.or.nam%local_diag.or.nam%displ_diag)) then
329  call mpl%ncerr(subr,nf90_inq_varid(ncid,'c2_to_c1',c2_to_c1_id))
330  call mpl%ncerr(subr,nf90_inq_varid(ncid,'c2_to_c0',c2_to_c0_id))
331 end if
332 
333 ! Read arrays
334 call mpl%ncerr(subr,nf90_get_var(ncid,c1_to_c0_id,samp%c1_to_c0))
335 call mpl%ncerr(subr,nf90_get_var(ncid,c1l0_log_id,c1l0_logint))
336 do il0=1,geom%nl0
337  do ic1=1,nam%nc1
338  if (c1l0_logint(ic1,il0)==0) then
339  samp%c1l0_log(ic1,il0) = .false.
340  else if (c1l0_logint(ic1,il0)==1) then
341  samp%c1l0_log(ic1,il0) = .true.
342  end if
343  end do
344 end do
345 call mpl%ncerr(subr,nf90_get_var(ncid,c1c3_to_c0_id,samp%c1c3_to_c0))
346 call mpl%ncerr(subr,nf90_get_var(ncid,c1c3l0_log_id,c1c3l0_logint))
347 do il0=1,geom%nl0
348  do jc3=1,nam%nc3
349  do ic1=1,nam%nc1
350  if (c1c3l0_logint(ic1,jc3,il0)==0) then
351  samp%c1c3l0_log(ic1,jc3,il0) = .false.
352  else if (c1c3l0_logint(ic1,jc3,il0)==1) then
353  samp%c1c3l0_log(ic1,jc3,il0) = .true.
354  end if
355  end do
356  end do
357 end do
358 if ((ios==0).and.(nam%new_lct.or.nam%var_diag.or.nam%local_diag.or.nam%displ_diag)) then
359  call mpl%ncerr(subr,nf90_get_var(ncid,c2_to_c1_id,samp%c2_to_c1))
360  call mpl%ncerr(subr,nf90_get_var(ncid,c2_to_c0_id,samp%c2_to_c0))
361 end if
362 
363 ! Close file
364 call mpl%ncerr(subr,nf90_close(ncid))
365 
366 ! Read nearest neighbors and interpolation
367 do il0i=1,geom%nl0i
368  if ((ios==0).and.(nam%new_vbal.or.nam%new_lct.or.(nam%new_hdiag.and.(nam%var_diag.or.nam%local_diag.or.nam%displ_diag)))) then
369  ! Open file
370  write(il0ichar,'(i3.3)') il0i
371  info = nf90_open(trim(nam%datadir)//'/'//trim(nam%prefix)//'_sampling_'//il0ichar//'.nc',nf90_nowrite,ncid)
372  if (info/=nf90_noerr) then
373  call mpl%warning('cannot find nearest neighbors and interpolation data to read, recomputing sampling')
374  nam%sam_write = .true.
375  ios = 3
376  return
377  end if
378 
379  ! Check dimensions
380  call mpl%ncerr(subr,nf90_inq_dimid(ncid,'nc1',nc1_id))
381  call mpl%ncerr(subr,nf90_inquire_dimension(ncid,nc1_id,len=nc1_test))
382  call mpl%ncerr(subr,nf90_inq_dimid(ncid,'nc2_1',nc2_1_id))
383  call mpl%ncerr(subr,nf90_inquire_dimension(ncid,nc2_1_id,len=nc2_1_test))
384  call mpl%ncerr(subr,nf90_inq_dimid(ncid,'nc2_2',nc2_2_id))
385  call mpl%ncerr(subr,nf90_inquire_dimension(ncid,nc2_2_id,len=nc2_2_test))
386  if ((nam%nc1/=nc1_test).or.(nam%nc2/=nc2_1_test).or.(nam%nc2/=nc2_2_test)) then
387  call mpl%warning('wrong dimension when reading sampling, recomputing sampling')
388  nam%sam_write = .true.
389  ios = 2
390  end if
391  info = nf90_inq_varid(ncid,'nn_c2_index',nn_c2_index_id)
392  if (info==nf90_noerr) then
393  call mpl%ncerr(subr,nf90_inq_varid(ncid,'nn_c2_dist',nn_c2_dist_id))
394  call mpl%ncerr(subr,nf90_get_var(ncid,nn_c2_index_id,samp%nn_c2_index(:,:,il0i)))
395  call mpl%ncerr(subr,nf90_get_var(ncid,nn_c2_dist_id,samp%nn_c2_dist(:,:,il0i)))
396  else
397  call mpl%warning('cannot find nc2 nearest neighbors data to read, recomputing sampling')
398  nam%sam_write = .true.
399  ios = 4
400  end if
401  write(samp%hfull(il0i)%prefix,'(a,i3.3)') 'hfull_',il0i
402  call samp%hfull(il0i)%read(mpl,ncid)
403  end if
404 
405  if ((ios==0).and.nam%new_vbal) then
406  ! Allocation
407  allocate(vbal_maskint(nam%nc1,nam%nc2))
408 
409  call mpl%ncerr(subr,nf90_inq_varid(ncid,'vbal_mask',vbal_mask_id))
410  call mpl%ncerr(subr,nf90_get_var(ncid,vbal_mask_id,vbal_maskint))
411  do ic2=1,nam%nc2
412  do ic1=1,nam%nc1
413  if (vbal_maskint(ic1,ic2)==1) then
414  samp%vbal_mask(ic1,ic2) = .true.
415  elseif (vbal_maskint(ic1,ic2)==0) then
416  samp%vbal_mask(ic1,ic2) = .false.
417  else
418  call mpl%abort('wrong vbal_mask')
419  end if
420  end do
421  end do
422 
423  ! Release memory
424  deallocate(vbal_maskint)
425  end if
426 
427  if ((ios==0).and.nam%local_diag) then
428  ! Allocation
429  allocate(local_maskint(nam%nc1,nam%nc2))
430 
431  call mpl%ncerr(subr,nf90_inq_varid(ncid,'local_mask',local_mask_id))
432  call mpl%ncerr(subr,nf90_get_var(ncid,local_mask_id,local_maskint))
433  do ic2=1,nam%nc2
434  do ic1=1,nam%nc1
435  if (local_maskint(ic1,ic2)==1) then
436  samp%local_mask(ic1,ic2) = .true.
437  elseif (local_maskint(ic1,ic2)==0) then
438  samp%local_mask(ic1,ic2) = .false.
439  else
440  call mpl%abort('wrong local_mask')
441  end if
442  end do
443  end do
444 
445  ! Release memory
446  deallocate(local_maskint)
447  end if
448 
449  if ((ios==0).and.nam%displ_diag) then
450  ! Allocation
451  allocate(displ_maskint(nam%nc1,nam%nc2))
452 
453  call mpl%ncerr(subr,nf90_inq_varid(ncid,'displ_mask',displ_mask_id))
454  call mpl%ncerr(subr,nf90_get_var(ncid,displ_mask_id,displ_maskint))
455  do ic2=1,nam%nc2
456  do ic1=1,nam%nc1
457  if (displ_maskint(ic1,ic2)==1) then
458  samp%displ_mask(ic1,ic2) = .true.
459  elseif (displ_maskint(ic1,ic2)==0) then
460  samp%displ_mask(ic1,ic2) = .false.
461  else
462  call mpl%abort('wrong displ_mask')
463  end if
464  end do
465  end do
466 
467  ! Release memory
468  deallocate(displ_maskint)
469  end if
470 
471  if ((ios==0).and.(nam%new_lct.or.nam%var_diag.or.nam%local_diag.or.nam%displ_diag)) then
472  ! Close file
473  call mpl%ncerr(subr,nf90_close(ncid))
474  end if
475 end do
476 
477 end subroutine samp_read
478 
479 !----------------------------------------------------------------------
480 ! Subroutine: samp_write
481 ! Purpose: write sampling
482 !----------------------------------------------------------------------
483 subroutine samp_write(samp,mpl,nam,geom,bpar)
485 implicit none
486 
487 ! Passed variables
488 class(samp_type),intent(in) :: samp ! Sampling
489 type(mpl_type),intent(in) :: mpl ! MPI data
490 type(nam_type),intent(in) :: nam ! Namelist
491 type(geom_type),intent(in) :: geom ! Geometry
492 type(bpar_type),intent(in) :: bpar ! Block parameters
493 
494 ! Local variables
495 integer :: il0,il0i,ic1,jc3,ic2
496 integer :: ncid,nl0_id,nc1_id,nc2_id,nc2_1_id,nc2_2_id,nc3_id
497 integer :: lat_id,lon_id,smax_id,c1_to_c0_id,c1l0_log_id,c1c3_to_c0_id,c1c3l0_log_id
498 integer :: c2_to_c1_id,c2_to_c0_id,vbal_mask_id,local_mask_id,displ_mask_id,nn_c2_index_id,nn_c2_dist_id
499 integer :: c1l0_logint(nam%nc1,geom%nl0),c1c3l0_logint(nam%nc1,nam%nc3,geom%nl0)
500 integer,allocatable :: vbal_maskint(:,:),local_maskint(:,:),displ_maskint(:,:)
501 real(kind_real) :: lon(nam%nc1,nam%nc3,geom%nl0),lat(nam%nc1,nam%nc3,geom%nl0)
502 character(len=3) :: il0ichar
503 character(len=1024) :: subr = 'samp_write'
504 
505 ! Processor verification
506 if (.not.mpl%main) call mpl%abort('only I/O proc should enter '//trim(subr))
507 
508 ! Create file
509 write(mpl%info,'(a7,a)') '','Write sampling'
510 call flush(mpl%info)
511 call mpl%ncerr(subr,nf90_create(trim(nam%datadir)//'/'//trim(nam%prefix)//'_sampling.nc',or(nf90_clobber,nf90_64bit_offset),ncid))
512 
513 ! Write namelist parameters
514 call nam%ncwrite(mpl,ncid)
515 
516 ! Define dimensions
517 call mpl%ncerr(subr,nf90_def_dim(ncid,'nl0',geom%nl0,nl0_id))
518 call mpl%ncerr(subr,nf90_put_att(ncid,nf90_global,'nl0r',bpar%nl0rmax))
519 call mpl%ncerr(subr,nf90_def_dim(ncid,'nc3',nam%nc3,nc3_id))
520 call mpl%ncerr(subr,nf90_def_dim(ncid,'nc1',nam%nc1,nc1_id))
521 if (nam%new_vbal.or.nam%new_lct.or.(nam%new_hdiag.and.(nam%var_diag.or.nam%local_diag.or.nam%displ_diag))) &
522  & call mpl%ncerr(subr,nf90_def_dim(ncid,'nc2',nam%nc2,nc2_id))
523 
524 ! Define variables
525 call mpl%ncerr(subr,nf90_def_var(ncid,'lat',ncfloat,(/nc1_id,nc3_id,nl0_id/),lat_id))
526 call mpl%ncerr(subr,nf90_put_att(ncid,lat_id,'_FillValue',msvalr))
527 call mpl%ncerr(subr,nf90_def_var(ncid,'lon',ncfloat,(/nc1_id,nc3_id,nl0_id/),lon_id))
528 call mpl%ncerr(subr,nf90_put_att(ncid,lon_id,'_FillValue',msvalr))
529 call mpl%ncerr(subr,nf90_def_var(ncid,'smax',ncfloat,(/nc3_id,nl0_id/),smax_id))
530 call mpl%ncerr(subr,nf90_put_att(ncid,smax_id,'_FillValue',msvalr))
531 call mpl%ncerr(subr,nf90_def_var(ncid,'c1_to_c0',nf90_int,(/nc1_id/),c1_to_c0_id))
532 call mpl%ncerr(subr,nf90_put_att(ncid,c1_to_c0_id,'_FillValue',msvali))
533 call mpl%ncerr(subr,nf90_def_var(ncid,'c1l0_log',nf90_int,(/nc1_id,nl0_id/),c1l0_log_id))
534 call mpl%ncerr(subr,nf90_put_att(ncid,c1l0_log_id,'_FillValue',msvali))
535 call mpl%ncerr(subr,nf90_def_var(ncid,'c1c3_to_c0',nf90_int,(/nc1_id,nc3_id/),c1c3_to_c0_id))
536 call mpl%ncerr(subr,nf90_put_att(ncid,c1c3_to_c0_id,'_FillValue',msvali))
537 call mpl%ncerr(subr,nf90_def_var(ncid,'c1c3l0_log',nf90_int,(/nc1_id,nc3_id,nl0_id/),c1c3l0_log_id))
538 call mpl%ncerr(subr,nf90_put_att(ncid,c1c3l0_log_id,'_FillValue',msvali))
539 if (nam%new_lct.or.nam%var_diag.or.nam%local_diag.or.nam%displ_diag) then
540  call mpl%ncerr(subr,nf90_def_var(ncid,'c2_to_c1',nf90_int,(/nc2_id/),c2_to_c1_id))
541  call mpl%ncerr(subr,nf90_put_att(ncid,c2_to_c1_id,'_FillValue',msvali))
542  call mpl%ncerr(subr,nf90_def_var(ncid,'c2_to_c0',nf90_int,(/nc2_id/),c2_to_c0_id))
543  call mpl%ncerr(subr,nf90_put_att(ncid,c2_to_c0_id,'_FillValue',msvali))
544 end if
545 
546 ! End definition mode
547 call mpl%ncerr(subr,nf90_enddef(ncid))
548 
549 ! Convert data
550 call msr(lon)
551 call msr(lat)
552 do il0=1,geom%nl0
553  do jc3=1,nam%nc3
554  do ic1=1,nam%nc1
555  if (samp%c1c3l0_log(ic1,jc3,il0)) then
556  lon(ic1,jc3,il0) = geom%lon(samp%c1c3_to_c0(ic1,jc3))*rad2deg
557  lat(ic1,jc3,il0) = geom%lat(samp%c1c3_to_c0(ic1,jc3))*rad2deg
558  c1c3l0_logint(ic1,jc3,il0) = 1
559  else
560  c1c3l0_logint(ic1,jc3,il0) = 0
561  end if
562  end do
563  end do
564  do ic1=1,nam%nc1
565  if (samp%c1l0_log(ic1,il0)) then
566  c1l0_logint(ic1,il0) = 1
567  else
568  c1l0_logint(ic1,il0) = 0
569  end if
570  end do
571 end do
572 
573 ! Write variables
574 call mpl%ncerr(subr,nf90_put_var(ncid,lon_id,lon))
575 call mpl%ncerr(subr,nf90_put_var(ncid,lat_id,lat))
576 call mpl%ncerr(subr,nf90_put_var(ncid,smax_id,real(count(samp%c1c3l0_log,dim=1),kind_real)))
577 call mpl%ncerr(subr,nf90_put_var(ncid,c1_to_c0_id,samp%c1_to_c0))
578 call mpl%ncerr(subr,nf90_put_var(ncid,c1l0_log_id,c1l0_logint))
579 call mpl%ncerr(subr,nf90_put_var(ncid,c1c3_to_c0_id,samp%c1c3_to_c0))
580 call mpl%ncerr(subr,nf90_put_var(ncid,c1c3l0_log_id,c1c3l0_logint))
581 if (nam%new_lct.or.nam%var_diag.or.nam%local_diag.or.nam%displ_diag) then
582  call mpl%ncerr(subr,nf90_put_var(ncid,c2_to_c1_id,samp%c2_to_c1))
583  call mpl%ncerr(subr,nf90_put_var(ncid,c2_to_c0_id,samp%c2_to_c0))
584 end if
585 
586 ! Close file
587 call mpl%ncerr(subr,nf90_close(ncid))
588 
589 ! Write nearest neighbors and interpolation
590 do il0i=1,geom%nl0i
591  if (nam%new_vbal.or.nam%new_lct.or.(nam%new_hdiag.and.(nam%var_diag.or.nam%local_diag.or.nam%displ_diag))) then
592  ! Create file
593  write(il0ichar,'(i3.3)') il0i
594  call mpl%ncerr(subr,nf90_create(trim(nam%datadir)//'/'//trim(nam%prefix)//'_sampling_'//il0ichar//'.nc', &
595  & or(nf90_clobber,nf90_64bit_offset),ncid))
596 
597  ! Write namelist parameters
598  call nam%ncwrite(mpl,ncid)
599 
600  ! Define dimensions
601  call mpl%ncerr(subr,nf90_def_dim(ncid,'nc1',nam%nc1,nc1_id))
602  call mpl%ncerr(subr,nf90_def_dim(ncid,'nc2_1',nam%nc2,nc2_1_id))
603  call mpl%ncerr(subr,nf90_def_dim(ncid,'nc2_2',nam%nc2,nc2_2_id))
604 
605  ! Define variables
606  call mpl%ncerr(subr,nf90_def_var(ncid,'nn_c2_index',nf90_int,(/nc2_1_id,nc2_2_id/),nn_c2_index_id))
607  call mpl%ncerr(subr,nf90_put_att(ncid,nn_c2_index_id,'_FillValue',msvali))
608  call mpl%ncerr(subr,nf90_def_var(ncid,'nn_c2_dist',ncfloat,(/nc2_1_id,nc2_2_id/),nn_c2_dist_id))
609  call mpl%ncerr(subr,nf90_put_att(ncid,nn_c2_dist_id,'_FillValue',msvalr))
610 
611  ! End definition mode
612  call mpl%ncerr(subr,nf90_enddef(ncid))
613 
614  ! Write variables
615  call mpl%ncerr(subr,nf90_put_var(ncid,nn_c2_index_id,samp%nn_c2_index(:,:,il0i)))
616  call mpl%ncerr(subr,nf90_put_var(ncid,nn_c2_dist_id,samp%nn_c2_dist(:,:,il0i)))
617  call samp%hfull(il0i)%write(mpl,ncid)
618  end if
619 
620  if (nam%new_vbal) then
621  ! Allocation
622  allocate(vbal_maskint(nam%nc1,nam%nc2))
623 
624  ! Definition mode
625  call mpl%ncerr(subr,nf90_redef(ncid))
626 
627  ! Define variables
628  call mpl%ncerr(subr,nf90_def_var(ncid,'vbal_mask',nf90_int,(/nc1_id,nc2_1_id/),vbal_mask_id))
629  call mpl%ncerr(subr,nf90_put_att(ncid,vbal_mask_id,'_FillValue',msvali))
630 
631  ! Convert data
632  do ic2=1,nam%nc2
633  do ic1=1,nam%nc1
634  if (samp%vbal_mask(ic1,ic2)) then
635  vbal_maskint(ic1,ic2) = 1
636  else
637  vbal_maskint(ic1,ic2) = 0
638  end if
639  end do
640  end do
641 
642  ! End definition mode
643  call mpl%ncerr(subr,nf90_enddef(ncid))
644 
645  ! Write variables
646  call mpl%ncerr(subr,nf90_put_var(ncid,vbal_mask_id,vbal_maskint))
647 
648  ! Release memory
649  deallocate(vbal_maskint)
650  end if
651 
652  if (nam%local_diag) then
653  ! Allocation
654  allocate(local_maskint(nam%nc1,nam%nc2))
655 
656  ! Definition mode
657  call mpl%ncerr(subr,nf90_redef(ncid))
658 
659  ! Define variables
660  call mpl%ncerr(subr,nf90_def_var(ncid,'local_mask',nf90_int,(/nc1_id,nc2_1_id/),local_mask_id))
661  call mpl%ncerr(subr,nf90_put_att(ncid,local_mask_id,'_FillValue',msvali))
662 
663  ! Convert data
664  do ic2=1,nam%nc2
665  do ic1=1,nam%nc1
666  if (samp%local_mask(ic1,ic2)) then
667  local_maskint(ic1,ic2) = 1
668  else
669  local_maskint(ic1,ic2) = 0
670  end if
671  end do
672  end do
673 
674  ! End definition mode
675  call mpl%ncerr(subr,nf90_enddef(ncid))
676 
677  ! Write variables
678  call mpl%ncerr(subr,nf90_put_var(ncid,local_mask_id,local_maskint))
679 
680  ! Release memory
681  deallocate(local_maskint)
682  end if
683 
684  if (nam%displ_diag) then
685  ! Allocation
686  allocate(displ_maskint(nam%nc1,nam%nc2))
687 
688  ! Definition mode
689  call mpl%ncerr(subr,nf90_redef(ncid))
690 
691  ! Define variables
692  call mpl%ncerr(subr,nf90_def_var(ncid,'displ_mask',nf90_int,(/nc1_id,nc2_1_id/),displ_mask_id))
693  call mpl%ncerr(subr,nf90_put_att(ncid,displ_mask_id,'_FillValue',msvali))
694 
695  ! Convert data
696  do ic2=1,nam%nc2
697  do ic1=1,nam%nc1
698  if (samp%displ_mask(ic1,ic2)) then
699  displ_maskint(ic1,ic2) = 1
700  else
701  displ_maskint(ic1,ic2) = 0
702  end if
703  end do
704  end do
705 
706  ! End definition mode
707  call mpl%ncerr(subr,nf90_enddef(ncid))
708 
709  ! Write variables
710  call mpl%ncerr(subr,nf90_put_var(ncid,displ_mask_id,displ_maskint))
711 
712  ! Release memory
713  deallocate(displ_maskint)
714  end if
715 
716  if (nam%new_lct.or.nam%var_diag.or.nam%local_diag.or.nam%displ_diag) then
717  ! Close file
718  call mpl%ncerr(subr,nf90_close(ncid))
719  end if
720 end do
721 
722 end subroutine samp_write
723 
724 !----------------------------------------------------------------------
725 ! Subroutine: samp_setup_sampling
726 ! Purpose: setup sampling
727 !----------------------------------------------------------------------
728 subroutine samp_setup_sampling(samp,mpl,rng,nam,geom,bpar,io,ens)
730 implicit none
731 
732 ! Passed variables
733 class(samp_type),intent(inout) :: samp ! Sampling
734 type(mpl_type),intent(inout) :: mpl ! MPI data
735 type(rng_type),intent(inout) :: rng ! Random number generator
736 type(nam_type),intent(inout) :: nam ! Namelist
737 type(geom_type),intent(in) :: geom ! Geometry
738 type(bpar_type),intent(in) :: bpar ! Block parameters
739 type(io_type),intent(in) :: io ! I/O
740 type(ens_type),intent(in) :: ens ! Ensemble
741 
742 ! Local variables
743 integer :: ios,ic0,il0,ic1,ic2,ildw,jc3,il0i,jc1,kc1
744 integer,allocatable :: vbot(:),vtop(:),nn_c1_index(:)
745 real(kind_real) :: lon_c1(nam%nc1),lat_c1(nam%nc1)
746 real(kind_real) :: lon_c2(nam%nc2),lat_c2(nam%nc2)
747 real(kind_real) :: rh_c0a(geom%nc0a,geom%nl0),nn_dist(1)
748 real(kind_real),allocatable :: rh_c1(:),nn_c1_dist(:)
749 logical :: mask_c1(nam%nc1),mask_c2(nam%nc2)
750 character(len=1024) :: filename
751 type(kdtree_type) :: kdtree
752 type(linop_type) :: hbase
753 
754 ! Check subsampling size
755 if (nam%nc1>maxval(geom%nc0_mask)) then
756  call mpl%warning('nc1 is too large for then mask, reset nc1 to the largest possible value')
757  nam%nc1 = maxval(geom%nc0_mask)
758 end if
759 
760 ! Allocation
761 call samp%alloc(nam,geom)
762 
763 ! Read or compute sampling data
764 ios = 1
765 if (nam%sam_read) call samp%read(mpl,nam,geom,bpar,ios)
766 if (ios==1) then
767  ! Compute mask
768  call samp%compute_mask(mpl,nam,geom,ens)
769 
770  ! Compute zero-separation sampling
771  call samp%compute_sampling_zs(mpl,rng,nam,geom)
772 
773  if (nam%new_lct) then
774  ! Compute LCT sampling
775  call samp%compute_sampling_lct(mpl,nam,geom)
776  elseif (nam%new_vbal.or.nam%new_hdiag) then
777  ! Compute positive separation sampling
778  call samp%compute_sampling_ps(mpl,rng,nam,geom)
779  end if
780 
781  ! Compute sampling mask
782  call samp%compute_sampling_mask(mpl,nam,geom)
783 end if
784 
785 if (nam%new_vbal.or.nam%new_lct.or.(nam%new_hdiag.and.(nam%var_diag.or.nam%local_diag.or.nam%displ_diag))) then
786  if ((ios==1).or.(ios==2)) then
787  ! Define subsampling
788  write(mpl%info,'(a7,a)',advance='no') '','Define subsampling:'
789  call flush(mpl%info)
790  allocate(rh_c1(nam%nc1))
791  lon_c1 = geom%lon(samp%c1_to_c0)
792  lat_c1 = geom%lat(samp%c1_to_c0)
793  mask_c1 = any(samp%c1l0_log(:,:),dim=2)
794  rh_c1 = 1.0
795  call rng%initialize_sampling(mpl,nam%nc1,lon_c1,lat_c1,mask_c1,rh_c1,nam%ntry,nam%nrep,nam%nc2,samp%c2_to_c1)
796  samp%c2_to_c0 = samp%c1_to_c0(samp%c2_to_c1)
797  deallocate(rh_c1)
798  end if
799 
800  if ((ios==1).or.(ios==2).or.(ios==3).or.(ios==4)) then
801  ! Find nearest neighbors
802  write(mpl%info,'(a7,a)') '','Find nearest neighbors'
803  call flush(mpl%info)
804  do il0=1,geom%nl0
805  if ((il0==1).or.(geom%nl0i>1)) then
806  write(mpl%info,'(a10,a,i3)') '','Level ',nam%levs(il0)
807  call flush(mpl%info)
808  lon_c2 = geom%lon(samp%c2_to_c0)
809  lat_c2 = geom%lat(samp%c2_to_c0)
810  mask_c2 = .true.
811  call kdtree%create(mpl,nam%nc2,lon_c2,lat_c2,mask=mask_c2)
812  do ic2=1,nam%nc2
813  ic1 = samp%c2_to_c1(ic2)
814  ic0 = samp%c2_to_c0(ic2)
815  call kdtree%find_nearest_neighbors(geom%lon(ic0),geom%lat(ic0),nam%nc2,samp%nn_c2_index(:,ic2,il0), &
816  & samp%nn_c2_dist(:,ic2,il0))
817  end do
818  call kdtree%dealloc
819  end if
820  end do
821  end if
822 
823  ! Compute sampling mesh
824  write(mpl%info,'(a7,a)') '','Compute sampling mesh'
825  call flush(mpl%info)
826  lon_c2 = geom%lon(samp%c2_to_c0)
827  lat_c2 = geom%lat(samp%c2_to_c0)
828  call samp%mesh%create(mpl,rng,nam%nc2,lon_c2,lat_c2)
829 
830  ! Compute triangles list
831  write(mpl%info,'(a7,a)') '','Compute triangles list '
832  call flush(mpl%info)
833  call samp%mesh%trlist
834 
835  ! Find boundary nodes
836  write(mpl%info,'(a7,a)') '','Find boundary nodes'
837  call flush(mpl%info)
838  call samp%mesh%bnodes
839 
840  ! Find boundary arcs
841  write(mpl%info,'(a7,a)') '','Find boundary arcs'
842  call flush(mpl%info)
843  call samp%mesh%barcs
844 
845  if ((ios==1).or.(ios==2).or.(ios==3)) then
846  if (nam%new_vbal.or.nam%local_diag.or.nam%displ_diag) then
847  ! Allocation
848  allocate(nn_c1_index(nam%nc1))
849  allocate(nn_c1_dist(nam%nc1))
850 
851  ! Compute local masks
852  write(mpl%info,'(a7,a)') '','Compute local masks'
853  call flush(mpl%info)
854  lon_c1 = geom%lon(samp%c1_to_c0)
855  lat_c1 = geom%lat(samp%c1_to_c0)
856  mask_c1 = any(samp%c1l0_log,dim=2)
857  call kdtree%create(mpl,nam%nc1,lon_c1,lat_c1,mask=mask_c1)
858  do ic2=1,nam%nc2
859  ! Inidices
860  ic1 = samp%c2_to_c1(ic2)
861  ic0 = samp%c2_to_c0(ic2)
862 
863  ! Find nearest neighbors
864  call kdtree%find_nearest_neighbors(geom%lon(ic0),geom%lat(ic0),nam%nc1,nn_c1_index,nn_c1_dist)
865  do jc1=1,nam%nc1
866  kc1 = nn_c1_index(jc1)
867  if (nam%new_vbal) samp%vbal_mask(kc1,ic2) = (jc1==1) &
868  & .or.(nn_c1_dist(jc1)<nam%vbal_rad)
869  if (nam%local_diag) samp%local_mask(kc1,ic2) = (jc1==1) &
870  & .or.(nn_c1_dist(jc1)<nam%local_rad)
871  if (nam%displ_diag) samp%displ_mask(kc1,ic2) = (jc1==1) &
872  & .or.(nn_c1_dist(jc1)<min(nam%displ_rad,samp%mesh%bdist(ic2)))
873  end do
874  end do
875  call kdtree%dealloc
876 
877  ! Release memory
878  deallocate(nn_c1_index)
879  deallocate(nn_c1_dist)
880  end if
881 
882  ! Allocation
883  allocate(vbot(nam%nc2))
884  allocate(vtop(nam%nc2))
885 
886  ! Initialize vbot and vtop
887  vbot = 1
888  vtop = geom%nl0
889 
890  ! Compute grid interpolation
891  write(mpl%info,'(a7,a)') '','Compute grid interpolation'
892  do il0i=1,geom%nl0i
893  ! Compute grid interpolation
894  write(samp%hfull(il0i)%prefix,'(a,i3.3)') 'hfull_',il0i
895  call samp%hfull(il0i)%interp(mpl,rng,geom,il0i,nam%nc2,samp%c2_to_c0,nam%mask_check,vbot,vtop,nam%diag_interp,hbase)
896  end do
897 
898  ! Release memory
899  deallocate(vbot)
900  deallocate(vtop)
901  end if
902 end if
903 
904 ! Write sampling data
905 if (nam%sam_write) then
906  if (mpl%main) call samp%write(mpl,nam,geom,bpar)
907 
908  ! Write rh_c0
909  if (trim(nam%draw_type)=='random_coast') then
910  call mpl%glb_to_loc(geom%nl0,geom%nc0,geom%c0_to_proc,geom%c0_to_c0a,samp%rh_c0,geom%nc0a,rh_c0a)
911  filename = trim(nam%prefix)//'_sampling_rh_c0'
912  call io%fld_write(mpl,nam,geom,filename,'rh_c0',rh_c0a)
913  end if
914 end if
915 
916 ! Compute nearest neighbors for local diagnostics output
917 if (nam%local_diag.and.(nam%nldwv>0)) then
918  write(mpl%info,'(a7,a)') '','Compute nearest neighbors for local diagnostics output'
919  call flush(mpl%info)
920  allocate(samp%nn_ldwv_index(nam%nldwv))
921  call kdtree%create(mpl,nam%nc2,geom%lon(samp%c2_to_c0),geom%lat(samp%c2_to_c0),mask=samp%c1l0_log(samp%c2_to_c1,1))
922  do ildw=1,nam%nldwv
923  call kdtree%find_nearest_neighbors(nam%lon_ldwv(ildw),nam%lat_ldwv(ildw),1,samp%nn_ldwv_index(ildw:ildw),nn_dist)
924  end do
925  call kdtree%dealloc
926 end if
927 
928 ! Print results
929 write(mpl%info,'(a7,a)') '','Sampling efficiency (%):'
930 do il0=1,geom%nl0
931  write(mpl%info,'(a10,a,i3,a)',advance='no') '','Level ',nam%levs(il0),' ~> '
932  do jc3=1,nam%nc3
933  if (count(samp%c1c3l0_log(:,jc3,il0))>=nam%nc1/2) then
934  ! Sucessful sampling
935  write(mpl%info,'(a,i3,a)',advance='no') trim(mpl%green), &
936  & int(100.0*real(count(samp%c1c3l0_log(:,jc3,il0)),kind_real)/real(nam%nc1,kind_real)),trim(mpl%black)
937  else
938  ! Insufficient sampling
939  write(mpl%info,'(a,i3,a)',advance='no') trim(mpl%peach), &
940  & int(100.0*real(count(samp%c1c3l0_log(:,jc3,il0)),kind_real)/real(nam%nc1,kind_real)),trim(mpl%black)
941  end if
942  if (jc3<nam%nc3) write(mpl%info,'(a)',advance='no') '-'
943  end do
944  write(mpl%info,'(a)') ' '
945 end do
946 call flush(mpl%info)
947 
948 end subroutine samp_setup_sampling
949 
950 !----------------------------------------------------------------------
951 ! Subroutine: samp_compute_mask
952 ! Purpose: compute mask
953 !----------------------------------------------------------------------
954 subroutine samp_compute_mask(samp,mpl,nam,geom,ens)
956 implicit none
957 
958 ! Passed variables
959 class(samp_type),intent(inout) :: samp ! Sampling
960 type(mpl_type),intent(inout) :: mpl ! MPI data
961 type(nam_type),intent(in) :: nam ! Namelist
962 type(geom_type),intent(in) :: geom ! Geometry
963 type(ens_type),intent(in) :: ens ! Ensemble
964 
965 ! Local variables
966 integer :: ic0a,il0,iv,its,ie,isub,ie_sub
967 real(kind_real),allocatable :: var(:,:,:,:)
968 logical :: valid,mask_c0a(geom%nc0a,geom%nl0)
969 
970 ! Copy geometry mask
971 mask_c0a = geom%mask_c0a
972 
973 ! Ensemble-based mask
974 select case (trim(nam%mask_type))
975 case ('stddev')
976  ! Allocation
977  allocate(var(geom%nc0a,geom%nl0,nam%nv,nam%nts))
978 
979  ! Compute variances
980  var = 0.0
981  do ie=1,ens%ne
982  var = var +ens%fld(:,:,:,:,ie)**2
983  end do
984  var = var/real(ens%ne-ens%nsub,kind_real)
985 
986  ! Check whether standard-deviation is over the threshold
987  do its=1,nam%nts
988  do iv=1,nam%nv
989  mask_c0a = mask_c0a.and.(var(:,:,iv,its)>nam%mask_th**2)
990  end do
991  end do
992 case ('all_members')
993  ! Check whether all members are over the threshold
994  do its=1,nam%nts
995  do iv=1,nam%nv
996  do il0=1,geom%nl0
997  do ic0a=1,geom%nc0a
998  valid = .true.
999  do isub=1,ens%nsub
1000  do ie_sub=1,ens%ne/ens%nsub
1001  ie = ie_sub+(isub-1)*ens%ne/ens%nsub
1002  valid = valid.and.(ens%mean(ic0a,il0,iv,its,isub)+ens%fld(ic0a,il0,iv,its,ie)>nam%mask_th)
1003  end do
1004  end do
1005  mask_c0a(ic0a,il0) = mask_c0a(ic0a,il0).and.valid
1006  end do
1007  end do
1008  end do
1009  end do
1010 end select
1011 
1012 ! Local to global
1013 call mpl%loc_to_glb(geom%nl0,geom%nc0a,mask_c0a,geom%nc0,geom%c0_to_proc,geom%c0_to_c0a,.true.,samp%mask_c0)
1014 
1015 ! Other masks
1016 samp%mask_hor_c0 = any(samp%mask_c0,dim=2)
1017 samp%nc0_mask = count(samp%mask_c0,dim=1)
1018 
1019 ! Print results
1020 select case (trim(nam%mask_type))
1021 case ('stddev','all_members','any_member')
1022  write(mpl%info,'(a7,a)') '','Number of points excluded from HDIAG sampling:'
1023  do il0=1,geom%nl0
1024  write(mpl%info,'(a10,a,i3,a,i8,a,i8)') '','Level',nam%levs(il0),': ',count(geom%mask_c0(:,il0))-count(samp%mask_c0(:,il0)), &
1025  & ' of ',count(geom%mask_c0(:,il0))
1026  end do
1027 end select
1028 
1029 end subroutine samp_compute_mask
1030 
1031 !----------------------------------------------------------------------
1032 ! Subroutine: samp_compute_sampling_zs
1033 ! Purpose: compute zero-separation sampling
1034 !----------------------------------------------------------------------
1035 subroutine samp_compute_sampling_zs(samp,mpl,rng,nam,geom)
1037 implicit none
1038 
1039 ! Passed variables
1040 class(samp_type),intent(inout) :: samp ! Sampling
1041 type(mpl_type),intent(inout) :: mpl ! MPI data
1042 type(rng_type),intent(inout) :: rng ! Random number generator
1043 type(nam_type),intent(in) :: nam ! Namelist
1044 type(geom_type),intent(in) :: geom ! Geometry
1045 
1046 ! Local variables
1047 integer :: ic0,ic1,il0
1048 integer :: nn_index(1)
1049 real(kind_real) :: nn_dist(1)
1050 type(kdtree_type) :: kdtree
1051 
1052 ! Compute subset
1053 if (nam%nc1<maxval(samp%nc0_mask)) then
1054  write(mpl%info,'(a7,a)',advance='no') '','Compute horizontal subset C1: '
1055  call flush(mpl%info)
1056  select case (trim(nam%draw_type))
1057  case ('random_uniform')
1058  ! Random draw
1059  do ic0=1,geom%nc0
1060  if (samp%mask_hor_c0(ic0)) samp%rh_c0(ic0,1) = 1.0
1061  end do
1062  case ('random_coast')
1063  ! More points around coasts
1064  do ic0=1,geom%nc0
1065  if (samp%mask_hor_c0(ic0)) samp%rh_c0(ic0,1) = 0.0
1066  end do
1067  do il0=1,geom%nl0
1068  call kdtree%create(mpl,geom%nc0,geom%lon,geom%lat,mask=.not.samp%mask_c0(:,il0))
1069  do ic0=1,geom%nc0
1070  if (samp%mask_c0(ic0,il0)) then
1071  call kdtree%find_nearest_neighbors(geom%lon(ic0),geom%lat(ic0),1,nn_index,nn_dist)
1072  samp%rh_c0(ic0,1) = samp%rh_c0(ic0,1)+exp(-nn_dist(1)/lcoast)
1073  else
1074  samp%rh_c0(ic0,1) = samp%rh_c0(ic0,1)+1.0
1075  end if
1076  end do
1077  call kdtree%dealloc
1078  end do
1079  samp%rh_c0(:,1) = rcoast+(1.0-rcoast)*(1.0-samp%rh_c0(:,1)/real(geom%nl0,kind_real))
1080  end select
1081 
1082  ! Initialize sampling
1083  call rng%initialize_sampling(mpl,geom%nc0,geom%lon,geom%lat,samp%mask_hor_c0,samp%rh_c0(:,1),nam%ntry,nam%nrep, &
1084  & nam%nc1,samp%c1_to_c0)
1085 else
1086  ic1 = 0
1087  do ic0=1,geom%nc0
1088  if (samp%mask_hor_c0(ic0)) then
1089  ic1 = ic1+1
1090  samp%c1_to_c0(ic1) = ic0
1091  end if
1092  end do
1093 end if
1094 
1095 end subroutine samp_compute_sampling_zs
1096 
1097 !----------------------------------------------------------------------
1098 ! Subroutine: samp_compute_sampling_ps
1099 ! Purpose: compute positive separation sampling
1100 !----------------------------------------------------------------------
1101 subroutine samp_compute_sampling_ps(samp,mpl,rng,nam,geom)
1103 implicit none
1104 
1105 ! Passed variables
1106 class(samp_type),intent(inout) :: samp ! Sampling
1107 type(mpl_type),intent(inout) :: mpl ! MPI data
1108 type(rng_type),intent(inout) :: rng ! Random number generator
1109 type(nam_type),intent(in) :: nam ! Namelist
1110 type(geom_type),intent(in) :: geom ! Geometry
1111 
1112 ! Local variables
1113 integer :: irmaxloc,jc3,ic1,ir,ic0,jc0,i,nvc0,ivc0,icinf,icsup,ictest
1114 integer,allocatable :: vic0(:)
1115 real(kind_real) :: d
1116 real(kind_real),allocatable :: x(:),y(:),z(:),v1(:),v2(:),va(:),vp(:),t(:)
1117 logical :: found
1118 
1119 ! First class
1120 samp%c1c3_to_c0(:,1) = samp%c1_to_c0
1121 
1122 if (nam%nc3>1) then
1123  write(mpl%info,'(a7,a)',advance='no') '','Compute positive separation sampling: '
1124  call flush(mpl%info)
1125 
1126  ! Initialize
1127  do jc3=1,nam%nc3
1128  if (jc3/=1) call msi(samp%c1c3_to_c0(:,jc3))
1129  end do
1130 
1131  ! Define valid nodes vector
1132  nvc0 = count(samp%mask_hor_c0)
1133  allocate(vic0(nvc0))
1134  ivc0 = 0
1135  do ic0=1,geom%nc0
1136  if (samp%mask_hor_c0(ic0)) then
1137  ivc0 = ivc0+1
1138  vic0(ivc0) = ic0
1139  end if
1140  end do
1141 
1142  ! Sample classes of positive separation
1143  call mpl%prog_init(nam%nc3*nam%nc1)
1144  ir = 0
1145  irmaxloc = irmax
1146  do while ((.not.all(isnotmsi(samp%c1c3_to_c0))).and.(nvc0>1).and.(ir<=irmaxloc))
1147  ! Try a random point
1148  if (mpl%main) call rng%rand_integer(1,nvc0,i)
1149  call mpl%f_comm%broadcast(i,mpl%ioproc-1)
1150  ir = ir+1
1151  jc0 = vic0(i)
1152 
1153  !$omp parallel do schedule(static) private(ic1,ic0,d,jc3,icinf,icsup,found,ictest) firstprivate(x,y,z,v1,v2,va,vp,t)
1154  do ic1=1,nam%nc1
1155  ! Allocation
1156  allocate(x(2))
1157  allocate(y(2))
1158  allocate(z(2))
1159  allocate(v1(3))
1160  allocate(v2(3))
1161  allocate(va(3))
1162  allocate(vp(3))
1163  allocate(t(4))
1164 
1165  ! Check if there is a valid first point
1166  if (isnotmsi(samp%c1_to_c0(ic1))) then
1167  ! Compute the distance
1168  ic0 = samp%c1_to_c0(ic1)
1169  call sphere_dist(geom%lon(ic0),geom%lat(ic0),geom%lon(jc0),geom%lat(jc0),d)
1170 
1171  ! Find the class (dichotomy method)
1172  if ((d>0.0).and.(d<(real(nam%nc3,kind_real)-0.5)*nam%dc)) then
1173  jc3 = 1
1174  icinf = 1
1175  icsup = nam%nc3
1176  found = .false.
1177  do while (.not.found)
1178  ! New value
1179  ictest = (icsup+icinf)/2
1180 
1181  ! Update
1182  if (d<(real(ictest,kind_real)-0.5)*nam%dc) icsup = ictest
1183  if (d>(real(ictest,kind_real)-0.5)*nam%dc) icinf = ictest
1184 
1185  ! Exit test
1186  if (icsup==icinf+1) then
1187  if (abs((real(icinf,kind_real)-0.5)*nam%dc-d)<abs((real(icsup,kind_real)-0.5)*nam%dc-d)) then
1188  jc3 = icinf
1189  else
1190  jc3 = icsup
1191  end if
1192  found = .true.
1193  end if
1194  end do
1195 
1196  ! Find if this class has not been aready filled
1197  if ((jc3/=1).and.(ismsi(samp%c1c3_to_c0(ic1,jc3)))) samp%c1c3_to_c0(ic1,jc3) = jc0
1198  end if
1199  end if
1200 
1201  ! Release memory
1202  deallocate(x)
1203  deallocate(y)
1204  deallocate(z)
1205  deallocate(v1)
1206  deallocate(v2)
1207  deallocate(va)
1208  deallocate(vp)
1209  deallocate(t)
1210  end do
1211  !$omp end parallel do
1212 
1213  ! Update valid nodes vector
1214  vic0(i) = vic0(nvc0)
1215  nvc0 = nvc0-1
1216 
1217  ! Update
1218  mpl%done = pack(isnotmsi(samp%c1c3_to_c0),mask=.true.)
1219  call mpl%prog_print
1220  end do
1221  write(mpl%info,'(a)') '100%'
1222  call flush(mpl%info)
1223 
1224  ! Release memory
1225  deallocate(vic0)
1226 end if
1227 
1228 end subroutine samp_compute_sampling_ps
1229 
1230 !----------------------------------------------------------------------
1231 ! Subroutine: samp_compute_sampling_lct
1232 ! Purpose: compute LCT sampling
1233 !----------------------------------------------------------------------
1234 subroutine samp_compute_sampling_lct(samp,mpl,nam,geom)
1236 implicit none
1237 
1238 ! Passed variables
1239 class(samp_type),intent(inout) :: samp ! Sampling
1240 type(mpl_type),intent(inout) :: mpl ! MPI data
1241 type(nam_type),intent(in) :: nam ! Namelist
1242 type(geom_type),intent(in) :: geom ! Geometry
1243 
1244 ! Local variables
1245 integer :: i,il0,ic1,ic0,jc0,ibnd,ic3
1246 integer :: nn_index(nam%nc3)
1247 integer :: iproc,ic1_s(mpl%nproc),ic1_e(mpl%nproc),nc1_loc(mpl%nproc),ic1_loc
1248 integer,allocatable :: sbufi(:),rbufi(:)
1249 real(kind_real) :: nn_dist(nam%nc3)
1250 real(kind_real),allocatable :: x(:),y(:),z(:),v1(:),v2(:),va(:),vp(:),t(:)
1251 logical,allocatable :: sbufl(:),rbufl(:)
1252 type(fckit_mpi_status) :: status
1253 
1254 write(mpl%info,'(a7,a)',advance='no') '','Compute LCT sampling: '
1255 call flush(mpl%info)
1256 
1257 ! MPI splitting
1258 call mpl%split(nam%nc1,ic1_s,ic1_e,nc1_loc)
1259 
1260 ! Initialization
1261 call mpl%prog_init(nc1_loc(mpl%myproc))
1262 
1263 do ic1_loc=1,nc1_loc(mpl%myproc)
1264  ! MPI offset
1265  ic1 = ic1_s(mpl%myproc)+ic1_loc-1
1266 
1267  ! Check location validity
1268  if (isnotmsi(samp%c1_to_c0(ic1))) then
1269  ! Find neighbors
1270  call geom%kdtree%find_nearest_neighbors(geom%lon(samp%c1_to_c0(ic1)),geom%lat(samp%c1_to_c0(ic1)), &
1271  & nam%nc3,nn_index,nn_dist)
1272 
1273  ! Copy neighbor index
1274  do ic3=1,nam%nc3
1275  jc0 = nn_index(ic3)
1276  samp%c1c3_to_c0(ic1,ic3) = nn_index(ic3)
1277  do il0=1,geom%nl0
1278  samp%c1c3l0_log(ic1,ic3,il0) = samp%mask_c0(jc0,il0)
1279  end do
1280  end do
1281 
1282  if (nam%mask_check) then
1283  ! Check that great circle to neighbors is not crossing mask boundaries
1284  do il0=1,geom%nl0
1285  !$omp parallel do schedule(static) private(ic3,ic0,jc0) firstprivate(x,y,z,v1,v2,va,vp,t)
1286  do ic3=1,nam%nc3
1287  ! Allocation
1288  allocate(x(2))
1289  allocate(y(2))
1290  allocate(z(2))
1291  allocate(v1(3))
1292  allocate(v2(3))
1293  allocate(va(3))
1294  allocate(vp(3))
1295  allocate(t(4))
1296 
1297  ! Indices
1298  ic0 = samp%c1_to_c0(ic1)
1299  jc0 = samp%c1c3_to_c0(ic1,ic3)
1300 
1301  ! Transform to cartesian coordinates
1302  call trans(2,geom%lat((/ic0,jc0/)),geom%lon((/ic0,jc0/)),x,y,z)
1303 
1304  ! Compute arc orthogonal vector
1305  v1 = (/x(1),y(1),z(1)/)
1306  v2 = (/x(2),y(2),z(2)/)
1307  call vector_product(v1,v2,va)
1308 
1309  ! Check if arc is crossing boundary arcs
1310  do ibnd=1,geom%nbnd(il0)
1311  call vector_product(va,geom%vbnd(:,ibnd,il0),vp)
1312  v1 = (/x(1),y(1),z(1)/)
1313  call vector_triple_product(v1,va,vp,t(1))
1314  v1 = (/x(2),y(2),z(2)/)
1315  call vector_triple_product(v1,va,vp,t(2))
1316  v1 = (/geom%xbnd(1,ibnd,il0),geom%ybnd(1,ibnd,il0),geom%zbnd(1,ibnd,il0)/)
1317  call vector_triple_product(v1,geom%vbnd(:,ibnd,il0),vp,t(3))
1318  v1 = (/geom%xbnd(2,ibnd,il0),geom%ybnd(2,ibnd,il0),geom%zbnd(2,ibnd,il0)/)
1319  call vector_triple_product(v1,geom%vbnd(:,ibnd,il0),vp,t(4))
1320  t(1) = -t(1)
1321  t(3) = -t(3)
1322  if (all(t>0).or.(all(t<0))) then
1323  samp%c1c3l0_log(ic1,ic3,il0) = .false.
1324  exit
1325  end if
1326  end do
1327 
1328  ! Memory release
1329  deallocate(x)
1330  deallocate(y)
1331  deallocate(z)
1332  deallocate(v1)
1333  deallocate(v2)
1334  deallocate(va)
1335  deallocate(vp)
1336  deallocate(t)
1337  end do
1338  !$omp end parallel do
1339  end do
1340  end if
1341  end if
1342 
1343  ! Update
1344  call mpl%prog_print(ic1_loc)
1345 end do
1346 write(mpl%info,'(a)') '100%'
1347 call flush(mpl%info)
1348 
1349 ! Communication
1350 write(mpl%info,'(a7,a)') '','Communication'
1351 call flush(mpl%info)
1352 if (mpl%main) then
1353  do iproc=1,mpl%nproc
1354  if (iproc/=mpl%ioproc) then
1355  ! Allocation
1356  allocate(rbufi(nc1_loc(iproc)*nam%nc3))
1357  allocate(rbufl(nc1_loc(iproc)*nam%nc3*geom%nl0))
1358 
1359  ! Receive data on ioproc
1360  call mpl%f_comm%receive(rbufi,iproc-1,mpl%tag,status)
1361  call mpl%f_comm%receive(rbufl,iproc-1,mpl%tag+1,status)
1362 
1363  ! Format data
1364  i = 0
1365  do ic3=1,nam%nc3
1366  do ic1_loc=1,nc1_loc(iproc)
1367  i = i+1
1368  ic1 = ic1_s(iproc)+ic1_loc-1
1369  samp%c1c3_to_c0(ic1,ic3) = rbufi(i)
1370  end do
1371  end do
1372  i = 0
1373  do il0=1,geom%nl0
1374  do ic3=1,nam%nc3
1375  do ic1_loc=1,nc1_loc(iproc)
1376  i = i+1
1377  ic1 = ic1_s(iproc)+ic1_loc-1
1378  samp%c1c3l0_log(ic1,ic3,il0) = rbufl(i)
1379  end do
1380  end do
1381  end do
1382 
1383  ! Release memory
1384  deallocate(rbufi)
1385  deallocate(rbufl)
1386  end if
1387  end do
1388 else
1389  ! Allocation
1390  allocate(sbufi(nc1_loc(mpl%myproc)*nam%nc3))
1391  allocate(sbufl(nc1_loc(mpl%myproc)*nam%nc3*geom%nl0))
1392 
1393  ! Prepare buffers
1394  i = 0
1395  do ic3=1,nam%nc3
1396  do ic1_loc=1,nc1_loc(mpl%myproc)
1397  i = i+1
1398  ic1 = ic1_s(mpl%myproc)+ic1_loc-1
1399  sbufi(i) = samp%c1c3_to_c0(ic1,ic3)
1400  end do
1401  end do
1402  i = 0
1403  do il0=1,geom%nl0
1404  do ic3=1,nam%nc3
1405  do ic1_loc=1,nc1_loc(mpl%myproc)
1406  i = i+1
1407  ic1 = ic1_s(mpl%myproc)+ic1_loc-1
1408  sbufl(i) = samp%c1c3l0_log(ic1,ic3,il0)
1409  end do
1410  end do
1411  end do
1412 
1413  ! Send data to ioproc
1414  call mpl%f_comm%send(sbufi,mpl%ioproc-1,mpl%tag)
1415  call mpl%f_comm%send(sbufl,mpl%ioproc-1,mpl%tag+1)
1416 
1417  ! Release memory
1418  deallocate(sbufi)
1419  deallocate(sbufl)
1420 end if
1421 call mpl%update_tag(2)
1422 call mpl%f_comm%broadcast(samp%c1c3_to_c0,mpl%ioproc-1)
1423 call mpl%f_comm%broadcast(samp%c1c3l0_log,mpl%ioproc-1)
1424 
1425 end subroutine samp_compute_sampling_lct
1426 
1427 !----------------------------------------------------------------------
1428 ! Subroutine: samp_compute_sampling_mask
1429 ! Purpose: compute sampling mask
1430 !----------------------------------------------------------------------
1431 subroutine samp_compute_sampling_mask(samp,mpl,nam,geom)
1433 implicit none
1434 
1435 ! Passed variables
1436 class(samp_type),intent(inout) :: samp ! Sampling
1437 type(mpl_type),intent(inout) :: mpl ! MPI data
1438 type(nam_type),intent(in) :: nam ! Namelist
1439 type(geom_type),intent(in) :: geom ! Geometry
1440 
1441 ! Local variables
1442 integer :: il0,jc3,ic1,ic0,jc0,i
1443 logical :: valid
1444 
1445 ! First point
1446 do il0=1,geom%nl0
1447  samp%c1l0_log(:,il0) = samp%mask_c0(samp%c1_to_c0,il0)
1448 end do
1449 
1450 ! Second point
1451 if (nam%mask_check) then
1452  write(mpl%info,'(a7,a)',advance='no') '','Check mask boundaries: '
1453  call mpl%prog_init(geom%nl0*nam%nc3*nam%nc1)
1454  i = 0
1455 end if
1456 do il0=1,geom%nl0
1457  do jc3=1,nam%nc3
1458  do ic1=1,nam%nc1
1459  ! Indices
1460  ic0 = samp%c1c3_to_c0(ic1,jc3)
1461  jc0 = samp%c1c3_to_c0(ic1,1)
1462 
1463  ! Check point index
1464  valid = isnotmsi(ic0).and.isnotmsi(jc0)
1465 
1466  if (valid) then
1467  ! Check mask
1468  valid = samp%mask_c0(ic0,il0).and.samp%mask_c0(jc0,il0)
1469 
1470  ! Check mask bounds
1471  if (nam%mask_check) then
1472  if (valid) call geom%check_arc(il0,geom%lon(ic0),geom%lat(ic0),geom%lon(jc0),geom%lat(jc0),valid)
1473  i = i+1
1474  call mpl%prog_print(i)
1475  end if
1476  end if
1477  samp%c1c3l0_log(ic1,jc3,il0) = valid
1478  end do
1479  end do
1480 end do
1481 if (nam%mask_check) then
1482  write(mpl%info,'(a)') '100%'
1483  call flush(mpl%info)
1484 end if
1485 
1486 end subroutine samp_compute_sampling_mask
1487 
1488 !----------------------------------------------------------------------
1489 ! Subroutine: samp_compute_mpi_a
1490 ! Purpose: compute sampling MPI distribution, halo A
1491 !----------------------------------------------------------------------
1492 subroutine samp_compute_mpi_a(samp,mpl,nam,geom)
1494 implicit none
1495 
1496 ! Passed variables
1497 class(samp_type),intent(inout) :: samp ! Sampling
1498 type(mpl_type),intent(in) :: mpl ! MPI data
1499 type(nam_type),intent(in) :: nam ! Namelist
1500 type(geom_type),intent(in) :: geom ! Geometry
1501 
1502 ! Local variables
1503 integer :: ic0a,ic0,ic1a,ic1
1504 
1505 ! Allocation
1506 allocate(samp%lcheck_c0a(geom%nc0))
1507 allocate(samp%lcheck_c1a(nam%nc1))
1508 
1509 ! Halo definitions
1510 
1511 ! Halo A
1512 samp%lcheck_c0a = .false.
1513 samp%lcheck_c1a = .false.
1514 do ic0a=1,geom%nc0a
1515  ic0 = geom%c0a_to_c0(ic0a)
1516  if (geom%c0_to_proc(ic0)==mpl%myproc) samp%lcheck_c0a(ic0) = .true.
1517 end do
1518 do ic1=1,nam%nc1
1519  ic0 = samp%c1_to_c0(ic1)
1520  if (geom%c0_to_proc(ic0)==mpl%myproc) samp%lcheck_c1a(ic1) = .true.
1521 end do
1522 
1523 ! Halo sizes
1524 samp%nc1a = count(samp%lcheck_c1a)
1525 
1526 ! Global <-> local conversions for fields
1527 
1528 ! Halo A
1529 allocate(samp%c1a_to_c1(samp%nc1a))
1530 allocate(samp%c1_to_c1a(nam%nc1))
1531 ic1a = 0
1532 do ic1=1,nam%nc1
1533  if (samp%lcheck_c1a(ic1)) then
1534  ic1a = ic1a+1
1535  samp%c1a_to_c1(ic1a) = ic1
1536  samp%c1_to_c1a(ic1) = ic1a
1537  end if
1538 end do
1539 
1540 ! Print results
1541 write(mpl%info,'(a7,a,i4)') '','Parameters for processor #',mpl%myproc
1542 write(mpl%info,'(a10,a,i8)') '','nc0 = ',geom%nc0
1543 write(mpl%info,'(a10,a,i8)') '','nc0a = ',geom%nc0a
1544 write(mpl%info,'(a10,a,i8)') '','nl0 = ',geom%nl0
1545 write(mpl%info,'(a10,a,i8)') '','nc1 = ',nam%nc1
1546 write(mpl%info,'(a10,a,i8)') '','nc1a = ',samp%nc1a
1547 call flush(mpl%info)
1548 
1549 end subroutine samp_compute_mpi_a
1550 
1551 !----------------------------------------------------------------------
1552 ! Subroutine: samp_compute_mpi_ab
1553 ! Purpose: compute sampling MPI distribution, halos A-B
1554 !----------------------------------------------------------------------
1555 subroutine samp_compute_mpi_ab(samp,mpl,nam,geom)
1557 implicit none
1558 
1559 ! Passed variables
1560 class(samp_type),intent(inout) :: samp ! Sampling
1561 type(mpl_type),intent(inout) :: mpl ! MPI data
1562 type(nam_type),intent(in) :: nam ! Namelist
1563 type(geom_type),intent(in) :: geom ! Geometry
1564 
1565 ! Local variables
1566 integer :: iproc,ic0,ic2a,ic2b,ic2,jc2,i_s,i_s_loc,h_n_s_max,il0i,h_n_s_max_loc
1567 integer,allocatable :: interph_lg(:,:)
1568 
1569 ! Allocation
1570 h_n_s_max = 0
1571 do il0i=1,geom%nl0i
1572  h_n_s_max = max(h_n_s_max,samp%hfull(il0i)%n_s)
1573 end do
1574 allocate(samp%c2_to_proc(nam%nc2))
1575 allocate(samp%proc_to_nc2a(mpl%nproc))
1576 allocate(samp%h(geom%nl0i))
1577 allocate(samp%lcheck_c2a(nam%nc2))
1578 allocate(samp%lcheck_c2b(nam%nc2))
1579 allocate(samp%lcheck_h(h_n_s_max,geom%nl0i))
1580 
1581 ! Halo definitions
1582 
1583 ! Halo A
1584 samp%lcheck_c2a = .false.
1585 do ic2=1,nam%nc2
1586  ic0 = samp%c2_to_c0(ic2)
1587  if (geom%c0_to_proc(ic0)==mpl%myproc) samp%lcheck_c2a(ic2) = .true.
1588 end do
1589 
1590 ! Halo B
1591 samp%lcheck_h = .false.
1592 samp%lcheck_c2b = .false.
1593 do il0i=1,geom%nl0i
1594  do i_s=1,samp%hfull(il0i)%n_s
1595  ic0 = samp%hfull(il0i)%row(i_s)
1596  iproc = geom%c0_to_proc(ic0)
1597  if (iproc==mpl%myproc) then
1598  jc2 = samp%hfull(il0i)%col(i_s)
1599  samp%lcheck_h(i_s,il0i) = .true.
1600  samp%lcheck_c2b(jc2) = .true.
1601  end if
1602  end do
1603 end do
1604 
1605 ! Halo sizes
1606 samp%nc2a = count(samp%lcheck_c2a)
1607 do il0i=1,geom%nl0i
1608  samp%h(il0i)%n_s = count(samp%lcheck_h(:,il0i))
1609 end do
1610 samp%nc2b = count(samp%lcheck_c2b)
1611 
1612 ! Global <-> local conversions for fields
1613 
1614 ! Halo A
1615 allocate(samp%c2a_to_c2(samp%nc2a))
1616 allocate(samp%c2_to_c2a(nam%nc2))
1617 ic2a = 0
1618 do ic2=1,nam%nc2
1619  if (samp%lcheck_c2a(ic2)) then
1620  ic2a = ic2a+1
1621  samp%c2a_to_c2(ic2a) = ic2
1622  end if
1623 end do
1624 call mpl%glb_to_loc_index(samp%nc2a,samp%c2a_to_c2,nam%nc2,samp%c2_to_c2a)
1625 
1626 ! Halo B
1627 allocate(samp%c2b_to_c2(samp%nc2b))
1628 allocate(samp%c2_to_c2b(nam%nc2))
1629 ic2b = 0
1630 do ic2=1,nam%nc2
1631  if (samp%lcheck_c2b(ic2)) then
1632  ic2b = ic2b+1
1633  samp%c2b_to_c2(ic2b) = ic2
1634  samp%c2_to_c2b(ic2) = ic2b
1635  end if
1636 end do
1637 
1638 ! Inter-halo conversions
1639 allocate(samp%c2a_to_c2b(samp%nc2a))
1640 do ic2a=1,samp%nc2a
1641  ic2 = samp%c2a_to_c2(ic2a)
1642  ic2b = samp%c2_to_c2b(ic2)
1643  samp%c2a_to_c2b(ic2a) = ic2b
1644 end do
1645 
1646 ! Global <-> local conversions for data
1647 h_n_s_max_loc = 0
1648 do il0i=1,geom%nl0i
1649  h_n_s_max_loc = max(h_n_s_max_loc,samp%h(il0i)%n_s)
1650 end do
1651 allocate(interph_lg(h_n_s_max_loc,geom%nl0i))
1652 do il0i=1,geom%nl0i
1653  i_s_loc = 0
1654  do i_s=1,samp%hfull(il0i)%n_s
1655  if (samp%lcheck_h(i_s,il0i)) then
1656  i_s_loc = i_s_loc+1
1657  interph_lg(i_s_loc,il0i) = i_s
1658  end if
1659  end do
1660 end do
1661 
1662 ! Local data
1663 
1664 ! Horizontal interpolation
1665 do il0i=1,geom%nl0i
1666  write(samp%h(il0i)%prefix,'(a,i3.3)') 'h_',il0i
1667  samp%h(il0i)%n_src = samp%nc2b
1668  samp%h(il0i)%n_dst = geom%nc0a
1669  call samp%h(il0i)%alloc
1670  do i_s_loc=1,samp%h(il0i)%n_s
1671  i_s = interph_lg(i_s_loc,il0i)
1672  samp%h(il0i)%row(i_s_loc) = geom%c0_to_c0a(samp%hfull(il0i)%row(i_s))
1673  samp%h(il0i)%col(i_s_loc) = samp%c2_to_c2b(samp%hfull(il0i)%col(i_s))
1674  samp%h(il0i)%S(i_s_loc) = samp%hfull(il0i)%S(i_s)
1675  end do
1676  call samp%h(il0i)%reorder(mpl)
1677 end do
1678 
1679 ! MPI splitting
1680 do ic2=1,nam%nc2
1681  ic0 = samp%c2_to_c0(ic2)
1682  samp%c2_to_proc(ic2) = geom%c0_to_proc(ic0)
1683 end do
1684 do iproc=1,mpl%nproc
1685  samp%proc_to_nc2a(iproc) = count(samp%c2_to_proc==iproc)
1686 end do
1687 
1688 ! Setup communications
1689 call samp%com_AB%setup(mpl,'com_AB',nam%nc2,samp%nc2a,samp%nc2b,samp%c2b_to_c2,samp%c2a_to_c2b,samp%c2_to_proc, &
1690  & samp%c2_to_c2a)
1691 
1692 ! Print results
1693 write(mpl%info,'(a7,a,i4)') '','Parameters for processor #',mpl%myproc
1694 write(mpl%info,'(a10,a,i8)') '','nc2 = ',nam%nc2
1695 write(mpl%info,'(a10,a,i8)') '','nc2a = ',samp%nc2a
1696 write(mpl%info,'(a10,a,i8)') '','nc2b = ',samp%nc2b
1697 do il0i=1,geom%nl0i
1698  write(mpl%info,'(a10,a,i3,a,i8)') '','h(',il0i,')%n_s = ',samp%h(il0i)%n_s
1699 end do
1700 call flush(mpl%info)
1701 
1702 end subroutine samp_compute_mpi_ab
1703 
1704 !----------------------------------------------------------------------
1705 ! Subroutine: samp_compute_mpi_d
1706 ! Purpose: compute sampling MPI distribution, halo D
1707 !----------------------------------------------------------------------
1708 subroutine samp_compute_mpi_d(samp,mpl,nam,geom)
1710 implicit none
1711 
1712 ! Passed variables
1713 class(samp_type),intent(inout) :: samp ! Sampling
1714 type(mpl_type),intent(inout) :: mpl ! MPI data
1715 type(nam_type),intent(in) :: nam ! Namelist
1716 type(geom_type),intent(in) :: geom ! Geometry
1717 
1718 ! Local variables
1719 integer :: ic0,ic0a,ic0d,ic1,ic2,ic2a,jc0,jc1
1720 
1721 ! Allocation
1722 allocate(samp%lcheck_c0d(geom%nc0))
1723 
1724 ! Halo definitions
1725 
1726 ! Halo D
1727 samp%lcheck_c0d = samp%lcheck_c0a
1728 do ic2a=1,samp%nc2a
1729  ic2 = samp%c2a_to_c2(ic2a)
1730  ic1 = samp%c2_to_c1(ic2)
1731  do jc1=1,nam%nc1
1732  if (samp%displ_mask(jc1,ic2)) then
1733  jc0 = samp%c1_to_c0(jc1)
1734  samp%lcheck_c0d(jc0) = .true.
1735  end if
1736  end do
1737 end do
1738 samp%nc0d = count(samp%lcheck_c0d)
1739 
1740 ! Global <-> local conversions for fields
1741 
1742 ! Halo D
1743 allocate(samp%c0d_to_c0(samp%nc0d))
1744 allocate(samp%c0_to_c0d(geom%nc0))
1745 call msi(samp%c0_to_c0d)
1746 ic0d = 0
1747 do ic0=1,geom%nc0
1748  if (samp%lcheck_c0d(ic0)) then
1749  ic0d = ic0d+1
1750  samp%c0d_to_c0(ic0d) = ic0
1751  samp%c0_to_c0d(ic0) = ic0d
1752  end if
1753 end do
1754 
1755 ! Inter-halo conversions
1756 allocate(samp%c0a_to_c0d(geom%nc0a))
1757 do ic0a=1,geom%nc0a
1758  ic0 = geom%c0a_to_c0(ic0a)
1759  ic0d = samp%c0_to_c0d(ic0)
1760  samp%c0a_to_c0d(ic0a) = ic0d
1761 end do
1762 
1763 ! Setup communications
1764 call samp%com_AD%setup(mpl,'com_AD',geom%nc0,geom%nc0a,samp%nc0d,samp%c0d_to_c0,samp%c0a_to_c0d,geom%c0_to_proc,geom%c0_to_c0a)
1765 
1766 ! Print results
1767 write(mpl%info,'(a7,a,i4)') '','Parameters for processor #',mpl%myproc
1768 write(mpl%info,'(a10,a,i8)') '','nc0d = ',samp%nc0d
1769 call flush(mpl%info)
1770 
1771 end subroutine samp_compute_mpi_d
1772 
1773 !----------------------------------------------------------------------
1774 ! Subroutine: samp_compute_mpi_c
1775 ! Purpose: compute sampling MPI distribution, halo C
1776 !----------------------------------------------------------------------
1777 subroutine samp_compute_mpi_c(samp,mpl,nam,geom)
1779 implicit none
1780 
1781 ! Passed variables
1782 class(samp_type),intent(inout) :: samp ! Sampling
1783 type(mpl_type),intent(inout) :: mpl ! MPI data
1784 type(nam_type),intent(in) :: nam ! Namelist
1785 type(geom_type),intent(in) :: geom ! Geometry
1786 
1787 ! Local variables
1788 integer :: jc3,ic0,ic0a,ic0c,ic1,ic1a,its,il0,d_n_s_max,d_n_s_max_loc,i_s,i_s_loc
1789 integer,allocatable :: interpd_lg(:,:,:)
1790 real(kind_real),allocatable :: displ_lon(:,:),displ_lat(:,:),lon_c1(:),lat_c1(:)
1791 type(linop_type),allocatable :: dfull(:,:)
1792 
1793 if (nam%displ_diag) then
1794  ! Allocation
1795  allocate(dfull(geom%nl0,nam%nts))
1796  allocate(displ_lon(geom%nc0,geom%nl0))
1797  allocate(displ_lat(geom%nc0,geom%nl0))
1798  allocate(lon_c1(nam%nc1))
1799  allocate(lat_c1(nam%nc1))
1800 
1801  ! Prepare displacement interpolation
1802  do its=1,nam%nts
1803  ! Local to global
1804  call mpl%loc_to_glb(geom%nl0,geom%nc0a,samp%displ_lon(:,:,its),geom%nc0,geom%c0_to_proc,geom%c0_to_c0a,.true.,displ_lon)
1805  call mpl%loc_to_glb(geom%nl0,geom%nc0a,samp%displ_lat(:,:,its),geom%nc0,geom%c0_to_proc,geom%c0_to_c0a,.true.,displ_lat)
1806 
1807  do il0=1,geom%nl0
1808  ! Copy Sc1 points
1809  do ic1=1,nam%nc1
1810  ic0 = samp%c1_to_c0(ic1)
1811  lon_c1(ic1) = displ_lon(ic0,il0)
1812  lat_c1(ic1) = displ_lat(ic0,il0)
1813  end do
1814 
1815  ! Compute interpolation
1816  call dfull(il0,its)%interp(mpl,geom%mesh,geom%kdtree,geom%nc0,geom%mask_c0(:,il0),nam%nc1,lon_c1,lat_c1, &
1817  & samp%c1l0_log(:,il0),nam%diag_interp)
1818  end do
1819  end do
1820 end if
1821 
1822 ! Allocation
1823 if (nam%displ_diag) then
1824  d_n_s_max = 0
1825  do its=1,nam%nts
1826  do il0=1,geom%nl0
1827  d_n_s_max = max(d_n_s_max,dfull(il0,its)%n_s)
1828  end do
1829  end do
1830  allocate(samp%lcheck_d(d_n_s_max,geom%nl0,nam%nts))
1831  allocate(samp%d(geom%nl0,nam%nts))
1832 end if
1833 allocate(samp%lcheck_c0c(geom%nc0))
1834 
1835 ! Halo C
1836 samp%lcheck_c0c = samp%lcheck_c0a
1837 do jc3=1,nam%nc3
1838  do ic1a=1,samp%nc1a
1839  ic1 = samp%c1a_to_c1(ic1a)
1840  if (any(samp%c1c3l0_log(ic1,jc3,:))) then
1841  ic0 = samp%c1c3_to_c0(ic1,jc3)
1842  samp%lcheck_c0c(ic0) = .true.
1843  end if
1844  end do
1845 end do
1846 if (nam%displ_diag) then
1847  samp%lcheck_d = .false.
1848  do its=1,nam%nts
1849  do il0=1,geom%nl0
1850  do i_s=1,dfull(il0,its)%n_s
1851  ic0 = dfull(il0,its)%col(i_s)
1852  ic1 = dfull(il0,its)%row(i_s)
1853  if (samp%lcheck_c1a(ic1)) then
1854  samp%lcheck_c0c(ic0) = .true.
1855  samp%lcheck_d(i_s,il0,its) = .true.
1856  end if
1857  end do
1858  end do
1859  end do
1860 end if
1861 samp%nc0c = count(samp%lcheck_c0c)
1862 if (nam%displ_diag) then
1863  do its=1,nam%nts
1864  do il0=1,geom%nl0
1865  samp%d(il0,its)%n_s = count(samp%lcheck_d(:,il0,its))
1866  end do
1867  end do
1868 end if
1869 
1870 ! Global <-> local conversions for fields
1871 
1872 ! Halo C
1873 allocate(samp%c0c_to_c0(samp%nc0c))
1874 allocate(samp%c0_to_c0c(geom%nc0))
1875 call msi(samp%c0_to_c0c)
1876 ic0c = 0
1877 do ic0=1,geom%nc0
1878  if (samp%lcheck_c0c(ic0)) then
1879  ic0c = ic0c+1
1880  samp%c0c_to_c0(ic0c) = ic0
1881  samp%c0_to_c0c(ic0) = ic0c
1882  end if
1883 end do
1884 
1885 ! Inter-halo conversions
1886 allocate(samp%c0a_to_c0c(geom%nc0a))
1887 do ic0a=1,geom%nc0a
1888  ic0 = geom%c0a_to_c0(ic0a)
1889  ic0c = samp%c0_to_c0c(ic0)
1890  samp%c0a_to_c0c(ic0a) = ic0c
1891 end do
1892 
1893 if (nam%displ_diag) then
1894  ! Global <-> local conversions for data
1895  d_n_s_max_loc = 0
1896  do its=1,nam%nts
1897  do il0=1,geom%nl0
1898  d_n_s_max_loc = max(d_n_s_max_loc,samp%d(il0,its)%n_s)
1899  end do
1900  end do
1901  allocate(interpd_lg(d_n_s_max_loc,geom%nl0,nam%nts))
1902  do its=1,nam%nts
1903  do il0=1,geom%nl0
1904  i_s_loc = 0
1905  do i_s=1,dfull(il0,its)%n_s
1906  if (samp%lcheck_d(i_s,il0,its)) then
1907  i_s_loc = i_s_loc+1
1908  interpd_lg(i_s_loc,il0,its) = i_s
1909  end if
1910  end do
1911  end do
1912  end do
1913 
1914  ! Local data
1915  do its=1,nam%nts
1916  do il0=1,geom%nl0
1917  write(samp%d(il0,its)%prefix,'(a,i3.3,a,i2.2)') 'd_',il0,'_',its
1918  samp%d(il0,its)%n_src = samp%nc0c
1919  samp%d(il0,its)%n_dst = samp%nc1a
1920  call samp%d(il0,its)%alloc
1921  do i_s_loc=1,samp%d(il0,its)%n_s
1922  i_s = interpd_lg(i_s_loc,il0,its)
1923  samp%d(il0,its)%row(i_s_loc) = samp%c1_to_c1a(dfull(il0,its)%row(i_s))
1924  samp%d(il0,its)%col(i_s_loc) = samp%c0_to_c0c(dfull(il0,its)%col(i_s))
1925  samp%d(il0,its)%S(i_s_loc) = dfull(il0,its)%S(i_s)
1926  end do
1927  call samp%d(il0,its)%reorder(mpl)
1928  end do
1929  end do
1930 end if
1931 
1932 ! Setup communications
1933 call samp%com_AC%setup(mpl,'com_AC',geom%nc0,geom%nc0a,samp%nc0c,samp%c0c_to_c0,samp%c0a_to_c0c,geom%c0_to_proc,geom%c0_to_c0a)
1934 
1935 ! Print results
1936 write(mpl%info,'(a7,a,i4)') '','Parameters for processor #',mpl%myproc
1937 write(mpl%info,'(a10,a,i8)') '','nc0c = ',samp%nc0c
1938 call flush(mpl%info)
1939 
1940 end subroutine samp_compute_mpi_c
1941 
1942 !----------------------------------------------------------------------
1943 ! Subroutine: samp_compute_mpi_f
1944 ! Purpose: compute sampling MPI distribution, halo F
1945 !----------------------------------------------------------------------
1946 subroutine samp_compute_mpi_f(samp,mpl,nam,geom)
1948 implicit none
1949 
1950 ! Passed variables
1951 class(samp_type),intent(inout) :: samp ! Sampling
1952 type(mpl_type),intent(inout) :: mpl ! MPI data
1953 type(nam_type),intent(in) :: nam ! Namelist
1954 type(geom_type),intent(in) :: geom ! Geometry
1955 
1956 ! Local variables
1957 integer :: ic2,ic1,jc2,ic2a,ic2f,il0,kc2
1958 
1959 ! Allocation
1960 allocate(samp%lcheck_c2f(nam%nc2))
1961 
1962 ! Halo definitions
1963 
1964 ! Halo F
1965 do il0=1,geom%nl0
1966  samp%lcheck_c2f = samp%lcheck_c2a
1967  do ic2a=1,samp%nc2a
1968  ic2 = samp%c2a_to_c2(ic2a)
1969  ic1 = samp%c2_to_c1(ic2)
1970  jc2 = 1
1971  do while (samp%nn_c2_dist(jc2,ic2,min(il0,geom%nl0i))<nam%diag_rhflt)
1972  kc2 = samp%nn_c2_index(jc2,ic2,min(il0,geom%nl0i))
1973  samp%lcheck_c2f(kc2) = .true.
1974  jc2 = jc2+1
1975  if (jc2>nam%nc2) exit
1976  end do
1977  end do
1978 end do
1979 samp%nc2f = count(samp%lcheck_c2f)
1980 
1981 ! Global <-> local conversions for fields
1982 
1983 ! Halo F
1984 allocate(samp%c2f_to_c2(samp%nc2f))
1985 allocate(samp%c2_to_c2f(nam%nc2))
1986 call msi(samp%c2_to_c2f)
1987 ic2f = 0
1988 do ic2=1,nam%nc2
1989  if (samp%lcheck_c2f(ic2)) then
1990  ic2f = ic2f+1
1991  samp%c2f_to_c2(ic2f) = ic2
1992  samp%c2_to_c2f(ic2) = ic2f
1993  end if
1994 end do
1995 
1996 ! Inter-halo conversions
1997 allocate(samp%c2a_to_c2f(samp%nc2a))
1998 do ic2a=1,samp%nc2a
1999  ic2 = samp%c2a_to_c2(ic2a)
2000  ic2f = samp%c2_to_c2f(ic2)
2001  samp%c2a_to_c2f(ic2a) = ic2f
2002 end do
2003 
2004 ! Setup communications
2005 call samp%com_AF%setup(mpl,'com_AF',nam%nc2,samp%nc2a,samp%nc2f,samp%c2f_to_c2,samp%c2a_to_c2f,samp%c2_to_proc, &
2006  & samp%c2_to_c2a)
2007 
2008 ! Print results
2009 write(mpl%info,'(a7,a,i4)') '','Parameters for processor #',mpl%myproc
2010 write(mpl%info,'(a10,a,i8)') '','nc2f = ',samp%nc2f
2011 call flush(mpl%info)
2012 
2013 end subroutine samp_compute_mpi_f
2014 
2015 !----------------------------------------------------------------------
2016 ! Subroutine: samp_diag_filter
2017 ! Purpose: filter diagnostics
2018 !----------------------------------------------------------------------
2019 subroutine samp_diag_filter(samp,mpl,nam,geom,il0,filter_type,rflt,diag)
2021 implicit none
2022 
2023 ! Passed variables
2024 class(samp_type),intent(in) :: samp ! Sampling
2025 type(mpl_type),intent(inout) :: mpl ! MPI data
2026 type(nam_type),intent(in) :: nam ! Namelist
2027 type(geom_type),intent(in) :: geom ! Geometry
2028 integer,intent(in) :: il0 ! Level
2029 character(len=*),intent(in) :: filter_type ! Filter type
2030 real(kind_real),intent(in) :: rflt ! Filter support radius
2031 real(kind_real),intent(inout) :: diag(samp%nc2a) ! Filtered diagnostic
2032 
2033 ! Local variables
2034 integer :: ic2a,ic2,ic1,jc2,nc2eff,kc2,kc2_glb
2035 integer,allocatable :: order(:)
2036 real(kind_real) :: distnorm,norm,wgt
2037 real(kind_real),allocatable :: diag_glb(:),diag_eff(:),diag_eff_dist(:)
2038 logical :: nam_rad
2039 
2040 ! Check radius
2041 nam_rad = .not.(abs(rflt-nam%diag_rhflt)>0.0)
2042 
2043 if (rflt>0.0) then
2044  if (nam_rad) then
2045  ! Allocation
2046  allocate(diag_glb(samp%nc2f))
2047 
2048  ! Communication
2049  call samp%com_AF%ext(mpl,diag,diag_glb)
2050  else
2051  ! Allocation
2052  allocate(diag_glb(nam%nc2))
2053 
2054  ! Local to global
2055  call mpl%loc_to_glb(samp%nc2a,diag,nam%nc2,samp%c2_to_proc,samp%c2_to_c2a,.true.,diag_glb)
2056  end if
2057 
2058  !$omp parallel do schedule(static) private(ic2a,ic2,ic1,nc2eff,jc2,distnorm,norm,wgt) firstprivate(diag_eff,diag_eff_dist,order)
2059  do ic2a=1,samp%nc2a
2060  ! Indices
2061  ic2 = samp%c2a_to_c2(ic2a)
2062  ic1 = samp%c2_to_c1(ic2)
2063 
2064  ! Allocation
2065  allocate(diag_eff(nam%nc2))
2066  allocate(diag_eff_dist(nam%nc2))
2067 
2068  ! Build diag_eff of valid points
2069  nc2eff = 0
2070  jc2 = 1
2071  do while (samp%nn_c2_dist(jc2,ic2,min(il0,geom%nl0i))<rflt)
2072  ! Check the point validity
2073  kc2 = samp%nn_c2_index(jc2,ic2,min(il0,geom%nl0i))
2074  if (nam_rad) then
2075  kc2_glb = samp%c2_to_c2f(kc2)
2076  else
2077  kc2_glb = kc2
2078  end if
2079  if (isnotmsr(diag_glb(kc2_glb))) then
2080  nc2eff = nc2eff+1
2081  diag_eff(nc2eff) = diag_glb(kc2_glb)
2082  diag_eff_dist(nc2eff) = samp%nn_c2_dist(jc2,ic2,min(il0,geom%nl0i))
2083  end if
2084  jc2 = jc2+1
2085  if (jc2>nam%nc2) exit
2086  end do
2087 
2088  ! Apply filter
2089  if (nc2eff>0) then
2090  select case (trim(filter_type))
2091  case ('average')
2092  ! Compute average
2093  diag(ic2a) = sum(diag_eff(1:nc2eff))/real(nc2eff,kind_real)
2094  case ('gc99')
2095  ! Gaspari-Cohn (1999) kernel
2096  diag(ic2a) = 0.0
2097  norm = 0.0
2098  do jc2=1,nc2eff
2099  distnorm = diag_eff_dist(jc2)/rflt
2100  wgt = gc99(mpl,distnorm)
2101  diag(ic2a) = diag(ic2a)+wgt*diag_eff(jc2)
2102  norm = norm+wgt
2103  end do
2104  if (norm>0.0) diag(ic2a) = diag(ic2a)/norm
2105  case ('median')
2106  ! Compute median
2107  allocate(order(nc2eff))
2108  call qsort(nc2eff,diag_eff(1:nc2eff),order)
2109  if (mod(nc2eff,2)==0) then
2110  diag(ic2a) = 0.5*(diag_eff(nc2eff/2)+diag_eff(nc2eff/2+1))
2111  else
2112  diag(ic2a) = diag_eff((nc2eff+1)/2)
2113  end if
2114  deallocate(order)
2115  case default
2116  ! Wrong filter
2117  call mpl%abort('wrong filter type')
2118  end select
2119  else
2120  call msr(diag(ic2a))
2121  end if
2122 
2123  ! Release memory
2124  deallocate(diag_eff)
2125  deallocate(diag_eff_dist)
2126  end do
2127  !$omp end parallel do
2128 end if
2129 
2130 end subroutine samp_diag_filter
2131 
2132 !----------------------------------------------------------------------
2133 ! Subroutine: samp_diag_fill
2134 ! Purpose: fill diagnostics missing values
2135 !----------------------------------------------------------------------
2136 subroutine samp_diag_fill(samp,mpl,nam,geom,il0,diag)
2138 implicit none
2139 
2140 ! Passed variables
2141 class(samp_type),intent(in) :: samp ! Sampling
2142 type(mpl_type),intent(inout) :: mpl ! MPI data
2143 type(nam_type),intent(in) :: nam ! Namelist
2144 type(geom_type),intent(in) :: geom ! Geometry
2145 integer,intent(in) :: il0 ! Level
2146 real(kind_real),intent(inout) :: diag(samp%nc2a) ! Filtered diagnostic
2147 
2148 ! Local variables
2149 integer :: nmsr,nmsr_tot,ic2,jc2,kc2
2150 real(kind_real),allocatable :: diag_glb(:)
2151 
2152 ! Count missing points
2153 if (samp%nc2a>0) then
2154  nmsr = count(ismsr(diag))
2155 else
2156  nmsr = 0
2157 end if
2158 call mpl%f_comm%allreduce(nmsr,nmsr_tot,fckit_mpi_sum())
2159 
2160 if (nmsr_tot>0) then
2161  ! Allocation
2162  allocate(diag_glb(nam%nc2))
2163 
2164  ! Local to global
2165  call mpl%loc_to_glb(samp%nc2a,diag,nam%nc2,samp%c2_to_proc,samp%c2_to_c2a,.false.,diag_glb)
2166 
2167  if (mpl%main) then
2168  do ic2=1,nam%nc2
2169  jc2 = 1
2170  do while (ismsr(diag_glb(ic2)))
2171  kc2 = samp%nn_c2_index(jc2,ic2,min(il0,geom%nl0i))
2172  if (isnotmsr(diag_glb(kc2))) diag_glb(ic2) = diag_glb(kc2)
2173  jc2 = jc2+1
2174  if (jc2>nam%nc2) exit
2175  end do
2176  end do
2177  end if
2178 
2179  ! Global to local
2180  call mpl%glb_to_loc(nam%nc2,samp%c2_to_proc,samp%c2_to_c2a,diag_glb,samp%nc2a,diag)
2181 
2182  ! Release memory
2183  deallocate(diag_glb)
2184 end if
2185 
2186 end subroutine samp_diag_fill
2187 
2188 end module type_samp
real(kind_real), parameter lcoast
Definition: type_samp.F90:35
real(kind_real), parameter, public rad2deg
Definition: tools_const.F90:17
subroutine samp_dealloc(samp, geom)
Definition: type_samp.F90:202
subroutine samp_diag_filter(samp, mpl, nam, geom, il0, filter_type, rflt, diag)
Definition: type_samp.F90:2020
integer, parameter, public msvali
Definition: tools_const.F90:23
real(kind_real) function, public gc99(mpl, distnorm)
Definition: tools_func.F90:518
subroutine, public trans(n, rlat, rlon, x, y, z)
subroutine samp_read(samp, mpl, nam, geom, bpar, ios)
Definition: type_samp.F90:253
subroutine samp_compute_mpi_a(samp, mpl, nam, geom)
Definition: type_samp.F90:1493
subroutine samp_compute_sampling_mask(samp, mpl, nam, geom)
Definition: type_samp.F90:1432
real(kind_real), parameter, public msvalr
Definition: tools_const.F90:24
subroutine, public vector_product(v1, v2, vp)
Definition: tools_func.F90:131
subroutine samp_alloc(samp, nam, geom)
Definition: type_samp.F90:140
real(kind_real), parameter rcoast
Definition: type_samp.F90:36
subroutine, public sphere_dist(lon_i, lat_i, lon_f, lat_f, dist)
Definition: tools_func.F90:67
integer, parameter irmax
Definition: type_samp.F90:34
subroutine samp_write(samp, mpl, nam, geom, bpar)
Definition: type_samp.F90:484
real(kind_real), parameter, public deg2rad
Definition: tools_const.F90:16
real(kind=kind_real), parameter req
Earth radius at equator (m)
subroutine samp_compute_mpi_f(samp, mpl, nam, geom)
Definition: type_samp.F90:1947
subroutine samp_compute_mpi_d(samp, mpl, nam, geom)
Definition: type_samp.F90:1709
subroutine samp_diag_fill(samp, mpl, nam, geom, il0, diag)
Definition: type_samp.F90:2137
subroutine samp_compute_mask(samp, mpl, nam, geom, ens)
Definition: type_samp.F90:955
subroutine samp_compute_sampling_zs(samp, mpl, rng, nam, geom)
Definition: type_samp.F90:1036
#define max(a, b)
Definition: mosaic_util.h:33
subroutine samp_setup_sampling(samp, mpl, rng, nam, geom, bpar, io, ens)
Definition: type_samp.F90:729
integer, parameter, public kind_real
#define min(a, b)
Definition: mosaic_util.h:32
subroutine samp_compute_sampling_lct(samp, mpl, nam, geom)
Definition: type_samp.F90:1235
subroutine, public vector_triple_product(v1, v2, v3, p)
Definition: tools_func.F90:158
subroutine samp_compute_sampling_ps(samp, mpl, rng, nam, geom)
Definition: type_samp.F90:1102
integer, parameter, public ncfloat
Definition: tools_nc.F90:27
subroutine samp_compute_mpi_ab(samp, mpl, nam, geom)
Definition: type_samp.F90:1556
subroutine samp_compute_mpi_c(samp, mpl, nam, geom)
Definition: type_samp.F90:1778
real(fp), parameter, public pi