11 use atlas_module,
only: atlas_geometry
24 integer,
parameter ::
m = 0
27 function c_fletcher32(n,var) bind(c,name='fletcher32')
result(hash)
29 integer(kind=c_int32_t) :: n
30 integer(kind=c_int16_t) :: var(*)
31 integer(kind=c_int32_t) :: hash
38 &
add,
divide,
fit_diag,
fit_func,
fit_lct,
lct_d2h,
lct_h2r,
lct_r2d,
check_cond,
cholesky,
syminv,
pseudoinv,
histogram
77 elseif (lat<-0.5*
pi)
then
102 integer,
intent(in),
optional :: il
137 type(atlas_geometry) :: ageometry
140 ageometry = atlas_geometry(
"UnitSphere")
170 if (
sup(dist,maxdist))
then
172 theta = atan2(sin(lon_f-lon_i)*cos(lat_f),cos(lat_i)*sin(lat_f)-sin(lat_i)*cos(lat_f)*cos(lon_f-lon_i))
178 lat_f = asin(sin(lat_i)*cos(dist)+cos(lat_i)*sin(dist)*cos(theta))
179 lon_f = lon_i+atan2(sin(theta)*sin(dist)*cos(lat_i),cos(dist)-sin(lat_i)*sin(lat_f))
201 type(atlas_geometry) :: ageometry
202 character(len=1024),
parameter :: subr =
'lonlat2xyz'
204 if (mpl%msv%isnot(lat).and.mpl%msv%isnot(lon))
then
206 if (
inf(lon,-
pi).and.
sup(lon,
pi))
call mpl%abort(subr,
'wrong longitude')
207 if (
inf(lat,-0.5*
pi).and.
sup(lat,-0.5*
pi))
call mpl%abort(subr,
'wrong latitude')
210 ageometry = atlas_geometry(
"UnitSphere")
240 type(atlas_geometry) :: ageometry
242 if (mpl%msv%isnot(x).and.mpl%msv%isnot(y).and.mpl%msv%isnot(z))
then
244 ageometry = atlas_geometry(
"UnitSphere")
247 call ageometry%xyz2lonlat(x,y,z,lon,lat)
277 vp(1) = v1(2)*v2(3)-v1(3)*v2(2)
278 vp(2) = v1(3)*v2(1)-v1(1)*v2(3)
279 vp(3) = v1(1)*v2(2)-v1(2)*v2(1)
300 logical,
intent(out) :: cflag
307 terms(1) = v1(2)*v2(3)*v3(1)
308 terms(2) = -v1(3)*v2(2)*v3(1)
309 terms(3) = v1(3)*v2(1)*v3(2)
310 terms(4) = -v1(1)*v2(3)*v3(2)
311 terms(5) = v1(1)*v2(2)*v3(3)
312 terms(6) = -v1(2)*v2(1)*v3(3)
320 if ((abs(terms(i))>0.0).and.
small(p,terms(i))) cflag = .false.
329 subroutine add(mpl,val,cumul,num,wgt)
338 real(
kind_real),
intent(in),
optional :: wgt
345 if (
present(wgt)) lwgt = wgt
348 if (mpl%msv%isnot(val))
then
349 cumul = cumul+lwgt*val
369 if (abs(num)>0.0)
then
381 subroutine fit_diag(mpl,nc3,nl0r,nl0,l0rl0_to_l0,disth,distv,coef,rh,rv,fit)
387 integer,
intent(in) :: nc3
388 integer,
intent(in) :: nl0r
389 integer,
intent(in) :: nl0
390 integer,
intent(in) :: l0rl0_to_l0(nl0r,nl0)
392 real(
kind_real),
intent(in) :: distv(nl0,nl0)
396 real(
kind_real),
intent(out) :: fit(nc3,nl0r,nl0)
399 integer :: jl0r,jl0,djl0,il0,kl0r,kl0,ic3,jc3,djc3,kc3,ip,jp,np,np_new,nc3max
400 integer :: plist(nc3*nl0r,2),plist_new(nc3*nl0r,2)
401 real(
kind_real) :: rhsq,rvsq,distvsq,disttest,rhmax
402 real(
kind_real) :: predistnorm(-1:1,nc3,-1:1,nl0),distnorm(nc3,nl0r)
403 logical :: add_to_front
412 if (disth(ic3)>rhmax)
exit
421 jl0 = max(1,min(il0+djl0,nl0))
424 if (mpl%msv%isnot(rh(il0)).and.mpl%msv%isnot(rh(jl0)))
then
425 rhsq = 0.5*(rh(il0)**2+rh(jl0)**2)
429 if (mpl%msv%isnot(rv(il0)).and.mpl%msv%isnot(rv(jl0)))
then
430 rvsq = 0.5*(rv(il0)**2+rv(jl0)**2)
437 distvsq = distv(jl0,il0)**2/rvsq
438 elseif (il0/=jl0)
then
447 jc3 = max(1,min(ic3+djc3,nc3max))
450 predistnorm(djc3,ic3,djl0,il0) = distvsq
454 predistnorm(djc3,ic3,djl0,il0) = predistnorm(djc3,ic3,djl0,il0)+(disth(jc3)-disth(ic3))**2/rhsq
455 elseif (ic3/=jc3)
then
456 predistnorm(djc3,ic3,djl0,il0) = predistnorm(djc3,ic3,djl0,il0)+1.0
460 predistnorm(djc3,ic3,djl0,il0) = sqrt(predistnorm(djc3,ic3,djl0,il0))
473 if (l0rl0_to_l0(jl0r,il0)==il0) plist(1,2) = jl0r
476 distnorm(plist(1,1),plist(1,2)) = 0.0
486 jl0 = l0rl0_to_l0(jl0r,il0)
489 do kc3=max(jc3-1,1),min(jc3+1,nc3max)
490 do kl0r=max(jl0r-1,1),min(jl0r+1,nl0r)
491 kl0 = l0rl0_to_l0(kl0r,il0)
492 disttest = distnorm(jc3,jl0r)+predistnorm(kc3-jc3,jc3,kl0-jl0,jl0)
494 if (disttest<1.0)
then
496 if (disttest<distnorm(kc3,kl0r))
then
498 distnorm(kc3,kl0r) = disttest
501 add_to_front = .true.
503 if ((plist_new(jp,1)==kc3).and.(plist_new(jp,2)==kl0r))
then
504 add_to_front = .false.
509 if (add_to_front)
then
512 plist_new(np_new,1) = kc3
513 plist_new(np_new,2) = kl0r
523 plist(1:np,:) = plist_new(1:np,:)
528 jl0 = l0rl0_to_l0(jl0r,il0)
532 fit(jc3,jl0r,il0) =
fit_func(mpl,distnorm(jc3,jl0r))
540 jl0 = l0rl0_to_l0(jl0r,il0)
541 fit(:,jl0r,il0) = fit(:,jl0r,il0)*sqrt(coef(il0)*coef(jl0))
547 if (mpl%msv%is(coef(il0)).or.mpl%msv%is(rh(il0)).or.mpl%msv%is(rv(il0))) fit(:,:,il0) = mpl%msv%valr
549 jl0 = l0rl0_to_l0(jl0r,il0)
550 if (mpl%msv%is(coef(jl0)).or.mpl%msv%is(rh(jl0)).or.mpl%msv%is(rv(jl0))) fit(:,jl0r,il0) = mpl%msv%valr
569 if (distnorm<0.5)
then
570 gc99 = -8.0*distnorm**5+8.0*distnorm**4+5.0*distnorm**3-20.0/3.0*distnorm**2+1.0
571 else if (distnorm<1.0)
then
572 gc99 = 8.0/3.0*distnorm**5-8.0*distnorm**4+5.0*distnorm**3+20.0/3.0*distnorm**2-10.0*distnorm+4.0-1.0/(3.0*distnorm)
593 character(len=1024),
parameter :: subr =
'fit_func'
596 if (distnorm<0.0)
call mpl%abort(subr,
'negative normalized distance')
610 subroutine fit_lct(mpl,nc,nl0,dxsq,dysq,dxdy,dzsq,dmask,nscales,D,coef,fit)
616 integer,
intent(in) :: nc
617 integer,
intent(in) :: nl0
618 real(
kind_real),
intent(in) :: dxsq(nc,nl0)
619 real(
kind_real),
intent(in) :: dysq(nc,nl0)
620 real(
kind_real),
intent(in) :: dxdy(nc,nl0)
621 real(
kind_real),
intent(in) :: dzsq(nc,nl0)
622 logical,
intent(in) :: dmask(nc,nl0)
623 integer,
intent(in) :: nscales
624 real(
kind_real),
intent(in) :: d(4,nscales)
625 real(
kind_real),
intent(in) :: coef(nscales)
626 real(
kind_real),
intent(out) :: fit(nc,nl0)
629 integer :: jl0,jc3,iscales
630 real(
kind_real) :: dcoef(nscales),d11,d22,d33,d12,h11,h22,h33,h12,rsq
636 dcoef = max(
dmin,min(coef,1.0_kind_real))
637 dcoef = dcoef/sum(dcoef)
641 d11 = max(
dmin,d(1,iscales))
642 d22 = max(
dmin,d(2,iscales))
644 d33 = max(
dmin,d(3,iscales))
648 d12 = sqrt(d11*d22)*max(-1.0_kind_real+
dmin,min(d(4,iscales),1.0_kind_real-
dmin))
651 call lct_d2h(mpl,d11,d22,d33,d12,h11,h22,h33,h12)
656 if (dmask(jc3,jl0))
then
658 if (iscales==1) fit(jc3,jl0) = 0.0
661 rsq = h11*dxsq(jc3,jl0)+h22*dysq(jc3,jl0)+h33*dzsq(jc3,jl0)+2.0*h12*dxdy(jc3,jl0)
665 if (rsq<40.0) fit(jc3,jl0) = fit(jc3,jl0)+dcoef(iscales)*exp(-0.5*rsq)
668 fit(jc3,jl0) = fit(jc3,jl0)+dcoef(iscales)*
matern(mpl,
m,sqrt(rsq))
681 subroutine lct_d2h(mpl,D11,D22,D33,D12,H11,H22,H33,H12)
698 character(len=1024),
parameter :: subr =
'lct_d2h'
709 call mpl%abort(subr,
'non-invertible tensor')
738 character(len=1024),
parameter :: subr =
'lct_h2r'
741 if ((h11<0.0).or.(h22<0.0))
call mpl%abort(subr,
'negative diagonal LCT coefficients')
750 diff = 0.25*(h11-h22)**2+h12**2
751 if ((det>0.0).and..not.(diff<0.0))
then
752 if (0.5*tr>sqrt(diff))
then
753 rh =
gau2gc/sqrt(0.5*tr-sqrt(diff))
755 call mpl%abort(subr,
'non positive-definite LCT (eigenvalue)')
758 call mpl%abort(subr,
'non positive-definite LCT (determinant)')
799 logical,
intent(out) :: valid
806 det = d1*d2*(1.0-nod**2)
807 diff = 0.25*(d1-d2)**2+d1*d2*nod**2
809 if ((det>0.0).and..not.(diff<0.0))
then
811 ev1 = 0.5*tr+sqrt(diff)
812 ev2 = 0.5*tr-sqrt(diff)
838 integer,
intent(in) ::
m
844 character(len=1024),
parameter :: subr =
'matern'
847 if (
m<2)
call mpl%abort(subr,
'M should be larger than 2')
848 if (mod(
m,2)>0)
call mpl%abort(subr,
'M should be even')
882 integer,
intent(in) :: n
885 integer,
intent(out) :: ierr
889 real(
kind_real),
allocatable :: apack(:),upack(:)
935 integer,
intent(in) :: n
938 integer,
intent(out) :: ierr
942 real(
kind_real),
allocatable :: apack(:),cpack(:)
988 integer,
intent(in) :: n
991 integer,
intent(out) :: ierr
992 integer,
intent(in),
optional :: mmax
993 real(
kind_real),
intent(in),
optional :: var_th
996 integer :: k,k2,
m,lmmax
997 real(
kind_real),
allocatable :: work(:,:),evec(:,:),eval(:),laminvet(:,:)
998 real(
kind_real),
allocatable :: summ,total_variance,cumul_variance
999 character(len=1024),
parameter :: subr =
'pseudoinv'
1005 allocate(laminvet(n,n))
1015 if (
present(mmax))
then
1019 if (
present(var_th))
then
1025 total_variance = summ
1026 cumul_variance = 0.0
1029 cumul_variance = cumul_variance+eval(
m)/total_variance
1030 if (cumul_variance>1.0-var_th )
then
1036 call mpl%abort(subr,
'either dominant mode or variance threshold should be specified')
1039 if (lmmax>n)
call mpl%abort(subr,
'dominant mode should smaller than the matrix rank')
1044 laminvet(
m,k) = evec(k,
m)/eval(
m)
1053 summ = summ+evec(k,
m)*laminvet(
m,k2)
1070 deallocate(laminvet)
1085 integer,
intent(in) :: kz
1086 real(kind_real),
intent(in) :: bx(1:kz,1:kz)
1087 real(kind_real),
intent(out) :: e(1:kz,1:kz)
1088 real(kind_real),
intent(out) :: l(1:kz)
1089 integer,
intent(out) :: ierr
1092 integer :: work,m,info
1093 real(kind_real) :: work_array(1:3*kz-1),ecopy(1:kz,1:kz),lcopy(1:kz)
1101 call dsyev(
'V',
'U',kz,ecopy,kz,lcopy,work_array,work,ierr)
1105 l(m) = lcopy(kz+1-m)
1106 e(1:kz,m) = ecopy(1:kz,kz+1-m)
1115 subroutine histogram(mpl,nlist,list,nbins,histmin,histmax,bins,hist)
1120 type(
mpl_type),
intent(inout) :: mpl
1121 integer,
intent(in) :: nlist
1122 real(
kind_real),
intent(in) :: list(nlist)
1123 integer,
intent(in) :: nbins
1126 real(
kind_real),
intent(out) :: bins(nbins+1)
1127 real(
kind_real),
intent(out) :: hist(nbins)
1130 integer :: ibins,ilist
1133 character(len=1024) :: subr =
'histogram'
1136 if (nbins<=0)
call mpl%abort(subr,
'the number of bins should be positive')
1137 if (histmax>histmin)
then
1138 if (minval(list,mask=mpl%msv%isnot(list))<histmin)
call mpl%abort(subr,
'values below histogram minimum')
1139 if (maxval(list,mask=mpl%msv%isnot(list))>histmax)
call mpl%abort(subr,
'values over histogram maximum')
1142 delta = (histmax-histmin)/real(nbins,
kind_real)
1145 bins(ibins) = histmin+real(ibins-1,
kind_real)*delta
1147 bins(nbins+1) = histmax
1150 bins(1) = bins(1)-1.0e-6*delta
1151 bins(nbins+1) = bins(nbins+1)+1.0e-6*delta
1156 if (mpl%msv%isnot(list(ilist)))
then
1159 do while (.not.found)
1161 if (ibins>nbins)
call mpl%abort(subr,
'bin not found')
1162 if (
infeq(bins(ibins),list(ilist)).and.
inf(list(ilist),bins(ibins+1)))
then
1163 hist(ibins) = hist(ibins)+1.0
1169 if (abs(sum(hist)-real(count(mpl%msv%isnot(list)),
kind_real))>0.5) &
1170 &
call mpl%abort(subr,
'histogram sum is not equal to the number of valid elements')