Ignore:
Timestamp:
Sep 4, 2023, 10:17:16 AM (10 months ago)
Author:
Laurent Fairhead
Message:

Merged with trunk revision 4586 corresponding to june 2023 testing

Location:
LMDZ6/branches/LMDZ_cdrag_LSCE
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • LMDZ6/branches/LMDZ_cdrag_LSCE

  • LMDZ6/branches/LMDZ_cdrag_LSCE/libf/phylmd/lscp_tools_mod.F90

    r4072 r4669  
    1616    ! 3212–3234. https://doi.org/10.1029/2019MS001642
    1717   
    18    
     18    use lscp_ini_mod, only: iflag_vice, ffallv_con, ffallv_lsc
     19    use lscp_ini_mod, only: cice_velo, dice_velo
     20
    1921    IMPLICIT NONE
    20 
    21     INCLUDE "nuage.h"
    22     INCLUDE "fisrtilp.h"
    2322
    2423    INTEGER, INTENT(IN) :: klon
     
    3332
    3433    INTEGER i
    35     REAL logvm,iwcg,tempc,phpa,cvel,dvel,fallv_tun
     34    REAL logvm,iwcg,tempc,phpa,fallv_tun
    3635    REAL m2ice, m2snow, vmice, vmsnow
    3736    REAL aice, bice, asnow, bsnow
     
    6261       
    6362        velo(i)=fallv_tun*velo(i)/100.0 ! from cm/s to m/s
    64         dvel=0.2
    65         cvel=fallv_tun*65.0*(rho(i)**0.2)*(150./phpa)**0.15
    6663
    6764    ELSE IF (iflag_vice .EQ. 2) THEN
     
    9491        vmsnow=vmsnow*((1000./phpa)**0.35)
    9592        velo(i)=fallv_tun*min(vmsnow,vmice)/100. ! to m/s
    96         dvel=0.2
    97         cvel=velo(i)/((iwcg/1000.*rho(i))**dvel)
    9893
    9994    ELSE
    10095        ! By default, fallspeed velocity of ice crystals according to Heymsfield & Donner 1990
    101         velo(i) = fallv_tun*3.29/2.0*((iwcg/1000.)**0.16)
    102         dvel=0.16
    103         cvel=fallv_tun*3.29/2.0*(rho(i)**0.16)
     96        velo(i) = fallv_tun*cice_velo*((iwcg/1000.)**dice_velo)
    10497    ENDIF
    10598    ENDDO
     
    109102
    110103!+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    111 SUBROUTINE ICEFRAC_LSCP(klon, temp, sig, icefrac, dicefracdT)
     104SUBROUTINE ICEFRAC_LSCP(klon, temp, iflag_ice_thermo, distcltop, icefrac, dicefracdT)
    112105!+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    113106 
     
    120113
    121114    USE print_control_mod, ONLY: lunout, prt_level
     115    USE lscp_ini_mod, ONLY: t_glace_min, t_glace_max, exposant_glace, iflag_t_glace
     116    USE lscp_ini_mod, ONLY : RTT, dist_liq
    122117
    123118    IMPLICIT NONE
    124119
    125 
    126     INCLUDE "YOMCST.h"
    127     INCLUDE "nuage.h"
    128     INCLUDE "clesphys.h"
    129 
    130 
    131   ! nuage.h contains:
    132   ! t_glace_min: if T < Tmin, the cloud is only made of water ice
    133   ! t_glace_max: if T > Tmax, the cloud is only made of liquid water
    134   ! exposant_glace: controls the sharpness of the transition
    135120
    136121    INTEGER, INTENT(IN)                 :: klon       ! number of horizontal grid points
    137122    REAL, INTENT(IN), DIMENSION(klon)   :: temp       ! temperature
    138     REAL, INTENT(IN), DIMENSION(klon)   :: sig
     123    REAL, INTENT(IN), DIMENSION(klon)   :: distcltop       ! distance to cloud top
     124    INTEGER, INTENT(IN)                 :: iflag_ice_thermo
    139125    REAL, INTENT(OUT), DIMENSION(klon)  :: icefrac
    140126    REAL, INTENT(OUT), DIMENSION(klon)  :: dicefracdT
     
    142128
    143129    INTEGER i
    144     REAL    sig0,www,tmin_tmp,liqfrac_tmp
     130    REAL    liqfrac_tmp, dicefrac_tmp
    145131    REAL    Dv, denomdep,beta,qsi,dqsidt
    146     INTEGER exposant_glace_old
    147     REAL t_glace_min_old
    148132    LOGICAL ice_thermo
    149133
    150     sig0=0.8
    151     t_glace_min_old = RTT - 15.0
    152     ice_thermo = (iflag_ice_thermo .EQ. 1).OR.(iflag_ice_thermo .GE. 3)
    153     IF (ice_thermo) THEN
    154       exposant_glace_old = 2
    155     ELSE
    156       exposant_glace_old = 6
     134    CHARACTER (len = 20) :: modname = 'lscp_tools'
     135    CHARACTER (len = 80) :: abort_message
     136
     137    IF ((iflag_t_glace.LT.2) .OR. (iflag_t_glace.GT.6)) THEN
     138       abort_message = 'lscp cannot be used if iflag_t_glace<2 or >6'
     139       CALL abort_physic(modname,abort_message,1)
    157140    ENDIF
    158141
    159 
    160 ! calculation of icefrac and dicefrac/dT
     142    IF (.NOT.((iflag_ice_thermo .EQ. 1).OR.(iflag_ice_thermo .GE. 3))) THEN
     143       abort_message = 'lscp cannot be used without ice thermodynamics'
     144       CALL abort_physic(modname,abort_message,1)
     145    ENDIF
     146
    161147
    162148    DO i=1,klon
    163 
    164     IF (iflag_t_glace.EQ.1) THEN
    165             ! Transition to ice close to surface for T<Tmax
    166             ! w=1 at the surface and 0 for sig < sig0
    167             www=(max(sig(i)-sig0,0.))/(1.-sig0)
    168     ELSEIF (iflag_t_glace.GE.2) THEN
    169             ! No convertion to ice close to surface
    170             www = 0.
    171     ENDIF
    172      
    173     tmin_tmp=www*t_glace_max+(1.-www)*t_glace_min
    174     liqfrac_tmp=  (temp(i)-tmin_tmp) / (t_glace_max-tmin_tmp)
    175     liqfrac_tmp = MIN(MAX(liqfrac_tmp,0.0),1.0)
    176        
    177     IF (iflag_t_glace.GE.3) THEN
    178             icefrac(i) = 1.0-liqfrac_tmp**exposant_glace
    179             IF ((icefrac(i) .GT.0.) .AND. (liqfrac_tmp .GT. 0)) THEN
    180                  dicefracdT(i)= exposant_glace * ((liqfrac_tmp)**(exposant_glace-1.)) &
    181                            / (t_glace_min - t_glace_max)
    182             ELSE
    183 
    184                  dicefracdT(i)=0.
    185             ENDIF
    186 
    187     ELSE
     149 
     150        ! old function with sole dependence upon temperature
     151        IF (iflag_t_glace .EQ. 2) THEN
     152            liqfrac_tmp = (temp(i)-t_glace_min) / (t_glace_max-t_glace_min)
     153            liqfrac_tmp = MIN(MAX(liqfrac_tmp,0.0),1.0)
    188154            icefrac(i) = (1.0-liqfrac_tmp)**exposant_glace
    189155            IF (icefrac(i) .GT.0.) THEN
     
    196162            ENDIF
    197163
    198     ENDIF
    199    
    200     ENDDO
    201 
    202 
    203     RETURN
    204 
     164        ENDIF
     165
     166        ! function of temperature used in CMIP6 physics
     167        IF (iflag_t_glace .EQ. 3) THEN
     168            liqfrac_tmp = (temp(i)-t_glace_min) / (t_glace_max-t_glace_min)
     169            liqfrac_tmp = MIN(MAX(liqfrac_tmp,0.0),1.0)
     170            icefrac(i) = 1.0-liqfrac_tmp**exposant_glace
     171            IF ((icefrac(i) .GT.0.) .AND. (liqfrac_tmp .GT. 0.)) THEN
     172                dicefracdT(i)= exposant_glace * ((liqfrac_tmp)**(exposant_glace-1.)) &
     173                          / (t_glace_min - t_glace_max)
     174            ELSE
     175                dicefracdT(i)=0.
     176            ENDIF
     177        ENDIF
     178
     179        ! for iflag_t_glace .GE. 4, the liquid fraction depends upon temperature at cloud top
     180        ! and then decreases with decreasing height
     181
     182        !with linear function of temperature at cloud top
     183        IF (iflag_t_glace .EQ. 4) THEN 
     184                liqfrac_tmp = (temp(i)-t_glace_min) / (t_glace_max-t_glace_min)
     185                liqfrac_tmp = MIN(MAX(liqfrac_tmp,0.0),1.0)
     186                icefrac(i)    =  MAX(MIN(1.,1.0 - liqfrac_tmp*exp(-distcltop(i)/dist_liq)),0.)
     187                dicefrac_tmp = - temp(i)/(t_glace_max-t_glace_min)
     188                dicefracdT(i) = dicefrac_tmp*exp(-distcltop(i)/dist_liq)
     189                IF ((liqfrac_tmp .LE.0) .OR. (liqfrac_tmp .GE. 1)) THEN
     190                        dicefracdT(i) = 0.
     191                ENDIF
     192        ENDIF
     193
     194        ! with CMIP6 function of temperature at cloud top
     195        IF (iflag_t_glace .EQ. 5) THEN
     196                liqfrac_tmp = (temp(i)-t_glace_min) / (t_glace_max-t_glace_min)
     197                liqfrac_tmp =  MIN(MAX(liqfrac_tmp,0.0),1.0)
     198                liqfrac_tmp = liqfrac_tmp**exposant_glace
     199                icefrac(i)  =  MAX(MIN(1.,1.0 - liqfrac_tmp*exp(-distcltop(i)/dist_liq)),0.)
     200                IF ((liqfrac_tmp .LE.0) .OR. (liqfrac_tmp .GE. 1)) THEN
     201                        dicefracdT(i) = 0.
     202                ELSE
     203                        dicefracdT(i) = exposant_glace*((liqfrac_tmp)**(exposant_glace-1.))/(t_glace_min- t_glace_max) &
     204                                        *exp(-distcltop(i)/dist_liq)
     205                ENDIF
     206        ENDIF
     207
     208        ! with modified function of temperature at cloud top
     209        ! to get largere values around 260 K, works well with t_glace_min = 241K
     210        IF (iflag_t_glace .EQ. 6) THEN
     211                IF (temp(i) .GT. t_glace_max) THEN
     212                        liqfrac_tmp = 1.
     213                ELSE
     214                        liqfrac_tmp = -((temp(i)-t_glace_max) / (t_glace_max-t_glace_min))**2+1.
     215                ENDIF
     216                liqfrac_tmp  = MIN(MAX(liqfrac_tmp,0.0),1.0)
     217                icefrac(i)   = MAX(MIN(1.,1.0 - liqfrac_tmp*exp(-distcltop(i)/dist_liq)),0.)       
     218                IF ((liqfrac_tmp .LE.0) .OR. (liqfrac_tmp .GE. 1)) THEN
     219                        dicefracdT(i) = 0.
     220                ELSE
     221                        dicefracdT(i) = 2*((temp(i)-t_glace_max) / (t_glace_max-t_glace_min))/(t_glace_max-t_glace_min) &
     222                                  *exp(-distcltop(i)/dist_liq)
     223                ENDIF
     224        ENDIF
     225
     226
     227
     228     ENDDO ! klon
     229 
     230     RETURN
     231 
    205232END SUBROUTINE ICEFRAC_LSCP
    206233!+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     
    276303!+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    277304
     305    use lscp_ini_mod, only: iflag_gammasat, t_glace_min, RTT
    278306
    279307    IMPLICIT NONE
    280308
    281     include "YOMCST.h"
    282     include "YOETHF.h"
    283     include "FCTTRE.h"
    284     include "nuage.h"
    285309
    286310    INTEGER, INTENT(IN) :: klon                       ! number of horizontal grid points
     
    348372
    349373END SUBROUTINE CALC_GAMMASAT
    350 
    351 
     374!+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     375
     376
     377!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     378SUBROUTINE DISTANCE_TO_CLOUD_TOP(klon,klev,k,temp,pplay,paprs,rneb,distcltop1D)
     379!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     380   
     381   USE lscp_ini_mod, ONLY : rd,rg,tresh_cl
     382
     383   IMPLICIT NONE
     384   
     385   INTEGER, INTENT(IN) :: klon,klev                !number of horizontal and vertical grid points
     386   INTEGER, INTENT(IN) :: k                        ! vertical index
     387   REAL, INTENT(IN), DIMENSION(klon,klev) :: temp  ! temperature in K
     388   REAL, INTENT(IN), DIMENSION(klon,klev) :: pplay ! pressure middle layer in Pa
     389   REAL, INTENT(IN), DIMENSION(klon,klev+1) :: paprs ! pressure interfaces in Pa
     390   REAL, INTENT(IN), DIMENSION(klon,klev) :: rneb  ! cloud fraction
     391
     392   REAL, INTENT(OUT), DIMENSION(klon) :: distcltop1D  ! distance from cloud top
     393
     394   REAL dzlay(klon,klev)
     395   REAL zlay(klon,klev)
     396   REAL dzinterf
     397   INTEGER i,k_top, kvert
     398   LOGICAL bool_cl
     399
     400
     401   DO i=1,klon
     402         ! Initialization height middle of first layer
     403          dzlay(i,1) = Rd * temp(i,1) / rg * log(paprs(i,1)/paprs(i,2))
     404          zlay(i,1) = dzlay(i,1)/2
     405
     406          DO kvert=2,klev
     407                 IF (kvert.EQ.klev) THEN
     408                       dzlay(i,kvert) = 2*(rd * temp(i,kvert) / rg * log(paprs(i,kvert)/pplay(i,kvert)))
     409                 ELSE
     410                       dzlay(i,kvert) = rd * temp(i,kvert) / rg * log(paprs(i,kvert)/paprs(i,kvert+1))
     411                 ENDIF
     412                       dzinterf       = rd * temp(i,kvert) / rg * log(pplay(i,kvert-1)/pplay(i,kvert))
     413                       zlay(i,kvert)  = zlay(i,kvert-1) + dzinterf
     414           ENDDO
     415   ENDDO
     416   
     417   k_top = k
     418   DO i=1,klon
     419          IF (rneb(i,k) .LE. tresh_cl) THEN
     420                 bool_cl = .FALSE.
     421          ELSE
     422                 bool_cl = .TRUE.
     423          ENDIF
     424
     425          DO WHILE ((bool_cl) .AND. (k_top .LE. klev))
     426          ! find cloud top
     427                IF (rneb(i,k_top) .GT. tresh_cl) THEN
     428                      k_top = k_top + 1
     429                ELSE
     430                      bool_cl = .FALSE.
     431                      k_top   = k_top - 1
     432                ENDIF
     433          ENDDO
     434          k_top=min(k_top,klev)
     435
     436          !dist to top is dist between current layer and layer of cloud top (from middle to middle) + dist middle to
     437          !interf for layer of cloud top
     438          distcltop1D(i) = zlay(i,k_top) - zlay(i,k) + dzlay(i,k_top)/2
     439   ENDDO ! klon
     440
     441END SUBROUTINE DISTANCE_TO_CLOUD_TOP
    352442!++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    353443
Note: See TracChangeset for help on using the changeset viewer.