Ignore:
Timestamp:
Jul 29, 2024, 11:01:04 PM (3 months ago)
Author:
abarral
Message:

Put YOMCST.h into modules

File:
1 edited

Legend:

Unmodified
Added
Removed
  • LMDZ6/branches/Amaury_dev/libf/phylmd/lmdz_lscp_tools.F90

    r5143 r5144  
    11MODULE lmdz_lscp_tools
    22
    3     IMPLICIT NONE
     3  IMPLICIT NONE
    44
    55CONTAINS
    66
    7 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    8 SUBROUTINE FALLICE_VELOCITY(klon,iwc,temp,rho,pres,ptconv,velo)
     7  !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     8  SUBROUTINE FALLICE_VELOCITY(klon, iwc, temp, rho, pres, ptconv, velo)
    99
    1010    ! Ref:
     
    1515    ! Advances in Modeling Earth Systems, 11,
    1616    ! 3212–3234. https://doi.org/10.1029/2019MS001642
    17    
     17
    1818    USE lmdz_lscp_ini, ONLY: iflag_vice, ffallv_con, ffallv_lsc
    1919    USE lmdz_lscp_ini, ONLY: cice_velo, dice_velo
     
    3030    REAL, INTENT(OUT), DIMENSION(klon) :: velo    ! fallspeed velocity of crystals [m/s]
    3131
    32 
    3332    INTEGER i
    34     REAL logvm,iwcg,tempc,phpa,fallv_tun
     33    REAL logvm, iwcg, tempc, phpa, fallv_tun
    3534    REAL m2ice, m2snow, vmice, vmsnow
    3635    REAL aice, bice, asnow, bsnow
    37    
    38 
    39     DO i=1,klon
    40 
    41         IF (ptconv(i)) THEN
    42             fallv_tun=ffallv_con
    43         ELSE
    44             fallv_tun=ffallv_lsc
    45         ENDIF
    46 
    47         tempc=temp(i)-273.15 ! celcius temp
    48         iwcg=MAX(iwc(i)*1000.,1E-3) ! iwc in g/m3. We set a minimum value to prevent from division by 0
    49         phpa=pres(i)/100.    ! pressure in hPa
    50 
    51     IF (iflag_vice == 1) THEN
     36
     37    DO i = 1, klon
     38
     39      IF (ptconv(i)) THEN
     40        fallv_tun = ffallv_con
     41      ELSE
     42        fallv_tun = ffallv_lsc
     43      ENDIF
     44
     45      tempc = temp(i) - 273.15 ! celcius temp
     46      iwcg = MAX(iwc(i) * 1000., 1E-3) ! iwc in g/m3. We set a minimum value to prevent from division by 0
     47      phpa = pres(i) / 100.    ! pressure in hPa
     48
     49      IF (iflag_vice == 1) THEN
    5250        ! so-called 'empirical parameterization' in Stubenrauch et al. 2019
    5351        IF (tempc >= -60.0) THEN
    54             logvm= -0.0000414122*tempc*tempc*log(iwcg)-0.00538922*tempc*log(iwcg) &
    55                     -0.0516344*log(iwcg)+0.00216078*tempc + 1.9714   
    56             velo(i)=exp(logvm)
     52          logvm = -0.0000414122 * tempc * tempc * log(iwcg) - 0.00538922 * tempc * log(iwcg) &
     53                  - 0.0516344 * log(iwcg) + 0.00216078 * tempc + 1.9714
     54          velo(i) = exp(logvm)
    5755        else
    58             velo(i)=65.0*(iwcg**0.2)*(150./phpa)**0.15
     56          velo(i) = 65.0 * (iwcg**0.2) * (150. / phpa)**0.15
    5957        endif
    60        
    61         velo(i)=fallv_tun*velo(i)/100.0 ! from cm/s to m/s
    62 
    63     ELSE IF (iflag_vice == 2) THEN
     58
     59        velo(i) = fallv_tun * velo(i) / 100.0 ! from cm/s to m/s
     60
     61      ELSE IF (iflag_vice == 2) THEN
    6462        ! so called  PSDM empirical coherent bulk ice scheme in Stubenrauch et al. 2019
    65         aice=0.587
    66         bice=2.45
    67         asnow=0.0444
    68         bsnow=2.1
    69        
    70         m2ice=((iwcg*0.001/aice)/(exp(13.6-bice*7.76+0.479*bice**2)* &
    71                 exp((-0.0361+bice*0.0151+0.00149*bice**2)*tempc)))   &
    72                 **(1./(0.807+bice*0.00581+0.0457*bice**2))
    73 
    74         vmice=100.*1042.4*exp(13.6-(bice+1)*7.76+0.479*(bice+1.)**2)*exp((-0.0361+ &
    75                  (bice+1.)*0.0151+0.00149*(bice+1.)**2)*tempc) &
    76                  *(m2ice**(0.807+(bice+1.)*0.00581+0.0457*(bice+1.)**2))/(iwcg*0.001/aice)
    77 
    78        
    79         vmice=vmice*((1000./phpa)**0.2)
    80      
    81         m2snow=((iwcg*0.001/asnow)/(exp(13.6-bsnow*7.76+0.479*bsnow**2)* &
    82                exp((-0.0361+bsnow*0.0151+0.00149*bsnow**2)*tempc)))         &
    83                **(1./(0.807+bsnow*0.00581+0.0457*bsnow**2))
    84 
    85 
    86         vmsnow=100.*14.3*exp(13.6-(bsnow+.416)*7.76+0.479*(bsnow+.416)**2)&
    87                   *exp((-0.0361+(bsnow+.416)*0.0151+0.00149*(bsnow+.416)**2)*tempc)&
    88                   *(m2snow**(0.807+(bsnow+.416)*0.00581+0.0457*(bsnow+.416)**2))/(iwcg*0.001/asnow)
    89 
    90         vmsnow=vmsnow*((1000./phpa)**0.35)
    91         velo(i)=fallv_tun*min(vmsnow,vmice)/100. ! to m/s
    92 
    93     ELSE
     63        aice = 0.587
     64        bice = 2.45
     65        asnow = 0.0444
     66        bsnow = 2.1
     67
     68        m2ice = ((iwcg * 0.001 / aice) / (exp(13.6 - bice * 7.76 + 0.479 * bice**2) * &
     69                exp((-0.0361 + bice * 0.0151 + 0.00149 * bice**2) * tempc)))   &
     70                **(1. / (0.807 + bice * 0.00581 + 0.0457 * bice**2))
     71
     72        vmice = 100. * 1042.4 * exp(13.6 - (bice + 1) * 7.76 + 0.479 * (bice + 1.)**2) * exp((-0.0361 + &
     73                (bice + 1.) * 0.0151 + 0.00149 * (bice + 1.)**2) * tempc) &
     74                * (m2ice**(0.807 + (bice + 1.) * 0.00581 + 0.0457 * (bice + 1.)**2)) / (iwcg * 0.001 / aice)
     75
     76        vmice = vmice * ((1000. / phpa)**0.2)
     77
     78        m2snow = ((iwcg * 0.001 / asnow) / (exp(13.6 - bsnow * 7.76 + 0.479 * bsnow**2) * &
     79                exp((-0.0361 + bsnow * 0.0151 + 0.00149 * bsnow**2) * tempc)))         &
     80                **(1. / (0.807 + bsnow * 0.00581 + 0.0457 * bsnow**2))
     81
     82        vmsnow = 100. * 14.3 * exp(13.6 - (bsnow + .416) * 7.76 + 0.479 * (bsnow + .416)**2)&
     83                * exp((-0.0361 + (bsnow + .416) * 0.0151 + 0.00149 * (bsnow + .416)**2) * tempc)&
     84                * (m2snow**(0.807 + (bsnow + .416) * 0.00581 + 0.0457 * (bsnow + .416)**2)) / (iwcg * 0.001 / asnow)
     85
     86        vmsnow = vmsnow * ((1000. / phpa)**0.35)
     87        velo(i) = fallv_tun * min(vmsnow, vmice) / 100. ! to m/s
     88
     89      ELSE
    9490        ! By default, fallspeed velocity of ice crystals according to Heymsfield & Donner 1990
    95         velo(i) = fallv_tun*cice_velo*((iwcg/1000.)**dice_velo)
    96     ENDIF
     91        velo(i) = fallv_tun * cice_velo * ((iwcg / 1000.)**dice_velo)
     92      ENDIF
    9793    ENDDO
    9894
    99 END SUBROUTINE FALLICE_VELOCITY
    100 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    101 
    102 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    103 SUBROUTINE ICEFRAC_LSCP(klon, temp, iflag_ice_thermo, distcltop, temp_cltop, icefrac, dicefracdT)
    104 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    105  
    106   ! Compute the ice fraction 1-xliq (see e.g.
    107   ! Doutriaux-Boucher & Quaas 2004, section 2.2.)
    108   ! as a function of temperature
    109   ! see also Fig 3 of Madeleine et al. 2020, JAMES
    110 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    111 
     95  END SUBROUTINE FALLICE_VELOCITY
     96  !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     97
     98  !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     99  SUBROUTINE ICEFRAC_LSCP(klon, temp, iflag_ice_thermo, distcltop, temp_cltop, icefrac, dicefracdT)
     100    !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     101
     102    ! Compute the ice fraction 1-xliq (see e.g.
     103    ! Doutriaux-Boucher & Quaas 2004, section 2.2.)
     104    ! as a function of temperature
     105    ! see also Fig 3 of Madeleine et al. 2020, JAMES
     106    !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    112107
    113108    USE lmdz_print_control, ONLY: lunout, prt_level
     
    118113    IMPLICIT NONE
    119114
    120 
    121     INTEGER, INTENT(IN)                 :: klon              ! number of horizontal grid points
    122     REAL, INTENT(IN), DIMENSION(klon)   :: temp              ! temperature
    123     REAL, INTENT(IN), DIMENSION(klon)   :: distcltop         ! distance to cloud top
    124     REAL, INTENT(IN), DIMENSION(klon)   :: temp_cltop        ! temperature of cloud top
    125     INTEGER, INTENT(IN)                 :: iflag_ice_thermo
    126     REAL, INTENT(OUT), DIMENSION(klon)  :: icefrac
    127     REAL, INTENT(OUT), DIMENSION(klon)  :: dicefracdT
    128 
     115    INTEGER, INTENT(IN) :: klon              ! number of horizontal grid points
     116    REAL, INTENT(IN), DIMENSION(klon) :: temp              ! temperature
     117    REAL, INTENT(IN), DIMENSION(klon) :: distcltop         ! distance to cloud top
     118    REAL, INTENT(IN), DIMENSION(klon) :: temp_cltop        ! temperature of cloud top
     119    INTEGER, INTENT(IN) :: iflag_ice_thermo
     120    REAL, INTENT(OUT), DIMENSION(klon) :: icefrac
     121    REAL, INTENT(OUT), DIMENSION(klon) :: dicefracdT
    129122
    130123    INTEGER i
    131124    REAL    liqfrac_tmp, dicefrac_tmp
    132     REAL    Dv, denomdep,beta,qsi,dqsidt
     125    REAL    Dv, denomdep, beta, qsi, dqsidt
    133126    LOGICAL ice_thermo
    134127
     
    137130
    138131    IF ((iflag_t_glace<2)) THEN !.OR. (iflag_t_glace.GT.6)) THEN
    139        abort_message = 'lscp cannot be used if iflag_t_glace<2 or >6'
    140        CALL abort_physic(modname,abort_message,1)
     132      abort_message = 'lscp cannot be used if iflag_t_glace<2 or >6'
     133      CALL abort_physic(modname, abort_message, 1)
    141134    ENDIF
    142135
    143136    IF (.NOT.((iflag_ice_thermo == 1).OR.(iflag_ice_thermo >= 3))) THEN
    144        abort_message = 'lscp cannot be used without ice thermodynamics'
    145        CALL abort_physic(modname,abort_message,1)
     137      abort_message = 'lscp cannot be used without ice thermodynamics'
     138      CALL abort_physic(modname, abort_message, 1)
    146139    ENDIF
    147140
    148 
    149     DO i=1,klon
    150  
    151         ! old function with sole dependence upon temperature
    152         IF (iflag_t_glace == 2) THEN
    153             liqfrac_tmp = (temp(i)-t_glace_min) / (t_glace_max-t_glace_min)
    154             liqfrac_tmp = MIN(MAX(liqfrac_tmp,0.0),1.0)
    155             icefrac(i) = (1.0-liqfrac_tmp)**exposant_glace
    156             IF (icefrac(i) >0.) THEN
    157                  dicefracdT(i)= exposant_glace * (icefrac(i)**(exposant_glace-1.)) &
    158                            / (t_glace_min - t_glace_max)
     141    DO i = 1, klon
     142
     143      ! old function with sole dependence upon temperature
     144      IF (iflag_t_glace == 2) THEN
     145        liqfrac_tmp = (temp(i) - t_glace_min) / (t_glace_max - t_glace_min)
     146        liqfrac_tmp = MIN(MAX(liqfrac_tmp, 0.0), 1.0)
     147        icefrac(i) = (1.0 - liqfrac_tmp)**exposant_glace
     148        IF (icefrac(i) >0.) THEN
     149          dicefracdT(i) = exposant_glace * (icefrac(i)**(exposant_glace - 1.)) &
     150                  / (t_glace_min - t_glace_max)
     151        ENDIF
     152
     153        IF ((icefrac(i)==0).OR.(icefrac(i)==1)) THEN
     154          dicefracdT(i) = 0.
     155        ENDIF
     156
     157      ENDIF
     158
     159      ! function of temperature used in CMIP6 physics
     160      IF (iflag_t_glace == 3) THEN
     161        liqfrac_tmp = (temp(i) - t_glace_min) / (t_glace_max - t_glace_min)
     162        liqfrac_tmp = MIN(MAX(liqfrac_tmp, 0.0), 1.0)
     163        icefrac(i) = 1.0 - liqfrac_tmp**exposant_glace
     164        IF ((icefrac(i) >0.) .AND. (liqfrac_tmp > 0.)) THEN
     165          dicefracdT(i) = exposant_glace * ((liqfrac_tmp)**(exposant_glace - 1.)) &
     166                  / (t_glace_min - t_glace_max)
     167        ELSE
     168          dicefracdT(i) = 0.
     169        ENDIF
     170      ENDIF
     171
     172      ! for iflag_t_glace .GE. 4, the liquid fraction depends upon temperature at cloud top
     173      ! and then decreases with decreasing height
     174
     175      !with linear function of temperature at cloud top
     176      IF (iflag_t_glace == 4) THEN
     177        liqfrac_tmp = (temp(i) - t_glace_min) / (t_glace_max - t_glace_min)
     178        liqfrac_tmp = MIN(MAX(liqfrac_tmp, 0.0), 1.0)
     179        icefrac(i) = MAX(MIN(1., 1.0 - liqfrac_tmp * exp(-distcltop(i) / dist_liq)), 0.)
     180        dicefrac_tmp = - temp(i) / (t_glace_max - t_glace_min)
     181        dicefracdT(i) = dicefrac_tmp * exp(-distcltop(i) / dist_liq)
     182        IF ((liqfrac_tmp <=0) .OR. (liqfrac_tmp >= 1)) THEN
     183          dicefracdT(i) = 0.
     184        ENDIF
     185      ENDIF
     186
     187      ! with CMIP6 function of temperature at cloud top
     188      IF ((iflag_t_glace == 5) .OR. (iflag_t_glace == 7)) THEN
     189        liqfrac_tmp = (temp(i) - t_glace_min) / (t_glace_max - t_glace_min)
     190        liqfrac_tmp = MIN(MAX(liqfrac_tmp, 0.0), 1.0)
     191        liqfrac_tmp = liqfrac_tmp**exposant_glace
     192        icefrac(i) = MAX(MIN(1., 1.0 - liqfrac_tmp * exp(-distcltop(i) / dist_liq)), 0.)
     193        IF ((liqfrac_tmp <=0) .OR. (liqfrac_tmp >= 1)) THEN
     194          dicefracdT(i) = 0.
     195        ELSE
     196          dicefracdT(i) = exposant_glace * ((liqfrac_tmp)**(exposant_glace - 1.)) / (t_glace_min - t_glace_max) &
     197                  * exp(-distcltop(i) / dist_liq)
     198        ENDIF
     199      ENDIF
     200
     201      ! with modified function of temperature at cloud top
     202      ! to get largere values around 260 K, works well with t_glace_min = 241K
     203      IF (iflag_t_glace == 6) THEN
     204        IF (temp(i) > t_glace_max) THEN
     205          liqfrac_tmp = 1.
     206        ELSE
     207          liqfrac_tmp = -((temp(i) - t_glace_max) / (t_glace_max - t_glace_min))**2 + 1.
     208        ENDIF
     209        liqfrac_tmp = MIN(MAX(liqfrac_tmp, 0.0), 1.0)
     210        icefrac(i) = MAX(MIN(1., 1.0 - liqfrac_tmp * exp(-distcltop(i) / dist_liq)), 0.)
     211        IF ((liqfrac_tmp <=0) .OR. (liqfrac_tmp >= 1)) THEN
     212          dicefracdT(i) = 0.
     213        ELSE
     214          dicefracdT(i) = 2 * ((temp(i) - t_glace_max) / (t_glace_max - t_glace_min)) / (t_glace_max - t_glace_min) &
     215                  * exp(-distcltop(i) / dist_liq)
     216        ENDIF
     217      ENDIF
     218
     219      ! if temperature of cloud top <-40°C,
     220      IF (iflag_t_glace >= 4) THEN
     221        IF ((temp_cltop(i) <= temp_nowater) .AND. (temp(i) <= t_glace_max)) THEN
     222          icefrac(i) = 1.
     223          dicefracdT(i) = 0.
     224        ENDIF
     225      ENDIF
     226
     227    ENDDO ! klon
     228
     229  END SUBROUTINE ICEFRAC_LSCP
     230  !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     231
     232  SUBROUTINE ICEFRAC_LSCP_TURB(klon, dtime, temp, pplay, paprsdn, paprsup, qice_ini, snowcld, qtot_incl, cldfra, tke, tke_dissip, qliq, qvap_cld, qice, icefrac, dicefracdT, cldfraliq, sigma2_icefracturb, mean_icefracturb)
     233    !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     234    ! Compute the liquid, ice and vapour content (+ice fraction) based
     235    ! on turbulence (see Fields 2014, Furtado 2016)
     236    !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     237
     238    USE lmdz_lscp_ini, ONLY: prt_level, lunout
     239    USE lmdz_lscp_ini, ONLY: RCPD, RLSTT, RLVTT, RLMLT, RVTMP2, RTT, RD, RG, RV, RPI
     240    USE lmdz_lscp_ini, ONLY: seuil_neb, temp_nowater
     241    USE lmdz_lscp_ini, ONLY: tau_mixenv, lmix_mpc, naero5, gamma_snwretro, gamma_taud, capa_crystal
     242    USE lmdz_lscp_ini, ONLY: eps
     243
     244    IMPLICIT NONE
     245
     246    INTEGER, INTENT(IN) :: klon              !--number of horizontal grid points
     247    REAL, INTENT(IN) :: dtime             !--time step [s]
     248
     249    REAL, INTENT(IN), DIMENSION(klon) :: temp              !--temperature
     250    REAL, INTENT(IN), DIMENSION(klon) :: pplay             !--pressure in the middle of the layer       [Pa]
     251    REAL, INTENT(IN), DIMENSION(klon) :: paprsdn           !--pressure at the bottom interface of the layer [Pa]
     252    REAL, INTENT(IN), DIMENSION(klon) :: paprsup           !--pressure at the top interface of the layer [Pa]
     253    REAL, INTENT(IN), DIMENSION(klon) :: qtot_incl         !--specific total cloud water content, in-cloud content [kg/kg]
     254    REAL, INTENT(IN), DIMENSION(klon) :: cldfra            !--cloud fraction in gridbox [-]
     255    REAL, INTENT(IN), DIMENSION(klon) :: tke               !--turbulent kinetic energy [m2/s2]
     256    REAL, INTENT(IN), DIMENSION(klon) :: tke_dissip        !--TKE dissipation [m2/s3]
     257
     258    REAL, INTENT(IN), DIMENSION(klon) :: qice_ini          !--initial specific ice content gridbox-mean [kg/kg]
     259    REAL, INTENT(IN), DIMENSION(klon) :: snowcld
     260    REAL, INTENT(OUT), DIMENSION(klon) :: qliq              !--specific liquid content gridbox-mean [kg/kg]
     261    REAL, INTENT(OUT), DIMENSION(klon) :: qvap_cld          !--specific cloud vapor content, gridbox-mean [kg/kg]
     262    REAL, INTENT(OUT), DIMENSION(klon) :: qice              !--specific ice content gridbox-mean [kg/kg]
     263    REAL, INTENT(OUT), DIMENSION(klon) :: icefrac           !--fraction of ice in condensed water [-]
     264    REAL, INTENT(OUT), DIMENSION(klon) :: dicefracdT
     265
     266    REAL, INTENT(OUT), DIMENSION(klon) :: cldfraliq         !--fraction of cldfra which is liquid only
     267    REAL, INTENT(OUT), DIMENSION(klon) :: sigma2_icefracturb     !--Temporary
     268    REAL, INTENT(OUT), DIMENSION(klon) :: mean_icefracturb      !--Temporary
     269
     270    REAL, DIMENSION(klon) :: qzero, qsatl, dqsatl, qsati, dqsati         !--specific humidity saturation values
     271    INTEGER :: i
     272
     273    REAL :: qvap_incl, qice_incl, qliq_incl, qiceini_incl                !--In-cloud specific quantities [kg/kg]
     274    REAL :: qsnowcld_incl
     275    !REAL :: capa_crystal                                                 !--Capacitance of ice crystals  [-]
     276    REAL :: water_vapor_diff                                             !--Water-vapour diffusion coefficient in air [m2/s] (function of T&P)
     277    REAL :: air_thermal_conduct                                          !--Thermal conductivity of air [J/m/K/s] (function of T)
     278    REAL :: C0                                                           !--Lagrangian structure function [-]
     279    REAL :: tau_mixingenv
     280    REAL :: tau_dissipturb
     281    REAL :: invtau_phaserelax
     282    REAL :: sigma2_pdf, mean_pdf
     283    REAL :: ai, bi, B0
     284    REAL :: sursat_iceliq
     285    REAL :: sursat_env
     286    REAL :: liqfra_max
     287    REAL :: sursat_iceext
     288    REAL :: nb_crystals                                                  !--number concentration of ice crystals [#/m3]
     289    REAL :: moment1_PSD                                                  !--1st moment of ice PSD
     290    REAL :: N0_PSD, lambda_PSD                                           !--parameters of the exponential PSD
     291
     292    REAL :: rho_ice                                                      !--ice density [kg/m3]
     293    REAL :: cldfra1D
     294    REAL :: deltaz, rho_air
     295    REAL :: psati                                                        !--saturation vapor pressure wrt i [Pa]
     296
     297    C0 = 10.                                                  !--value assumed in Field2014
     298    rho_ice = 950.
     299    sursat_iceext = -0.1
     300    !capa_crystal  = 1. !r_ice
     301    qzero(:) = 0.
     302    cldfraliq(:) = 0.
     303    icefrac(:) = 0.
     304    dicefracdT(:) = 0.
     305
     306    sigma2_icefracturb(:) = 0.
     307    mean_icefracturb(:) = 0.
     308
     309    !--wrt liquid water
     310    CALL calc_qsat_ecmwf(klon, temp(:), qzero(:), pplay(:), RTT, 1, .FALSE., qsatl(:), dqsatl(:))
     311    !--wrt ice
     312    CALL calc_qsat_ecmwf(klon, temp(:), qzero(:), pplay(:), RTT, 2, .FALSE., qsati(:), dqsati(:))
     313
     314    DO i = 1, klon
     315
     316      rho_air = pplay(i) / temp(i) / RD
     317      !deltaz   = ( paprsdn(i) - paprsup(i) ) / RG / rho_air(i)
     318      ! because cldfra is intent in, but can be locally modified due to test
     319      cldfra1D = cldfra(i)
     320      IF (cldfra(i) <= 0.) THEN
     321        qvap_cld(i) = 0.
     322        qliq(i) = 0.
     323        qice(i) = 0.
     324        cldfraliq(i) = 0.
     325        icefrac(i) = 0.
     326        dicefracdT(i) = 0.
     327
     328        ! If there is a cloud
     329      ELSE
     330        IF (cldfra(i) >= 1.0) THEN
     331          cldfra1D = 1.0
     332        END IF
     333
     334        ! T>0°C, no ice allowed
     335        IF (temp(i) >= RTT) THEN
     336          qvap_cld(i) = qsatl(i) * cldfra1D
     337          qliq(i) = MAX(0.0, qtot_incl(i) - qsatl(i)) * cldfra1D
     338          qice(i) = 0.
     339          cldfraliq(i) = 1.
     340          icefrac(i) = 0.
     341          dicefracdT(i) = 0.
     342
     343          ! T<-38°C, no liquid allowed
     344        ELSE IF (temp(i) <= temp_nowater) THEN
     345          qvap_cld(i) = qsati(i) * cldfra1D
     346          qliq(i) = 0.
     347          qice(i) = MAX(0.0, qtot_incl(i) - qsati(i)) * cldfra1D
     348          cldfraliq(i) = 0.
     349          icefrac(i) = 1.
     350          dicefracdT(i) = 0.
     351
     352          ! MPC temperature
     353        ELSE
     354          ! Not enough TKE
     355          IF (tke_dissip(i) <= eps)  THEN
     356            qvap_cld(i) = qsati(i) * cldfra1D
     357            qliq(i) = 0.
     358            qice(i) = MAX(0., qtot_incl(i) - qsati(i)) * cldfra1D
     359            cldfraliq(i) = 0.
     360            icefrac(i) = 1.
     361            dicefracdT(i) = 0.
     362
     363            ! Enough TKE
     364          ELSE
     365            !---------------------------------------------------------
     366            !--               ICE SUPERSATURATION PDF
     367            !---------------------------------------------------------
     368            !--If -38°C< T <0°C and there is enough turbulence,
     369            !--we compute the cloud liquid properties with a Gaussian PDF
     370            !--of ice supersaturation F(Si) (Field2014, Furtado2016).
     371            !--Parameters of the PDF are function of turbulence and
     372            !--microphysics/existing ice.
     373
     374            sursat_iceliq = qsatl(i) / qsati(i) - 1.
     375            psati = qsati(i) * pplay(i) / (RD / RV)
     376
     377            !-------------- MICROPHYSICAL TERMS --------------
     378            !--We assume an exponential ice PSD whose parameters
     379            !--are computed following Morrison&Gettelman 2008
     380            !--Ice number density is assumed equals to INP density
     381            !--which is a function of temperature (DeMott 2010)
     382            !--bi and B0 are microphysical function characterizing
     383            !--vapor/ice interactions
     384            !--tau_phase_relax is the typical time of vapor deposition
     385            !--onto ice crystals
     386
     387            qiceini_incl = qice_ini(i) / cldfra1D
     388            qsnowcld_incl = snowcld(i) * RG * dtime / (paprsdn(i) - paprsup(i)) / cldfra1D
     389            sursat_env = max(0., (qtot_incl(i) - qiceini_incl) / qsati(i) - 1.)
     390            IF (qiceini_incl > eps) THEN
     391              nb_crystals = 1.e3 * 5.94e-5 * (RTT - temp(i))**3.33 * naero5**(0.0264 * (RTT - temp(i)) + 0.0033)
     392              lambda_PSD = ((RPI * rho_ice * nb_crystals * 24.) / (6. * (qiceini_incl + gamma_snwretro * qsnowcld_incl))) ** (1. / 3.)
     393              N0_PSD = nb_crystals * lambda_PSD
     394              moment1_PSD = N0_PSD / 2. / lambda_PSD**2
     395            ELSE
     396              moment1_PSD = 0.
    159397            ENDIF
    160398
    161             IF ((icefrac(i)==0).OR.(icefrac(i)==1)) THEN
    162                  dicefracdT(i)=0.
     399            !--Formulae for air thermal conductivity and water vapor diffusivity
     400            !--comes respectively from Beard and Pruppacher (1971)
     401            !--and  Hall and Pruppacher (1976)
     402
     403            air_thermal_conduct = (5.69 + 0.017 * (temp(i) - RTT)) * 1.e-3 * 4.184
     404            water_vapor_diff = 2.11 * 1e-5 * (temp(i) / RTT)**1.94 * (101325 / pplay(i))
     405
     406            bi = 1. / ((qsati(i) + qsatl(i)) / 2.) + RLSTT**2 / RCPD / RV / temp(i)**2
     407            B0 = 4. * RPI * capa_crystal * 1. / (RLSTT**2 / air_thermal_conduct / RV / temp(i)**2  &
     408                    + RV * temp(i) / psati / water_vapor_diff)
     409
     410            invtau_phaserelax = (bi * B0 * moment1_PSD)
     411
     412            !             Old way of estimating moment1 : spherical crystals + monodisperse PSD
     413            !             nb_crystals = rho_air * qiceini_incl / ( 4. / 3. * RPI * r_ice**3. * rho_ice )
     414            !             moment1_PSD = nb_crystals * r_ice
     415
     416            !----------------- TURBULENT SOURCE/SINK TERMS -----------------
     417            !--Tau_mixingenv is the time needed to homogeneize the parcel
     418            !--with its environment by turbulent diffusion over the parcel
     419            !--length scale
     420            !--if lmix_mpc <0, tau_mixigenv value is prescribed
     421            !--else tau_mixigenv value is derived from tke_dissip and lmix_mpc
     422            !--Tau_dissipturb is the time needed turbulence to decay due to
     423            !--viscosity
     424
     425            ai = RG / RD / temp(i) * (RD * RLSTT / RCPD / RV / temp(i) - 1.)
     426            IF (lmix_mpc > 0) THEN
     427              tau_mixingenv = (lmix_mpc**2. / tke_dissip(i))**(1. / 3.)
     428            ELSE
     429              tau_mixingenv = tau_mixenv
    163430            ENDIF
    164431
    165         ENDIF
    166 
    167         ! function of temperature used in CMIP6 physics
    168         IF (iflag_t_glace == 3) THEN
    169             liqfrac_tmp = (temp(i)-t_glace_min) / (t_glace_max-t_glace_min)
    170             liqfrac_tmp = MIN(MAX(liqfrac_tmp,0.0),1.0)
    171             icefrac(i) = 1.0-liqfrac_tmp**exposant_glace
    172             IF ((icefrac(i) >0.) .AND. (liqfrac_tmp > 0.)) THEN
    173                 dicefracdT(i)= exposant_glace * ((liqfrac_tmp)**(exposant_glace-1.)) &
    174                           / (t_glace_min - t_glace_max)
     432            tau_dissipturb = gamma_taud * 2. * 2. / 3. * tke(i) / tke_dissip(i) / C0
     433
     434            !--------------------- PDF COMPUTATIONS ---------------------
     435            !--Formulae for sigma2_pdf (variance), mean of PDF in Furtado2016
     436            !--cloud liquid fraction and in-cloud liquid content are given
     437            !--by integrating resp. F(Si) and Si*F(Si)
     438            !--Liquid is limited by the available water vapor trough a
     439            !--maximal liquid fraction
     440
     441            liqfra_max = MAX(0., (MIN (1., (qtot_incl(i) - qiceini_incl - qsati(i) * (1 + sursat_iceext)) / (qsatl(i) - qsati(i)))))
     442            sigma2_pdf = 1. / 2. * (ai**2) * 2. / 3. * tke(i) * tau_dissipturb / (invtau_phaserelax + 1. / tau_mixingenv)
     443            mean_pdf = sursat_env * 1. / tau_mixingenv / (invtau_phaserelax + 1. / tau_mixingenv)
     444            cldfraliq(i) = 0.5 * (1. - erf((sursat_iceliq - mean_pdf) / (SQRT(2. * sigma2_pdf))))
     445            !IF (cldfraliq(i) .GT. liqfra_max) THEN
     446            !    cldfraliq(i) = liqfra_max
     447            !ENDIF
     448
     449            qliq_incl = qsati(i) * SQRT(sigma2_pdf) / SQRT(2. * RPI) * EXP(-1. * (sursat_iceliq - mean_pdf)**2. / (2. * sigma2_pdf))  &
     450                    - qsati(i) * cldfraliq(i) * (sursat_iceliq - mean_pdf)
     451
     452            sigma2_icefracturb(i) = sigma2_pdf
     453            mean_icefracturb(i) = mean_pdf
     454            !------------ ICE AMOUNT AND WATER CONSERVATION  ------------
     455
     456            IF ((qliq_incl <= eps) .OR. (cldfraliq(i) <= eps)) THEN
     457              qliq_incl = 0.
     458              cldfraliq(i) = 0.
     459            END IF
     460
     461            !--Choice for in-cloud vapor :
     462            !--1.Weighted mean between qvap in MPC parts and in ice-only parts
     463            !--2.Always at ice saturation
     464            qvap_incl = MAX(qsati(i), (1. - cldfraliq(i)) * (sursat_iceext + 1.) * qsati(i) + cldfraliq(i) * qsatl(i))
     465
     466            IF (qvap_incl  >= qtot_incl(i)) THEN
     467              qvap_incl = qsati(i)
     468              qliq_incl = qtot_incl(i) - qvap_incl
     469              qice_incl = 0.
     470
     471            ELSEIF ((qvap_incl + qliq_incl) >= qtot_incl(i)) THEN
     472              qliq_incl = MAX(0.0, qtot_incl(i) - qvap_incl)
     473              qice_incl = 0.
    175474            ELSE
    176                 dicefracdT(i)=0.
    177             ENDIF
    178         ENDIF
    179 
    180         ! for iflag_t_glace .GE. 4, the liquid fraction depends upon temperature at cloud top
    181         ! and then decreases with decreasing height
    182 
    183         !with linear function of temperature at cloud top
    184         IF (iflag_t_glace == 4) THEN
    185                 liqfrac_tmp = (temp(i)-t_glace_min) / (t_glace_max-t_glace_min)
    186                 liqfrac_tmp = MIN(MAX(liqfrac_tmp,0.0),1.0)
    187                 icefrac(i)    =  MAX(MIN(1.,1.0 - liqfrac_tmp*exp(-distcltop(i)/dist_liq)),0.)
    188                 dicefrac_tmp = - temp(i)/(t_glace_max-t_glace_min)
    189                 dicefracdT(i) = dicefrac_tmp*exp(-distcltop(i)/dist_liq)
    190                 IF ((liqfrac_tmp <=0) .OR. (liqfrac_tmp >= 1)) THEN
    191                         dicefracdT(i) = 0.
    192                 ENDIF
    193         ENDIF
    194 
    195         ! with CMIP6 function of temperature at cloud top
    196         IF ((iflag_t_glace == 5) .OR. (iflag_t_glace == 7)) THEN
    197                 liqfrac_tmp = (temp(i)-t_glace_min) / (t_glace_max-t_glace_min)
    198                 liqfrac_tmp =  MIN(MAX(liqfrac_tmp,0.0),1.0)
    199                 liqfrac_tmp = liqfrac_tmp**exposant_glace
    200                 icefrac(i)  =  MAX(MIN(1.,1.0 - liqfrac_tmp*exp(-distcltop(i)/dist_liq)),0.)
    201                 IF ((liqfrac_tmp <=0) .OR. (liqfrac_tmp >= 1)) THEN
    202                         dicefracdT(i) = 0.
    203                 ELSE
    204                         dicefracdT(i) = exposant_glace*((liqfrac_tmp)**(exposant_glace-1.))/(t_glace_min- t_glace_max) &
    205                                         *exp(-distcltop(i)/dist_liq)
    206                 ENDIF
    207         ENDIF
    208 
    209         ! with modified function of temperature at cloud top
    210         ! to get largere values around 260 K, works well with t_glace_min = 241K
    211         IF (iflag_t_glace == 6) THEN
    212                 IF (temp(i) > t_glace_max) THEN
    213                         liqfrac_tmp = 1.
    214                 ELSE
    215                         liqfrac_tmp = -((temp(i)-t_glace_max) / (t_glace_max-t_glace_min))**2+1.
    216                 ENDIF
    217                 liqfrac_tmp  = MIN(MAX(liqfrac_tmp,0.0),1.0)
    218                 icefrac(i)   = MAX(MIN(1.,1.0 - liqfrac_tmp*exp(-distcltop(i)/dist_liq)),0.)       
    219                 IF ((liqfrac_tmp <=0) .OR. (liqfrac_tmp >= 1)) THEN
    220                         dicefracdT(i) = 0.
    221                 ELSE
    222                         dicefracdT(i) = 2*((temp(i)-t_glace_max) / (t_glace_max-t_glace_min))/(t_glace_max-t_glace_min) &
    223                                   *exp(-distcltop(i)/dist_liq)
    224                 ENDIF
    225         ENDIF
    226 
    227         ! if temperature of cloud top <-40°C,
    228         IF (iflag_t_glace >= 4) THEN
    229                 IF ((temp_cltop(i) <= temp_nowater) .AND. (temp(i) <= t_glace_max)) THEN
    230                         icefrac(i) = 1.
    231                         dicefracdT(i) = 0.
    232                 ENDIF
    233         ENDIF
    234      
    235 
    236      ENDDO ! klon
    237 
    238  
    239 END SUBROUTINE ICEFRAC_LSCP
    240 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    241 
    242 SUBROUTINE ICEFRAC_LSCP_TURB(klon, dtime, temp, pplay, paprsdn, paprsup, qice_ini, snowcld, qtot_incl, cldfra, tke, tke_dissip, qliq, qvap_cld, qice, icefrac, dicefracdT, cldfraliq, sigma2_icefracturb, mean_icefracturb)
    243 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    244   ! Compute the liquid, ice and vapour content (+ice fraction) based
    245   ! on turbulence (see Fields 2014, Furtado 2016)
    246 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    247 
    248 
    249    USE lmdz_lscp_ini, ONLY: prt_level, lunout
    250    USE lmdz_lscp_ini, ONLY: RCPD, RLSTT, RLVTT, RLMLT, RVTMP2, RTT, RD, RG, RV, RPI
    251    USE lmdz_lscp_ini, ONLY: seuil_neb, temp_nowater
    252    USE lmdz_lscp_ini, ONLY: tau_mixenv, lmix_mpc, naero5, gamma_snwretro, gamma_taud, capa_crystal
    253    USE lmdz_lscp_ini, ONLY: eps
    254 
    255    IMPLICIT NONE
    256 
    257    INTEGER,   INTENT(IN)                           :: klon              !--number of horizontal grid points
    258    REAL,      INTENT(IN)                           :: dtime             !--time step [s]
    259 
    260    REAL,      INTENT(IN),       DIMENSION(klon)    :: temp              !--temperature
    261    REAL,      INTENT(IN),       DIMENSION(klon)    :: pplay             !--pressure in the middle of the layer       [Pa]
    262    REAL,      INTENT(IN),       DIMENSION(klon)    :: paprsdn           !--pressure at the bottom interface of the layer [Pa]
    263    REAL,      INTENT(IN),       DIMENSION(klon)    :: paprsup           !--pressure at the top interface of the layer [Pa]
    264    REAL,      INTENT(IN),       DIMENSION(klon)    :: qtot_incl         !--specific total cloud water content, in-cloud content [kg/kg]
    265    REAL,      INTENT(IN),       DIMENSION(klon)    :: cldfra            !--cloud fraction in gridbox [-]
    266    REAL,      INTENT(IN),       DIMENSION(klon)    :: tke               !--turbulent kinetic energy [m2/s2]
    267    REAL,      INTENT(IN),       DIMENSION(klon)    :: tke_dissip        !--TKE dissipation [m2/s3]
    268 
    269    REAL,      INTENT(IN),       DIMENSION(klon)    :: qice_ini          !--initial specific ice content gridbox-mean [kg/kg]
    270    REAL,      INTENT(IN),       DIMENSION(klon)    :: snowcld
    271    REAL,      INTENT(OUT),      DIMENSION(klon)    :: qliq              !--specific liquid content gridbox-mean [kg/kg]
    272    REAL,      INTENT(OUT),      DIMENSION(klon)    :: qvap_cld          !--specific cloud vapor content, gridbox-mean [kg/kg]
    273    REAL,      INTENT(OUT),      DIMENSION(klon)    :: qice              !--specific ice content gridbox-mean [kg/kg]
    274    REAL,      INTENT(OUT),      DIMENSION(klon)    :: icefrac           !--fraction of ice in condensed water [-]
    275    REAL,      INTENT(OUT),      DIMENSION(klon)    :: dicefracdT
    276 
    277    REAL,      INTENT(OUT),      DIMENSION(klon)    :: cldfraliq         !--fraction of cldfra which is liquid only
    278    REAL,      INTENT(OUT),      DIMENSION(klon)    :: sigma2_icefracturb     !--Temporary
    279    REAL,      INTENT(OUT),      DIMENSION(klon)    :: mean_icefracturb      !--Temporary
    280 
    281    REAL, DIMENSION(klon) :: qzero, qsatl, dqsatl, qsati, dqsati         !--specific humidity saturation values
    282    INTEGER :: i
    283 
    284    REAL :: qvap_incl, qice_incl, qliq_incl, qiceini_incl                !--In-cloud specific quantities [kg/kg]
    285    REAL :: qsnowcld_incl
    286    !REAL :: capa_crystal                                                 !--Capacitance of ice crystals  [-]
    287    REAL :: water_vapor_diff                                             !--Water-vapour diffusion coefficient in air [m2/s] (function of T&P)
    288    REAL :: air_thermal_conduct                                          !--Thermal conductivity of air [J/m/K/s] (function of T)
    289    REAL :: C0                                                           !--Lagrangian structure function [-]
    290    REAL :: tau_mixingenv
    291    REAL :: tau_dissipturb
    292    REAL :: invtau_phaserelax
    293    REAL :: sigma2_pdf, mean_pdf
    294    REAL :: ai, bi, B0
    295    REAL :: sursat_iceliq
    296    REAL :: sursat_env
    297    REAL :: liqfra_max
    298    REAL :: sursat_iceext
    299    REAL :: nb_crystals                                                  !--number concentration of ice crystals [#/m3]
    300    REAL :: moment1_PSD                                                  !--1st moment of ice PSD
    301    REAL :: N0_PSD, lambda_PSD                                           !--parameters of the exponential PSD
    302 
    303    REAL :: rho_ice                                                      !--ice density [kg/m3]
    304    REAL :: cldfra1D
    305    REAL :: deltaz, rho_air
    306    REAL :: psati                                                        !--saturation vapor pressure wrt i [Pa]
    307    
    308    C0            = 10.                                                  !--value assumed in Field2014           
    309    rho_ice       = 950.
    310    sursat_iceext = -0.1
    311    !capa_crystal  = 1. !r_ice                                       
    312    qzero(:)      = 0.
    313    cldfraliq(:)  = 0.
    314    icefrac(:)    = 0.
    315    dicefracdT(:) = 0.
    316 
    317    sigma2_icefracturb(:) = 0.
    318    mean_icefracturb(:)  = 0.
    319 
    320    !--wrt liquid water
    321    CALL calc_qsat_ecmwf(klon,temp(:),qzero(:),pplay(:),RTT,1,.FALSE.,qsatl(:),dqsatl(:))
    322    !--wrt ice
    323    CALL calc_qsat_ecmwf(klon,temp(:),qzero(:),pplay(:),RTT,2,.FALSE.,qsati(:),dqsati(:))
    324 
    325 
    326     DO i=1,klon
    327 
    328 
    329      rho_air  = pplay(i) / temp(i) / RD
    330      !deltaz   = ( paprsdn(i) - paprsup(i) ) / RG / rho_air(i)
    331      ! because cldfra is intent in, but can be locally modified due to test
    332      cldfra1D = cldfra(i)
    333      IF (cldfra(i) <= 0.) THEN
    334         qvap_cld(i)   = 0.
    335         qliq(i)       = 0.
    336         qice(i)       = 0.
    337         cldfraliq(i)  = 0.
    338         icefrac(i)    = 0.
    339         dicefracdT(i) = 0.
    340 
    341      ! If there is a cloud
    342      ELSE
    343         IF (cldfra(i) >= 1.0) THEN
    344            cldfra1D = 1.0
    345         END IF
    346        
    347         ! T>0°C, no ice allowed
    348         IF ( temp(i) >= RTT ) THEN
    349            qvap_cld(i)   = qsatl(i) * cldfra1D
    350            qliq(i)       = MAX(0.0,qtot_incl(i)-qsatl(i))  * cldfra1D
    351            qice(i)       = 0.
    352            cldfraliq(i)  = 1.
    353            icefrac(i)    = 0.
    354            dicefracdT(i) = 0.
    355        
    356         ! T<-38°C, no liquid allowed
    357         ELSE IF ( temp(i) <= temp_nowater) THEN
    358            qvap_cld(i)   = qsati(i) * cldfra1D
    359            qliq(i)       = 0.
    360            qice(i)       = MAX(0.0,qtot_incl(i)-qsati(i)) * cldfra1D
    361            cldfraliq(i)  = 0.
    362            icefrac(i)    = 1.
    363            dicefracdT(i) = 0.
    364 
    365         ! MPC temperature
    366         ELSE
    367            ! Not enough TKE     
    368            IF ( tke_dissip(i) <= eps )  THEN
    369               qvap_cld(i)   = qsati(i) * cldfra1D
    370               qliq(i)       = 0.
    371               qice(i)       = MAX(0.,qtot_incl(i)-qsati(i)) * cldfra1D   
    372               cldfraliq(i)  = 0.
    373               icefrac(i)    = 1.
    374               dicefracdT(i) = 0.
    375            
    376            ! Enough TKE   
    377            ELSE   
    378               !---------------------------------------------------------
    379               !--               ICE SUPERSATURATION PDF   
    380               !---------------------------------------------------------
    381               !--If -38°C< T <0°C and there is enough turbulence,
    382               !--we compute the cloud liquid properties with a Gaussian PDF
    383               !--of ice supersaturation F(Si) (Field2014, Furtado2016).
    384               !--Parameters of the PDF are function of turbulence and
    385               !--microphysics/existing ice.
    386 
    387               sursat_iceliq = qsatl(i)/qsati(i) - 1.
    388               psati         = qsati(i) * pplay(i) / (RD/RV)
    389 
    390               !-------------- MICROPHYSICAL TERMS --------------
    391               !--We assume an exponential ice PSD whose parameters
    392               !--are computed following Morrison&Gettelman 2008
    393               !--Ice number density is assumed equals to INP density
    394               !--which is a function of temperature (DeMott 2010) 
    395               !--bi and B0 are microphysical function characterizing
    396               !--vapor/ice interactions
    397               !--tau_phase_relax is the typical time of vapor deposition
    398               !--onto ice crystals
    399              
    400               qiceini_incl  = qice_ini(i) / cldfra1D
    401               qsnowcld_incl = snowcld(i) * RG * dtime / ( paprsdn(i) - paprsup(i) ) / cldfra1D
    402               sursat_env    = max(0., (qtot_incl(i) - qiceini_incl)/qsati(i) - 1.)
    403               IF ( qiceini_incl > eps ) THEN
    404                 nb_crystals = 1.e3 * 5.94e-5 * ( RTT - temp(i) )**3.33 * naero5**(0.0264*(RTT-temp(i))+0.0033)
    405                 lambda_PSD  = ( (RPI*rho_ice*nb_crystals*24.) / (6.*(qiceini_incl + gamma_snwretro * qsnowcld_incl)) ) ** (1./3.)
    406                 N0_PSD      = nb_crystals * lambda_PSD
    407                 moment1_PSD = N0_PSD/2./lambda_PSD**2
    408               ELSE
    409                 moment1_PSD = 0.
    410               ENDIF
    411 
    412               !--Formulae for air thermal conductivity and water vapor diffusivity
    413               !--comes respectively from Beard and Pruppacher (1971)
    414               !--and  Hall and Pruppacher (1976)
    415 
    416               air_thermal_conduct = ( 5.69 + 0.017 * ( temp(i) - RTT ) ) * 1.e-3 * 4.184
    417               water_vapor_diff    = 2.11*1e-5 * ( temp(i) / RTT )**1.94 * ( 101325 / pplay(i) )
    418              
    419               bi = 1./((qsati(i)+qsatl(i))/2.) + RLSTT**2 / RCPD / RV / temp(i)**2
    420               B0 = 4. * RPI * capa_crystal * 1. / (  RLSTT**2 / air_thermal_conduct / RV / temp(i)**2  &
    421                                                   +  RV * temp(i) / psati / water_vapor_diff  )
    422 
    423               invtau_phaserelax  = (bi * B0 * moment1_PSD )
    424 
    425 !             Old way of estimating moment1 : spherical crystals + monodisperse PSD             
    426 !             nb_crystals = rho_air * qiceini_incl / ( 4. / 3. * RPI * r_ice**3. * rho_ice )
    427 !             moment1_PSD = nb_crystals * r_ice
    428 
    429               !----------------- TURBULENT SOURCE/SINK TERMS -----------------
    430               !--Tau_mixingenv is the time needed to homogeneize the parcel
    431               !--with its environment by turbulent diffusion over the parcel
    432               !--length scale
    433               !--if lmix_mpc <0, tau_mixigenv value is prescribed
    434               !--else tau_mixigenv value is derived from tke_dissip and lmix_mpc
    435               !--Tau_dissipturb is the time needed turbulence to decay due to
    436               !--viscosity
    437 
    438               ai = RG / RD / temp(i) * ( RD * RLSTT / RCPD / RV / temp(i) - 1. )
    439               IF ( lmix_mpc > 0 ) THEN
    440                  tau_mixingenv = ( lmix_mpc**2. / tke_dissip(i) )**(1./3.)
    441               ELSE
    442                  tau_mixingenv = tau_mixenv
    443               ENDIF
    444              
    445               tau_dissipturb = gamma_taud * 2. * 2./3. * tke(i) / tke_dissip(i) / C0
    446 
    447               !--------------------- PDF COMPUTATIONS ---------------------
    448               !--Formulae for sigma2_pdf (variance), mean of PDF in Furtado2016
    449               !--cloud liquid fraction and in-cloud liquid content are given
    450               !--by integrating resp. F(Si) and Si*F(Si)
    451               !--Liquid is limited by the available water vapor trough a
    452               !--maximal liquid fraction
    453 
    454               liqfra_max = MAX(0., (MIN (1.,( qtot_incl(i) - qiceini_incl - qsati(i) * (1 + sursat_iceext ) ) / ( qsatl(i) - qsati(i) ) ) ) )
    455               sigma2_pdf = 1./2. * ( ai**2 ) *  2./3. * tke(i) * tau_dissipturb / ( invtau_phaserelax + 1./tau_mixingenv )
    456               mean_pdf   = sursat_env * 1./tau_mixingenv / ( invtau_phaserelax + 1./tau_mixingenv )
    457               cldfraliq(i) = 0.5 * (1. - erf( ( sursat_iceliq - mean_pdf) / (SQRT(2.* sigma2_pdf) ) ) )
    458               !IF (cldfraliq(i) .GT. liqfra_max) THEN
    459               !    cldfraliq(i) = liqfra_max
    460               !ENDIF
    461              
    462               qliq_incl = qsati(i) * SQRT(sigma2_pdf) / SQRT(2.*RPI) * EXP( -1.*(sursat_iceliq - mean_pdf)**2. / (2.*sigma2_pdf) )  &
    463                         - qsati(i) * cldfraliq(i) * (sursat_iceliq - mean_pdf )
    464              
    465               sigma2_icefracturb(i)= sigma2_pdf
    466               mean_icefracturb(i)  = mean_pdf     
    467               !------------ ICE AMOUNT AND WATER CONSERVATION  ------------
    468 
    469               IF ( (qliq_incl <= eps) .OR. (cldfraliq(i) <= eps) ) THEN
    470                   qliq_incl    = 0.
    471                   cldfraliq(i) = 0.
    472               END IF
    473              
    474               !--Choice for in-cloud vapor :
    475               !--1.Weighted mean between qvap in MPC parts and in ice-only parts
    476               !--2.Always at ice saturation
    477               qvap_incl = MAX(qsati(i), ( 1. - cldfraliq(i) ) * (sursat_iceext + 1.) * qsati(i) + cldfraliq(i) * qsatl(i) )
    478                
    479               IF ( qvap_incl  >= qtot_incl(i) ) THEN
    480                  qvap_incl = qsati(i)
    481                  qliq_incl = qtot_incl(i) - qvap_incl
    482                  qice_incl = 0.
    483 
    484               ELSEIF ( (qvap_incl + qliq_incl) >= qtot_incl(i) ) THEN
    485                  qliq_incl = MAX(0.0,qtot_incl(i) - qvap_incl)
    486                  qice_incl = 0.
    487               ELSE
    488                  qice_incl = qtot_incl(i) - qvap_incl - qliq_incl
    489               END IF
    490 
    491               qvap_cld(i)   = qvap_incl * cldfra1D
    492               qliq(i)       = qliq_incl * cldfra1D
    493               qice(i)       = qice_incl * cldfra1D
    494               icefrac(i)    = qice(i) / ( qice(i) + qliq(i) )
    495               dicefracdT(i) = 0.
    496               !PRINT*,'MPC turb'
    497 
    498            END IF ! Enough TKE
     475              qice_incl = qtot_incl(i) - qvap_incl - qliq_incl
     476            END IF
     477
     478            qvap_cld(i) = qvap_incl * cldfra1D
     479            qliq(i) = qliq_incl * cldfra1D
     480            qice(i) = qice_incl * cldfra1D
     481            icefrac(i) = qice(i) / (qice(i) + qliq(i))
     482            dicefracdT(i) = 0.
     483            !PRINT*,'MPC turb'
     484
     485          END IF ! Enough TKE
    499486
    500487        END IF ! MPC temperature
    501488
    502      END IF ! cldfra
    503    
    504    ENDDO ! klon
    505 END SUBROUTINE ICEFRAC_LSCP_TURB
    506 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    507 
    508 
    509 SUBROUTINE CALC_QSAT_ECMWF(klon,temp,qtot,pressure,tref,phase,flagth,qs,dqs)
    510 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     489      END IF ! cldfra
     490
     491    ENDDO ! klon
     492  END SUBROUTINE ICEFRAC_LSCP_TURB
     493  !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     494
     495
     496  SUBROUTINE CALC_QSAT_ECMWF(klon, temp, qtot, pressure, tref, phase, flagth, qs, dqs)
     497    !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    511498    ! Calculate qsat following ECMWF method
    512 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    513   USE lmdz_YOETHF
    514   USE lmdz_fcttre, ONLY: foeew, foede, qsats, qsatl, dqsats, dqsatl, thermcep
     499    !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     500    USE lmdz_yoethf
     501    USE lmdz_fcttre, ONLY: foeew, foede, qsats, qsatl, dqsats, dqsatl, thermcep
     502    USE lmdz_yomcst
    515503
    516504    IMPLICIT NONE
    517 
    518     include "YOMCST.h"
    519505
    520506    INTEGER, INTENT(IN) :: klon  ! number of horizontal grid points
     
    522508    REAL, INTENT(IN), DIMENSION(klon) :: qtot     ! total specific water in kg/kg
    523509    REAL, INTENT(IN), DIMENSION(klon) :: pressure ! pressure in Pa
    524     REAL, INTENT(IN)                  :: tref     ! reference temperature in K
     510    REAL, INTENT(IN) :: tref     ! reference temperature in K
    525511    LOGICAL, INTENT(IN) :: flagth     ! flag for qsat calculation for thermals
    526     INTEGER, INTENT(IN) :: phase 
     512    INTEGER, INTENT(IN) :: phase
    527513    ! phase: 0=depend on temperature sign (temp>tref -> liquid, temp<tref, solid)
    528514    !        1=liquid
     
    535521    INTEGER i
    536522
    537     DO i=1,klon
    538 
    539     IF (phase == 1) THEN
    540         delta=0.
    541     ELSEIF (phase == 2) THEN
    542         delta=1.
    543     ELSE
    544         delta=MAX(0.,SIGN(1.,tref-temp(i)))
    545     ENDIF
    546 
    547     IF (flagth) THEN
    548     cvm5=R5LES*(1.-delta) + R5IES*delta
    549     ELSE
    550     cvm5 = R5LES*RLVTT*(1.-delta) + R5IES*RLSTT*delta
    551     cvm5 = cvm5 /RCPD/(1.0+RVTMP2*(qtot(i)))
    552     ENDIF
    553 
    554     qs(i)= R2ES*FOEEW(temp(i),delta)/pressure(i)
    555     qs(i)=MIN(0.5,qs(i))
    556     cor=1./(1.-RETV*qs(i))
    557     qs(i)=qs(i)*cor
    558     dqs(i)= FOEDE(temp(i),delta,cvm5,qs(i),cor)
     523    DO i = 1, klon
     524
     525      IF (phase == 1) THEN
     526        delta = 0.
     527      ELSEIF (phase == 2) THEN
     528        delta = 1.
     529      ELSE
     530        delta = MAX(0., SIGN(1., tref - temp(i)))
     531      ENDIF
     532
     533      IF (flagth) THEN
     534        cvm5 = R5LES * (1. - delta) + R5IES * delta
     535      ELSE
     536        cvm5 = R5LES * RLVTT * (1. - delta) + R5IES * RLSTT * delta
     537        cvm5 = cvm5 / RCPD / (1.0 + RVTMP2 * (qtot(i)))
     538      ENDIF
     539
     540      qs(i) = R2ES * FOEEW(temp(i), delta) / pressure(i)
     541      qs(i) = MIN(0.5, qs(i))
     542      cor = 1. / (1. - RETV * qs(i))
     543      qs(i) = qs(i) * cor
     544      dqs(i) = FOEDE(temp(i), delta, cvm5, qs(i), cor)
    559545
    560546    END DO
    561547
    562 END SUBROUTINE CALC_QSAT_ECMWF
    563 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    564 
    565 
    566 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    567 SUBROUTINE CALC_GAMMASAT(klon,temp,qtot,pressure,gammasat,dgammasatdt)
    568 
    569 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     548  END SUBROUTINE CALC_QSAT_ECMWF
     549  !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     550
     551
     552  !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     553  SUBROUTINE CALC_GAMMASAT(klon, temp, qtot, pressure, gammasat, dgammasatdt)
     554
     555    !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    570556    ! programme that calculates the gammasat parameter that determines the
    571557    ! homogeneous condensation thresholds for cold (<0oC) clouds
    572558    ! condensation at q>gammasat*qsat
    573559    ! Etienne Vignon, March 2021
    574 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     560    !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    575561
    576562    USE lmdz_lscp_ini, ONLY: iflag_gammasat, t_glace_min, RTT
    577563
    578564    IMPLICIT NONE
    579 
    580565
    581566    INTEGER, INTENT(IN) :: klon                       ! number of horizontal grid points
     
    588573    REAL, INTENT(OUT), DIMENSION(klon) :: dgammasatdt ! derivative of gammasat wrt temperature
    589574
    590     REAL, DIMENSION(klon) ::  qsi,qsl,dqsl,dqsi
     575    REAL, DIMENSION(klon) :: qsi, qsl, dqsl, dqsi
    591576    REAL  fcirrus, fac
    592     REAL, PARAMETER :: acirrus=2.349
    593     REAL, PARAMETER :: bcirrus=259.0
     577    REAL, PARAMETER :: acirrus = 2.349
     578    REAL, PARAMETER :: bcirrus = 259.0
    594579
    595580    INTEGER i
    596    
    597         CALL CALC_QSAT_ECMWF(klon,temp,qtot,pressure,RTT,1,.FALSE.,qsl,dqsl)
    598         CALL CALC_QSAT_ECMWF(klon,temp,qtot,pressure,RTT,2,.FALSE.,qsi,dqsi)
    599 
    600     DO i=1,klon
    601 
    602         IF (temp(i) >= RTT) THEN
    603             ! warm clouds: condensation at saturation wrt liquid
    604             gammasat(i)=1.
    605             dgammasatdt(i)=0.
    606 
    607         ELSEIF ((temp(i) < RTT) .AND. (temp(i) > t_glace_min)) THEN
    608            
    609             IF (iflag_gammasat >= 2) THEN
    610                gammasat(i)=qsl(i)/qsi(i)
    611                dgammasatdt(i)=(dqsl(i)*qsi(i)-dqsi(i)*qsl(i))/qsi(i)/qsi(i)
    612             ELSE
    613                gammasat(i)=1.
    614                dgammasatdt(i)=0.
    615             ENDIF
    616 
    617         ELSE
    618 
    619             IF (iflag_gammasat >=1) THEN
    620             ! homogeneous freezing of aerosols, according to
    621             ! Koop, 2000 and Karcher 2008, QJRMS
    622             ! 'Cirrus regime'
    623                fcirrus=acirrus-temp(i)/bcirrus
    624                IF (fcirrus > qsl(i)/qsi(i)) THEN
    625                   gammasat(i)=qsl(i)/qsi(i)
    626                   dgammasatdt(i)=(dqsl(i)*qsi(i)-dqsi(i)*qsl(i))/qsi(i)/qsi(i)
    627                ELSE
    628                   gammasat(i)=fcirrus
    629                   dgammasatdt(i)=-1.0/bcirrus
    630                ENDIF
    631            
    632             ELSE
    633 
    634                gammasat(i)=1.
    635                dgammasatdt(i)=0.
    636 
    637             ENDIF
    638 
    639         ENDIF
    640    
     581
     582    CALL CALC_QSAT_ECMWF(klon, temp, qtot, pressure, RTT, 1, .FALSE., qsl, dqsl)
     583    CALL CALC_QSAT_ECMWF(klon, temp, qtot, pressure, RTT, 2, .FALSE., qsi, dqsi)
     584
     585    DO i = 1, klon
     586
     587      IF (temp(i) >= RTT) THEN
     588        ! warm clouds: condensation at saturation wrt liquid
     589        gammasat(i) = 1.
     590        dgammasatdt(i) = 0.
     591
     592      ELSEIF ((temp(i) < RTT) .AND. (temp(i) > t_glace_min)) THEN
     593
     594        IF (iflag_gammasat >= 2) THEN
     595          gammasat(i) = qsl(i) / qsi(i)
     596          dgammasatdt(i) = (dqsl(i) * qsi(i) - dqsi(i) * qsl(i)) / qsi(i) / qsi(i)
     597        ELSE
     598          gammasat(i) = 1.
     599          dgammasatdt(i) = 0.
     600        ENDIF
     601
     602      ELSE
     603
     604        IF (iflag_gammasat >=1) THEN
     605          ! homogeneous freezing of aerosols, according to
     606          ! Koop, 2000 and Karcher 2008, QJRMS
     607          ! 'Cirrus regime'
     608          fcirrus = acirrus - temp(i) / bcirrus
     609          IF (fcirrus > qsl(i) / qsi(i)) THEN
     610            gammasat(i) = qsl(i) / qsi(i)
     611            dgammasatdt(i) = (dqsl(i) * qsi(i) - dqsi(i) * qsl(i)) / qsi(i) / qsi(i)
     612          ELSE
     613            gammasat(i) = fcirrus
     614            dgammasatdt(i) = -1.0 / bcirrus
     615          ENDIF
     616
     617        ELSE
     618
     619          gammasat(i) = 1.
     620          dgammasatdt(i) = 0.
     621
     622        ENDIF
     623
     624      ENDIF
     625
    641626    END DO
    642627
    643 
    644 END SUBROUTINE CALC_GAMMASAT
    645 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    646 
    647 
    648 !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    649 SUBROUTINE DISTANCE_TO_CLOUD_TOP(klon,klev,k,temp,pplay,paprs,rneb,distcltop1D,temp_cltop)
    650 !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    651    
    652    USE lmdz_lscp_ini, ONLY: rd,rg,tresh_cl
    653 
    654    IMPLICIT NONE
    655    
    656    INTEGER, INTENT(IN) :: klon,klev                !number of horizontal and vertical grid points
    657    INTEGER, INTENT(IN) :: k                        ! vertical index
    658    REAL, INTENT(IN), DIMENSION(klon,klev) :: temp  ! temperature in K
    659    REAL, INTENT(IN), DIMENSION(klon,klev) :: pplay ! pressure middle layer in Pa
    660    REAL, INTENT(IN), DIMENSION(klon,klev+1) :: paprs ! pressure interfaces in Pa
    661    REAL, INTENT(IN), DIMENSION(klon,klev) :: rneb  ! cloud fraction
    662 
    663    REAL, INTENT(OUT), DIMENSION(klon) :: distcltop1D  ! distance from cloud top
    664    REAL, INTENT(OUT), DIMENSION(klon) :: temp_cltop     ! temperature of cloud top
    665    
    666    REAL dzlay(klon,klev)
    667    REAL zlay(klon,klev)
    668    REAL dzinterf
    669    INTEGER i,k_top, kvert
    670    LOGICAL bool_cl
    671 
    672 
    673    DO i=1,klon
    674          ! Initialization height middle of first layer
    675           dzlay(i,1) = Rd * temp(i,1) / rg * log(paprs(i,1)/paprs(i,2))
    676           zlay(i,1) = dzlay(i,1)/2
    677 
    678           DO kvert=2,klev
    679                  IF (kvert==klev) THEN
    680                        dzlay(i,kvert) = 2*(rd * temp(i,kvert) / rg * log(paprs(i,kvert)/pplay(i,kvert)))
    681                  ELSE
    682                        dzlay(i,kvert) = rd * temp(i,kvert) / rg * log(paprs(i,kvert)/paprs(i,kvert+1))
    683                  ENDIF
    684                        dzinterf       = rd * temp(i,kvert) / rg * log(pplay(i,kvert-1)/pplay(i,kvert))
    685                        zlay(i,kvert)  = zlay(i,kvert-1) + dzinterf
    686            ENDDO
    687    ENDDO
    688    
    689    DO i=1,klon
    690           k_top = k
    691           IF (rneb(i,k) <= tresh_cl) THEN
    692                  bool_cl = .FALSE.
    693           ELSE
    694                  bool_cl = .TRUE.
    695           ENDIF
    696 
    697           DO WHILE ((bool_cl) .AND. (k_top <= klev))
    698           ! find cloud top
    699                 IF (rneb(i,k_top) > tresh_cl) THEN
    700                       k_top = k_top + 1
    701                 ELSE
    702                       bool_cl = .FALSE.
    703                       k_top   = k_top - 1
    704                 ENDIF
    705           ENDDO
    706           k_top=min(k_top,klev)
    707 
    708           !dist to top is dist between current layer and layer of cloud top (from middle to middle) + dist middle to
    709           !interf for layer of cloud top
    710           distcltop1D(i) = zlay(i,k_top) - zlay(i,k) + dzlay(i,k_top)/2
    711           temp_cltop(i)  = temp(i,k_top)
    712    ENDDO ! klon
    713 
    714 END SUBROUTINE DISTANCE_TO_CLOUD_TOP
    715 !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     628  END SUBROUTINE CALC_GAMMASAT
     629  !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     630
     631
     632  !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     633  SUBROUTINE DISTANCE_TO_CLOUD_TOP(klon, klev, k, temp, pplay, paprs, rneb, distcltop1D, temp_cltop)
     634    !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     635
     636    USE lmdz_lscp_ini, ONLY: rd, rg, tresh_cl
     637
     638    IMPLICIT NONE
     639
     640    INTEGER, INTENT(IN) :: klon, klev                !number of horizontal and vertical grid points
     641    INTEGER, INTENT(IN) :: k                        ! vertical index
     642    REAL, INTENT(IN), DIMENSION(klon, klev) :: temp  ! temperature in K
     643    REAL, INTENT(IN), DIMENSION(klon, klev) :: pplay ! pressure middle layer in Pa
     644    REAL, INTENT(IN), DIMENSION(klon, klev + 1) :: paprs ! pressure interfaces in Pa
     645    REAL, INTENT(IN), DIMENSION(klon, klev) :: rneb  ! cloud fraction
     646
     647    REAL, INTENT(OUT), DIMENSION(klon) :: distcltop1D  ! distance from cloud top
     648    REAL, INTENT(OUT), DIMENSION(klon) :: temp_cltop     ! temperature of cloud top
     649
     650    REAL dzlay(klon, klev)
     651    REAL zlay(klon, klev)
     652    REAL dzinterf
     653    INTEGER i, k_top, kvert
     654    LOGICAL bool_cl
     655
     656    DO i = 1, klon
     657      ! Initialization height middle of first layer
     658      dzlay(i, 1) = Rd * temp(i, 1) / rg * log(paprs(i, 1) / paprs(i, 2))
     659      zlay(i, 1) = dzlay(i, 1) / 2
     660
     661      DO kvert = 2, klev
     662        IF (kvert==klev) THEN
     663          dzlay(i, kvert) = 2 * (rd * temp(i, kvert) / rg * log(paprs(i, kvert) / pplay(i, kvert)))
     664        ELSE
     665          dzlay(i, kvert) = rd * temp(i, kvert) / rg * log(paprs(i, kvert) / paprs(i, kvert + 1))
     666        ENDIF
     667        dzinterf = rd * temp(i, kvert) / rg * log(pplay(i, kvert - 1) / pplay(i, kvert))
     668        zlay(i, kvert) = zlay(i, kvert - 1) + dzinterf
     669      ENDDO
     670    ENDDO
     671
     672    DO i = 1, klon
     673      k_top = k
     674      IF (rneb(i, k) <= tresh_cl) THEN
     675        bool_cl = .FALSE.
     676      ELSE
     677        bool_cl = .TRUE.
     678      ENDIF
     679
     680      DO WHILE ((bool_cl) .AND. (k_top <= klev))
     681        ! find cloud top
     682        IF (rneb(i, k_top) > tresh_cl) THEN
     683          k_top = k_top + 1
     684        ELSE
     685          bool_cl = .FALSE.
     686          k_top = k_top - 1
     687        ENDIF
     688      ENDDO
     689      k_top = min(k_top, klev)
     690
     691      !dist to top is dist between current layer and layer of cloud top (from middle to middle) + dist middle to
     692      !interf for layer of cloud top
     693      distcltop1D(i) = zlay(i, k_top) - zlay(i, k) + dzlay(i, k_top) / 2
     694      temp_cltop(i) = temp(i, k_top)
     695    ENDDO ! klon
     696
     697  END SUBROUTINE DISTANCE_TO_CLOUD_TOP
     698  !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    716699
    717700END MODULE lmdz_lscp_tools
Note: See TracChangeset for help on using the changeset viewer.