24 use fckit_mpi_module,
only: fckit_mpi_sum,fckit_mpi_min,fckit_mpi_max,fckit_mpi_status
38 integer,
allocatable :: c0_to_lon(:)
39 integer,
allocatable :: c0_to_lat(:)
40 integer,
allocatable :: c0_to_tile(:)
49 real(kind_real),
allocatable :: lon(:)
50 real(kind_real),
allocatable :: lat(:)
51 real(kind_real),
allocatable :: area(:)
52 real(kind_real),
allocatable :: vunit(:,:)
53 real(kind_real),
allocatable :: vunitavg(:)
54 real(kind_real),
allocatable :: disth(:)
57 logical,
allocatable :: mask_hor_mg(:)
58 logical,
allocatable :: mask_c0(:,:)
59 logical,
allocatable :: mask_c0a(:,:)
60 logical,
allocatable :: mask_hor_c0(:)
61 logical,
allocatable :: mask_hor_c0a(:)
62 logical,
allocatable :: mask_ver_c0(:)
63 integer,
allocatable :: nc0_mask(:)
73 integer,
allocatable :: nbnd(:)
74 real(kind_real),
allocatable :: xbnd(:,:,:)
75 real(kind_real),
allocatable :: ybnd(:,:,:)
76 real(kind_real),
allocatable :: zbnd(:,:,:)
77 real(kind_real),
allocatable :: vbnd(:,:,:)
80 integer,
allocatable :: redundant(:)
81 integer,
allocatable :: c0_to_mg(:)
82 integer,
allocatable :: mg_to_c0(:)
86 real(kind_real),
allocatable :: londir(:)
87 real(kind_real),
allocatable :: latdir(:)
88 integer,
allocatable :: iprocdir(:)
89 integer,
allocatable :: ic0adir(:)
90 integer,
allocatable :: il0dir(:)
91 integer,
allocatable :: ivdir(:)
92 integer,
allocatable :: itsdir(:)
97 integer,
allocatable :: mg_to_proc(:)
98 integer,
allocatable :: mg_to_mga(:)
99 integer,
allocatable :: mga_to_mg(:)
100 integer,
allocatable :: proc_to_nmga(:)
101 integer,
allocatable :: c0_to_proc(:)
102 integer,
allocatable :: c0_to_c0a(:)
103 integer,
allocatable :: c0a_to_c0(:)
104 integer,
allocatable :: proc_to_nc0a(:)
105 integer,
allocatable :: mga_to_c0(:)
106 integer,
allocatable :: c0a_to_mga(:)
138 class(geom_type),
intent(inout) :: geom
141 allocate(geom%c0_to_proc(geom%nc0))
142 allocate(geom%c0_to_c0a(geom%nc0))
143 allocate(geom%c0_to_lon(geom%nc0))
144 allocate(geom%c0_to_lat(geom%nc0))
145 allocate(geom%c0_to_tile(geom%nc0))
146 allocate(geom%lon(geom%nc0))
147 allocate(geom%lat(geom%nc0))
148 allocate(geom%area(geom%nl0))
149 allocate(geom%vunit(geom%nc0,geom%nl0))
150 allocate(geom%vunitavg(geom%nl0))
151 allocate(geom%mask_c0(geom%nc0,geom%nl0))
152 allocate(geom%mask_hor_c0(geom%nc0))
153 allocate(geom%mask_ver_c0(geom%nl0))
154 allocate(geom%nc0_mask(geom%nl0))
157 call msi(geom%c0_to_proc)
158 call msi(geom%c0_to_c0a)
159 call msi(geom%c0_to_lon)
160 call msi(geom%c0_to_lat)
161 call msi(geom%c0_to_tile)
166 call msr(geom%vunitavg)
167 geom%mask_c0 = .false.
168 geom%mask_hor_c0 = .false.
169 geom%mask_ver_c0 = .false.
170 call msi(geom%nc0_mask)
183 class(geom_type),
intent(inout) :: geom
186 if (
allocated(geom%c0_to_lon))
deallocate(geom%c0_to_lon)
187 if (
allocated(geom%c0_to_lat))
deallocate(geom%c0_to_lat)
188 if (
allocated(geom%c0_to_tile))
deallocate(geom%c0_to_tile)
189 if (
allocated(geom%lon))
deallocate(geom%lon)
190 if (
allocated(geom%lat))
deallocate(geom%lat)
191 if (
allocated(geom%area))
deallocate(geom%area)
192 if (
allocated(geom%vunit))
deallocate(geom%vunit)
193 if (
allocated(geom%vunitavg))
deallocate(geom%vunitavg)
194 if (
allocated(geom%disth))
deallocate(geom%disth)
195 if (
allocated(geom%mask_c0))
deallocate(geom%mask_c0)
196 if (
allocated(geom%mask_c0a))
deallocate(geom%mask_c0a)
197 if (
allocated(geom%mask_hor_c0))
deallocate(geom%mask_hor_c0)
198 if (
allocated(geom%mask_hor_c0a))
deallocate(geom%mask_hor_c0a)
199 if (
allocated(geom%mask_ver_c0))
deallocate(geom%mask_ver_c0)
200 if (
allocated(geom%nc0_mask))
deallocate(geom%nc0_mask)
201 call geom%mesh%dealloc
202 call geom%kdtree%dealloc
203 if (
allocated(geom%redundant))
deallocate(geom%redundant)
204 if (
allocated(geom%nbnd))
deallocate(geom%nbnd)
205 if (
allocated(geom%xbnd))
deallocate(geom%xbnd)
206 if (
allocated(geom%ybnd))
deallocate(geom%ybnd)
207 if (
allocated(geom%zbnd))
deallocate(geom%zbnd)
208 if (
allocated(geom%vbnd))
deallocate(geom%vbnd)
209 if (
allocated(geom%c0_to_mg))
deallocate(geom%c0_to_mg)
210 if (
allocated(geom%mg_to_c0))
deallocate(geom%mg_to_c0)
211 if (
allocated(geom%mg_to_proc))
deallocate(geom%mg_to_proc)
212 if (
allocated(geom%mg_to_mga))
deallocate(geom%mg_to_mga)
213 if (
allocated(geom%mga_to_mg))
deallocate(geom%mga_to_mg)
214 if (
allocated(geom%proc_to_nmga))
deallocate(geom%proc_to_nmga)
215 if (
allocated(geom%c0_to_proc))
deallocate(geom%c0_to_proc)
216 if (
allocated(geom%c0_to_c0a))
deallocate(geom%c0_to_c0a)
217 if (
allocated(geom%c0a_to_c0))
deallocate(geom%c0a_to_c0)
218 if (
allocated(geom%proc_to_nc0a))
deallocate(geom%proc_to_nc0a)
219 if (
allocated(geom%mga_to_c0))
deallocate(geom%mga_to_c0)
220 if (
allocated(geom%c0a_to_mga))
deallocate(geom%c0a_to_mga)
221 call geom%com_mg%dealloc
229 subroutine geom_setup_online(geom,mpl,rng,nam,nmga,nl0,lon,lat,area,vunit,lmask)
234 class(geom_type),
intent(inout) :: geom
235 type(mpl_type),
intent(inout) :: mpl
236 type(rng_type),
intent(inout) :: rng
237 type(nam_type),
intent(in) :: nam
238 integer,
intent(in) :: nmga
239 integer,
intent(in) :: nl0
240 real(kind_real),
intent(in) :: lon(nmga)
241 real(kind_real),
intent(in) :: lat(nmga)
242 real(kind_real),
intent(in) :: area(nmga)
243 real(kind_real),
intent(in) :: vunit(nmga,nl0)
244 logical,
intent(in) :: lmask(nmga,nl0)
247 integer :: ic0,ic0a,il0,offset,iproc,img,imga
248 integer,
allocatable :: order(:),order_inv(:)
249 real(kind_real),
allocatable :: lon_mg(:),lat_mg(:),area_mg(:),vunit_mg(:,:),list(:)
250 logical,
allocatable :: lmask_mg(:,:)
251 type(fckit_mpi_status) :: status
259 allocate(geom%proc_to_nmga(mpl%nproc))
262 call mpl%f_comm%allgather(geom%nmga,geom%proc_to_nmga)
265 geom%nmg = sum(geom%proc_to_nmga)
268 allocate(lon_mg(geom%nmg))
269 allocate(lat_mg(geom%nmg))
270 allocate(area_mg(geom%nmg))
271 allocate(vunit_mg(geom%nmg,geom%nl0))
272 allocate(lmask_mg(geom%nmg,geom%nl0))
273 allocate(geom%mg_to_proc(geom%nmg))
274 allocate(geom%mg_to_mga(geom%nmg))
275 allocate(geom%mga_to_mg(geom%nmga))
282 if (iproc==mpl%ioproc)
then 284 lon_mg(offset+1:offset+geom%proc_to_nmga(iproc)) = lon
285 lat_mg(offset+1:offset+geom%proc_to_nmga(iproc)) = lat
286 area_mg(offset+1:offset+geom%proc_to_nmga(iproc)) = area
288 vunit_mg(offset+1:offset+geom%proc_to_nmga(iproc),il0) = vunit(:,il0)
289 lmask_mg(offset+1:offset+geom%proc_to_nmga(iproc),il0) = lmask(:,il0)
293 call mpl%f_comm%receive(lon_mg(offset+1:offset+geom%proc_to_nmga(iproc)),iproc-1,mpl%tag,status)
294 call mpl%f_comm%receive(lat_mg(offset+1:offset+geom%proc_to_nmga(iproc)),iproc-1,mpl%tag+1,status)
295 call mpl%f_comm%receive(area_mg(offset+1:offset+geom%proc_to_nmga(iproc)),iproc-1,mpl%tag+2,status)
297 call mpl%f_comm%receive(vunit_mg(offset+1:offset+geom%proc_to_nmga(iproc),il0),iproc-1,mpl%tag+2+il0,status)
298 call mpl%f_comm%receive(lmask_mg(offset+1:offset+geom%proc_to_nmga(iproc),il0),iproc-1, &
299 & mpl%tag+2+geom%nl0+il0,status)
304 offset = offset+geom%proc_to_nmga(iproc)
308 call mpl%f_comm%send(lon,mpl%ioproc-1,mpl%tag)
309 call mpl%f_comm%send(lat,mpl%ioproc-1,mpl%tag+1)
310 call mpl%f_comm%send(area,mpl%ioproc-1,mpl%tag+2)
312 call mpl%f_comm%send(vunit(:,il0),mpl%ioproc-1,mpl%tag+2+il0)
313 call mpl%f_comm%send(lmask(:,il0),mpl%ioproc-1,mpl%tag+2+geom%nl0+il0)
316 call mpl%update_tag(3+2*geom%nl0)
325 call mpl%f_comm%broadcast(lon_mg,mpl%ioproc-1)
326 call mpl%f_comm%broadcast(lat_mg,mpl%ioproc-1)
327 call mpl%f_comm%broadcast(area_mg,mpl%ioproc-1)
328 call mpl%f_comm%broadcast(vunit_mg,mpl%ioproc-1)
329 call mpl%f_comm%broadcast(lmask_mg,mpl%ioproc-1)
332 call geom%find_sc0(mpl,rng,lon_mg,lat_mg,lmask_mg,.true.,nam%mask_check,.false.)
336 allocate(geom%proc_to_nc0a(mpl%nproc))
337 allocate(list(geom%nc0))
338 allocate(order(geom%nc0))
339 allocate(order_inv(geom%nc0))
343 geom%proc_to_nc0a = 0
345 do imga=1,geom%proc_to_nmga(iproc)
347 geom%mg_to_proc(img) = iproc
348 geom%mg_to_mga(img) = imga
349 if (iproc==mpl%myproc) geom%mga_to_mg(imga) = img
350 if (geom%mask_hor_mg(img)) geom%proc_to_nc0a(iproc) = geom%proc_to_nc0a(iproc)+1
353 geom%nc0a = geom%proc_to_nc0a(mpl%myproc)
356 allocate(geom%c0a_to_c0(geom%nc0a))
359 do ic0a=1,geom%proc_to_nc0a(iproc)
361 geom%c0_to_proc(ic0) = iproc
362 if (iproc==mpl%myproc) geom%c0a_to_c0(ic0a) = ic0
365 call mpl%glb_to_loc_index(geom%nc0a,geom%c0a_to_c0,geom%nc0,geom%c0_to_c0a)
368 allocate(geom%mga_to_c0(geom%nmga))
369 allocate(geom%c0a_to_mga(geom%nc0a))
371 img = geom%mga_to_mg(imga)
372 ic0 = geom%mg_to_c0(img)
373 geom%mga_to_c0(imga) = ic0
376 ic0 = geom%c0a_to_c0(ic0a)
377 img = geom%c0_to_mg(ic0)
378 imga = geom%mg_to_mga(img)
379 geom%c0a_to_mga(ic0a) = imga
385 if (
isnotmsi(geom%redundant(img))) lmask_mg(img,il0) = lmask_mg(img,il0).or.lmask_mg(geom%redundant(img),il0)
390 geom%lon = lon_mg(geom%c0_to_mg)
391 geom%lat = lat_mg(geom%c0_to_mg)
393 geom%area(il0) = sum(area_mg(geom%c0_to_mg),lmask_mg(geom%c0_to_mg,il0))/
req**2
394 geom%vunit(:,il0) = vunit_mg(geom%c0_to_mg,il0)
395 geom%mask_c0(:,il0) = lmask_mg(geom%c0_to_mg,il0)
400 list(ic0) = aint(abs(geom%lon(ic0))*1.0e6)+abs(geom%lat(ic0))*1.0e-1
401 if (geom%lon(ic0)<0.0) list(ic0) = list(ic0)+2.0e7
402 if (geom%lat(ic0)<0.0) list(ic0) = list(ic0)+1.0e7
404 call qsort(geom%nc0,list,order)
406 order_inv(order(ic0)) = ic0
408 geom%c0_to_proc = geom%c0_to_proc(order)
409 geom%c0_to_c0a = geom%c0_to_c0a(order)
410 geom%c0a_to_c0 = order_inv(geom%c0a_to_c0)
411 geom%lon = geom%lon(order)
412 geom%lat = geom%lat(order)
414 geom%vunit(:,il0) = geom%vunit(order,il0)
415 geom%mask_c0(:,il0) = geom%mask_c0(order,il0)
417 geom%c0_to_mg = geom%c0_to_mg(order)
418 geom%mg_to_c0 = order_inv(geom%mg_to_c0)
419 geom%mga_to_c0 = order_inv(geom%mga_to_c0)
422 allocate(geom%mask_c0a(geom%nc0a,geom%nl0))
423 allocate(geom%mask_hor_c0a(geom%nc0a))
424 geom%mask_c0a = geom%mask_c0(geom%c0a_to_c0,:)
425 geom%mask_hor_c0 = any(geom%mask_c0,dim=2)
426 geom%mask_hor_c0a = geom%mask_hor_c0(geom%c0a_to_c0)
427 geom%mask_ver_c0 = any(geom%mask_c0,dim=1)
428 geom%nc0_mask = count(geom%mask_c0,dim=1)
431 call geom%com_mg%setup(mpl,
'com_mg',geom%nc0,geom%nc0a,geom%nmga,geom%mga_to_c0,geom%c0a_to_mga,geom%c0_to_proc,geom%c0_to_c0a)
439 subroutine geom_find_sc0(geom,mpl,rng,lon,lat,lmask,red_check,mask_check,mask_del)
444 class(geom_type),
intent(inout) :: geom
445 type(mpl_type),
intent(in) :: mpl
446 type(rng_type),
intent(inout) :: rng
447 real(kind_real),
intent(in) :: lon(geom%nmg)
448 real(kind_real),
intent(in) :: lat(geom%nmg)
449 logical,
intent(in) :: lmask(geom%nmg,geom%nl0)
450 logical,
intent(in) :: red_check
451 logical,
intent(in) :: mask_check
452 logical,
intent(in) :: mask_del
455 integer :: img,ic0,ired,nn_index(nredmax),nc0full,ic0full,jc0full,kc0full,i,j,k,iend,ibnd,il0
456 integer,
allocatable :: c0full_to_mg(:),mg_to_c0full(:),ic0full_bnd(:,:,:)
457 real(kind_real) :: nn_dist(nredmax),latbnd(2),lonbnd(2),v1(3),v2(3)
458 real(kind_real),
allocatable :: lon_c0full(:),lat_c0full(:)
460 logical,
allocatable :: lmask_c0full(:,:)
461 type(kdtree_type) :: kdtree
462 type(mesh_type) :: mesh
465 allocate(geom%mask_hor_mg(geom%nmg))
466 allocate(geom%redundant(geom%nmg))
467 allocate(geom%mg_to_c0(geom%nmg))
470 call msi(geom%redundant)
474 write(mpl%info,
'(a7,a)')
'',
'Look for redundant points in the model grid' 477 call kdtree%create(mpl,geom%nmg,lon,lat)
482 call kdtree%find_nearest_neighbors(lon(img),lat(img),nredmax,nn_index,nn_dist)
486 if ((nn_dist(ired)>
distminred).or.(nn_index(ired)>=img)) nn_index(ired) = geom%nmg+1
489 if (any(nn_index<=geom%nmg))
then 491 geom%redundant(img) = minval(nn_index)
497 if (
isnotmsi(geom%redundant(img)))
then 498 do while (
isnotmsi(geom%redundant(geom%redundant(img))))
499 geom%redundant(img) = geom%redundant(geom%redundant(img))
509 geom%mask_hor_mg =
ismsi(geom%redundant)
512 nc0full = count(geom%mask_hor_mg)
513 allocate(c0full_to_mg(nc0full))
514 allocate(mg_to_c0full(geom%nmg))
515 allocate(lon_c0full(nc0full))
516 allocate(lat_c0full(nc0full))
517 allocate(lmask_c0full(nc0full,geom%nl0))
522 if (
ismsi(geom%redundant(img)))
then 524 c0full_to_mg(ic0full) = img
525 mg_to_c0full(img) = ic0full
528 lon_c0full = lon(c0full_to_mg)
529 lat_c0full = lat(c0full_to_mg)
530 lmask_c0full = lmask(c0full_to_mg,:)
533 geom%mask_del = mask_del.and.(any(.not.lmask_c0full))
535 if (geom%mask_del.or.mask_check)
then 537 call mesh%create(mpl,rng,nc0full,lon_c0full,lat_c0full)
540 allocate(geom%nbnd(geom%nl0))
541 allocate(ic0full_bnd(2,mesh%n,geom%nl0))
548 ic0full = mesh%order(i)
549 if (.not.lmask_c0full(ic0full,il0))
then 552 do while ((iend/=mesh%lend(i)).or.init)
553 j = abs(mesh%list(iend))
554 k = abs(mesh%list(mesh%lptr(iend)))
555 jc0full = mesh%order(j)
556 kc0full = mesh%order(k)
557 if (.not.lmask_c0full(jc0full,il0).and.lmask_c0full(kc0full,il0))
then 559 geom%nbnd(il0) = geom%nbnd(il0)+1
560 if (geom%nbnd(il0)>mesh%n)
call mpl%abort(
'too many boundary arcs')
561 ic0full_bnd(1,geom%nbnd(il0),il0) = ic0full
562 ic0full_bnd(2,geom%nbnd(il0),il0) = jc0full
564 iend = mesh%lptr(iend)
572 allocate(geom%xbnd(2,maxval(geom%nbnd),geom%nl0))
573 allocate(geom%ybnd(2,maxval(geom%nbnd),geom%nl0))
574 allocate(geom%zbnd(2,maxval(geom%nbnd),geom%nl0))
575 allocate(geom%vbnd(3,maxval(geom%nbnd),geom%nl0))
579 do ibnd=1,geom%nbnd(il0)
580 latbnd = lat_c0full(ic0full_bnd(:,ibnd,il0))
581 lonbnd = lon_c0full(ic0full_bnd(:,ibnd,il0))
582 call trans(2,latbnd,lonbnd,geom%xbnd(:,ibnd,il0),geom%ybnd(:,ibnd,il0),geom%zbnd(:,ibnd,il0))
584 do ibnd=1,geom%nbnd(il0)
585 v1 = (/geom%xbnd(1,ibnd,il0),geom%ybnd(1,ibnd,il0),geom%zbnd(1,ibnd,il0)/)
586 v2 = (/geom%xbnd(2,ibnd,il0),geom%ybnd(2,ibnd,il0),geom%zbnd(2,ibnd,il0)/)
592 if (geom%mask_del)
then 595 if (geom%mask_hor_mg(img))
then 596 ic0full = mg_to_c0full(img)
597 geom%mask_hor_mg(img) = any(lmask_c0full(ic0full,:))
603 geom%nc0 = count(geom%mask_hor_mg)
604 allocate(geom%c0_to_mg(geom%nc0))
607 call msi(geom%mg_to_c0)
612 if (geom%mask_hor_mg(img))
then 614 geom%c0_to_mg(ic0) = img
615 geom%mg_to_c0(img) = ic0
621 if (
isnotmsi(geom%redundant(img))) geom%mg_to_c0(img) = geom%mg_to_c0(geom%redundant(img))
625 if (red_check)
write(mpl%info,
'(a7,a,i6,a,f6.2,a)')
'',
'Number of redundant points: ',(geom%nmg-nc0full), &
626 &
' (',
real(geom%nmg-nc0full,kind_real)/
real(geom%nmg,kind_real)*100.0,
'%)' 627 if (mask_del)
write(mpl%info,
'(a7,a,i6,a,f6.2,a)')
'',
'Number of masked points :',(nc0full-geom%nc0), &
628 &
' (',
real(nc0full-geom%nc0,kind_real)/
real(geom%nmg,kind_real)*100.0,
'%)' 629 if (red_check.and.mask_del)
write(mpl%info,
'(a7,a,i6,a,f6.2,a)')
'',
'Total number of removed points:',(geom%nmg-geom%nc0), &
630 &
' (',
real(geom%nmg-geom%nc0,kind_real)/
real(geom%nmg,kind_real)*100.0,
'%)' 632 write(mpl%info,
'(a7,a,i8)')
'',
'Model grid size: ',geom%nmg
633 if (red_check)
write(mpl%info,
'(a7,a,i8)')
'',
'Non-redundant grid size: ',nc0full
634 write(mpl%info,
'(a7,a,i8)')
'',
'Subset Sc0 size: ',geom%nc0
647 class(geom_type),
intent(inout) :: geom
648 type(mpl_type),
intent(in) :: mpl
649 type(rng_type),
intent(inout) :: rng
650 type(nam_type),
intent(in) :: nam
653 integer :: ic0,il0,jc3,iproc
658 call lonlatmod(geom%lon(ic0),geom%lat(ic0))
662 call geom%define_mask(mpl,nam)
666 if (geom%mask_ver_c0(il0))
then 667 geom%vunitavg(il0) = sum(geom%vunit(:,il0),geom%mask_c0(:,il0))/
real(geom%nc0_mask(il0),kind_real)
669 geom%vunitavg(il0) = 0.0
674 call geom%mesh%create(mpl,rng,geom%nc0,geom%lon,geom%lat)
675 call geom%mesh%bnodes
678 if (.not.
isanynotmsr(geom%area))
call geom%compute_area(mpl)
683 same_mask = same_mask.and.(all((geom%mask_c0(:,il0).and.geom%mask_c0(:,1)) &
684 & .or.(.not.geom%mask_c0(:,il0).and..not.geom%mask_c0(:,1))))
693 write(mpl%info,
'(a7,a,i3)')
'',
'Number of independent levels: ',geom%nl0i
697 call geom%kdtree%create(mpl,geom%nc0,geom%lon,geom%lat)
700 allocate(geom%disth(nam%nc3))
702 geom%disth(jc3) =
real(jc3-1,kind_real)*nam%dc
706 if (nam%ndir>0)
call geom%define_dirac(nam)
709 write(mpl%info,
'(a10,a,f7.1,a,f7.1)')
'',
'Min. / max. longitudes:',minval(geom%lon)*
rad2deg,
' / ',maxval(geom%lon)*
rad2deg 710 write(mpl%info,
'(a10,a,f7.1,a,f7.1)')
'',
'Min. / max. latitudes: ',minval(geom%lat)*
rad2deg,
' / ',maxval(geom%lat)*
rad2deg 711 write(mpl%info,
'(a10,a)')
'',
'Unmasked area (% of Earth area) / masked points / vertical unit:' 713 write(mpl%info,
'(a13,a,i3,a,f5.1,a,f5.1,a,f12.1,a)')
'',
'Level ',nam%levs(il0),
' ~> ',geom%area(il0)/(4.0*
pi)*100.0,
'% / ', &
714 &
real(count(.not.geom%mask_c0(:,il0)),kind_real)/
real(geom%nc0,kind_real)*100.0,
'% / ',geom%vunitavg(il0),
' '//trim(mpl%vunitchar)
716 write(mpl%info,
'(a7,a)')
'',
'Distribution summary:' 718 write(mpl%info,
'(a10,a,i3,a,i8,a)')
'',
'Proc #',iproc,
': ',geom%proc_to_nc0a(iproc),
' grid-points' 733 class(geom_type),
intent(inout) :: geom
734 type(mpl_type),
intent(in) :: mpl
735 type(nam_type),
intent(in) :: nam
738 integer :: latmin,latmax,il0,ic0,ildw
739 integer :: ncid,nlon_id,nlon_test,nlat_id,nlat_test,mask_id
740 real(kind_real) :: dist
741 real(kind_real),
allocatable :: hydmask(:,:)
743 character(len=3) :: il0char
744 character(len=1024) :: subr =
'geom_define_mask' 747 if (nam%mask_type(1:3)==
'lat')
then 749 read(nam%mask_type(4:6),
'(i3)') latmin
750 read(nam%mask_type(7:9),
'(i3)') latmax
751 if (latmin>=latmax)
call mpl%abort(
'latmin should be lower than latmax')
753 geom%mask_c0(:,il0) = geom%mask_c0(:,il0).and.(geom%lat>=
real(latmin,kind_real)*deg2rad) &
754 & .and.(geom%lat<=real(latmax,kind_real)*deg2rad)
756 elseif (trim(nam%mask_type)==
'hyd')
then 758 call mpl%ncerr(subr,nf90_open(trim(nam%datadir)//
'/'//trim(nam%prefix)//
'_hyd.nc',nf90_nowrite,ncid))
759 if (trim(nam%model)==
'aro')
then 760 call mpl%ncerr(subr,nf90_inq_dimid(ncid,
'X',nlon_id))
761 call mpl%ncerr(subr,nf90_inquire_dimension(ncid,nlon_id,len=nlon_test))
762 call mpl%ncerr(subr,nf90_inq_dimid(ncid,
'Y',nlat_id))
763 call mpl%ncerr(subr,nf90_inquire_dimension(ncid,nlat_id,len=nlat_test))
764 if ((nlon_test/=geom%nlon).or.(nlat_test/=geom%nlat))
call mpl%abort(
'wrong dimensions in the mask')
765 allocate(hydmask(geom%nlon,geom%nlat))
767 write(il0char,
'(i3.3)') nam%levs(il0)
768 call mpl%ncerr(subr,nf90_inq_varid(ncid,
'S'//il0char//
'MASK',mask_id))
769 call mpl%ncerr(subr,nf90_get_var(ncid,mask_id,hydmask,(/1,1/),(/geom%nlon,geom%nlat/)))
770 geom%mask_c0(:,il0) = geom%mask_c0(:,il0).and.pack(
real(hydmask,kind(1.0))>nam%mask_th,mask=.true.)
773 call mpl%ncerr(subr,nf90_close(ncid))
775 elseif (trim(nam%mask_type)==
'ldwv')
then 778 if (geom%mask_hor_c0(ic0))
then 781 call sphere_dist(nam%lon_ldwv(ildw),nam%lat_ldwv(ildw),geom%lon(ic0),geom%lat(ic0),dist)
782 mask_test = mask_test.or.(dist<1.1*nam%local_rad)
785 if (geom%mask_c0(ic0,il0)) geom%mask_c0(ic0,:) = mask_test
802 class(geom_type),
intent(inout) :: geom
803 type(mpl_type),
intent(in) :: mpl
807 real(kind_real) :: area,frac
809 write(mpl%info,
'(a7,a)')
'',
'Compute area (might take a long time)' 812 if (.not.
allocated(geom%mesh%ltri))
call geom%mesh%trlist
817 area =
areas((/geom%mesh%x(geom%mesh%ltri(1,it)),geom%mesh%y(geom%mesh%ltri(1,it)),geom%mesh%z(geom%mesh%ltri(1,it))/), &
818 & (/geom%mesh%x(geom%mesh%ltri(2,it)),geom%mesh%y(geom%mesh%ltri(2,it)),geom%mesh%z(geom%mesh%ltri(2,it))/), &
819 & (/geom%mesh%x(geom%mesh%ltri(3,it)),geom%mesh%y(geom%mesh%ltri(3,it)),geom%mesh%z(geom%mesh%ltri(3,it))/))
821 frac =
real(count(geom%mask_c0(geom%mesh%order(geom%mesh%ltri(1:3,it)),il0)),kind_real)/3.0
822 geom%area(il0) = geom%area(il0)+frac*area
837 class(geom_type),
intent(inout) :: geom
838 type(nam_type),
intent(in) :: nam
841 integer :: idir,il0,nn_index(1),ic0dir,il0dir
842 real(kind_real) :: nn_dist(1)
846 allocate(geom%londir(nam%ndir))
847 allocate(geom%latdir(nam%ndir))
848 allocate(geom%iprocdir(nam%ndir))
849 allocate(geom%ic0adir(nam%ndir))
850 allocate(geom%il0dir(nam%ndir))
851 allocate(geom%ivdir(nam%ndir))
852 allocate(geom%itsdir(nam%ndir))
859 if (nam%levs(il0)==nam%levdir(idir)) il0dir = il0
863 call geom%kdtree%find_nearest_neighbors(nam%londir(idir),nam%latdir(idir),1,nn_index,nn_dist)
867 if (geom%mask_del)
then 868 call geom%check_arc(il0dir,nam%londir(idir),nam%latdir(idir),geom%lon(ic0dir),geom%lat(ic0dir),valid)
870 valid = geom%mask_c0(ic0dir,il0dir)
875 geom%ndir = geom%ndir+1
876 geom%londir(geom%ndir) = nam%londir(idir)
877 geom%latdir(geom%ndir) = nam%latdir(idir)
878 geom%iprocdir(geom%ndir) = geom%c0_to_proc(ic0dir)
879 geom%ic0adir(geom%ndir) = geom%c0_to_c0a(ic0dir)
880 geom%il0dir(geom%ndir) = il0dir
881 geom%ivdir(geom%ndir) = nam%ivdir(idir)
882 geom%itsdir(geom%ndir) = nam%itsdir(idir)
897 class(geom_type),
intent(inout) :: geom
898 type(mpl_type),
intent(inout) :: mpl
899 type(nam_type),
intent(in) :: nam
900 type(rng_type),
intent(inout) :: rng
903 integer :: ic0,il0,info,iproc,ic0a,nc0a,ny,nres,iy,delta,ix
904 integer :: ncid,nc0_id,c0_to_proc_id,c0_to_c0a_id,lon_id,lat_id
905 integer :: c0_reorder(geom%nc0),nn_index(1)
906 integer,
allocatable :: center_to_c0(:),nx(:),ic0a_arr(:)
907 real(kind_real) :: nn_dist(1),dlat,dlon
908 real(kind_real),
allocatable :: rh_c0(:),lon_center(:),lat_center(:)
909 logical,
allocatable :: mask_hor_c0(:)
910 character(len=4) :: nprocchar
911 character(len=1024) :: filename_nc
912 character(len=1024) :: subr =
'geom_define_distribution' 913 type(kdtree_type) :: kdtree
915 if (mpl%nproc==1)
then 919 geom%c0_to_c0a(ic0) = ic0
921 elseif (mpl%nproc>1)
then 924 write(nprocchar,
'(i4.4)') mpl%nproc
925 filename_nc = trim(nam%prefix)//
'_distribution_'//nprocchar//
'.nc' 926 info = nf90_open(trim(nam%datadir)//
'/'//trim(filename_nc),nf90_nowrite,ncid)
928 call mpl%f_comm%broadcast(info,mpl%ioproc-1)
930 if (info==nf90_noerr)
then 932 write(mpl%info,
'(a7,a,i4,a)')
'',
'Read local distribution for: ',mpl%nproc,
' MPI tasks' 937 call mpl%ncerr(subr,nf90_inq_varid(ncid,
'c0_to_proc',c0_to_proc_id))
938 call mpl%ncerr(subr,nf90_inq_varid(ncid,
'c0_to_c0a',c0_to_c0a_id))
941 call mpl%ncerr(subr,nf90_get_var(ncid,c0_to_proc_id,geom%c0_to_proc))
942 call mpl%ncerr(subr,nf90_get_var(ncid,c0_to_c0a_id,geom%c0_to_c0a))
945 call mpl%ncerr(subr,nf90_close(ncid))
949 call mpl%f_comm%broadcast(geom%c0_to_proc,mpl%ioproc-1)
950 call mpl%f_comm%broadcast(geom%c0_to_c0a,mpl%ioproc-1)
953 if (maxval(geom%c0_to_proc)>mpl%nproc)
call mpl%abort(
'wrong distribution')
958 allocate(lon_center(mpl%nproc))
959 allocate(lat_center(mpl%nproc))
960 allocate(ic0a_arr(mpl%nproc))
967 allocate(mask_hor_c0(geom%nc0))
968 allocate(rh_c0(geom%nc0))
969 allocate(center_to_c0(mpl%nproc))
972 mask_hor_c0 = any(geom%mask_c0,dim=2)
976 write(mpl%info,
'(a7,a)',advance=
'no')
'',
'Define distribution centers:' 977 call rng%initialize_sampling(mpl,geom%nc0,geom%lon,geom%lat,mask_hor_c0,rh_c0,nam%ntry,nam%nrep,mpl%nproc,center_to_c0)
980 lon_center = geom%lon(center_to_c0)
981 lat_center = geom%lat(center_to_c0)
986 ny = nint(sqrt(
real(mpl%nproc,kind_real)))
987 if (ny**2<mpl%nproc) ny = ny+1
992 if (nres>(ny-iy+1)*delta) delta = delta+1
996 if (sum(nx)/=mpl%nproc)
call mpl%abort(
'wrong number of tiles in define_distribution')
997 dlat = (maxval(geom%lat)-minval(geom%lat))/ny
1000 dlon = (maxval(geom%lon)-minval(geom%lon))/nx(iy)
1003 lat_center(iproc) = minval(geom%lat)+(
real(iy,kind_real)-0.5)*dlat
1004 lon_center(iproc) = minval(geom%lon)+(
real(ix,kind_real)-0.5)*dlon
1011 call kdtree%create(mpl,mpl%nproc,lon_center,lat_center)
1015 call kdtree%find_nearest_neighbors(geom%lon(ic0),geom%lat(ic0),1,nn_index,nn_dist)
1016 geom%c0_to_proc(ic0) = nn_index(1)
1022 iproc = geom%c0_to_proc(ic0)
1023 ic0a_arr(iproc) = ic0a_arr(iproc)+1
1024 geom%c0_to_c0a(ic0) = ic0a_arr(iproc)
1029 call mpl%f_comm%broadcast(geom%c0_to_proc,mpl%ioproc-1)
1030 call mpl%f_comm%broadcast(geom%c0_to_c0a,mpl%ioproc-1)
1035 nc0a = count(geom%c0_to_proc==mpl%nproc-1)
1039 if (geom%c0_to_proc(ic0)==mpl%nproc)
then 1041 geom%c0_to_proc(ic0) = mpl%nproc-1
1042 geom%c0_to_c0a(ic0) = nc0a
1050 call mpl%ncerr(subr,nf90_create(trim(nam%datadir)//
'/'//trim(filename_nc),or(nf90_clobber,nf90_64bit_offset),ncid))
1053 call nam%ncwrite(mpl,ncid)
1056 call mpl%ncerr(subr,nf90_def_dim(ncid,
'nc0',geom%nc0,nc0_id))
1059 call mpl%ncerr(subr,nf90_def_var(ncid,
'lon',
ncfloat,(/nc0_id/),lon_id))
1060 call mpl%ncerr(subr,nf90_def_var(ncid,
'lat',
ncfloat,(/nc0_id/),lat_id))
1061 call mpl%ncerr(subr,nf90_def_var(ncid,
'c0_to_proc',nf90_int,(/nc0_id/),c0_to_proc_id))
1062 call mpl%ncerr(subr,nf90_def_var(ncid,
'c0_to_c0a',nf90_int,(/nc0_id/),c0_to_c0a_id))
1065 call mpl%ncerr(subr,nf90_enddef(ncid))
1068 call mpl%ncerr(subr,nf90_put_var(ncid,lon_id,geom%lon*
rad2deg))
1069 call mpl%ncerr(subr,nf90_put_var(ncid,lat_id,geom%lat*
rad2deg))
1070 call mpl%ncerr(subr,nf90_put_var(ncid,c0_to_proc_id,geom%c0_to_proc))
1071 call mpl%ncerr(subr,nf90_put_var(ncid,c0_to_c0a_id,geom%c0_to_c0a))
1074 call mpl%ncerr(subr,nf90_close(ncid))
1080 allocate(geom%proc_to_nc0a(mpl%nproc))
1081 do iproc=1,mpl%nproc
1082 geom%proc_to_nc0a(iproc) = count(geom%c0_to_proc==iproc)
1084 geom%nc0a = geom%proc_to_nc0a(mpl%myproc)
1087 allocate(geom%c0a_to_c0(geom%nc0a))
1090 if (geom%c0_to_proc(ic0)==mpl%myproc)
then 1092 geom%c0a_to_c0(ic0a) = ic0
1098 iproc = geom%c0_to_proc(ic0)
1099 ic0a = geom%c0_to_c0a(ic0)
1101 c0_reorder(ic0) = ic0a
1103 c0_reorder(ic0) = sum(geom%proc_to_nc0a(1:iproc-1))+ic0a
1106 geom%c0_to_lon(c0_reorder) = geom%c0_to_lon
1107 geom%c0_to_lat(c0_reorder) = geom%c0_to_lat
1108 geom%c0_to_tile(c0_reorder) = geom%c0_to_tile
1109 geom%lon(c0_reorder) = geom%lon
1110 geom%lat(c0_reorder) = geom%lat
1112 geom%vunit(c0_reorder,il0) = geom%vunit(:,il0)
1113 geom%mask_c0(c0_reorder,il0) = geom%mask_c0(:,il0)
1115 geom%c0_to_proc(c0_reorder) = geom%c0_to_proc
1116 geom%c0_to_c0a(c0_reorder) = geom%c0_to_c0a
1118 geom%c0a_to_c0(ic0a) = c0_reorder(geom%c0a_to_c0(ic0a))
1122 allocate(geom%mask_c0a(geom%nc0a,geom%nl0))
1123 allocate(geom%mask_hor_c0a(geom%nc0a))
1124 geom%mask_c0a = geom%mask_c0(geom%c0a_to_c0,:)
1125 geom%mask_hor_c0 = any(geom%mask_c0,dim=2)
1126 geom%mask_hor_c0a = geom%mask_hor_c0(geom%c0a_to_c0)
1127 geom%mask_ver_c0 = any(geom%mask_c0,dim=1)
1128 geom%nc0_mask = count(geom%mask_c0,dim=1)
1136 subroutine geom_check_arc(geom,il0,lon_s,lat_s,lon_e,lat_e,valid)
1141 class(geom_type),
intent(in) :: geom
1142 integer,
intent(in) :: il0
1143 real(kind_real),
intent(in) :: lon_s
1144 real(kind_real),
intent(in) :: lat_s
1145 real(kind_real),
intent(in) :: lon_e
1146 real(kind_real),
intent(in) :: lat_e
1147 logical,
intent(out) :: valid
1151 real(kind_real) :: x(2),y(2),z(2),v1(3),v2(3),va(3),vp(3),t(4)
1154 call trans(2,(/lat_s,lat_e/),(/lon_s,lon_e/),x,y,z)
1157 v1 = (/x(1),y(1),z(1)/)
1158 v2 = (/x(2),y(2),z(2)/)
1163 do ibnd=1,geom%nbnd(il0)
1165 v1 = (/x(1),y(1),z(1)/)
1167 v1 = (/x(2),y(2),z(2)/)
1169 v1 = (/geom%xbnd(1,ibnd,il0),geom%ybnd(1,ibnd,il0),geom%zbnd(1,ibnd,il0)/)
1171 v1 = (/geom%xbnd(2,ibnd,il0),geom%ybnd(2,ibnd,il0),geom%zbnd(2,ibnd,il0)/)
1175 if (all(t>0).or.(all(t<0)))
then 1192 class(geom_type),
intent(in) :: geom
1193 type(mpl_type),
intent(in) :: mpl
1194 real(kind_real),
intent(in) :: fld_c0a(geom%nc0a,geom%nl0)
1195 real(kind_real),
intent(out) :: fld_mga(geom%nmga,geom%nl0)
1197 if (geom%nc0==geom%nmg)
then 1202 call geom%com_mg%ext(mpl,geom%nl0,fld_c0a,fld_mga)
1205 write(mpl%info,*)
'c0a_to_mga',mpl%myproc,maxval(fld_c0a),maxval(fld_mga),sum(fld_c0a),sum(fld_mga)
1218 class(geom_type),
intent(in) :: geom
1219 type(mpl_type),
intent(in) :: mpl
1220 real(kind_real),
intent(in) :: fld_mga(geom%nmga,geom%nl0)
1221 real(kind_real),
intent(out) :: fld_c0a(geom%nc0a,geom%nl0)
1224 integer :: ic0a,imga,il0
1225 real(kind_real) :: fld_mga_zero(geom%nmga,geom%nl0)
1227 if (geom%nc0==geom%nmg)
then 1232 fld_mga_zero = fld_mga
1234 imga = geom%c0a_to_mga(ic0a)
1235 fld_mga_zero(imga,:) = 0.0
1239 call geom%com_mg%red(mpl,geom%nl0,fld_mga_zero,fld_c0a)
1241 write(mpl%info,*)
'mga_to_c0a',mpl%myproc,maxval(fld_mga_zero),maxval(fld_c0a),sum(fld_mga_zero),sum(fld_c0a)
1246 imga = geom%c0a_to_mga(ic0a)
1247 if (abs(fld_mga(imga,il0)-fld_c0a(ic0a,il0))>0.0)
then 1249 if (
ismsr(fld_c0a(ic0a,il0)))
then 1251 fld_c0a(ic0a,il0) = fld_mga(imga,il0)
1252 elseif (
ismsr(fld_mga(imga,il0)))
then 1256 if (.not.(abs(fld_c0a(ic0a,il0))>0.0))
then 1258 fld_c0a(ic0a,il0) = fld_mga(imga,il0)
1259 elseif (.not.(abs(fld_mga(imga,il0))>0.0))
then 1262 call mpl%abort(
'both redundant values are different, not missing and nonzero')
1270 write(mpl%info,*)
'mga_to_c0a',mpl%myproc,maxval(fld_mga),maxval(fld_c0a),sum(fld_mga),sum(fld_c0a)
1283 class(geom_type),
intent(in) :: geom
1284 integer,
intent(in) :: ic0
1285 integer,
intent(in) :: il0
1286 integer,
intent(in) :: jc0
1287 integer,
intent(in) :: jl0
1288 real(kind_real),
intent(out) :: dx
1289 real(kind_real),
intent(out) :: dy
1290 real(kind_real),
intent(out) :: dz
1293 dx = geom%lon(jc0)-geom%lon(ic0)
1294 dy = geom%lat(jc0)-geom%lat(ic0)
1296 dx = dx*cos(geom%lat(ic0))
1297 dz =
real(geom%vunit(ic0,jl0)-geom%vunit(ic0,il0),kind_real)
subroutine geom_dealloc(geom)
subroutine geom_compute_deltas(geom, ic0, il0, jc0, jl0, dx, dy, dz)
subroutine geom_copy_c0a_to_mga(geom, mpl, fld_c0a, fld_mga)
subroutine geom_define_distribution(geom, mpl, nam, rng)
subroutine geom_define_dirac(geom, nam)
logical, parameter test_no_point
integer, parameter nredmax
subroutine geom_compute_area(geom, mpl)
real(kind_real), parameter distminred
real(kind=kind_real), parameter req
Earth radius at equator (m)
subroutine geom_alloc(geom)
subroutine geom_init(geom, mpl, rng, nam)
subroutine geom_check_arc(geom, il0, lon_s, lat_s, lon_e, lat_e, valid)
subroutine geom_find_sc0(geom, mpl, rng, lon, lat, lmask, red_check, mask_check, mask_del)
subroutine geom_copy_mga_to_c0a(geom, mpl, fld_mga, fld_c0a)
subroutine geom_setup_online(geom, mpl, rng, nam, nmga, nl0, lon, lat, area, vunit, lmask)
integer, parameter, public kind_real
subroutine geom_define_mask(geom, mpl, nam)
real(fp), parameter, public pi