Skip to content
Snippets Groups Projects
pbldia_new_sfx.f90 13.5 KiB
Newer Older
      implicit none
      private
      
      public :: pbldia_new_sheba,pbldia_new_sheba_noit,&
      pbldia_new_most,pbldia_new_esm,pbldia_new_log,pbldia_new_sheba_coare
      
      real,parameter,private::kappa=0.4,R=287.,appa=0.287
      
      contains
      
      ! in this module interpolation is performed using integration of universal functions from z1 to z2, 
      ! where z1 is measurement or lowest model level height and z2 is required height
      ! The input-output structure is preserved as much as possible as in the climate model (pbldia subroutine in pblflx)
      !C*    DIAGNOSIS OF WIND VELOCITY (AT HEIGHT Z = HWIND),
      !C*    OF POTENTIAL TEMPERATURE DEFICIT (BETWEEN HEIGHT Z = HTEMP AND SURFACE),
      !C*    OF SPECIFIC HUMIDITY DEFICIT (BETWEEN HEIGHT Z = HTEMP AND SURFACE)
      !C*    INPUT DATA USED:
      !C*    ARRAY AR2 (OUTPUT FROM DRAG3 - SUBROUTINE)
      !C*    AR2(1)    - NON-DIMENSIONAL (NORMALIZED BY MONIN-OBUKHOV LENGTH)
      !C*                HEIGHT OF CONSTANT FLUX LAYER TOP
      !C*    AR2(8)    - INTEGRAL TRANSFER COEFFICIENT FOR MOMENTUM
      !C*    AR2(9)    - INTEGRAL TRANSFER COEFFICIENT FOR TEMPERATURE AND HUMIDITY
      !C*    ARRAY ARDIN
      !C*    ARDIN(1)  - MODULE OF WIND VELOCITY AT THE TOP OF CONSTANT FLUX LAYER
      !C*    ARDIN(2)  - POTENTIAL TEMPERATURE DEFICIT IN CONSTANT FLUX LAYER
      !C*    ARDIN(3)  - SPECIFIC HUMIDITY DEFICIT IN CONSTANT FLUX LAYER
      !C*    ARDIN(4)  - DIMENSIONAL HEIGHT OF CONSTANT FLUX LAYER TOP
      !C*    ARDIN(5)  - = HWIND
      !C*    ARDIN(6)  - = HTEMP
      !C*    OUTPUT DATA (ARRAY ARDOUT):
      !C*    ARDOUT(1)  - MODULE OF WIND VELOCITY AT REQUIRED HEIGHT
      !C*    ARDOUT(2)  - deficit of POTENTIAL TEMPERATURE between REQUIRED HEIGHT and the surface
      !C*    ARDOUT(3)  - deficit of SPECIFIC HUMIDITY between REQUIRED HEIGHT and the surface
      !C*    UFWIND     - UNIVERSAL FUNCTION FOR WIND VELOCITY
      !C*    UFTEMP     - UNIVERSAL FUNCTION FOR SCALARS
      
      
      subroutine pbldia_new_log(AR2,ARDIN,ARDOUT)
            real,intent(in):: AR2(11),ARDIN(6)
            real,intent(out)::ARDOUT(3)
            real hwind,htemp,ustar,tstar,qstar
            real dteta,dq,wind,HIN,zeta
      
            HWIND = ARDIN(5)
            HTEMP = ARDIN(6)
            HIN = ardin(4)
            zeta = AR2(1)
      
            USTAR = AR2(8) * ARDIN(1)
            TSTAR = AR2(9) * ARDIN(2)
            QSTAR = AR2(9) * ARDIN(3)
      
            WIND = (USTAR/kappa)*ALOG(hwind/HIN)
            DTETA = (TSTAR/kappa)*ALOG(htemp/HIN)
            DQ = (QSTAR/kappa)*ALOG(htemp/HIN)
      
      
            ARDOUT(1) = ARDIN(1)+WIND
            ARDOUT(2) = DTETA+ardin(2)
            ARDOUT(3) = DQ+ardin(3)
      
      
            return
        end subroutine pbldia_new_log
      
      subroutine pbldia_new_sheba(AR2,ARDIN,ARDOUT)
      use sfx_sheba, only: get_psi_sheba => get_psi
      
            real,intent(in):: AR2(11),ARDIN(6)
            real,intent(out)::ARDOUT(3)
            real,parameter::zetalim = 1. !maximum value of z/L for 
      !      stable SL for wind
            real psi_m,psi_h,psi_m_hs,psi_h_hs
            real hwind,htemp,ustar,tstar,qstar,&
      & ufwind,uftemp,dteta,dq,wind,L,HIN,zeta
            real Rib,ksi,wg,f,L_lim
      
            HWIND = ARDIN(5)
            HTEMP = ARDIN(6)
            HIN = ardin(4)
            zeta = AR2(1)
            Rib = AR2(2)
      
            USTAR = AR2(8) * ARDIN(1)
            TSTAR = AR2(9) * ARDIN(2)
            QSTAR = AR2(9) * ARDIN(3)
      
           if (zeta.ne.0) then
               L = HIN/zeta
               if(zeta.gt.zetalim) then
                    L_lim = HIN/zetalim
               else
                   L_lim = L
               end if
      
           call get_psi_sheba(psi_m_hs,psi_h_hs,HIN/L_lim)
           call get_psi_sheba(psi_m,psi_h,HWIND/L_lim)
           UFWIND = ALOG(hwind/HIN) - (psi_m - psi_m_hs)
           call get_psi_sheba(psi_m_hs,psi_h_hs,HIN/L)
           call get_psi_sheba(psi_m,psi_h,HTEMP/L)
           UFTEMP = ALOG(HTEMP/HIN) - (psi_h - psi_h_hs)
      
           else
      
            UFWIND = ALOG(HWIND/HIN)
            UFTEMP = ALOG(HTEMP/HIN) 
      
           endif
      
            WIND = (USTAR/kappa) * UFWIND
            DTETA = (TSTAR/kappa) * UFTEMP
            DQ = (QSTAR/kappa) * UFTEMP
      
      
            ARDOUT(1) = ARDIN(1)+WIND
            ARDOUT(2) = DTETA+ardin(2)
            ARDOUT(3) = DQ+ardin(3)
      
      
            return
        end subroutine pbldia_new_sheba
      
      subroutine pbldia_new_sheba_coare(AR2,ARDIN,ARDOUT)
      use sfx_sheba_coare, only: &
                      get_psi_coare => get_psi_a, &
                      get_psi_stable_sheba => get_psi_stable
      
            real,intent(in):: AR2(11),ARDIN(6)
            real,intent(out)::ARDOUT(3)
            real,parameter::zetalim = 1. !maximum value of z/L for stable SL
            real psi_m,psi_h,psi_m_hs,psi_h_hs
            real hwind,htemp,ustar,tstar,qstar,&
      & ufwind,uftemp,dteta,dq,wind,L,HIN,zeta,L_lim
      
            HWIND = ARDIN(5)
            HTEMP = ARDIN(6)
            HIN = ardin(4)
            zeta = AR2(1)
      
            USTAR = AR2(8) * ARDIN(1)
            TSTAR = AR2(9) * ARDIN(2)
            QSTAR = AR2(9) * ARDIN(3)
      
           if(zeta.ne.0)then

               L = HIN/zeta
               if(zeta.gt.zetalim) then
                   L_lim = HIN/zetalim
               else
                   L_lim = L
               end if
      
           if(zeta.gt.0)then ! stable stratification
      
      
           call get_psi_stable_sheba(psi_m_hs,psi_h_hs,HIN/L_lim,HIN/L)
           call get_psi_stable_sheba(psi_m,psi_h,HWIND/L_lim,HTEMP/L)
      
           else 
      
           call get_psi_coare(psi_m_hs,psi_h_hs,HIN/L,HIN/L)
           call get_psi_coare(psi_m,psi_h,HWIND/L,HTEMP/L)
      
           endif
      
           UFWIND = ALOG(hwind/HIN) - (psi_m - psi_m_hs)
           UFTEMP = ALOG(HTEMP/HIN) - (psi_h - psi_h_hs)
           
           else
      
            UFWIND = ALOG(HWIND/HIN)
            UFTEMP = ALOG(HTEMP/HIN) 
      
           endif
      
            WIND = (USTAR/kappa) * UFWIND
            DTETA = (TSTAR/kappa) * UFTEMP
            DQ = (QSTAR/kappa) * UFTEMP
      
      
            ARDOUT(1) = ARDIN(1)+WIND
            ARDOUT(2) = DTETA+ardin(2)
            ARDOUT(3) = DQ+ardin(3)
      
      
            return
        end subroutine pbldia_new_sheba_coare
      
      
      subroutine pbldia_new_sheba_noit(AR2,ARDIN,ARDOUT)
      use sfx_sheba_noniterative, only: &
                      get_psi_stable_sheba => get_psi_stable
      
            real,intent(in):: AR2(11),ARDIN(6)
            real,intent(out)::ARDOUT(3)
            real,parameter::zetalim = 1. !maximum value of z/L for stable SL
            real psi_m,psi_h,psi_m_hs,psi_h_hs
            real hwind,htemp,ustar,tstar,qstar,&
      & ufwind,uftemp,dteta,dq,wind,L,HIN,zeta
            real Rib,wg,ksi,f, L_lim
      
            HWIND = ARDIN(5)
            HTEMP = ARDIN(6)
            HIN = ardin(4)
            zeta = AR2(1)
            Rib = AR2(2)
      
            USTAR = AR2(8) * ARDIN(1)
            TSTAR = AR2(9) * ARDIN(2)
            QSTAR = AR2(9) * ARDIN(3)
      
           if(zeta.ne.0)then

               L = HIN/zeta
               if(zeta.gt.zetalim) then
                   L_lim = HIN/zetalim
               else
                   L_lim = L
               end if
      
           if(zeta.gt.0)then ! stable stratification
      
      
           call get_psi_stable_sheba(psi_m_hs,psi_h_hs,HIN/L_lim,HIN/L)
           call get_psi_stable_sheba(psi_m,psi_h,HWIND/L_lim,HTEMP/L)
           UFWIND = ALOG(hwind/HIN) - (psi_m - psi_m_hs)
           UFTEMP = ALOG(HTEMP/HIN) - (psi_h - psi_h_hs)
      
      
           else    ! unstable stratification (functions from ESM)
      
           call get_psi_esm1(psi_m,psi_h,HIN,HWIND,L)
           UFWIND = psi_m
           call get_psi_esm1(psi_m,psi_h,HIN,HTEMP,L)
           UFTEMP = psi_h
      
           endif
      
           else
      
      ! neutral stratification (z/L=0)
      
            UFWIND = ALOG(HWIND/HIN)
            UFTEMP = ALOG(HTEMP/HIN) 
      
           endif
      
            WIND = (USTAR/kappa) * UFWIND
            DTETA = (TSTAR/kappa) * UFTEMP
            DQ = (QSTAR/kappa) * UFTEMP
      
      
            ARDOUT(1) = ARDIN(1)+WIND
            ARDOUT(2) = DTETA+ardin(2)
            ARDOUT(3) = DQ+ardin(3)
      
      
            return
        end subroutine pbldia_new_sheba_noit
      
      subroutine pbldia_new_most(AR2,ARDIN,ARDOUT)
      use sfx_most, only: &
                      get_psi_most => get_psi
      
            real,intent(in):: AR2(11),ARDIN(6)
            real,intent(out)::ARDOUT(3)
            real,parameter::zetalim = 1. !maximum value of z/L for stable SL
            real psi_m,psi_h,psi_m_hs,psi_h_hs
            real hwind,htemp,ustar,tstar,qstar,&
      & ufwind,uftemp,dteta,dq,wind,L,HIN,zeta
            real Rib,ksi,wg,f,L_lim
      
            HWIND = ARDIN(5)
            HTEMP = ARDIN(6)
            HIN = ardin(4)
            zeta = AR2(1)
            Rib = AR2(2)
      
            USTAR = AR2(8) * ARDIN(1)
            TSTAR = AR2(9) * ARDIN(2)
            QSTAR = AR2(9) * ARDIN(3)
      
           if(zeta.ne.0)then

               L = HIN/zeta
               if(zeta.gt.zetalim) then
                   L_lim = HIN/zetalim
               else
                   L_lim = L
               end if
      
           call get_psi_most(psi_m_hs,psi_h_hs,HIN/L_lim)
           call get_psi_most(psi_m,psi_h,HWIND/L_lim)
           UFWIND = ALOG(hwind/HIN) - (psi_m - psi_m_hs)
           call get_psi_most(psi_m_hs,psi_h_hs,HIN/L)
           call get_psi_most(psi_m,psi_h,HTEMP/L)
            UFTEMP = ALOG(HTEMP/HIN) - (psi_h - psi_h_hs)
      
           else
      
            UFWIND = ALOG(HWIND/HIN)
            UFTEMP = ALOG(HTEMP/HIN) 
      
           endif
      
            WIND = (USTAR/kappa) * UFWIND
            DTETA = (TSTAR/kappa) * UFTEMP
            DQ = (QSTAR/kappa) * UFTEMP
      
            ARDOUT(1) = ARDIN(1)+WIND
            ARDOUT(2) = DTETA+ardin(2)
            ARDOUT(3) = DQ+ardin(3)
      
      
            return
        end subroutine pbldia_new_most
      
      subroutine pbldia_new_esm(AR2,ARDIN,ARDOUT)
            real,intent(in):: AR2(11),ARDIN(6)
            real,intent(out)::ARDOUT(3)
            real,parameter::zetalim = 1. !maximum value of z/L for stable SL
            real psi_m,psi_h,psi_m_hs,psi_h_hs
            real hwind,htemp,ustar,tstar,qstar,&
      & ufwind,uftemp,dteta,dq,wind,L_lim,L,HIN,zeta
      
            HWIND = ARDIN(5)
            HTEMP = ARDIN(6)
            HIN = ardin(4)
            zeta = AR2(1)
      
            USTAR = AR2(8) * ARDIN(1)
            TSTAR = AR2(9) * ARDIN(2)
            QSTAR = AR2(9) * ARDIN(3)
      
           if(zeta.ne.0)then
               L = HIN/zeta
               if(zeta.gt.zetalim) then
                   L_lim = HIN/zetalim
               else
                   L_lim = L
               end if
      
           call get_psi_esm1(psi_m,psi_h,HIN,HWIND,L_lim)
           UFWIND = psi_m
           call get_psi_esm1(psi_m,psi_h,HIN,HTEMP,L)
           UFTEMP = psi_h
      
           else
      
            UFWIND = ALOG(HWIND/HIN)
            UFTEMP = ALOG(HTEMP/HIN) 
      
           endif
      
            WIND = (USTAR/kappa) * UFWIND
            DTETA = (TSTAR/kappa) * UFTEMP
            DQ = (QSTAR/kappa) * UFTEMP
      
            ARDOUT(1) = ARDIN(1)+WIND
            ARDOUT(2) = DTETA+ardin(2)
            ARDOUT(3) = DQ+ardin(3)
      
      
            return
        end subroutine pbldia_new_esm
      
      
      subroutine get_psi_esm1(psi_m,psi_h,z1,z2,L)
      
      use sfx_esm_param
      
      real, intent(out) :: psi_m, psi_h
      real, intent(in) :: z1,z2,L
      
      real an5,d1,gmz1,gtz1,gmz2,gtz2,gmst,gtst,zeta1,zeta2
      
            an5 = (Pr_t_inf_inv/Pr_t_0_inv)**4
            d1=(2.0E0*alpha_h-an5*alpha_m-sqrt((an5*alpha_m)**2+4.0E0*an5*alpha_h*&
      &        (alpha_h-alpha_m)))/(2.0E0*alpha_h**2)
      
      
            zeta1 = z1 / L
            zeta2 = z2 / L
      
            if(zeta2 .ge. 0.) then
      
            psi_m = alog(z2/z1) + beta_m*(zeta2-zeta1)
            psi_h = alog(z2/z1) + beta_m*(zeta2-zeta1)
      
            else
      
            gmz2 = sqrt(sqrt(1.E0 - alpha_m * zeta2))
            gmz1 = sqrt(sqrt(1.E0 - alpha_m * zeta1))
            gmst = sqrt(sqrt(1.E0 - alpha_m * D1))
            gtz2 = sqrt(1.E0 - alpha_h * zeta2)
            gtz1 = sqrt(1.E0 - alpha_h * zeta1)
            gtst = sqrt(1.E0 - alpha_h * D1)
      
            if(zeta2 .ge. d1) then
            psi_m = fim(gmz2) - fim(gmz1)
            psi_h = fit(gtz2) - fit(gtz1)
            else
            psi_m = (3.E0/gmst) * (1.E0 - (d1/zeta2)**(1.E0/3.E0)) + fim(gmst) - fim(gmz1)
            psi_h = (3.E0/gtst) * (1.E0 - (d1/zeta2)**(1.E0/3.E0)) + fit(gtst) - fit(gtz1)
            endif
            endif
      
      end subroutine get_psi_esm1
      
      ! functions fim,fit were copied from the original pbldia
      REAL FUNCTION FIM(XX)
        IMPLICIT NONE
        REAL X, XX
        X = AMAX1(XX,1.000001E0)
        FIM = ALOG((X-1.E0)/(X+1.E0)) + 2.E0*ATAN(X)
        RETURN
      END function
      
      REAL FUNCTION FIT(XX)
        IMPLICIT NONE
        REAL X, XX
        X = AMAX1(XX,1.000001E0)
        FIT = ALOG((X-1.E0)/(X+1.E0))
        RETURN
      END function
      
      end module pbldia_new_sfx