22 use fckit_mpi_module,
only: fckit_mpi_status
29 real(kind_real),
parameter ::
s_inf = 1.0e-2_kind_real
33 character(len=1024) :: prefix
37 integer,
allocatable :: row(:)
38 integer,
allocatable :: col(:)
39 real(kind_real),
allocatable :: s(:)
41 real(kind_real),
allocatable :: svec(:,:)
76 class(linop_type),
intent(inout) :: linop
77 integer,
intent(in),
optional :: nvec
80 if (
present(nvec))
then 87 allocate(linop%row(linop%n_s))
88 allocate(linop%col(linop%n_s))
89 if (
present(nvec))
then 90 allocate(linop%Svec(linop%n_s,linop%nvec))
92 allocate(linop%S(linop%n_s))
99 if (
present(nvec))
then 100 if (linop%nvec>0)
call msr(linop%Svec)
117 class(linop_type),
intent(inout) :: linop
120 if (
allocated(linop%row))
deallocate(linop%row)
121 if (
allocated(linop%col))
deallocate(linop%col)
122 if (
allocated(linop%S))
deallocate(linop%S)
123 if (
allocated(linop%Svec))
deallocate(linop%Svec)
131 type(linop_type) function linop_copy(linop)
139 linop_copy%prefix = trim(linop%prefix)
140 linop_copy%n_src = linop%n_src
141 linop_copy%n_dst = linop%n_dst
142 linop_copy%n_s = linop%n_s
145 call linop_copy%dealloc
149 call linop_copy%alloc(linop%nvec)
151 call linop_copy%alloc
155 if (linop%n_s>0)
then 156 linop_copy%row = linop%row
157 linop_copy%col = linop%col
159 if (linop_copy%nvec>0) linop_copy%Svec = linop%Svec
161 linop_copy%S = linop%S
176 class(linop_type),
intent(inout) :: linop
177 type(mpl_type),
intent(in) :: mpl
180 integer :: row,i_s_s,i_s_e,n_s,i_s
181 integer,
allocatable :: order(:)
183 if ((linop%n_s>0).and.(linop%n_s<
reorder_max))
then 185 allocate(order(linop%n_s))
186 call qsort(linop%n_s,linop%row,order)
189 linop%col = linop%col(order)
190 if (isnotmsi(linop%nvec))
then 191 if (linop%nvec>0) linop%Svec = linop%Svec(order,:)
193 linop%S = linop%S(order)
198 row = minval(linop%row)
202 if (linop%row(i_s)==row)
then 207 call qsort(n_s,linop%col(i_s_s:i_s_e),order)
208 order = order+i_s_s-1
209 if (isnotmsi(linop%nvec))
then 210 if (linop%nvec>0) linop%Svec(i_s_s:i_s_e,:) = linop%Svec(order,:)
212 linop%S(i_s_s:i_s_e) = linop%S(order)
220 call mpl%warning(
'linear operator is too big, impossible to reorder')
234 class(linop_type),
intent(inout) :: linop
235 type(mpl_type),
intent(in) :: mpl
236 integer,
intent(in) :: ncid
240 integer :: n_s_id,row_id,col_id,S_id,Svec_id
241 character(len=1024) :: subr =
'linop_read' 244 info = nf90_inq_dimid(ncid,trim(linop%prefix)//
'_n_s',n_s_id)
245 if (info==nf90_noerr)
then 246 call mpl%ncerr(subr,nf90_inquire_dimension(ncid,n_s_id,len=linop%n_s))
252 call mpl%ncerr(subr,nf90_get_att(ncid,nf90_global,trim(linop%prefix)//
'_n_src',linop%n_src))
253 call mpl%ncerr(subr,nf90_get_att(ncid,nf90_global,trim(linop%prefix)//
'_n_dst',linop%n_dst))
254 call mpl%ncerr(subr,nf90_get_att(ncid,nf90_global,trim(linop%prefix)//
'_nvec',nvec))
257 if (isnotmsi(nvec))
then 258 call linop%alloc(nvec)
263 if (linop%n_s>0)
then 265 call mpl%ncerr(subr,nf90_inq_varid(ncid,trim(linop%prefix)//
'_row',row_id))
266 call mpl%ncerr(subr,nf90_inq_varid(ncid,trim(linop%prefix)//
'_col',col_id))
267 if (isnotmsi(linop%nvec))
then 268 if (linop%nvec>0)
call mpl%ncerr(subr,nf90_inq_varid(ncid,trim(linop%prefix)//
'_Svec',svec_id))
270 call mpl%ncerr(subr,nf90_inq_varid(ncid,trim(linop%prefix)//
'_S',s_id))
274 call mpl%ncerr(subr,nf90_get_var(ncid,row_id,linop%row))
275 call mpl%ncerr(subr,nf90_get_var(ncid,col_id,linop%col))
276 if (isnotmsi(linop%nvec))
then 277 if (linop%nvec>0)
call mpl%ncerr(subr,nf90_get_var(ncid,svec_id,linop%Svec))
279 call mpl%ncerr(subr,nf90_get_var(ncid,s_id,linop%S))
294 class(linop_type),
intent(in) :: linop
295 type(mpl_type),
intent(in) :: mpl
296 integer,
intent(in) :: ncid
299 integer :: n_s_id,nvec_id,row_id,col_id,S_id,Svec_id
300 character(len=1024) :: subr =
'linop_write' 303 call mpl%ncerr(subr,nf90_redef(ncid))
306 call mpl%ncerr(subr,nf90_put_att(ncid,nf90_global,trim(linop%prefix)//
'_n_src',linop%n_src))
307 call mpl%ncerr(subr,nf90_put_att(ncid,nf90_global,trim(linop%prefix)//
'_n_dst',linop%n_dst))
308 call mpl%ncerr(subr,nf90_put_att(ncid,nf90_global,trim(linop%prefix)//
'_nvec',linop%nvec))
310 if (linop%n_s>0)
then 312 call mpl%ncerr(subr,nf90_def_dim(ncid,trim(linop%prefix)//
'_n_s',linop%n_s,n_s_id))
313 if (isnotmsi(linop%nvec).and.(linop%nvec>0))
call mpl%ncerr(subr,nf90_def_dim(ncid,trim(linop%prefix)//
'_nvec',linop%nvec, &
317 call mpl%ncerr(subr,nf90_def_var(ncid,trim(linop%prefix)//
'_row',nf90_int,(/n_s_id/),row_id))
318 call mpl%ncerr(subr,nf90_def_var(ncid,trim(linop%prefix)//
'_col',nf90_int,(/n_s_id/),col_id))
319 if (isnotmsi(linop%nvec))
then 320 if (linop%nvec>0)
call mpl%ncerr(subr,nf90_def_var(ncid,trim(linop%prefix)//
'_Svec',ncfloat,(/n_s_id,nvec_id/),svec_id))
322 call mpl%ncerr(subr,nf90_def_var(ncid,trim(linop%prefix)//
'_S',ncfloat,(/n_s_id/),s_id))
326 call mpl%ncerr(subr,nf90_enddef(ncid))
329 call mpl%ncerr(subr,nf90_put_var(ncid,row_id,linop%row))
330 call mpl%ncerr(subr,nf90_put_var(ncid,col_id,linop%col))
331 if (isnotmsi(linop%nvec))
then 332 if (linop%nvec>0)
call mpl%ncerr(subr,nf90_put_var(ncid,svec_id,linop%Svec))
334 call mpl%ncerr(subr,nf90_put_var(ncid,s_id,linop%S))
338 call mpl%ncerr(subr,nf90_enddef(ncid))
347 subroutine linop_apply(linop,mpl,fld_src,fld_dst,ivec,mssrc,msdst)
352 class(linop_type),
intent(in) :: linop
353 type(mpl_type),
intent(in) :: mpl
354 real(kind_real),
intent(in) :: fld_src(linop%n_src)
355 real(kind_real),
intent(out) :: fld_dst(linop%n_dst)
356 integer,
intent(in),
optional :: ivec
357 logical,
intent(in),
optional :: mssrc
358 logical,
intent(in),
optional :: msdst
362 logical :: lmssrc,lmsdst,valid
363 logical,
allocatable :: missing(:)
367 if (minval(linop%col)<1)
call mpl%abort(
'col<1 for linear operation '//trim(linop%prefix))
368 if (maxval(linop%col)>linop%n_src)
call mpl%abort(
'col>n_src for linear operation '//trim(linop%prefix))
369 if (minval(linop%row)<1)
call mpl%abort(
'row<1 for linear operation '//trim(linop%prefix))
370 if (maxval(linop%row)>linop%n_dst)
call mpl%abort(
'row>n_dst for linear operation '//trim(linop%prefix))
371 if (
present(ivec))
then 372 if (any(isnan(linop%Svec)))
call mpl%abort(
'NaN in Svec for linear operation '//trim(linop%prefix))
374 if (any(isnan(linop%S)))
call mpl%abort(
'NaN in S for linear operation '//trim(linop%prefix))
378 if (any(fld_src>huge(1.0)))
call mpl%abort(
'Overflowing number in fld_src for linear operation '//trim(linop%prefix))
379 if (any(isnan(fld_src)))
call mpl%abort(
'NaN in fld_src for linear operation '//trim(linop%prefix))
385 if (
present(mssrc)) lmssrc = mssrc
387 if (
present(msdst)) lmsdst = msdst
389 allocate(missing(linop%n_dst))
397 valid = isnotmsr(fld_src(linop%col(i_s)))
404 if (
present(ivec))
then 405 fld_dst(linop%row(i_s)) = fld_dst(linop%row(i_s))+linop%Svec(i_s,ivec)*fld_src(linop%col(i_s))
407 fld_dst(linop%row(i_s)) = fld_dst(linop%row(i_s))+linop%S(i_s)*fld_src(linop%col(i_s))
411 if (lmsdst) missing(linop%row(i_s)) = .false.
417 do i_dst=1,linop%n_dst
418 if (missing(i_dst))
call msr(fld_dst(i_dst))
424 if (any(isnan(fld_dst)))
call mpl%abort(
'NaN in fld_dst for linear operation '//trim(linop%prefix))
438 class(linop_type),
intent(in) :: linop
439 type(mpl_type),
intent(in) :: mpl
440 real(kind_real),
intent(in) :: fld_dst(linop%n_dst)
441 real(kind_real),
intent(out) :: fld_src(linop%n_src)
442 integer,
intent(in),
optional :: ivec
449 if (minval(linop%col)<1)
call mpl%abort(
'col<1 for adjoint linear operation '//trim(linop%prefix))
450 if (maxval(linop%col)>linop%n_src)
call mpl%abort(
'col>n_src for adjoint linear operation '//trim(linop%prefix))
451 if (minval(linop%row)<1)
call mpl%abort(
'row<1 for adjoint linear operation '//trim(linop%prefix))
452 if (maxval(linop%row)>linop%n_dst)
call mpl%abort(
'row>n_dst for adjoint linear operation '//trim(linop%prefix))
453 if (
present(ivec))
then 454 if (any(isnan(linop%Svec)))
call mpl%abort(
'NaN in Svec for adjoint linear operation '//trim(linop%prefix))
456 if (any(isnan(linop%S)))
call mpl%abort(
'NaN in S for adjoint linear operation '//trim(linop%prefix))
460 if (any(fld_dst>huge(1.0)))
call mpl%abort(
'Overflowing number in fld_dst for adjoint linear operation '//trim(linop%prefix))
461 if (any(isnan(fld_dst)))
call mpl%abort(
'NaN in fld_dst for adjoint linear operation '//trim(linop%prefix))
469 if (
present(ivec))
then 470 fld_src(linop%col(i_s)) = fld_src(linop%col(i_s))+linop%Svec(i_s,ivec)*fld_dst(linop%row(i_s))
472 fld_src(linop%col(i_s)) = fld_src(linop%col(i_s))+linop%S(i_s)*fld_dst(linop%row(i_s))
478 if (any(isnan(fld_src)))
call mpl%abort(
'NaN in fld_src for adjoint linear operation '//trim(linop%prefix))
492 class(linop_type),
intent(in) :: linop
493 type(mpl_type),
intent(in) :: mpl
494 real(kind_real),
intent(inout) :: fld(linop%n_src)
495 integer,
intent(in),
optional :: ivec
498 integer :: i_s,ithread
499 real(kind_real) :: fld_arr(linop%n_dst,mpl%nthread)
503 if (minval(linop%col)<1)
call mpl%abort(
'col<1 for symmetric linear operation '//trim(linop%prefix))
504 if (maxval(linop%col)>linop%n_src)
call mpl%abort(
'col>n_src for symmetric linear operation '//trim(linop%prefix))
505 if (minval(linop%row)<1)
call mpl%abort(
'row<1 for symmetric linear operation '//trim(linop%prefix))
506 if (maxval(linop%row)>linop%n_src)
call mpl%abort(
'row>n_dst for symmetric linear operation '//trim(linop%prefix))
507 if (
present(ivec))
then 508 if (any(isnan(linop%Svec)))
call mpl%abort(
'NaN in Svec for symmetric linear operation '//trim(linop%prefix))
510 if (any(isnan(linop%S)))
call mpl%abort(
'NaN in S for symmetric linear operation '//trim(linop%prefix))
514 if (any(fld>huge(1.0)))
call mpl%abort(
'Overflowing number in fld for symmetric linear operation '//trim(linop%prefix))
515 if (any(isnan(fld)))
call mpl%abort(
'NaN in fld for symmetric linear operation '//trim(linop%prefix))
524 if (
present(ivec))
then 525 fld_arr(linop%row(i_s),ithread) = fld_arr(linop%row(i_s),ithread)+linop%Svec(i_s,ivec)*fld(linop%col(i_s))
526 if (linop%col(i_s)/=linop%row(i_s)) fld_arr(linop%col(i_s),ithread) = fld_arr(linop%col(i_s),ithread) &
527 & +linop%Svec(i_s,ivec)*fld(linop%row(i_s))
529 fld_arr(linop%row(i_s),ithread) = fld_arr(linop%row(i_s),ithread)+linop%S(i_s)*fld(linop%col(i_s))
530 if (linop%col(i_s)/=linop%row(i_s)) fld_arr(linop%col(i_s),ithread) = fld_arr(linop%col(i_s),ithread) &
531 & +linop%S(i_s)*fld(linop%row(i_s))
538 do ithread=1,mpl%nthread
539 fld = fld+fld_arr(:,ithread)
544 if (any(isnan(fld)))
call mpl%abort(
'NaN in fld for symmetric linear operation '//trim(linop%prefix))
558 class(linop_type),
intent(inout) :: linop
559 integer,
intent(inout) :: n_s
560 integer,
intent(in) :: row
561 integer,
intent(in) :: col
562 real(kind_real),
intent(in) :: S
565 type(linop_type) :: linop_tmp
569 if (n_s>linop%n_s)
then 571 linop_tmp = linop%copy()
575 linop%n_s = 2*linop_tmp%n_s
579 linop%row(1:linop_tmp%n_s) = linop_tmp%row
580 linop%col(1:linop_tmp%n_s) = linop_tmp%col
581 linop%S(1:linop_tmp%n_s) = linop_tmp%S
584 call linop_tmp%dealloc
603 class(linop_type),
intent(inout) :: linop
604 type(mpl_type),
intent(in) :: mpl
605 integer,
intent(in) :: n_s_arr(mpl%nthread)
606 type(linop_type),
intent(in) :: linop_arr(mpl%nthread)
609 integer :: ithread,offset
612 linop%n_s = sum(n_s_arr)
619 do ithread=1,mpl%nthread
620 linop%row(offset+1:offset+n_s_arr(ithread)) = linop_arr(ithread)%row(1:n_s_arr(ithread))
621 linop%col(offset+1:offset+n_s_arr(ithread)) = linop_arr(ithread)%col(1:n_s_arr(ithread))
622 linop%S(offset+1:offset+n_s_arr(ithread)) = linop_arr(ithread)%S(1:n_s_arr(ithread))
623 offset = offset+n_s_arr(ithread)
632 subroutine linop_interp_from_lat_lon(linop,mpl,rng,n_src,lon_src,lat_src,mask_src,n_dst,lon_dst,lat_dst,mask_dst,interp_type)
637 class(linop_type),
intent(inout) :: linop
638 type(mpl_type),
intent(inout) :: mpl
639 type(rng_type),
intent(inout) :: rng
640 integer,
intent(in) :: n_src
641 real(kind_real),
intent(in) :: lon_src(n_src)
642 real(kind_real),
intent(in) :: lat_src(n_src)
643 logical,
intent(in) :: mask_src(n_src)
644 integer,
intent(in) :: n_dst
645 real(kind_real),
intent(in) :: lon_dst(n_dst)
646 real(kind_real),
intent(in) :: lat_dst(n_dst)
647 logical,
intent(in) :: mask_dst(n_dst)
648 character(len=*),
intent(in) :: interp_type
651 integer :: n_src_eff,i_src,i_src_eff
652 integer,
allocatable :: src_eff_to_src(:)
653 real(kind_real),
allocatable :: lon_src_eff(:),lat_src_eff(:)
654 logical,
allocatable :: mask_src_eff(:)
655 type(kdtree_type) :: kdtree
656 type(mesh_type) :: mesh
659 n_src_eff = count(mask_src)
662 allocate(src_eff_to_src(n_src_eff))
663 allocate(lon_src_eff(n_src_eff))
664 allocate(lat_src_eff(n_src_eff))
665 allocate(mask_src_eff(n_src_eff))
670 if (mask_src(i_src))
then 671 i_src_eff = i_src_eff+1
672 src_eff_to_src(i_src_eff) = i_src
675 lon_src_eff = lon_src(src_eff_to_src)
676 lat_src_eff = lat_src(src_eff_to_src)
677 mask_src_eff = .true.
680 call mesh%create(mpl,rng,n_src_eff,lon_src_eff,lat_src_eff)
683 call kdtree%create(mpl,n_src_eff,lon_src_eff,lat_src_eff)
686 call linop%interp(mpl,mesh,kdtree,n_src_eff,mask_src_eff,n_dst,lon_dst,lat_dst,mask_dst,interp_type)
690 linop%col = src_eff_to_src(linop%col)
701 subroutine linop_interp_from_mesh_kdtree(linop,mpl,mesh,kdtree,n_src,mask_src,n_dst,lon_dst,lat_dst,mask_dst,interp_type)
706 class(linop_type),
intent(inout) :: linop
707 type(mpl_type),
intent(inout) :: mpl
708 type(mesh_type),
intent(in) :: mesh
709 type(kdtree_type),
intent(in) :: kdtree
710 integer,
intent(in) :: n_src
711 logical,
intent(in) :: mask_src(n_src)
712 integer,
intent(in) :: n_dst
713 real(kind_real),
intent(in) :: lon_dst(n_dst)
714 real(kind_real),
intent(in) :: lat_dst(n_dst)
715 logical,
intent(in) :: mask_dst(n_dst)
716 character(len=*),
intent(in) :: interp_type
719 integer :: i,i_src,i_dst,nn_index(1),n_s,ib(3),nnat,inat,np,iproc,offset,i_s
720 integer :: i_dst_s(mpl%nproc),i_dst_e(mpl%nproc),n_dst_loc(mpl%nproc),i_dst_loc,proc_to_n_s(mpl%nproc)
721 integer,
allocatable :: natis(:),row(:),col(:)
722 real(kind_real) :: nn_dist(1),b(3)
723 real(kind_real),
allocatable :: area_polygon(:),area_polygon_new(:),natwgt(:),S(:)
725 logical,
allocatable :: missing(:)
726 type(mesh_type) :: meshnew
727 type(fckit_mpi_status) :: status
730 call mpl%split(n_dst,i_dst_s,i_dst_e,n_dst_loc)
734 if (trim(interp_type)==
'bilin')
then 737 elseif (trim(interp_type)==
'natural')
then 740 allocate(area_polygon(mesh%n))
741 allocate(area_polygon_new(
nnatmax))
742 allocate(natis(mesh%n))
745 call mpl%abort(
'wrong interpolation type')
747 allocate(row(np*n_dst_loc(mpl%myproc)))
748 allocate(col(np*n_dst_loc(mpl%myproc)))
749 allocate(s(np*n_dst_loc(mpl%myproc)))
751 if (trim(interp_type)==
'natural')
then 756 call mesh%polygon(mesh%n,natis,area_polygon)
760 write(mpl%info,
'(a10,a)',advance=
'no')
'',
'Compute interpolation: ' 762 call mpl%prog_init(n_dst_loc(mpl%myproc))
764 do i_dst_loc=1,n_dst_loc(mpl%myproc)
766 i_dst = i_dst_s(mpl%myproc)+i_dst_loc-1
768 if (mask_dst(i_dst))
then 770 call kdtree%find_nearest_neighbors(lon_dst(i_dst),lat_dst(i_dst),1,nn_index,nn_dist)
772 if (abs(nn_dist(1))>0.0)
then 774 call mesh%barycentric(lon_dst(i_dst),lat_dst(i_dst),nn_index(1),b,ib)
775 if (sum(b)>0.0) b = b/sum(b)
777 if (inf(b(i),
s_inf)) b(i) = 0.0
779 if (sum(b)>0.0) b = b/sum(b)
782 if (all(mask_src(mesh%order(ib))))
then 784 if (trim(interp_type)==
'bilin')
then 790 col(n_s) = mesh%order(ib(i))
794 elseif (trim(interp_type)==
'natural')
then 798 meshnew = mesh%copy()
801 call meshnew%addnode(mpl,lon_dst(i_dst),lat_dst(i_dst))
804 i_src = meshnew%lend(meshnew%n)
809 natis(nnat) = abs(meshnew%list(i_src))
810 i_src = meshnew%lptr(i_src)
811 loop = (i_src/=meshnew%lend(meshnew%n))
814 if (all(mask_src(natis(1:nnat))))
then 816 call meshnew%polygon(nnat,natis(1:nnat),area_polygon_new(1:nnat))
820 natwgt(1:nnat) = area_polygon(natis(1:nnat))-area_polygon_new(1:nnat)
821 if (sum(natwgt(1:nnat))>0.0) natwgt(1:nnat) = natwgt(1:nnat)/sum(natwgt(1:nnat))
823 if (inf(natwgt(inat),
s_inf)) natwgt(inat) = 0.0
825 if (sum(natwgt(1:nnat))>0.0) natwgt(1:nnat) = natwgt(1:nnat)/sum(natwgt(1:nnat))
829 if (natwgt(inat)>0.0)
then 832 col(n_s) = mesh%order(natis(inat))
833 s(n_s) = natwgt(inat)
844 col(n_s) = nn_index(1)
850 call mpl%prog_print(i_dst_loc)
852 write(mpl%info,
'(a)')
'100%' 856 call mpl%f_comm%allgather(n_s,proc_to_n_s)
859 linop%n_s = sum(proc_to_n_s)
868 if (proc_to_n_s(iproc)>0)
then 869 if (iproc==mpl%ioproc)
then 871 linop%row(offset+1:offset+proc_to_n_s(iproc)) = row(1:proc_to_n_s(iproc))
872 linop%col(offset+1:offset+proc_to_n_s(iproc)) = col(1:proc_to_n_s(iproc))
873 linop%S(offset+1:offset+proc_to_n_s(iproc)) = s(1:proc_to_n_s(iproc))
876 call mpl%f_comm%receive(linop%row(offset+1:offset+proc_to_n_s(iproc)),iproc-1,mpl%tag,status)
877 call mpl%f_comm%receive(linop%col(offset+1:offset+proc_to_n_s(iproc)),iproc-1,mpl%tag+1,status)
878 call mpl%f_comm%receive(linop%S(offset+1:offset+proc_to_n_s(iproc)),iproc-1,mpl%tag+2,status)
883 offset = offset+proc_to_n_s(iproc)
888 call mpl%f_comm%send(row(1:n_s),mpl%ioproc-1,mpl%tag)
889 call mpl%f_comm%send(col(1:n_s),mpl%ioproc-1,mpl%tag+1)
890 call mpl%f_comm%send(s(1:n_s),mpl%ioproc-1,mpl%tag+2)
893 call mpl%update_tag(3)
896 call mpl%f_comm%broadcast(linop%row,mpl%ioproc-1)
897 call mpl%f_comm%broadcast(linop%col,mpl%ioproc-1)
898 call mpl%f_comm%broadcast(linop%S,mpl%ioproc-1)
901 call linop%interp_missing(mpl,n_dst,lon_dst,lat_dst,mask_dst,interp_type)
904 allocate(missing(n_dst))
907 if (mask_dst(i_dst)) missing(i_dst) = .true.
910 missing(linop%row(i_s)) = .false.
912 if (any(missing))
call mpl%abort(
'missing destination points in interp_from_mesh_kdtree')
920 subroutine linop_interp_grid(linop,mpl,rng,geom,il0i,nc1,c1_to_c0,mask_check,vbot,vtop,interp_type,interp_base)
925 class(linop_type),
intent(inout) :: linop
926 type(mpl_type),
intent(inout) :: mpl
927 type(rng_type),
intent(inout) :: rng
928 type(geom_type),
intent(in) :: geom
929 integer,
intent(in) :: il0i
930 integer,
intent(in) :: nc1
931 integer,
intent(in) :: c1_to_c0(nc1)
932 logical,
intent(in) :: mask_check
933 integer,
intent(in) :: vbot(nc1)
934 integer,
intent(in) :: vtop(nc1)
935 character(len=*),
intent(in) :: interp_type
936 type(linop_type),
intent(inout) :: interp_base
939 integer :: ic0,ic1,jc0,jc1,i_s
940 real(kind_real) :: renorm(geom%nc0)
941 real(kind_real),
allocatable :: lon_c1(:),lat_c1(:),lon_col(:),lat_col(:)
942 logical :: test_c0(geom%nc0)
943 logical,
allocatable :: mask_c1(:),mask_extra(:),valid(:)
945 if (.not.
allocated(interp_base%row))
then 947 allocate(lon_c1(nc1))
948 allocate(lat_c1(nc1))
949 allocate(mask_c1(nc1))
952 lon_c1 = geom%lon(c1_to_c0)
953 lat_c1 = geom%lat(c1_to_c0)
954 mask_c1 = geom%mask_hor_c0(c1_to_c0)
957 call interp_base%interp(mpl,rng,nc1,lon_c1,lat_c1,mask_c1,geom%nc0,geom%lon,geom%lat,geom%mask_hor_c0,interp_type)
961 allocate(valid(interp_base%n_s))
962 allocate(mask_extra(nc1))
965 do i_s=1,interp_base%n_s
966 ic0 = interp_base%row(i_s)
967 jc1 = interp_base%col(i_s)
969 valid(i_s) = geom%mask_c0(ic0,il0i).and.geom%mask_c0(jc0,il0i)
973 write(mpl%info,
'(a10,a,i3,a)',advance=
'no')
'',
'Sublevel ',il0i,
': ' 977 allocate(lon_col(nc1))
978 allocate(lat_col(nc1))
981 lon_col = geom%lon(c1_to_c0)
982 lat_col = geom%lat(c1_to_c0)
985 call interp_base%interp_check_mask(mpl,geom,valid,il0i,lon_col=lon_col,lat_col=lat_col)
988 if (geom%nl0i>1)
then 993 if (geom%mask_c0(ic0,il0i).and.((il0i<vbot(ic1)).or.(il0i>vtop(ic1)))) mask_extra(ic1) = .true.
997 do i_s=1,interp_base%n_s
999 ic1 = interp_base%col(i_s)
1000 if (mask_extra(ic1)) valid(i_s) = .false.
1003 if (count(mask_extra)>0)
then 1004 write(mpl%info,
'(a10,a,i5)')
'',
'Extrapolated points: ',count(mask_extra)
1005 call flush(mpl%info)
1008 mask_extra = .false.
1013 do i_s=1,interp_base%n_s
1014 if (valid(i_s)) renorm(interp_base%row(i_s)) = renorm(interp_base%row(i_s))+interp_base%S(i_s)
1019 linop%n_dst = geom%nc0
1020 linop%n_s = count(valid)
1023 do i_s=1,interp_base%n_s
1024 if (valid(i_s))
then 1025 linop%n_s = linop%n_s+1
1026 linop%row(linop%n_s) = interp_base%row(i_s)
1027 linop%col(linop%n_s) = interp_base%col(i_s)
1028 linop%S(linop%n_s) = interp_base%S(i_s)/renorm(interp_base%row(i_s))
1033 call interp_base%dealloc
1036 call linop%interp_missing(mpl,geom%nc0,geom%lon,geom%lat,geom%mask_c0(:,il0i),interp_type)
1039 test_c0 = geom%mask_c0(:,il0i)
1041 test_c0(linop%row(i_s)) = .false.
1043 if (any(test_c0))
call mpl%abort(
'error with the grid interpolation row')
1047 deallocate(mask_extra)
1060 class(linop_type),
intent(inout) :: linop
1061 type(mpl_type),
intent(inout) :: mpl
1062 type(geom_type),
intent(in) :: geom
1063 logical,
intent(inout) :: valid(linop%n_s)
1064 real(kind_real),
intent(in),
optional :: lon_row(linop%n_dst)
1065 real(kind_real),
intent(in),
optional :: lat_row(linop%n_dst)
1066 real(kind_real),
intent(in),
optional :: lon_col(linop%n_src)
1067 real(kind_real),
intent(in),
optional :: lat_col(linop%n_src)
1070 integer :: i_s,il0,iproc
1071 integer :: i_s_s(mpl%nproc),i_s_e(mpl%nproc),n_s_loc(mpl%nproc),i_s_loc
1072 real(kind_real) :: llon_row,llat_row,llon_col,llat_col
1073 type(fckit_mpi_status) :: status
1076 call mpl%split(linop%n_s,i_s_s,i_s_e,n_s_loc)
1079 call mpl%prog_init(n_s_loc(mpl%myproc))
1081 do i_s_loc=1,n_s_loc(mpl%myproc)
1083 i_s = i_s_s(mpl%myproc)+i_s_loc-1
1085 if (valid(i_s))
then 1087 if (
present(lon_row).and.
present(lat_row))
then 1088 llon_row = lon_row(linop%row(i_s))
1089 llat_row = lat_row(linop%row(i_s))
1091 llon_row = geom%lon(linop%row(i_s))
1092 llat_row = geom%lat(linop%row(i_s))
1096 if (
present(lon_col).and.
present(lat_col))
then 1097 llon_col = lon_col(linop%col(i_s))
1098 llat_col = lat_col(linop%col(i_s))
1100 llon_col = geom%lon(linop%col(i_s))
1101 llat_col = geom%lat(linop%col(i_s))
1105 call geom%check_arc(il0,llon_row,llat_row,llon_col,llat_col,valid(i_s))
1109 call mpl%prog_print(i_s_loc)
1112 write(mpl%info,
'(a)')
'100%' 1113 call flush(mpl%info)
1117 do iproc=1,mpl%nproc
1118 if (n_s_loc(iproc)>0)
then 1119 if (iproc/=mpl%ioproc)
then 1121 call mpl%f_comm%receive(valid(i_s_s(iproc):i_s_e(iproc)),iproc-1,mpl%tag,status)
1126 if (n_s_loc(mpl%myproc)>0)
then 1128 call mpl%f_comm%send(valid(i_s_s(mpl%myproc):i_s_e(mpl%myproc)),mpl%ioproc-1,mpl%tag)
1131 call mpl%update_tag(1)
1134 call mpl%f_comm%broadcast(valid,mpl%ioproc-1)
1147 class(linop_type),
intent(inout) :: linop
1148 type(mpl_type),
intent(in) :: mpl
1149 integer,
intent(in) :: n_dst
1150 real(kind_real),
intent(in) :: lon_dst(n_dst)
1151 real(kind_real),
intent(in) :: lat_dst(n_dst)
1152 logical,
intent(in) :: mask_dst(n_dst)
1153 character(len=*),
intent(in) :: interp_type
1156 integer :: i_dst,i_s
1158 real(kind_real) :: dum(1)
1159 logical :: missing(n_dst),lmask(n_dst),found
1160 type(linop_type) :: interp_tmp
1161 type(kdtree_type) :: kdtree
1166 if (mask_dst(i_dst)) missing(i_dst) = .true.
1169 missing(linop%row(i_s)) = .false.
1172 if (count(missing)>0)
then 1173 write(mpl%info,
'(a10,a,i6,a)')
'',
'Deal with ',count(missing),
' missing interpolation points' 1176 if (trim(interp_type)==
'bilin')
then 1177 interp_tmp%n_s = linop%n_s+3*count(missing)
1178 elseif (trim(interp_type)==
'natural')
then 1179 interp_tmp%n_s = linop%n_s+40*count(missing)
1181 call mpl%abort(
'wrong interpolation')
1183 call interp_tmp%alloc
1186 interp_tmp%row(1:linop%n_s) = linop%row
1187 interp_tmp%col(1:linop%n_s) = linop%col
1188 interp_tmp%S(1:linop%n_s) = linop%S
1191 interp_tmp%n_s = linop%n_s
1194 lmask = mask_dst.and.(.not.missing)
1197 call kdtree%create(mpl,n_dst,lon_dst,lat_dst,mask=lmask)
1200 if (missing(i_dst))
then 1202 call kdtree%find_nearest_neighbors(lon_dst(i_dst),lat_dst(i_dst),1,nn,dum)
1207 if (linop%row(i_s)==nn(1))
then 1209 interp_tmp%n_s = interp_tmp%n_s+1
1210 interp_tmp%row(interp_tmp%n_s) = i_dst
1211 interp_tmp%col(interp_tmp%n_s) = linop%col(i_s)
1212 interp_tmp%S(interp_tmp%n_s) = linop%S(i_s)
1215 if (.not.found)
call mpl%abort(
'missing point not found')
1221 linop%n_s = interp_tmp%n_s
1225 linop%row = interp_tmp%row(1:linop%n_s)
1226 linop%col = interp_tmp%col(1:linop%n_s)
1227 linop%S = interp_tmp%S(1:linop%n_s)
1231 call interp_tmp%dealloc
subroutine linop_alloc(linop, nvec)
integer, parameter nnatmax
subroutine linop_interp_missing(linop, mpl, n_dst, lon_dst, lat_dst, mask_dst, interp_type)
subroutine linop_gather(linop, mpl, n_s_arr, linop_arr)
subroutine linop_interp_from_lat_lon(linop, mpl, rng, n_src, lon_src, lat_src, mask_src, n_dst, lon_dst, lat_dst, mask_dst, interp_type)
subroutine, public copy(self, rhs)
subroutine linop_read(linop, mpl, ncid)
subroutine linop_interp_from_mesh_kdtree(linop, mpl, mesh, kdtree, n_src, mask_src, n_dst, lon_dst, lat_dst, mask_dst, interp_type)
type(linop_type) function linop_copy(linop)
subroutine linop_interp_check_mask(linop, mpl, geom, valid, il0, lon_row, lat_row, lon_col, lat_col)
subroutine linop_apply_sym(linop, mpl, fld, ivec)
subroutine linop_apply_ad(linop, mpl, fld_dst, fld_src, ivec)
integer, parameter reorder_max
subroutine linop_write(linop, mpl, ncid)
subroutine linop_dealloc(linop)
subroutine linop_reorder(linop, mpl)
subroutine linop_interp_grid(linop, mpl, rng, geom, il0i, nc1, c1_to_c0, mask_check, vbot, vtop, interp_type, interp_base)
subroutine linop_apply(linop, mpl, fld_src, fld_dst, ivec, mssrc, msdst)
subroutine linop_add_op(linop, n_s, row, col, S)
real(kind_real), parameter s_inf
logical, parameter check_data
integer, parameter, public kind_real