1 # 1 "/Users/miesch/JEDI/code/working_copy/public/fv3-bundle/saber/src/saber/bump/tools_func.fypp"
2 # 1 "/Users/miesch/JEDI/code/working_copy/public/fv3-bundle/saber/src/saber/bump/../instrumentation.fypp" 1
3 # 1 "/Users/miesch/JEDI/code/working_copy/public/fv3-bundle/saber/src/saber/bump/../subr_list.fypp" 1
12 # 726 "/Users/miesch/JEDI/code/working_copy/public/fv3-bundle/saber/src/saber/bump/../subr_list.fypp"
13 # 2 "/Users/miesch/JEDI/code/working_copy/public/fv3-bundle/saber/src/saber/bump/../instrumentation.fypp" 2
22 # 112 "/Users/miesch/JEDI/code/working_copy/public/fv3-bundle/saber/src/saber/bump/../instrumentation.fypp"
23 # 2 "/Users/miesch/JEDI/code/working_copy/public/fv3-bundle/saber/src/saber/bump/tools_func.fypp" 2
33 use atlas_module,
only: atlas_geometry
34 use iso_c_binding,
only: c_int16_t,c_int32_t
36 use tools_const,
only:
zero,
tenth,
hundredth,
half,
quarter,
one,
two,
three,
four,
five,
eight,
ten,
thousand,
pi,
deg2rad,
rad2deg
49 integer,
parameter ::
m = 0
52 function c_fletcher32(n,var) bind(c,name='fletcher32')
result(hash)
53 use iso_c_binding,
only: c_int16_t,c_int32_t
54 integer(c_int32_t) :: n
55 integer(c_int16_t) :: var(*)
56 integer(c_int32_t) :: hash
146 public ::
fletcher32,
lonlatmod,
gridhash,
independent_levels,
lonlathash,
sphere_dist,
lonlat2xyz,
xyz2lonlat,
vector_product,
det, &
147 &
order_cc,
add,
divide,
fit_diag,
fit_func,
fit_lct,
lct_d2h,
lct_h2r,
lct_r2d,
check_cond,
cholesky,
syminv,
histogram, &
173 value =
c_fletcher32(
size(transfer(var,(/0_kind_short/))),transfer(var,(/0_kind_short/)))
189 real(kind_real),
intent(inout) :: lon
190 real(kind_real),
intent(inout) :: lat
202 elseif (lat<-
half*
pi)
then
210 elseif (lon<-
pi)
then
215 if (abs(lat)>(
half-1.0e-6_kind_real)*
pi) lon =
zero
231 integer,
intent(in) :: ncx
232 integer,
intent(in) :: nlx
233 real(kind_real),
intent(in) :: lon_cx(ncx)
234 real(kind_real),
intent(in) :: lat_cx(ncx)
235 logical,
intent(in) :: mask_cx(ncx,nlx)
236 integer,
intent(out) :: grid_hash(0:nlx)
239 integer :: ilx,ncx_eff,icx_eff,icx
240 real(kind_real),
allocatable :: lonlat(:)
250 ncx_eff = count(mask_cx(:,ilx))
254 allocate(lonlat(2*ncx_eff))
259 if (mask_cx(icx,ilx))
then
261 lonlat(icx_eff) = lon_cx(icx)
263 lonlat(icx_eff) = lat_cx(icx)
278 grid_hash(0) =
fletcher32(real(grid_hash(1:nlx),kind_real))
295 integer,
intent(in) :: nlx
296 integer,
intent(in) :: grid_hash(nlx)
297 integer,
intent(out) :: nlxi
298 integer,
intent(out) :: lx_to_lxi(nlx)
299 integer,
intent(out) :: lxi_to_lx(nlx)
300 integer,
intent(in) :: ifmt
303 integer :: ilx,ilxi,jlx,jlxi,n
304 integer :: proc_to_grid_hash(mpl%nproc),grid_hash_glb(nlx)
305 character(len=1024) :: cfmt
315 call mpl%f_comm%allgather(grid_hash(ilx),proc_to_grid_hash)
322 if (all(grid_hash_glb(1:ilx-1)/=grid_hash_glb(ilx))) nlxi = nlxi+1
326 lxi_to_lx = mpl%msv%vali
331 lx_to_lxi(ilx) = ilxi
332 lxi_to_lx(ilxi) = ilx
334 if (all(grid_hash_glb(1:ilx-1)/=grid_hash_glb(ilx)))
then
337 lx_to_lxi(ilx) = ilxi
338 lxi_to_lx(ilxi) = ilx
342 if (grid_hash_glb(jlx)==grid_hash_glb(ilx))
then
343 jlxi = lx_to_lxi(jlx)
344 lx_to_lxi(ilx) = jlxi
352 write(cfmt,
'(a,i2.2,a)')
'(a',ifmt,
',a)'
353 write(mpl%info,trim(cfmt))
'',
'Compute independent levels: '
354 call mpl%flush(.false.)
356 ilx = lxi_to_lx(ilxi)
357 n = count(lx_to_lxi==ilxi)
365 write(mpl%info,trim(cfmt)) ilx,
'[',n,
'] '
366 call mpl%flush(.false.)
368 write(mpl%info,
'(a)')
''
387 integer,
intent(in),
optional :: il
407 value = aint((lontmp+
pi)*1.0e7_kind_real)+(lattmp+
half*
pi)*
tenth
408 if (
present(il))
value =
value+real(il*1e8,
kind_real)
424 real(kind_real),
intent(in) :: lon_i
425 real(kind_real),
intent(in) :: lat_i
426 real(kind_real),
intent(in) :: lon_f
427 real(kind_real),
intent(in) :: lat_f
428 real(kind_real),
intent(out) :: dist
431 type(atlas_geometry) :: ageometry
440 ageometry = atlas_geometry(
'UnitSphere')
460 real(kind_real),
intent(in) :: lon
461 real(kind_real),
intent(in) :: lat
462 real(kind_real),
intent(out) :: x
463 real(kind_real),
intent(out) :: y
464 real(kind_real),
intent(out) :: z
467 type(atlas_geometry) :: ageometry
475 if (mpl%msv%isnot(lat).and.mpl%msv%isnot(lon))
then
477 if (
inf(lon,-
pi).and.
sup(lon,
pi))
call mpl%abort(
'func_lonlat2xyz',
'wrong longitude')
478 if (
inf(lat,-
half*
pi).and.
sup(lat,-
half*
pi))
call mpl%abort(
'func_lonlat2xyz',
'wrong latitude')
481 ageometry = atlas_geometry(
'UnitSphere')
507 real(kind_real),
intent(in) :: x
508 real(kind_real),
intent(in) :: y
509 real(kind_real),
intent(in) :: z
510 real(kind_real),
intent(out) :: lon
511 real(kind_real),
intent(out) :: lat
514 type(atlas_geometry) :: ageometry
522 if (mpl%msv%isnot(x).and.mpl%msv%isnot(y).and.mpl%msv%isnot(z))
then
524 ageometry = atlas_geometry(
'UnitSphere')
527 call ageometry%xyz2lonlat(x,y,z,lon,lat)
552 real(kind_real),
intent(in) :: v1(3)
553 real(kind_real),
intent(in) :: v2(3)
554 real(kind_real),
intent(out) :: vp(3)
566 vp(1) = v1(2)*v2(3)-v1(3)*v2(2)
567 vp(2) = v1(3)*v2(1)-v1(1)*v2(3)
568 vp(3) = v1(1)*v2(2)-v1(2)*v2(1)
572 if (r>
zero) vp = vp/r
588 real(kind_real),
intent(in) :: v1(3)
589 real(kind_real),
intent(in) :: v2(3)
590 real(kind_real),
intent(in) :: v3(3)
591 real(kind_real),
intent(out) :: p
592 logical,
intent(out) :: cflag
596 real(kind_real) :: terms(6)
605 terms(1) = v1(2)*v2(3)*v3(1)
606 terms(2) = -v1(3)*v2(2)*v3(1)
607 terms(3) = v1(3)*v2(1)*v3(2)
608 terms(4) = -v1(1)*v2(3)*v3(2)
609 terms(5) = v1(1)*v2(2)*v3(3)
610 terms(6) = -v1(2)*v2(1)*v3(3)
618 if ((abs(terms(i))>
zero).and.
small(p,terms(i))) cflag = .false.
636 real(kind_real),
intent(in) :: lon
637 real(kind_real),
intent(in) :: lat
639 real(kind_real),
intent(in) :: x(n)
640 real(kind_real),
intent(in) :: y(n)
641 real(kind_real),
intent(in) :: z(n)
642 integer,
intent(out) :: order(n)
643 real(kind_real),
intent(out),
optional :: diff(n)
647 real(kind_real) :: rvec(3),costheta,sintheta,p(3),rvecxv(3),v(3),list(n)
648 real(kind_real),
allocatable :: list_save(:)
660 costheta = cos(
half*
pi-lat)
661 sintheta = sin(
half*
pi-lat)
666 p = (/x(i),y(i),z(i)/)
668 v = p*costheta+rvecxv*sintheta+rvec*sum(rvec*p)*(
one-costheta)
671 list(i) = atan2(v(2),v(1))
674 if (
present(diff))
then
676 allocate(list_save(n))
683 call qsort(n,list,order)
685 if (
present(diff))
then
687 diff(order(1)) = list_save(order(1))-list_save(order(n))+
two*
pi
689 diff(order(i)) = list_save(order(i))-list_save(order(i-1))
693 deallocate(list_save)
711 real(kind_real),
intent(in) :: val
712 real(kind_real),
intent(inout) :: cumul
713 real(kind_real),
intent(inout) :: num
714 real(kind_real),
intent(in),
optional :: wgt
717 real(kind_real) :: lwgt
727 if (
present(wgt)) lwgt = wgt
730 if (mpl%msv%isnot(val))
then
731 cumul = cumul+lwgt*val
750 real(kind_real),
intent(inout) :: val
751 real(kind_real),
intent(in) :: num
760 if (abs(num)>
zero)
then
775 subroutine func_fit_diag(mpl,nc3,nl0r,nl0,l0rl0_to_l0,disth,distv,coef,rh,rv,fit)
781 integer,
intent(in) :: nc3
782 integer,
intent(in) :: nl0r
783 integer,
intent(in) :: nl0
784 integer,
intent(in) :: l0rl0_to_l0(nl0r,nl0)
785 real(kind_real),
intent(in) :: disth(nc3)
786 real(kind_real),
intent(in) :: distv(nl0,nl0)
787 real(kind_real),
intent(in) :: coef(nl0)
788 real(kind_real),
intent(in) :: rh(nl0)
789 real(kind_real),
intent(in) :: rv(nl0)
790 real(kind_real),
intent(out) :: fit(nc3,nl0r,nl0)
793 integer :: jl0r,jl0,djl0,il0,kl0r,kl0,ic3,jc3,djc3,kc3,ip,jp,np,np_new,nc3max
794 integer :: plist(nc3*nl0r,2),plist_new(nc3*nl0r,2)
795 real(kind_real) :: rhsq,rvsq,distvsq,disttest,rhmax
796 real(kind_real) :: predistnorm(-1:1,nc3,-1:1,nl0),distnorm(nc3,nl0r)
797 logical :: add_to_front
812 if (disth(ic3)>rhmax)
exit
821 jl0 = max(1,min(il0+djl0,nl0))
824 if (mpl%msv%isnot(rh(il0)).and.mpl%msv%isnot(rh(jl0)))
then
825 rhsq =
half*(rh(il0)**2+rh(jl0)**2)
829 if (mpl%msv%isnot(rv(il0)).and.mpl%msv%isnot(rv(jl0)))
then
830 rvsq =
half*(rv(il0)**2+rv(jl0)**2)
837 distvsq = distv(jl0,il0)**2/rvsq
838 elseif (il0/=jl0)
then
847 jc3 = max(1,min(ic3+djc3,nc3max))
850 predistnorm(djc3,ic3,djl0,il0) = distvsq
854 predistnorm(djc3,ic3,djl0,il0) = predistnorm(djc3,ic3,djl0,il0)+(disth(jc3)-disth(ic3))**2/rhsq
855 elseif (ic3/=jc3)
then
856 predistnorm(djc3,ic3,djl0,il0) = predistnorm(djc3,ic3,djl0,il0)+
one
860 predistnorm(djc3,ic3,djl0,il0) = sqrt(predistnorm(djc3,ic3,djl0,il0))
873 if (l0rl0_to_l0(jl0r,il0)==il0) plist(1,2) = jl0r
876 distnorm(plist(1,1),plist(1,2)) =
zero
886 jl0 = l0rl0_to_l0(jl0r,il0)
889 do kc3=max(jc3-1,1),min(jc3+1,nc3max)
890 do kl0r=max(jl0r-1,1),min(jl0r+1,nl0r)
891 kl0 = l0rl0_to_l0(kl0r,il0)
892 disttest = distnorm(jc3,jl0r)+predistnorm(kc3-jc3,jc3,kl0-jl0,jl0)
894 if (disttest<
one)
then
896 if (disttest<distnorm(kc3,kl0r))
then
898 distnorm(kc3,kl0r) = disttest
901 add_to_front = .true.
903 if ((plist_new(jp,1)==kc3).and.(plist_new(jp,2)==kl0r))
then
904 add_to_front = .false.
909 if (add_to_front)
then
912 plist_new(np_new,1) = kc3
913 plist_new(np_new,2) = kl0r
923 plist(1:np,:) = plist_new(1:np,:)
928 jl0 = l0rl0_to_l0(jl0r,il0)
932 fit(jc3,jl0r,il0) =
fit_func(mpl,distnorm(jc3,jl0r))
940 jl0 = l0rl0_to_l0(jl0r,il0)
941 fit(:,jl0r,il0) = fit(:,jl0r,il0)*sqrt(coef(il0)*coef(jl0))
947 if (mpl%msv%is(coef(il0)).or.mpl%msv%is(rh(il0)).or.mpl%msv%is(rv(il0))) fit(:,:,il0) = mpl%msv%valr
949 jl0 = l0rl0_to_l0(jl0r,il0)
950 if (mpl%msv%is(coef(jl0)).or.mpl%msv%is(rh(jl0)).or.mpl%msv%is(rv(jl0))) fit(:,jl0r,il0) = mpl%msv%valr
978 if (distnorm<
half)
then
982 value =
one-20.0_kind_real/
three*distnorm**2*
value
983 else if (distnorm<
one)
then
989 value =
one-12.0_kind_real*distnorm*
value
990 value = -
value/(
three*distnorm)
1007 type(
mpl_type),
intent(inout) :: mpl
1020 if (distnorm<
zero)
call mpl%abort(
'func_fit_func',
'negative normalized distance')
1023 value =
gc99(distnorm)
1026 value = max(
value,
zero)
1037 subroutine func_fit_lct(mpl,nc,nl0,dxsq,dysq,dxdy,dzsq,dmask,nscales,D,coef,fit)
1042 type(
mpl_type),
intent(inout) :: mpl
1043 integer,
intent(in) :: nc
1044 integer,
intent(in) :: nl0
1045 real(kind_real),
intent(in) :: dxsq(nc,nl0)
1046 real(kind_real),
intent(in) :: dysq(nc,nl0)
1047 real(kind_real),
intent(in) :: dxdy(nc,nl0)
1048 real(kind_real),
intent(in) :: dzsq(nc,nl0)
1049 logical,
intent(in) :: dmask(nc,nl0)
1050 integer,
intent(in) :: nscales
1051 real(kind_real),
intent(in) :: D(4,nscales)
1052 real(kind_real),
intent(in) :: coef(nscales)
1053 real(kind_real),
intent(out) :: fit(nc,nl0)
1056 integer :: jl0,jc3,iscales
1057 real(kind_real) :: Dcoef(nscales),D11,D22,D33,D12,H11,H22,H33,H12,rsq
1069 dcoef = max(
dmin,min(coef,
one))
1070 dcoef = dcoef/sum(dcoef)
1072 do iscales=1,nscales
1074 d11 = max(
dmin,d(1,iscales))
1075 d22 = max(
dmin,d(2,iscales))
1077 d33 = max(
dmin,d(3,iscales))
1084 call lct_d2h(mpl,d11,d22,d33,d12,h11,h22,h33,h12)
1089 if (dmask(jc3,jl0))
then
1091 if (iscales==1) fit(jc3,jl0) =
zero
1094 rsq = h11*dxsq(jc3,jl0)+h22*dysq(jc3,jl0)+h33*dzsq(jc3,jl0)+
two*h12*dxdy(jc3,jl0)
1098 if (rsq<40.0_kind_real) fit(jc3,jl0) = fit(jc3,jl0)+dcoef(iscales)*exp(-
half*rsq)
1101 fit(jc3,jl0) = fit(jc3,jl0)+dcoef(iscales)*
matern(mpl,
m,sqrt(rsq))
1122 type(
mpl_type),
intent(inout) :: mpl
1123 real(kind_real),
intent(in) :: D11
1124 real(kind_real),
intent(in) :: D22
1125 real(kind_real),
intent(in) :: D33
1126 real(kind_real),
intent(in) :: D12
1127 real(kind_real),
intent(out) :: H11
1128 real(kind_real),
intent(out) :: H22
1129 real(kind_real),
intent(out) :: H33
1130 real(kind_real),
intent(out) :: H12
1133 real(kind_real) :: det
1142 det = d11*d22-d12**2
1150 call mpl%abort(
'func_lct_d2h',
'non-invertible tensor')
1172 type(
mpl_type),
intent(inout) :: mpl
1173 real(kind_real),
intent(in) :: H11
1174 real(kind_real),
intent(in) :: H22
1175 real(kind_real),
intent(in) :: H33
1176 real(kind_real),
intent(in) :: H12
1177 real(kind_real),
intent(out) :: rh
1178 real(kind_real),
intent(out) :: rv
1181 real(kind_real) :: tr,det,diff
1190 if ((h11<
zero).or.(h22<
zero))
call mpl%abort(
'func_lct_h2r',
'negative diagonal LCT coefficients')
1196 det = h11*h22-h12**2
1199 diff =
quarter*(h11-h22)**2+h12**2
1201 if (
half*tr>sqrt(diff))
then
1204 call mpl%abort(
'func_lct_h2r',
'non positive-definite LCT (eigenvalue)')
1207 call mpl%abort(
'func_lct_h2r',
'non positive-definite LCT (determinant)')
1231 real(kind_real),
intent(in) :: r
1232 real(kind_real),
intent(out) :: D
1257 real(kind_real),
intent(in) :: d1
1258 real(kind_real),
intent(in) :: d2
1259 real(kind_real),
intent(in) :: nod
1260 logical,
intent(out) :: valid
1263 real(kind_real) :: det,tr,diff,ev1,ev2
1274 diff =
quarter*(d1-d2)**2+d1*d2*nod**2
1278 ev1 =
half*tr+sqrt(diff)
1279 ev2 =
half*tr-sqrt(diff)
1307 type(
mpl_type),
intent(inout) :: mpl
1308 integer,
intent(in) ::
m
1325 if (
m<2)
call mpl%abort(
'func_matern',
'M should be larger than 2')
1326 if (mod(
m,2)>0)
call mpl%abort(
'func_matern',
'M should be even')
1335 value =
value+beta*(xtmp)**(
m-2-j)
1342 value =
value/beta+
one
1345 value =
value*exp(-xtmp)
1362 type(
mpl_type),
intent(inout) :: mpl
1363 integer,
intent(in) :: n
1364 real(kind_real),
intent(in) :: a(n,n)
1365 real(kind_real),
intent(out) :: u(n,n)
1368 integer :: nn,i,j,ij
1369 real(kind_real),
allocatable :: apack(:),upack(:)
1392 call cholesky(mpl,n,nn,apack,upack)
1423 type(
mpl_type),
intent(inout) :: mpl
1424 integer,
intent(in) :: n
1425 real(kind_real),
intent(in) :: a(n,n)
1426 real(kind_real),
intent(out) :: c(n,n)
1429 integer :: nn,i,j,ij
1430 real(kind_real),
allocatable :: apack(:),cpack(:)
1453 call syminv(mpl,n,nn,apack,cpack)
1483 type(
mpl_type),
intent(inout) :: mpl
1484 integer,
intent(in) :: nlist
1485 real(kind_real),
intent(in) :: list(nlist)
1486 integer,
intent(in) :: nbins
1487 real(kind_real),
intent(in) :: histmin
1488 real(kind_real),
intent(in) :: histmax
1489 real(kind_real),
intent(out) :: bins(nbins+1)
1490 real(kind_real),
intent(out) :: hist(nbins)
1493 integer :: ibins,ilist
1494 real(kind_real) :: delta
1504 if (nbins<=0)
call mpl%abort(
'func_histogram',
'the number of bins should be positive')
1505 if (histmax>histmin)
then
1506 if (minval(list,mask=mpl%msv%isnot(list))<histmin)
call mpl%abort(
'func_histogram',
'values below histogram minimum')
1507 if (maxval(list,mask=mpl%msv%isnot(list))>histmax)
call mpl%abort(
'func_histogram',
'values over histogram maximum')
1510 delta = (histmax-histmin)/real(nbins,kind_real)
1513 bins(ibins) = histmin+real(ibins-1,kind_real)*delta
1515 bins(nbins+1) = histmax
1518 bins(1) = bins(1)-1.0e-6_kind_real*delta
1519 bins(nbins+1) = bins(nbins+1)+1.0e-6_kind_real*delta
1524 if (mpl%msv%isnot(list(ilist)))
then
1527 do while (.not.found)
1529 if (ibins>nbins)
call mpl%abort(
'func_histogram',
'bin not found')
1530 if (
infeq(bins(ibins),list(ilist)).and.
inf(list(ilist),bins(ibins+1)))
then
1531 hist(ibins) = hist(ibins)+
one
1537 if (abs(sum(hist)-real(count(mpl%msv%isnot(list)),kind_real))>
half) &
1538 &
call mpl%abort(
'func_histogram',
'histogram sum is not equal to the number of valid elements')
1558 integer,
intent(in) :: nproc
1559 integer,
intent(in) :: proc_to_cx_offset(nproc)
1560 integer,
intent(in) :: icx
1575 iproc =
cx_to_proc(nproc,proc_to_cx_offset,icx)
1578 icxa = icx-proc_to_cx_offset(iproc)
1594 integer,
intent(in) :: nproc
1595 integer,
intent(in) :: proc_to_cx_offset(nproc)
1596 integer,
intent(in) :: icx
1609 if ((proc_to_cx_offset(iproc)<icx).and.(icx<=proc_to_cx_offset(iproc+1)))
then
1624 function func_cx_to_cxu(nproc,proc_to_cx_offset,proc_to_ncxa,myuniverse,icx)
result(icxu)
1629 integer,
intent(in) :: nproc
1630 integer,
intent(in) :: proc_to_cx_offset(nproc)
1631 integer,
intent(in) :: proc_to_ncxa(nproc)
1632 logical,
intent(in) :: myuniverse(nproc)
1633 integer,
intent(in) :: icx
1639 integer :: iproc,icxa,offset,jproc
1648 iproc =
cx_to_proc(nproc,proc_to_cx_offset,icx)
1650 if (myuniverse(iproc))
then
1652 icxa = icx-proc_to_cx_offset(iproc)
1657 if (myuniverse(jproc)) offset = offset+proc_to_ncxa(jproc)
Generic ranks, dimensions and types.