module GVTDX_main !! The main module of GVTD-X use GVTDX_sub implicit none public :: Retrieve_velocity_GVTDX private :: calc_fkij private :: calc_fkij2akp private :: calc_fkijVd2bk private :: set_xk2variables private :: calc_phi2Vrot private :: calc_D2Vdiv private :: calc_Vn2Vtot private :: check_zero private :: check_undef_grid private :: set_undef_value private :: calc_Phi2Phin private :: calc_Phi2Zetan private :: calc_pseudo_GVTD0 private :: calc_phi2sc contains subroutine Retrieve_velocity_GVTDX( nrot, ndiv, r, t, rh, td, rdiv, Vd, Vn, RadTC, & & VT, VR, VRT0, VDR0, VRTn, VRRn, VDTm, VDRm, & & undef, phin, zetan, VRT0_GVTD, VDR0_GVTD, Vn_0, & & VRTns_r, VRTnc_r, VRRns_r, VRRnc_r, & & zetans_r, zetanc_r ) !! Solve unknown variables and return wind velocity on R-T coordinates. <br> !!------------------------------------------------------- <br> !!-- [relationship between r and rh] -- <br> !!------------------------------------------------------- <br> !!-- i-1 i i+1 <br> !!-- ...|-- --|-- --|... : r(1:size(r)) = velocity radii <br> !!-- |-- --|-- --|-- --| : rh(1,size(r)+1) = potential radii <br> !!--i-1 i i+1 i+2 <br> !!------------------------------------------------------- implicit none !-- input/output integer, intent(in) :: nrot !! wave number for rotating wind integer, intent(in) :: ndiv !! wave number for divergent wind double precision, intent(in) :: r(:) !! radial coordinate on which Vd is defined [m] double precision, intent(in) :: t(:) !! azimuthal coordinate on which Vd is defined [rad] double precision, intent(in) :: rh(size(r)+1) !! radial coordinate on which Phi (staggered for Vd) is defined [m] double precision, intent(in) :: td(size(r),size(t)) !! radar azimuthal angle defined at Vd(r,t) [rad] double precision, intent(in) :: rdiv(:) !! radial coordinate on which Dc (staggered for Vd) is defined [m] double precision, intent(inout) :: Vd(size(r),size(t)) !! Doppler velocity defined on r-t [m s-1] double precision, intent(in) :: Vn !! y component of storm-relative mean wind on Cartesian coordinate (x,y) which is defined in the direction of the radar to TC ccenter [m s-1] double precision, intent(in) :: RadTC !! Distance from radar to TC center [m] double precision, intent(out) :: VT(size(r),size(t)) !! retrieved total tangential wind [m s-1] double precision, intent(out) :: VR(size(r),size(t)) !! retrieved total radial wind [m s-1] double precision, intent(out) :: VRT0(size(r),size(t)) !! retrieved axisymmetric radial component of rotating wind [m s-1] double precision, intent(out) :: VDR0(size(r),size(t)) !! retrieved axisymmetric tangential component of divergent wind [m s-1] double precision, intent(out) :: VRTn(nrot,size(r),size(t)) !! retrieved tangential component of rotating wind [m s-1] double precision, intent(out) :: VRRn(nrot,size(r),size(t)) !! retrieved radial component of rotating wind [m s-1] double precision, intent(out) :: VDTm(ndiv,size(r),size(t)) !! retrieved tangential component of divergent wind [m s-1] double precision, intent(out) :: VDRm(ndiv,size(r),size(t)) !! retrieved radial component of divergent wind [m s-1] double precision, intent(in), optional :: undef !! undefined value for Vd double precision, intent(out), optional :: phin(nrot,size(r),size(t)) !! retrieved stream function [m2 s-1] double precision, intent(out), optional :: zetan(nrot,size(r),size(t)) !! retrieved vorticity [s-1] double precision, intent(out), optional :: VRT0_GVTD(size(r),size(t)) !! retrieved axisymmetric radial component of pseudo-GVTD tangential wind [m s-1] double precision, intent(out), optional :: VDR0_GVTD(size(r),size(t)) !! retrieved axisymmetric tangential component of pseudo-GVTD tangential wind [m s-1] double precision, intent(out), optional :: Vn_0(size(r),size(t)) !! Aliased component to asymmetric tangential wind from (storm-relative) mean wind [m s-1] double precision, intent(out), optional :: VRTns_r(nrot,size(r)) !! Sine component of retrieved asymmetric radial wind [m s-1] double precision, intent(out), optional :: VRTnc_r(nrot,size(r)) !! Cosine component of retrieved asymmetric radial wind [m s-1] double precision, intent(out), optional :: VRRns_r(nrot,size(r)) !! Sine component of retrieved asymmetric tangential wind [m s-1] double precision, intent(out), optional :: VRRnc_r(nrot,size(r)) !! Cosine component of retrieved asymmetric tangential wind [m s-1] double precision, intent(out), optional :: zetans_r(nrot,size(r)) !! Sine amplitude of retrieved vorticity [s-1] double precision, intent(out), optional :: zetanc_r(nrot,size(r)) !! Cosine amplitude of retrieved vorticity [s-1] !-- internal variables integer :: i, j, k, p, irad, cstat ! dummy indexes integer :: icounter_div ! Index for nrdiv integer :: nr, nt ! array numbers for r and t, respectively integer :: nk ! array number of a_k integer :: nrdiv ! array number for rdiv integer :: nrdiv2 ! array number for rdiv_n integer :: nbound ! element number for variables related to the outermost radius (i.e., 2*nrot-1) double precision, allocatable, dimension(:) :: Vdivr_r ! axisymmetric divergent wind (VDR0(r)) double precision, allocatable, dimension(:) :: Vrott_r ! axisymmetric rotating wind (VRT0(r)) double precision, allocatable, dimension(:,:) :: phis_nr ! asymmetric (sine) stream function (Phi_S(n,r)) double precision, allocatable, dimension(:,:) :: phic_nr ! asymmetric (cosine) stream function (Phi_C(n,r)) double precision, allocatable, dimension(:,:) :: divc_mr ! asymmetric (cosine) stream function (D_C(n,r)) double precision, allocatable, dimension(:) :: GVTDU_r ! axisymmetric radial wind for pseudo-GVTD double precision, allocatable, dimension(:) :: GVTDV_r ! axisymmetric tangential wind for pseudo-GVTD double precision, allocatable, dimension(:) :: x_k ! unknown vector for retrieved coefficients double precision, allocatable, dimension(:) :: b_k ! known vector given by observed values double precision, allocatable, dimension(:,:) :: a_kp ! coefficient matrix for x_k double precision, allocatable, dimension(:,:,:) :: f_kij ! a_kp = sum_{i,j}(f_kij * f_pij) double precision :: dundef, vmax, tmprho double precision, dimension(size(r)) :: r_n ! Nondimensional r double precision, dimension(size(rh)) :: rh_n ! Nondimensional rh double precision, dimension(size(rdiv)*2) :: rdiv_n ! Nondimensional rdiv (internal variable) double precision :: rtc_n ! Nondimensional RadTC double precision, dimension(size(r),size(t)) :: delta ! delta_ij logical, allocatable, dimension(:,:) :: undeflag ! Flag for Vd grid with undef call stdout( "Enter procedure.", "Retrieve_velocity_GVTDX", 0 ) nr=size(r) nt=size(t) nrdiv=size(rdiv) ! Changeable to icounter_div nrdiv2=size(rdiv)*2 ! Changeable to icounter_div*2 vmax=50.0d0 if(present(undef))then dundef=undef else dundef=-1.0d35 end if VT=dundef VR=dundef VRT0=dundef VDR0=dundef VRTn=dundef VRRn=dundef VDTm=dundef VDRm=dundef delta=undef if(present(phin))then phin=dundef end if if(present(zetan))then zetans_r=dundef zetanc_r=dundef zetan=dundef end if if(present(VRT0_GVTD))then VRT0_GVTD=dundef allocate(GVTDV_r(nr),stat=cstat) end if if(present(VDR0_GVTD))then VDR0_GVTD=dundef allocate(GVTDU_r(nr),stat=cstat) end if if(present(VRTns_r))then VRTns_r=dundef VRTnc_r=dundef VRRns_r=dundef VRRnc_r=dundef end if !-- Check retrieved asymmetric wave number if(nrot<0)then call stdout( "nrot is greater equal to 0. stop.", "Retrieve_velocity_GVTDX", -1 ) stop end if if(ndiv<0)then call stdout( "ndiv is greater equal to 0. stop.", "Retrieve_velocity_GVTDX", -1 ) stop end if !-- Normalized r and rh r_n=r/rh(nr+1) rh_n=rh/rh(nr+1) rtc_n=RadTC/rh(nr+1) !-- Check and search divergent radii icounter_div=0 do i=1,nrdiv call interpo_search_1d( rh, rdiv(i), irad ) if((irad==nr+1).and.(rh(nr+1)<rdiv(i)))then ! if(ndiv>0)then ! call stdout( "Detect out of range. stop.", "Retrieve_velocity_GVTDX", 1 ) ! stop ! else ! Not use of rdiv call stdout( "Detect out of range (out).", "Retrieve_velocity_GVTDX", 1 ) ! irad=nr ! end if cycle else if(irad==0)then call stdout( "Detect out of range (in).", "Retrieve_velocity_GVTDX", 1 ) cycle else if(icounter_div>0)then ! Check previously asigned grid and currently determined irad if(rdiv_n(2*icounter_div)==rh(irad+1)/rh(nr+1))then call stdout( "Detect assigned grid. skip.", "Retrieve_velocity_GVTDX", 1 ) cycle end if end if icounter_div=icounter_div+1 rdiv_n(2*icounter_div-1)=rh(irad)/rh(nr+1) rdiv_n(2*icounter_div)=rh(irad+1)/rh(nr+1) end do nrdiv=icounter_div nrdiv2=icounter_div*2 !-- Calculate delta_ij !$omp parallel default(shared) !$omp do schedule(runtime) private(i,j,tmprho) do j=1,nt do i=1,nr if(r_n(i)>0.0d0)then tmprho=rtc_n/r_n(i) delta(i,j)=dsqrt(tmprho**2+2.0d0*tmprho*dcos(t(j))+1.0d0) end if end do end do !$omp end do !$omp end parallel !-- Set total number for unknown variables in a_k if(nrot>0)then !-- nk = free variable + boundary variable (=nbound) !-- all arrays and matrices are composed of nk + nbound !-- The last "nbound" is asigned for "lambda" (i.e., additional constraints) nk=(2+2*nrot)*(nr-1)+2+2+ndiv*nrdiv+(2*nrot-1) nbound=2*nrot-1 else nk=2*(nr-1)+2+ndiv*nrdiv nbound=0 end if !-- Allocate and initialize arrays allocate(Vdivr_r(nr),stat=cstat) allocate(Vrott_r(nr),stat=cstat) allocate(phis_nr(nrot,nr+1),stat=cstat) allocate(phic_nr(nrot,nr+1),stat=cstat) allocate(divc_mr(ndiv,nrdiv),stat=cstat) allocate(x_k(nk+nbound),stat=cstat) allocate(b_k(nk+nbound),stat=cstat) allocate(a_kp(nk+nbound,nk+nbound),stat=cstat) allocate(f_kij(nk,nr,nt),stat=cstat) allocate(undeflag(nr,nt),stat=cstat) undeflag=.false. call check_undef_grid( Vd, dundef, undeflag ) if(cstat/=0)then call stdout( "Failed to allocate variables. stop.", "Retrieve_velocity_GVTDX", -1 ) stop end if Vdivr_r=0.0d0 Vrott_r=0.0d0 phis_nr=0.0d0 phic_nr=0.0d0 divc_mr=0.0d0 x_k=0.0d0 b_k=0.0d0 a_kp=0.0d0 f_kij=0.0d0 !-- Calculate f_kij !-- ** normalized radius is used in r_n ** call calc_fkij( nrot, ndiv, nk, Vn, rtc_n, r_n, t, rh_n, td, & & rdiv_n(1:nrdiv2), f_kij, Vd, undeflag ) !-- Calculate b_k call calc_fkijVd2bk( vmax, f_kij, Vd, delta, b_k(1:nk), undeflag ) !-- Calculate a_kp call calc_fkij2akp( f_kij, a_kp(1:nk,1:nk), undeflag ) call check_zero( a_kp(1:nk,1:nk) ) !-- Set elements for additional constraints if(nrot>0)then do k=1,nbound a_kp(nk+k,nk-nbound+k)=1.0d0 a_kp(nk-nbound+k,nk+k)=1.0d0 end do b_k(nk+1)=-rh_n(nr)*Vn/vmax end if !-- Solve x_k call fp_gauss( a_kp, b_k, x_k ) !-- Set each unknown variable from x_k call set_xk2variables( nrot, ndiv, nrdiv, Vn, vmax, & & x_k(1:nk), Vrott_r, Vdivr_r, & & phis_nr, phic_nr, divc_mr, undef=dundef ) !-- Calculate Vr and Vt components of rotating wind call calc_phi2Vrot( nrot, Vn, vmax, r_n, rh_n, t, & & Vrott_r, VRT0, VRTn, VRRn, phis_nr, phic_nr, & & undef=dundef ) !-- Calculate Vr and Vt components of divergent wind call calc_D2Vdiv( ndiv, vmax, r_n, rh_n, t, rdiv_n(1:nrdiv2), Vdivr_r, & & VDR0, VDTm, VDRm, divc_mr, undef=dundef ) !-- Calculate total retrieved Vr and Vt call calc_Vn2Vtot( nrot, ndiv, VRT0, VRTn, VDTm, VT ) call calc_Vn2Vtot( nrot, ndiv, VDR0, VRRn, VDRm, VR ) !-- Set undef in each output variable at undefined grids call set_undef_value( undeflag, dundef, VT ) call set_undef_value( undeflag, dundef, VR ) if(nrot>0)then do k=1,nrot call set_undef_value( undeflag, dundef, VRTn(k,1:nr,1:nt) ) call set_undef_value( undeflag, dundef, VRRn(k,1:nr,1:nt) ) end do end if if(ndiv>0)then do k=1,ndiv call set_undef_value( undeflag, dundef, VDTm(k,1:nr,1:nt) ) call set_undef_value( undeflag, dundef, VDRm(k,1:nr,1:nt) ) end do end if !-- monitor variables if((present(phin)).and.(nrot>0))then call calc_Phi2Phin( nrot, vmax, rh(nr+1), r_n, rh_n, t, phis_nr, phic_nr, phin ) end if if((present(zetan)).and.(nrot>0))then call calc_Phi2Zetan( nrot, vmax, rh(nr+1), r_n, rh_n, t, phis_nr, phic_nr, & & zetans_r, zetanc_r, zetan ) end if if(present(VRT0_GVTD).and.(nrot>0))then call calc_pseudo_GVTD0( nrot, vmax, rtc_n, r_n, rh_n, VRT0(1:nr,1), VDR0(1:nr,1), & & phis_nr, phic_nr, GVTDV_r(1:nr), GVTDU_r(1:nr) ) do i=1,nr VRT0_GVTD(i,1:nt)=GVTDV_r(i) VDR0_GVTD(i,1:nt)=GVTDU_r(i) end do end if if(present(VRTns_r).and.(nrot>0))then call calc_phi2sc( nrot, vmax, r_n, rh_n, phis_nr, phic_nr, & & VRTns_r(1:nrot,1:nr), VRTnc_r(1:nrot,1:nr), & & VRRns_r(1:nrot,1:nr), VRRnc_r(1:nrot,1:nr) ) end if if(present(Vn_0))then do i=1,nr if(VRT0(i,1)/=dundef)then Vn_0(i,1:nt)=(r(i)/RadTC)*Vn end if end do end if call stdout( "Finish procedure.", "Retrieve_velocity_GVTDX", 0 ) end subroutine Retrieve_velocity_GVTDX subroutine calc_fkij( nrot, ndiv, nnk, Vsrn, rtc, rd, theta, rdh, thetad, rddiv, & & fkij, Vdij, undeflag ) !! Calculate the coefficient matrix \(f_{kij}\) implicit none integer, intent(in) :: nrot !! Maximum wavenumber for stream function integer, intent(in) :: ndiv !! Maximum wavenumber for velocity potential integer, intent(in) :: nnk !! Matrix dimension for fkij double precision, intent(in) :: Vsrn !! y-component of storm-relative mean wind [m/s] double precision, intent(in) :: rtc !! Distance between the radar to vortex center [m] double precision, intent(in) :: rd(:) !! Normalized radius [1] double precision, intent(in) :: theta(:) !! Azimuthal angle [rad] double precision, intent(in) :: rdh(size(rd)+1) !! Normalized radius [1] double precision, intent(in) :: thetad(size(rd),size(theta)) !! \(\theta_d \) double precision, intent(in) :: rddiv(:) !! Normalized radius of the defined point for divergence [1] double precision, intent(out) :: fkij(nnk,size(rd),size(theta)) !! Coefficient matrix double precision, intent(inout) :: Vdij(size(rd),size(theta)) !! Doppler velocity [m/s] logical, intent(in) :: undeflag(size(rd),size(theta)) !! Undefined flag at each sampling point !-- internal variables integer :: nnr, nnt, nnrdiv, nnrdiv2, ii, jj, kk, pp, nmax, cstat, ncyc double precision :: r1_out_coef !MOD, r_infty double precision, dimension(size(rd)) :: dr, dr_inv, alp double precision, dimension(size(rd)) :: r_inv double precision, dimension(size(rd),size(theta)) :: sines, cosines double precision, allocatable, dimension(:,:) :: sinen, cosinen double precision, allocatable, dimension(:,:,:) :: gkrr call stdout( "Enter procedure.", "calc_fkij", 0 ) nnr=size(rd) nnt=size(theta) nnrdiv2=size(rddiv) nnrdiv=nnrdiv2/2 ncyc=2+2*nrot ! unknown variable number at a certain radius nmax=max(max(0,nrot),ndiv) ! maximum wave number for rotating and divergent components fkij=0.0d0 if(nmax>0)then allocate(sinen(nmax,nnt),stat=cstat) allocate(cosinen(nmax,nnt),stat=cstat) allocate(gkrr(nmax,nnrdiv2,nnr+1),stat=cstat) ! Gk(r_p,r), r_p at rdh, r at rd if(cstat/=0)then call stdout( "Failed to allocate variables. stop.", "calc_fkij", -1 ) stop end if sinen=0.0d0 cosinen=0.0d0 gkrr=0.0d0 end if if(nrot>0)then if(nnk/=ncyc*(nnr-1)+2+2+ndiv*nnrdiv+2*nrot-1)then call stdout( "nnk is not identical to (2+2N)(m-1)+2+2+M*(mm-1). stop.", "calc_fkij", -1 ) stop end if else if(nnk/=ncyc*(nnr-1)+2+ndiv*nnrdiv)then call stdout( "nnk is not identical to (2+2N)(m-1)+2+M*(mm-1). stop.", "calc_fkij", -1 ) stop end if end if do ii=1,nnr dr(ii)=rdh(ii+1)-rdh(ii) dr_inv(ii)=1.0d0/dr(ii) r_inv(ii)=1.0d0/rd(ii) alp(ii)=(rd(ii)-rdh(ii))/(rdh(ii+1)-rdh(ii)) end do !$omp parallel default(shared) !-- Set fixed variables for R-T, in advance !$omp do schedule(runtime) private(ii,jj) do jj=1,nnt do ii=1,nnr sines(ii,jj)=rtc*r_inv(ii)*dsin(theta(jj)) ! MOD = delta x sin(theta-thetad) cosines(ii,jj)=1.0d0+rtc*r_inv(ii)*dcos(theta(jj)) ! MOD = delta x cos(theta-thetad) end do end do !$omp end do !$omp barrier if(nmax>0)then !$omp do schedule(runtime) private(kk,jj) do jj=1,nnt do kk=1,nmax sinen(kk,jj)=dsin(dble(kk)*theta(jj)) cosinen(kk,jj)=dcos(dble(kk)*theta(jj)) end do end do !$omp end do !$omp barrier !$omp do schedule(runtime) private(kk,ii,jj) do jj=1,nnr ! For r do ii=1,nnrdiv2 ! For rdiv do kk=1,nmax gkrr(kk,ii,jj)=green_func( rddiv(ii), rd(jj), kk ) end do end do end do !$omp end do !$omp barrier !$omp do schedule(runtime) private(kk,ii) do ii=1,nnrdiv2 ! For rddiv do kk=1,nmax gkrr(kk,ii,nnr+1)=green_func( rddiv(ii), rd(nnr)+dr(nnr), kk ) end do end do !$omp end do end if !$omp barrier !-- Set coefficients for VRT0 at each (ii,jj) !$omp do schedule(runtime) private(ii,jj) do jj=1,nnt do ii=1,nnr fkij(1+ncyc*(ii-1),ii,jj)=-sines(ii,jj) end do end do !$omp end do !$omp barrier !-- Set coefficients for VDR0 at each (ii,jj) !$omp do schedule(runtime) private(ii,jj) do jj=1,nnt do ii=1,nnr fkij(2+ncyc*(ii-1),ii,jj)=cosines(ii,jj) end do end do !$omp end do !$omp barrier if(nrot>0)then !-- Set coefficients for Phi_s and Phi_c at each (ii,jj) for wavenumber 1 !$omp do schedule(runtime) private(ii,jj) do jj=1,nnt do ii=1,nnr-2 !-- Phi(s)*delta(s,i) fkij(2+1+ncyc*(ii-1),ii,jj) & & =(dr_inv(ii)*sinen(1,jj)) & & *(-sines(ii,jj)) & & +((1.0d0-alp(ii))*dble(1)*cosinen(1,jj)) & & *(r_inv(ii)*cosines(ii,jj)) !-- Phi(c)*delta(s,i) fkij(2+nrot+1+ncyc*(ii-1),ii,jj) & & =(dr_inv(ii)*cosinen(1,jj)) & & *(-sines(ii,jj)) & & -((1.0d0-alp(ii))*dble(1)*sinen(1,jj)) & & *(r_inv(ii)*cosines(ii,jj)) !-- Phi(s)*delta(s,i+1) fkij(2+1+ncyc*(ii),ii,jj) & & =(dr_inv(ii)*sinen(1,jj)) & & *(sines(ii,jj)) & & +(alp(ii)*dble(1)*cosinen(1,jj)) & & *(r_inv(ii)*cosines(ii,jj)) !-- Phi(c)*delta(s,i+1) fkij(2+nrot+1+ncyc*(ii),ii,jj) & & =(dr_inv(ii)*cosinen(1,jj)) & & *(sines(ii,jj)) & & -(alp(ii)*dble(1)*sinen(1,jj)) & & *(r_inv(ii)*cosines(ii,jj)) end do end do !$omp end do !$omp barrier !-- Set coefficients for Phi_s and Phi_c !-- at one inner radius from the outermost (nnr-1,jj) for wavenumber 1 !$omp do schedule(runtime) private(jj) do jj=1,nnt !-- Phi(s)*delta(s,nnr-2) fkij(2+1+ncyc*(nnr-2),nnr-1,jj) & & =(dr_inv(nnr-1)*sinen(1,jj))*(-sines(nnr-1,jj)) & & +((1.0d0-alp(nnr-1))*cosinen(1,jj)) & & *(r_inv(nnr-1)*cosines(nnr-1,jj)) !-- Phi(c)*delta(s,nnr-2) fkij(2+nrot+1+ncyc*(nnr-2),nnr-1,jj) & & =(dr_inv(nnr-1)*cosinen(1,jj))*(-sines(nnr-1,jj)) & & -((1.0d0-alp(nnr-1))*dble(1)*sinen(1,jj)) & & *(r_inv(nnr-1)*cosines(nnr-1,jj)) !-- Phi(s)*delta(s,nnr-1) fkij(2+1+ncyc*(nnr-1),nnr-1,jj) & & =(dr_inv(nnr-1)*sinen(1,jj))*(sines(nnr-1,jj)) & & +(alp(nnr-1)*cosinen(1,jj)) & & *(r_inv(nnr-1)*cosines(nnr-1,jj)) !-- Phi(c)*delta(s,nnr-1) (related to the outermost radius) fkij(2+2+ndiv*nnrdiv+1+ncyc*(nnr-1),nnr-1,jj) & & =(dr_inv(nnr-1)*cosinen(1,jj))*(sines(nnr-1,jj)) & & -(alp(nnr-1)*dble(1)*sinen(1,jj)) & & *(r_inv(nnr-1)*cosines(nnr-1,jj)) end do !$omp end do !$omp barrier !-- Set coefficients for Phi_s and Phi_c !-- at the outermost (nnr,jj) for wavenumber 1 !$omp do schedule(runtime) private(jj) do jj=1,nnt !-- Phi(s)*delta(s,nnr-1) fkij(2+1+ncyc*(nnr-1),nnr,jj) & & =(dr_inv(nnr)*sinen(1,jj))*(-sines(nnr,jj)) & & +((1.0d0-alp(nnr))*cosinen(1,jj)) & & *(r_inv(nnr)*cosines(nnr,jj)) !-- Phi(s)*delta(s,nnr) fkij(2+2+ncyc*(nnr-1),nnr,jj) & & =(dr_inv(nnr)*sinen(1,jj))*(sines(nnr,jj)) & & +(alp(nnr)*cosinen(1,jj)) & & *(r_inv(nnr)*cosines(nnr,jj)) if(undeflag(nnr,jj).eqv..false.)then ! Remove WN-1 Vm at the outermost radius Vdij(nnr,jj) & & =Vdij(nnr,jj) & & -Vsrn*(-cosinen(1,jj)*sines(nnr,jj) & & +sinen(1,jj)*cosines(nnr,jj)) end if end do !$omp end do !$omp barrier !-- 2. For wavenumber >= 2 if(nrot>1)then !-- Set coefficients for Phi_s and Phi_c at each (ii,jj) !$omp do schedule(runtime) private(kk,ii,jj) do jj=1,nnt do ii=1,nnr-2 do kk=2,nrot !-- Phi(s)*delta(s,i) fkij(2+kk+ncyc*(ii-1),ii,jj) & & =(dr_inv(ii)*sinen(kk,jj)) & & *(-sines(ii,jj)) & & +((1.0d0-alp(ii))*dble(kk)*cosinen(kk,jj)) & & *(r_inv(ii)*cosines(ii,jj)) !-- Phi(c)*delta(s,i) fkij(2+nrot+kk+ncyc*(ii-1),ii,jj) & & =(dr_inv(ii)*cosinen(kk,jj)) & & *(-sines(ii,jj)) & & -((1.0d0-alp(ii))*dble(kk)*sinen(kk,jj)) & & *(r_inv(ii)*cosines(ii,jj)) !-- Phi(s)*delta(s,i+1) fkij(2+kk+ncyc*(ii),ii,jj) & & =(dr_inv(ii)*sinen(kk,jj)) & & *(sines(ii,jj)) & & +(alp(ii)*dble(kk)*cosinen(kk,jj)) & & *(r_inv(ii)*cosines(ii,jj)) !-- Phi(c)*delta(s,i+1) fkij(2+nrot+kk+ncyc*(ii),ii,jj) & & =(dr_inv(ii)*cosinen(kk,jj)) & & *(sines(ii,jj)) & & -(alp(ii)*dble(kk)*sinen(kk,jj)) & & *(r_inv(ii)*cosines(ii,jj)) end do end do end do !$omp end do !$omp barrier !-- Set coefficients for Phi_s and Phi_c at one inner radius from the outermost (nnr-1,jj) !$omp do schedule(runtime) private(kk,jj) do jj=1,nnt do kk=2,nrot !-- Phi(s)*delta(s,nnr-1) fkij(2+kk+ncyc*(nnr-2),nnr-1,jj) & & =-dr_inv(nnr-1)*sinen(kk,jj)*sines(nnr-1,jj) & & +(1.0d0-alp(nnr-1))*dble(kk)*cosinen(kk,jj) & & *r_inv(nnr-1)*cosines(nnr-1,jj) !-- Phi(c)*delta(s,nnr-1) fkij(2+nrot+kk+ncyc*(nnr-2),nnr-1,jj) & & =-dr_inv(nnr-1)*cosinen(kk,jj)*sines(nnr-1,jj) & & -(1.0d0-alp(nnr-1))*dble(kk)*sinen(kk,jj) & & *r_inv(nnr-1)*cosines(nnr-1,jj) !-- Phi(s)*delta(s,nnr) (related to the outermost radius) fkij(2+2+ndiv*nnrdiv+kk+ncyc*(nnr-1),nnr-1,jj) & & =(dr_inv(nnr-1)*sinen(kk,jj)) & & *(sines(nnr-1,jj)) & & +(alp(nnr-1)*dble(kk)*cosinen(kk,jj)) & & *(r_inv(nnr-1)*cosines(nnr-1,jj)) !-- Phi(c)*delta(s,nnr) (related to the outermost radius) fkij(2+2+ndiv*nnrdiv+nrot-1+kk+ncyc*(nnr-1),nnr-1,jj) & & =(dr_inv(nnr-1)*cosinen(kk,jj)) & & *(sines(nnr-1,jj)) & & -(alp(nnr-1)*dble(kk)*sinen(kk,jj)) & & *(r_inv(nnr-1)*cosines(nnr-1,jj)) end do end do !$omp end do end if end if !$omp barrier if(ndiv>0)then !-- Set coefficients for D_s and D_c at each (ii,jj) !$omp do schedule(runtime) private(kk,pp,ii,jj) do jj=1,nnt do ii=1,nnr do pp=1,nnrdiv do kk=1,ndiv fkij(ncyc*(nnr-1)+2+2+kk+ndiv*(pp-1),ii,jj) & & =-(r_inv(ii)*dble(kk)*0.5d0*(rddiv(2*pp)-rddiv(2*pp-1)) & ! For Dc & *(rddiv(2*pp)*gkrr(kk,2*pp,ii)+rddiv(2*pp-1)*gkrr(kk,2*pp-1,ii)) & & *sinen(kk,jj)*sines(ii,jj) & & +0.5d0*(rddiv(2*pp)-rddiv(2*pp-1))*dr_inv(ii) & & *(rddiv(2*pp)*(gkrr(kk,2*pp,ii+1)-gkrr(kk,2*pp,ii)) & & +rddiv(2*pp-1)*(gkrr(kk,2*pp-1,ii+1)-gkrr(kk,2*pp-1,ii))) & & *cosinen(kk,jj)*cosines(ii,jj)) end do end do end do end do !$omp end do !$omp barrier end if !$omp end parallel if(nmax>0)then deallocate(sinen) deallocate(cosinen) deallocate(gkrr) end if call stdout( "Finish procedure.", "calc_fkij", 0 ) end subroutine calc_fkij subroutine calc_fkij2akp( fkij, akp, undeflag ) !! Calculation of the coefficient matrix \(A \) in LSM from \(f_{k,i,j}\) implicit none double precision, intent(in) :: fkij(:,:,:) !! Coefficient matrix double precision, intent(out) :: akp(size(fkij,1),size(fkij,1)) !! Coefficient matrix in LSM logical, intent(in) :: undeflag(size(fkij,2),size(fkij,3)) !! Undefined flag at each sampling point integer :: nnk, nni, nnj, ii, jj, kk, ll, cstat double precision, allocatable, dimension(:,:,:) :: fkl, fpl !-- OpenMP variables !$ integer :: OMP_GET_THREAD_NUM, OMP_GET_MAX_THREADS integer :: ompnum, omppe call stdout( "Enter procedure.", "calc_fkij2akp", 0 ) nnk=size(fkij,1) nni=size(fkij,2) nnj=size(fkij,3) ompnum=1 omppe=1 !$ ompnum=OMP_GET_MAX_THREADS() allocate(fkl(nni,nnj,ompnum),stat=cstat) allocate(fpl(nni,nnj,ompnum),stat=cstat) if(cstat/=0)then call stdout( "Failed to allocate variables. stop.", "calc_fkij2akp", -1 ) stop end if do ll=1,nnk !$omp parallel default(shared) !$omp do schedule(dynamic) private(kk,omppe) do kk=ll,nnk !$ omppe=OMP_GET_THREAD_NUM()+1 fkl(1:nni,1:nnj,omppe)=fkij(kk,1:nni,1:nnj) fpl(1:nni,1:nnj,omppe)=fkij(ll,1:nni,1:nnj) akp(kk,ll)=matrix_sum( fkl(1:nni,1:nnj,omppe), fpl(1:nni,1:nnj,omppe), & & undeflag(1:nni,1:nnj) ) akp(ll,kk)=akp(kk,ll) end do !$omp end do !$omp end parallel end do deallocate(fkl) deallocate(fpl) call stdout( "Finish procedure.", "calc_fkij2akp", 0 ) end subroutine calc_fkij2akp subroutine calc_fkijVd2bk( vmax, fkij, Vdl, deltaij, bk, undeflag ) !! Calculate the vector \(b_k \) from \(f_{k,i,j}\) and \(V_d) implicit none double precision, intent(in) :: vmax !! Scaling factor for velocity [m/s] double precision, intent(in) :: fkij(:,:,:) !! Coefficient matrix double precision, intent(in) :: Vdl(size(fkij,2),size(fkij,3)) !! Doppler velocity [m/s] double precision, intent(in) :: deltaij(size(fkij,2),size(fkij,3)) !! Geometric coefficient: (\(=\delta /\rho )\) double precision, intent(out) :: bk(size(fkij,1)) !! Vector \(\textbf{b}\) logical, intent(in) :: undeflag(size(fkij,2),size(fkij,3)) !! Undefined flag at each sampling point integer :: nnk, nni, nnj, ii, jj, kk, ll, cstat double precision, allocatable, dimension(:,:,:) :: fkl double precision :: dVdl(size(fkij,2),size(fkij,3)) !-- OpenMP variables !$ integer :: OMP_GET_THREAD_NUM, OMP_GET_MAX_THREADS integer :: ompnum, omppe call stdout( "Enter procedure.", "calc_fkijVd2bk", 0 ) nnk=size(fkij,1) nni=size(fkij,2) nnj=size(fkij,3) ompnum=1 omppe=1 !$ ompnum=OMP_GET_MAX_THREADS() allocate(fkl(nni,nnj,ompnum),stat=cstat) if(cstat/=0)then call stdout( "Failed to allocate variables. stop.", "calc_fkijVd2bk", -1 ) stop end if !$omp parallel default(shared) !$omp do schedule(runtime) private(ii,jj) do jj=1,nnj do ii=1,nni if(undeflag(ii,jj).eqv..true.)then dVdl(ii,jj)=Vdl(ii,jj) else dVdl(ii,jj)=deltaij(ii,jj)*Vdl(ii,jj) end if end do end do !$omp end do !$omp barrier !$omp do schedule(runtime) private(kk,omppe) do kk=1,nnk !$ omppe=OMP_GET_THREAD_NUM()+1 fkl(1:nni,1:nnj,omppe)=fkij(kk,1:nni,1:nnj) bk(kk)=matrix_sum( dVdl(1:nni,1:nnj), fkl(1:nni,1:nnj,omppe), & & undeflag(1:nni,1:nnj) )/vmax end do !$omp end do !$omp end parallel deallocate(fkl) call stdout( "Finish procedure.", "calc_fkijVd2bk", 0 ) end subroutine calc_fkijVd2bk subroutine set_xk2variables( nrot, ndiv, nnrdiv, Vsrn, vmax, & & xk, VRT0, VDR0, & & phis_n, phic_n, Ds_m, undef ) !! Set each unknown variable from the solved \(x_k\) implicit none integer, intent(in) :: nrot !! Maximum wavenumber of stream function integer, intent(in) :: ndiv !! Maximum wavenumber of velocity potential integer, intent(in) :: nnrdiv !! Radial grid number for divergence double precision, intent(in) :: Vsrn !! y-component of storm-relative mean wind [m/s] double precision, intent(in) :: vmax !! Scaling factor for velocity [m/s] double precision, intent(in) :: xk(:) !! Solved unknown variable vector double precision, intent(out) :: VRT0(:) !! Wavenumber-0 tangential wind [m/s] double precision, intent(out) :: VDR0(size(VRT0)) !! Wavenumber-0 radial wind [m/s] double precision, intent(out), optional :: phis_n(nrot,size(VRT0)+1) !! Sine components of stream function [m^2/s] double precision, intent(out), optional :: phic_n(nrot,size(VRT0)+1) !! Cosine components of stream function [m^2/s] double precision, intent(out), optional :: Ds_m(ndiv,nnrdiv) !! Divergence [s-1] double precision, intent(in), optional :: undef !! Undefined value integer :: ii, kk, nnk, nnr, ncyc double precision :: Vsrn_n call stdout( "Enter procedure.", "set_xk2variables", 0 ) nnk=size(xk) nnr=size(VRT0) ncyc=2+2*nrot Vsrn_n=Vsrn/vmax !-- Set VRT0 and VDR0 do ii=1,nnr-1 VRT0(ii)=xk(1+ncyc*(ii-1)) VDR0(ii)=xk(2+ncyc*(ii-1)) end do VRT0(nnr)=xk(1+ncyc*(nnr-1)) VDR0(nnr)=xk(2+ncyc*(nnr-1)) !-- Set Phi_s and Phi_c if(nrot>0)then !$omp parallel default(shared) !$omp do schedule(runtime) private(kk,ii) do ii=1,nnr-1 do kk=1,nrot phis_n(kk,ii)=xk(2+kk+ncyc*(ii-1)) phic_n(kk,ii)=xk(2+nrot+kk+ncyc*(ii-1)) end do end do !$omp end do !$omp end parallel phis_n(1,nnr)=xk(2+1+ncyc*(nnr-1)) phis_n(1,nnr+1)=xk(2+2+ncyc*(nnr-1)) end if !-- Set D_s and D_c if(ndiv>0)then !$omp parallel default(shared) !$omp do schedule(runtime) private(kk,ii) do ii=1,nnrdiv do kk=1,ndiv Ds_m(kk,ii)=xk(ncyc*(nnr-1)+2+2+kk+ndiv*(ii-1)) end do end do !$omp end do !$omp end parallel end if call stdout( "Finish procedure.", "set_xk2variables", 0 ) end subroutine set_xk2variables subroutine calc_phi2Vrot( nrot, Vsrn, vmax, rd, rdh, theta, VRT0_r, & & VRT0_rt, VRT_nrt, VRR_nrt, & & phis_nr, phic_nr, undef ) !! Calculate radial and tangential components of rotating wind implicit none integer, intent(in) :: nrot !! Maximum wavenumber of stream function double precision, intent(in) :: Vsrn !! y-component of storm-relative mean wind [m/s] double precision, intent(in) :: vmax !! Scaling factor for velocity [m/s] double precision, intent(in) :: rd(:) !! Normalized radius [1] double precision, intent(in) :: rdh(size(rd)+1) !! Normalized radius [1] double precision, intent(in) :: theta(:) !! Azimuthal angle [rad] double precision, intent(in) :: VRT0_r(size(rd)) !! Wavenumber-0 tangential wind [m/s] double precision, intent(out) :: VRT0_rt(size(rd),size(theta)) !! = VRT0_r double precision, intent(out), optional :: VRT_nrt(nrot,size(rd),size(theta)) !! Tangential components of rotating wind for each wavenumber double precision, intent(out), optional :: VRR_nrt(nrot,size(rd),size(theta)) !! Radial components of rotating wind for each wavenumber double precision, intent(inout), optional :: phis_nr(nrot,size(rd)+1) !! Sine components of stream function double precision, intent(inout), optional :: phic_nr(nrot,size(rd)+1) !! Cosine components of stream function double precision, intent(in), optional :: undef !! No use integer :: ii, jj, kk, nnr, nnt, cstat double precision :: Vsrn_n double precision, dimension(size(rd)) :: dr, dr_inv, r_inv, alp double precision, allocatable, dimension(:,:) :: cosinen, sinen call stdout( "Enter procedure.", "calc_phi2Vrot", 0 ) nnr=size(rd) nnt=size(theta) if(nrot>0)then allocate(cosinen(nrot,nnt),stat=cstat) allocate(sinen(nrot,nnt),stat=cstat) if(cstat/=0)then call stdout( "Failed to allocate variables. stop.", "calc_phi2Vrot", -1 ) stop end if !$omp parallel default(shared) !$omp do schedule(runtime) private(kk,jj) do jj=1,nnt do kk=1,nrot cosinen(kk,jj)=dcos(dble(kk)*theta(jj)) sinen(kk,jj)=dsin(dble(kk)*theta(jj)) end do end do !$omp end do !$omp end parallel end if do ii=1,nnr dr(ii)=rdh(ii+1)-rdh(ii) dr_inv(ii)=1.0d0/dr(ii) alp(ii)=(rd(ii)-rdh(ii))/(rdh(ii+1)-rdh(ii)) end do r_inv(1:nnr)=1.0d0/rd(1:nnr) Vsrn_n=Vsrn/vmax do ii=1,nnr VRT0_rt(ii,1:nnt)=VRT0_r(ii)*vmax end do if(nrot>0)then VRT_nrt=0.0d0 VRR_nrt=0.0d0 !-- set the outermost boundary for wavenumber 1 phic_nr(1,nnr+1)=-rdh(nnr+1)*Vsrn_n phic_nr(1,nnr)=-rdh(nnr)*Vsrn_n !-- set the outermost boundary for wavenumber 2 if(nrot>1)then do kk=2,nrot phis_nr(kk,nnr+1)=0.0d0 phic_nr(kk,nnr+1)=0.0d0 phis_nr(kk,nnr)=0.0d0 phic_nr(kk,nnr)=0.0d0 end do end if !$omp parallel default(shared) !$omp do schedule(runtime) private(kk,ii,jj) do jj=1,nnt do ii=1,nnr do kk=1,nrot VRT_nrt(kk,ii,jj)=-dr_inv(ii)*((phis_nr(kk,ii+1)-phis_nr(kk,ii))*sinen(kk,jj) & & +(phic_nr(kk,ii+1)-phic_nr(kk,ii))*cosinen(kk,jj)) VRR_nrt(kk,ii,jj)=dble(kk)*r_inv(ii) & & *((alp(ii)*phis_nr(kk,ii+1)+(1.0d0-alp(ii))*phis_nr(kk,ii))*cosinen(kk,jj) & & -(alp(ii)*phic_nr(kk,ii+1)+(1.0d0-alp(ii))*phic_nr(kk,ii))*sinen(kk,jj)) VRT_nrt(kk,ii,jj)=VRT_nrt(kk,ii,jj)*vmax VRR_nrt(kk,ii,jj)=VRR_nrt(kk,ii,jj)*vmax end do end do end do !$omp end do !$omp end parallel end if if(nrot>0)then deallocate(cosinen) deallocate(sinen) end if call stdout( "Finish procedure.", "calc_phi2Vrot", 0 ) end subroutine calc_phi2Vrot subroutine calc_D2Vdiv( ndiv, vmax, rd, rdh, theta, rddiv, VDR0_r, & & VDR0_rt, VDT_mrt, VDR_mrt, Ds_mr, undef ) !! Calculate radial and tangential components of divergent wind implicit none integer, intent(in) :: ndiv !! Maximum wavenumber of velocity potential double precision, intent(in) :: vmax !! Scaling factor for velocity [m/s] double precision, intent(in) :: rd(:) !! Nomalized radius [1] double precision, intent(in) :: rdh(size(rd)+1) !! Normalized radius [1] double precision, intent(in) :: theta(:) !! Azimuthal angle [rad] double precision, intent(in) :: rddiv(:) !! Normalized radius for defined grid of divergence [1] double precision, intent(in) :: VDR0_r(size(rd)) !! Wavenumber-0 radial wind [m/s] double precision, intent(out) :: VDR0_rt(size(rd),size(theta)) !! = VDR0_r double precision, intent(out), optional :: VDT_mrt(ndiv,size(rd),size(theta)) !! Tangential components of divergent wind for each wavenumber [m/s] double precision, intent(out), optional :: VDR_mrt(ndiv,size(rd),size(theta)) !! Radial components of divergent wind for each wavenumber [m/s] double precision, intent(in), optional :: Ds_mr(ndiv,size(rddiv)) !! Divergence [1/s] double precision, intent(in), optional :: undef !! Undefined value integer :: ii, jj, kk, nnr, nnt, nnrdiv, nnrdiv2, cstat, irad ! double precision :: rmax_inv double precision, dimension(size(rd)) :: dr_inv, dr, r_inv double precision, allocatable, dimension(:,:) :: cosinen, sinen double precision, allocatable, dimension(:,:,:) :: gkrr, gkrrh, dgkrr double precision :: tmp_Ds_mr(ndiv,size(rd)+1) call stdout( "Enter procedure.", "calc_D2Vdiv", 0 ) nnr=size(rd) nnt=size(theta) nnrdiv2=size(rddiv) nnrdiv=nnrdiv2/2 if(ndiv>0)then allocate(cosinen(ndiv,nnt),stat=cstat) allocate(sinen(ndiv,nnt),stat=cstat) allocate(gkrr(ndiv,nnr+1,nnr+1),stat=cstat) ! Gk(r_p,r), r_p at rdh, r at rdh allocate(gkrrh(ndiv,nnr+1,nnr+1),stat=cstat) ! Gk(r_p,r), r_p at rdh, r at rdh allocate(dgkrr(ndiv,nnr+1,nnr+1),stat=cstat) ! Gk(r_p,r+1)-Gk(r_p,r), r_p at rdh, r at rdh if(cstat/=0)then call stdout( "Failed to allocate variables. stop.", "calc_D2Vdiv", -1 ) stop end if cosinen=0.0d0 sinen=0.0d0 gkrr=0.0d0 gkrrh=0.0d0 dgkrr=0.0d0 tmp_Ds_mr=0.0d0 do kk=1,ndiv do ii=1,nnrdiv call interpo_search_1d( rdh, rddiv(2*ii-1), irad ) tmp_Ds_mr(kk,irad)=Ds_mr(kk,ii) call interpo_search_1d( rdh, rddiv(2*ii), irad ) tmp_Ds_mr(kk,irad)=Ds_mr(kk,ii) end do end do end if do ii=1,nnr dr(ii)=rdh(ii+1)-rdh(ii) dr_inv(ii)=1.0d0/dr(ii) end do r_inv(1:nnr)=1.0d0/rd(1:nnr) do ii=1,nnr VDR0_rt(ii,1:nnt)=VDR0_r(ii)*vmax end do if(ndiv>0)then VDT_mrt=0.0d0 VDR_mrt=0.0d0 !$omp parallel default(shared) !$omp do schedule(runtime) private(kk,jj) do jj=1,nnt do kk=1,ndiv cosinen(kk,jj)=dcos(dble(kk)*theta(jj)) sinen(kk,jj)=dsin(dble(kk)*theta(jj)) end do end do !$omp end do !$omp barrier !$omp do schedule(runtime) private(kk,ii,jj) do jj=1,nnr ! For r do ii=1,nnr+1 ! For r_p do kk=1,ndiv gkrr(kk,ii,jj)=green_func( rdh(ii), rd(jj), kk ) end do end do end do !$omp end do !$omp barrier !$omp do schedule(runtime) private(kk,ii) ! At the outer boundary for r do ii=1,nnr+1 ! For r_p do kk=1,ndiv gkrr(kk,ii,nnr+1)=green_func( rdh(ii), rdh(nnr+1), kk ) end do end do !$omp end do !$omp barrier !$omp do schedule(runtime) private(kk,ii,jj) do jj=1,nnr+1 ! For r do ii=1,nnr+1 ! For r_p do kk=1,ndiv gkrrh(kk,ii,jj)=green_func( rdh(ii), rdh(jj), kk ) end do end do end do !$omp end do !$omp barrier !$omp do schedule(runtime) private(kk,ii,jj) do jj=1,nnr ! For r do ii=1,nnr+1 ! For r_p do kk=1,ndiv dgkrr(kk,ii,jj)=gkrr(kk,ii,jj+1)-gkrr(kk,ii,jj) end do end do end do !$omp end do !$omp barrier !$omp do schedule(runtime) private(kk,ii,jj) do jj=1,nnt do ii=1,nnr do kk=1,ndiv VDT_mrt(kk,ii,jj)=-(dr(ii)*dble(kk)*r_inv(ii)*vmax) & & *(-line_integral( nnr, rdh(1:nnr+1), gkrr(kk,1:nnr+1,ii), tmp_Ds_mr(kk,1:nnr+1) ) & & *sinen(kk,jj)) VDR_mrt(kk,ii,jj)=-(vmax) & & *(+line_integral( nnr, rdh(1:nnr+1), dgkrr(kk,1:nnr+1,ii), tmp_Ds_mr(kk,1:nnr+1) ) & & *cosinen(kk,jj)) end do end do end do !$omp end do !$omp end parallel end if if(ndiv>0)then deallocate(cosinen) deallocate(sinen) deallocate(gkrr) deallocate(gkrrh) deallocate(dgkrr) end if call stdout( "Finish procedure.", "calc_D2Vdiv", 0 ) end subroutine calc_D2Vdiv subroutine calc_Vn2Vtot( nrot, ndiv, V0, Vn, Vm, Vtot, undef ) !! Calculate (radial or tangential) total wind from all wavenumbers implicit none integer, intent(in) :: nrot !! Maximum wavenumber for stream function integer, intent(in) :: ndiv !! Maximum wavenumber for velocity potential double precision, intent(in) :: V0(:,:) !! Wavenumber-0 component [m/s] double precision, intent(in) :: Vn(nrot,size(V0,1),size(V0,2)) !! rotating components [m/s] double precision, intent(in) :: Vm(ndiv,size(V0,1),size(V0,2)) !! divergent components [m/s] double precision, intent(inout) :: Vtot(size(V0,1),size(V0,2)) !! Total wind [m/s] double precision, intent(in), optional :: undef !! Undefined value integer :: ii, jj, kk, nnr, nnt call stdout( "Enter procedure.", "calc_Vn2Vtot", 0 ) nnr=size(V0,1) nnt=size(V0,2) Vtot=V0 if(present(undef))then do jj=1,nnt do ii=1,nnr do kk=1,nrot if(Vn(kk,ii,jj)/=undef)then Vtot(ii,jj)=Vtot(ii,jj)+Vn(kk,ii,jj) end if end do do kk=1,ndiv if(Vn(kk,ii,jj)/=undef)then Vtot(ii,jj)=Vtot(ii,jj)+Vm(kk,ii,jj) end if end do end do end do else do jj=1,nnt do ii=1,nnr do kk=1,nrot Vtot(ii,jj)=Vtot(ii,jj)+Vn(kk,ii,jj) end do do kk=1,ndiv Vtot(ii,jj)=Vtot(ii,jj)+Vm(kk,ii,jj) end do end do end do end if call stdout( "Finish procedure.", "calc_Vn2Vtot", 0 ) end subroutine calc_Vn2Vtot double precision function dot_prod( v1, v2 ) !! Calculate inner product of two vectors implicit none double precision, intent(in) :: v1(:) !! Vector 1 double precision, intent(in) :: v2(size(v1)) ! Vector 2 integer :: ii, ni double precision :: res ni=size(v1) res=0.0d0 do ii=1,ni res=res+v1(ii)*v2(ii) end do dot_prod=res return end function dot_prod double precision function matrix_sum( aij, akj, undeflag ) !! Calculate product for a component in a matrix implicit none double precision, intent(in) :: aij(:,:) !! Matrix A1 double precision, intent(in) :: akj(size(aij,1),size(aij,2)) !! Matrix A2 logical, intent(in), optional :: undeflag(size(aij,1),size(aij,2)) !! Undefined flag at each sampling point integer :: ii, jj, ni, nj double precision :: res ni=size(aij,1) nj=size(aij,2) res=0.0d0 if(present(undeflag))then do jj=1,nj do ii=1,ni if(undeflag(ii,jj).eqv..false.)then res=res+aij(ii,jj)*akj(ii,jj) end if end do end do else do jj=1,nj do ii=1,ni res=res+aij(ii,jj)*akj(ii,jj) end do end do end if matrix_sum=res return end function matrix_sum subroutine check_zero( a ) !! Check zero components in the matrix "a" implicit none double precision, intent(in) :: a(:,:) !! Matrix a integer :: ii, jj, nni, nnj logical :: res nni=size(a,1) nnj=size(a,2) do jj=1,nnj res=.false. do ii=1,nni if(a(ii,jj)/=0.0d0)then res=.true. exit end if end do if(res.eqv..false.)then write(*,*) "Detect all zero", jj end if end do end subroutine check_zero subroutine check_undef_grid( vval, undefv, undeflag ) !! Check undefined grids implicit none double precision, intent(in) :: vval(:,:) !! Grid value double precision, intent(in) :: undefv !! Undefined value logical, intent(out) :: undeflag(size(vval,1),size(vval,2)) ! Undefined flag integer :: ii, jj, nni, nnj nni=size(vval,1) nnj=size(vval,2) undeflag=.false. do jj=1,nnj do ii=1,nni if(vval(ii,jj)==undefv)then undeflag(ii,jj)=.true. end if end do end do end subroutine check_undef_grid subroutine set_undef_value( undeflag, undefv, vval ) !! Set undef value (="undefv") to val if undeflag == true. implicit none logical, intent(in) :: undeflag(:,:) !! Undefined flag at each sampling point double precision, intent(in) :: undefv !! Undefined value double precision, intent(inout) :: vval(size(undeflag,1),size(undeflag,2)) !! Original value at each sampling point integer :: ii, jj, nni, nnj nni=size(undeflag,1) nnj=size(undeflag,2) do jj=1,nnj do ii=1,nni if(undeflag(ii,jj).eqv..true.)then vval(ii,jj)=undefv end if end do end do end subroutine set_undef_value subroutine calc_Phi2Phin( nrot, vmax, rmax, rd, rdh, theta, phis_nr, phic_nr, phi_nr ) !! Calculate streamfunction for each wavenumber implicit none integer, intent(in) :: nrot !!! Maximum wavenumber for stream function double precision, intent(in) :: vmax !! Scaling factor for velocity [m/s] double precision, intent(in) :: rmax !! Scaling factor for radius [m] double precision, intent(in) :: rd(:) !! Normalized radius [1] double precision, intent(in) :: rdh(size(rd)+1) !! Normalized radius [1] double precision, intent(in) :: theta(:) !! Azimuthal angle [rad] double precision, intent(in) :: phis_nr(nrot,size(rd)+1) !! Sine components of stream function [m2/s] double precision, intent(in) :: phic_nr(nrot,size(rd)+1) !! Cosine components of stream function [m2/s] double precision, intent(out) :: phi_nr(nrot,size(rd),size(theta)) !! Stream function [m2/s] integer :: ii, jj, kk, nnr, nnt, cstat double precision, dimension(size(rd)) :: alp double precision, dimension(nrot,size(theta)) :: sinen, cosinen double precision :: phisi, phici call stdout( "Enter procedure.", "calc_Phi2Phin", 0 ) nnr=size(rd) nnt=size(theta) !$omp parallel default(shared) !$omp do schedule(runtime) private(kk,ii) do jj=1,nnt do kk=1,nrot sinen(kk,jj)=dsin(dble(kk)*theta(jj)) cosinen(kk,jj)=dcos(dble(kk)*theta(jj)) end do end do !$omp end do !$omp end parallel do ii=1,nnr alp(ii)=(rd(ii)-rdh(ii))/(rdh(ii+1)-rdh(ii)) end do !$omp parallel default(shared) !$omp do schedule(runtime) private(kk,ii,jj,phisi,phici) do jj=1,nnt do ii=1,nnr do kk=1,nrot phisi=alp(ii)*phis_nr(kk,ii+1)+(1.0d0-alp(ii))*phis_nr(kk,ii) phici=alp(ii)*phic_nr(kk,ii+1)+(1.0d0-alp(ii))*phic_nr(kk,ii) phi_nr(kk,ii,jj)=(phisi*sinen(kk,jj)+phici*cosinen(kk,jj))*vmax*rmax end do end do end do !$omp end do !$omp end parallel call stdout( "Finish procedure.", "calc_Phi2Phin", 0 ) end subroutine calc_Phi2Phin subroutine calc_Phi2Zetan( nrot, vmax, rmax, rd, rdh, theta, phis_nr, phic_nr, & & zetas_nr, zetac_nr, zetan ) !! Calculate vorticity for each wavenumber implicit none integer, intent(in) :: nrot !! Maximum wavenumber for stream function double precision, intent(in) :: vmax !! Scaling factor for velocity [m/s] double precision, intent(in) :: rmax !! Scaling factor for radius [m] double precision, intent(in) :: rd(:) !! Normalized radius [1] double precision, intent(in) :: rdh(size(rd)+1) !! Normalized radius [1] double precision, intent(in) :: theta(:) !! Azimuthal angle [rad] double precision, intent(in) :: phis_nr(nrot,size(rd)+1) !! Sine components of stream function [m2/s] double precision, intent(in) :: phic_nr(nrot,size(rd)+1) !! Cosine components of stream function [m2/s] double precision, intent(out) :: zetas_nr(nrot,size(rd)) !! Sine components of vorticity [1/s] double precision, intent(out) :: zetac_nr(nrot,size(rd)) !! Cosine components of vorticity [1/s] double precision, intent(out) :: zetan(nrot,size(rd),size(theta)) !! Vorticity [1/s] integer :: ii, jj, kk, nnr, nnt, cstat double precision, dimension(size(rd)) :: alp double precision, dimension(nrot,size(rd)+1) :: d2psdr2, d2pcdr2, dpsdr, dpcdr double precision, dimension(nrot,size(theta)) :: sinen, cosinen double precision, dimension(nrot,0:size(rd)+2) :: tmpphis, tmpphic double precision, dimension(nrot,size(rd)) :: tmpzetas, tmpzetac double precision, dimension(size(rd)+1) :: drc_inv, drf_inv, drb_inv, rh_inv, rh2_inv double precision, dimension(size(rd)) :: r_inv double precision :: dpfs, dpfc, dpbs, dpbc, rmax_inv double precision :: d2psdr2i, dpsdri, d2pcdr2i, dpcdri, phisi, phici, zetasi, zetaci call stdout( "Enter procedure.", "calc_Phi2Zetan", 0 ) if(nrot<1)then call stdout( "nrot is greater than 0. stop.", "calc_Phi2Zetan", -1 ) stop end if nnr=size(rd) nnt=size(theta) drc_inv(1)=1.0d0/(rdh(2)-rdh(1)) drc_inv(nnr+1)=1.0d0/(rdh(nnr+1)-rdh(nnr)) drb_inv(1)=1.0d0/(rdh(2)-rdh(1)) drb_inv(nnr+1)=1.0d0/(rdh(nnr+1)-rdh(nnr)) drf_inv(1)=1.0d0/(rdh(2)-rdh(1)) drf_inv(nnr+1)=1.0d0/(rdh(nnr+1)-rdh(nnr)) rh_inv(nnr+1)=1.0/rdh(nnr+1) if(rdh(1)==0.0d0)then rh_inv(1)=0.0d0 end if if(rd(1)==0.0d0)then r_inv(1)=0.0d0 end if do ii=2,nnr drc_inv(ii)=1.0d0/(rdh(ii+1)-rdh(ii-1)) drb_inv(ii)=1.0d0/(rdh(ii)-rdh(ii-1)) drf_inv(ii)=1.0d0/(rdh(ii+1)-rdh(ii)) rh_inv(ii)=1.0d0/rdh(ii) r_inv(ii)=1.0d0/rd(ii) end do rmax_inv=1.0d0/rmax rh2_inv=rh_inv**2 tmpphis(1:nrot,1:nnr+1)=phis_nr(1:nrot,1:nnr+1) tmpphic(1:nrot,1:nnr+1)=phic_nr(1:nrot,1:nnr+1) tmpphis(1:nrot,0)=phis_nr(1:nrot,1) ! dummy tmpphis(1:nrot,nnr+2)=phis_nr(1:nrot,nnr+1) ! dummy tmpphic(1:nrot,0)=phic_nr(1:nrot,1) ! dummy tmpphic(1:nrot,nnr+2)=phic_nr(1:nrot,nnr+1) ! dummy zetan=0.0d0 do ii=1,nnr alp(ii)=(rd(ii)-rdh(ii))/(rdh(ii+1)-rdh(ii)) end do !$omp parallel default(shared) !$omp do schedule(runtime) private(kk,ii) do jj=1,nnt do kk=1,nrot sinen(kk,jj)=dsin(dble(kk)*theta(jj)) cosinen(kk,jj)=dcos(dble(kk)*theta(jj)) end do end do !$omp end do !$omp barrier !$omp do schedule(runtime) private(kk,ii) do ii=1,nnr+1 do kk=1,nrot d2psdr2(kk,ii)=2.0d0*drc_inv(ii) & & *((tmpphis(kk,ii+1)-tmpphis(kk,ii))*drf_inv(ii) & & +(tmpphis(kk,ii-1)-tmpphis(kk,ii))*drb_inv(ii)) d2pcdr2(kk,ii)=2.0d0*drc_inv(ii) & & *((tmpphic(kk,ii+1)-tmpphic(kk,ii))*drf_inv(ii) & & +(tmpphic(kk,ii-1)-tmpphic(kk,ii))*drb_inv(ii)) dpsdr(kk,ii)=0.5d0*((tmpphis(kk,ii+1)-tmpphis(kk,ii))*drf_inv(ii) & & -(tmpphis(kk,ii-1)-tmpphis(kk,ii))*drb_inv(ii)) dpcdr(kk,ii)=0.5d0*((tmpphic(kk,ii+1)-tmpphic(kk,ii))*drf_inv(ii) & & -(tmpphic(kk,ii-1)-tmpphic(kk,ii))*drb_inv(ii)) end do end do !$omp end do !$omp barrier !$omp do schedule(runtime) private(kk,ii,d2psdr2i,dpsdri,d2pcdr2i,dpcdri,phisi,phici) do ii=1,nnr do kk=1,nrot phisi=alp(ii)*phis_nr(kk,ii+1)+(1.0d0-alp(ii))*phis_nr(kk,ii) phici=alp(ii)*phic_nr(kk,ii+1)+(1.0d0-alp(ii))*phic_nr(kk,ii) d2psdr2i=alp(ii)*d2psdr2(kk,ii+1)+(1.0d0-alp(ii))*d2psdr2(kk,ii) dpsdri=alp(ii)*dpsdr(kk,ii+1)+(1.0d0-alp(ii))*dpsdr(kk,ii) d2pcdr2i=alp(ii)*d2pcdr2(kk,ii+1)+(1.0d0-alp(ii))*d2pcdr2(kk,ii) dpcdri=alp(ii)*dpcdr(kk,ii+1)+(1.0d0-alp(ii))*dpcdr(kk,ii) tmpzetas(kk,ii)=-(d2psdr2i+dpsdri*r_inv(ii)-((dble(kk)*r_inv(ii))**2)*phisi) & & *vmax*rmax_inv tmpzetac(kk,ii)=-(d2pcdr2i+dpcdri*r_inv(ii)-((dble(kk)*r_inv(ii))**2)*phici) & & *vmax*rmax_inv zetas_nr(kk,ii)=tmpzetas(kk,ii) zetac_nr(kk,ii)=tmpzetac(kk,ii) end do end do !$omp end do !$omp barrier !$omp do schedule(runtime) private(kk,ii,jj) do jj=1,nnt do ii=1,nnr do kk=1,nrot zetan(kk,ii,jj)=tmpzetas(kk,ii)*sinen(kk,jj)+tmpzetac(kk,ii)*cosinen(kk,jj) end do end do end do !$omp end do !$omp end parallel call stdout( "Finish procedure.", "calc_Phi2Zetan", 0 ) end subroutine calc_Phi2Zetan subroutine calc_pseudo_GVTD0( nrot, vmax, rtc, rd, rdh, VRT0_r, VDR0_r, & & phis_nr, phic_nr, VRT0_GVTD_r, VDR0_GVTD_r ) !! Calculate pseudo retrieval of VT and VR for GVTD implicit none integer, intent(in) :: nrot !! Maximum wavenumber for stream function double precision, intent(in) :: vmax !! Scaling factor for velocity [m/s] double precision, intent(in) :: rtc !! Normalized distance between the radar to vortex center [1] double precision, intent(in) :: rd(:) !! Normalized radius [1] double precision, intent(in) :: rdh(size(rd)+1) !! Normalized radius [1] double precision, intent(in) :: VRT0_r(size(rd)) !! Wavenumber-0 tangential wind [m/s] double precision, intent(in) :: VDR0_r(size(rd)) !! Wanumber-0 radial wind [m/s] double precision, intent(in) :: phis_nr(nrot,size(rd)+1) !! Sine components of stream function [m2/s] double precision, intent(in) :: phic_nr(nrot,size(rd)+1) !! Cosine components of stream function [m2/s] double precision, intent(out) :: VRT0_GVTD_r(size(rd)) !! GVTD-reconstructed wavenumber-0 tangential wind [m/s] double precision, intent(out) :: VDR0_GVTD_r(size(rd)) !! GVTD-reconstructed wavenumber-0 radial wind [m/s] integer :: ii, jj, kk, nnr, cstat double precision, dimension(size(rd)) :: dr, dr_inv, r_inv, alp double precision, dimension(size(rd)) :: tmp_VRT0_r, tmp_VDR0_r call stdout( "Enter procedure.", "calc_pseudo_GVTD0", 0 ) nnr=size(rd) do ii=1,nnr dr(ii)=rdh(ii+1)-rdh(ii) dr_inv(ii)=1.0d0/dr(ii) alp(ii)=(rd(ii)-rdh(ii))/(rdh(ii+1)-rdh(ii)) end do r_inv(1:nnr)=1.0d0/rd(1:nnr) tmp_VRT0_r(1:nnr)=VRT0_r(1:nnr) tmp_VDR0_r(1:nnr)=VDR0_r(1:nnr) if(nrot>0)then !$omp parallel default(shared) !-- For wavenumber 1 !$omp do schedule(runtime) private(ii) do ii=1,nnr tmp_VRT0_r(ii)=tmp_VRT0_r(ii) & & +((alp(ii)*phic_nr(1,ii+1)+(1.0d0-alp(ii))*phic_nr(1,ii))/rtc)*vmax tmp_VDR0_r(ii)=tmp_VDR0_r(ii) & & +r_inv(ii)*(alp(ii)*phis_nr(1,ii+1)+(1.0d0-alp(ii))*phis_nr(1,ii))*vmax end do !$omp end do !$omp barrier !-- For wavenumber 2 if(nrot>1)then !$omp do schedule(runtime) private(ii) do ii=1,nnr tmp_VRT0_r(ii)=tmp_VRT0_r(ii) & & +2.0d0*r_inv(ii)*(alp(ii)*phic_nr(2,ii+1)+(1.0d0-alp(ii))*phic_nr(2,ii))*vmax tmp_VDR0_r(ii)=tmp_VDR0_r(ii) & & +2.0d0*r_inv(ii)*(alp(ii)*phis_nr(2,ii+1)+(1.0d0-alp(ii))*phis_nr(2,ii))*vmax end do !$omp end do end if !$omp barrier !-- For wavenumber 3 if(nrot>2)then !$omp do schedule(runtime) private(ii) do ii=1,nnr tmp_VRT0_r(ii)=tmp_VRT0_r(ii) & & +3.0d0*((alp(ii)*phic_nr(3,ii+1)+(1.0d0-alp(ii))*phic_nr(3,ii))/rtc)*vmax tmp_VDR0_r(ii)=tmp_VDR0_r(ii) & & +3.0d0*r_inv(ii)*(alp(ii)*phis_nr(3,ii+1)+(1.0d0-alp(ii))*phis_nr(3,ii))*vmax end do !$omp end do end if !$omp end parallel VRT0_GVTD_r(1:nnr)=tmp_VRT0_r(1:nnr) VDR0_GVTD_r(1:nnr)=tmp_VDR0_r(1:nnr) end if call stdout( "Finish procedure.", "calc_pseudo_GVTD0", 0 ) end subroutine calc_pseudo_GVTD0 subroutine calc_phi2sc( nrot, vmax, rd, rdh, phis_nr, phic_nr, & & VRTns_r, VRTnc_r, VRRns_r, VRRnc_r ) !! Calculate sine and cosine components of Vt and VR for rot implicit none integer, intent(in) :: nrot !! Maximum wavenumber for stream function double precision, intent(in) :: vmax !! Scaling factor for velocity [m/s] double precision, intent(in) :: rd(:) !! Normalized radius [1] double precision, intent(in) :: rdh(size(rd)+1) !! Normalized radius [1] double precision, intent(in) :: phis_nr(nrot,size(rd)+1) !! Sine components of stream function [m2/s] double precision, intent(in) :: phic_nr(nrot,size(rd)+1) !! Cosine components of stream function [m2/s] double precision, intent(out) :: VRTns_r(nrot,size(rd)) !! Sine compoents of tangential wind [m/s] double precision, intent(out) :: VRTnc_r(nrot,size(rd)) !! Cosine components of tangential wind [m/s] double precision, intent(out) :: VRRns_r(nrot,size(rd)) !! Sine components of radial wind [m/s] double precision, intent(out) :: VRRnc_r(nrot,size(rd)) !! Cosine components of radial wind [m/s] integer :: ii, jj, kk, nnr, cstat double precision, dimension(size(rd)) :: dr, dr_inv, r_inv, alp call stdout( "Enter procedure.", "calc_phi2sc", 0 ) nnr=size(rd) do ii=1,nnr dr(ii)=rdh(ii+1)-rdh(ii) dr_inv(ii)=1.0d0/dr(ii) alp(ii)=(rd(ii)-rdh(ii))/(rdh(ii+1)-rdh(ii)) end do r_inv(1:nnr)=1.0d0/rd(1:nnr) if(nrot>0)then !$omp parallel default(shared) !$omp do schedule(runtime) private(kk,ii) do ii=1,nnr do kk=1,nrot VRTns_r(kk,ii)=-(phis_nr(kk,ii+1)-phis_nr(kk,ii))*dr_inv(ii)*vmax VRTnc_r(kk,ii)=-(phic_nr(kk,ii+1)-phic_nr(kk,ii))*dr_inv(ii)*vmax VRRns_r(kk,ii)=-dble(kk)*(alp(ii)*phic_nr(kk,ii+1)+(1.0d0-alp(ii))*phic_nr(kk,ii))*r_inv(ii)*vmax VRRnc_r(kk,ii)=dble(kk)*(alp(ii)*phis_nr(kk,ii+1)+(1.0d0-alp(ii))*phis_nr(kk,ii))*r_inv(ii)*vmax end do end do !$omp end do !$omp end parallel end if call stdout( "Finish procedure.", "calc_phi2sc", 0 ) end subroutine calc_phi2sc end module GVTDX_main