| 1 | MODULE MP2M_MICROPHYSICS |
|---|
| 2 | !============================================================================ |
|---|
| 3 | ! |
|---|
| 4 | ! Purpose |
|---|
| 5 | ! ------- |
|---|
| 6 | ! Interface to main microphysics subroutine. |
|---|
| 7 | ! The interface computes all aerosols microphysics processes in a single call. |
|---|
| 8 | ! |
|---|
| 9 | ! The module contains two methods: |
|---|
| 10 | ! - mm_muphys |
|---|
| 11 | ! - mm_diagnostics |
|---|
| 12 | ! |
|---|
| 13 | ! Authors |
|---|
| 14 | ! ------- |
|---|
| 15 | ! B. de Batz de Trenquelléon, J. Burgalat (11/2024) |
|---|
| 16 | ! |
|---|
| 17 | !============================================================================ |
|---|
| 18 | |
|---|
| 19 | USE MP2M_MPREC |
|---|
| 20 | USE MP2M_GLOBALS |
|---|
| 21 | USE MP2M_HAZE |
|---|
| 22 | USE MP2M_CLOUDS |
|---|
| 23 | USE MP2M_METHODS |
|---|
| 24 | USE MP2M_CLOUDS_METHODS |
|---|
| 25 | IMPLICIT NONE |
|---|
| 26 | |
|---|
| 27 | PUBLIC :: mm_muphys, mm_diagnostics |
|---|
| 28 | |
|---|
| 29 | !! Interface to main microphysics subroutine: |
|---|
| 30 | !! Computes either all the microphysics processes [[muphys_all]] |
|---|
| 31 | !! or only aerosols microphysics [[muphys_nocld]] in a single call. |
|---|
| 32 | INTERFACE mm_muphys |
|---|
| 33 | MODULE PROCEDURE muphys_all,muphys_nocld |
|---|
| 34 | END INTERFACE mm_muphys |
|---|
| 35 | |
|---|
| 36 | CONTAINS |
|---|
| 37 | |
|---|
| 38 | FUNCTION muphys_all(m3as_prod,dm0as,dm3as,dm0af,dm3af,dm0ccn,dm3ccn,dm3ices,dmugases,dtlc) RESULT(ret) |
|---|
| 39 | !! Compute the evolution of moments tracers through haze microphysics processes. |
|---|
| 40 | !! |
|---|
| 41 | !! This method computes the evolution of all the microphysics tracers, given under the form |
|---|
| 42 | !! of moments during a time step. |
|---|
| 43 | !! |
|---|
| 44 | !! The method requires that global variables of the model (i.e. variables declared in mm_globals |
|---|
| 45 | !! module) are initialized/updated correctly (see mm_global_init, mm_column_init, and mm_aerosols_init). |
|---|
| 46 | !! |
|---|
| 47 | !! The tendencies returned by the method are defined on the vertical __layers__ of the model from the __GROUND__ to |
|---|
| 48 | !! the __TOP__ of the atmosphere. They should be added to the input variables used in the initialization methods |
|---|
| 49 | !! before the latter are called to initialize a new step. |
|---|
| 50 | !! |
|---|
| 51 | ! Production of the 3rd order moment of the spherical mode distribution (m3.m-2). |
|---|
| 52 | REAL(kind=mm_wp), INTENT(in), DIMENSION(:) :: m3as_prod |
|---|
| 53 | ! Tendency of the 0th order moment of the spherical mode distribution (m-2). |
|---|
| 54 | REAL(kind=mm_wp), INTENT(inout), DIMENSION(:) :: dm0as |
|---|
| 55 | ! Tendency of the 3rd order moment of the spherical mode distribution (m3.m-2). |
|---|
| 56 | REAL(kind=mm_wp), INTENT(inout), DIMENSION(:) :: dm3as |
|---|
| 57 | ! Tendency of the 0th order moment of the fractal mode distribution (m-2). |
|---|
| 58 | REAL(kind=mm_wp), INTENT(inout), DIMENSION(:) :: dm0af |
|---|
| 59 | ! Tendency of the 3rd order moment of the fractal mode distribution (m3.m-2). |
|---|
| 60 | REAL(kind=mm_wp), INTENT(inout), DIMENSION(:) :: dm3af |
|---|
| 61 | ! Tendency of the 0th order moment of the CCN distribution (m-2). |
|---|
| 62 | REAL(kind=mm_wp), INTENT(inout), DIMENSION(:) :: dm0ccn |
|---|
| 63 | ! Tendency of the 3rd order moment of the CCN distribution (m3.m-2). |
|---|
| 64 | REAL(kind=mm_wp), INTENT(inout), DIMENSION(:) :: dm3ccn |
|---|
| 65 | ! Tendency of the 3rd order moment of each ice components (m3.m-2). |
|---|
| 66 | REAL(kind=mm_wp), INTENT(inout), DIMENSION(:,:) :: dm3ices |
|---|
| 67 | ! Tendencies of each condensible gaz species (mol.mol-1). |
|---|
| 68 | REAL(kind=mm_wp), INTENT(inout), DIMENSION(:,:) :: dmugases |
|---|
| 69 | ! Latent heat of condensation (J.kg-1). |
|---|
| 70 | REAL(kind=mm_wp), INTENT(inout), DIMENSION(:) :: dtlc |
|---|
| 71 | |
|---|
| 72 | ! .true. on succes (i.e. model has been initialized at least once previously), .false. otherwise. |
|---|
| 73 | LOGICAL :: ret |
|---|
| 74 | |
|---|
| 75 | ! Local variables: |
|---|
| 76 | !~~~~~~~~~~~~~~~~~ |
|---|
| 77 | INTEGER :: i |
|---|
| 78 | ! Production of the spherical aerosols (m3.m-3). |
|---|
| 79 | REAL(kind=mm_wp), DIMENSION(:), ALLOCATABLE :: m3a_s_prod |
|---|
| 80 | ! Tendencies related to haze model (X/m3). |
|---|
| 81 | REAL(kind=mm_wp), DIMENSION(SIZE(dm0as)) :: Hdm0as,Hdm3as,Hdm0af,Hdm3af |
|---|
| 82 | ! Tendencies related to cloud model (X/m3). |
|---|
| 83 | REAL(kind=mm_wp), DIMENSION(SIZE(dm0as)) :: Cdm0as,Cdm3as,Cdm0af,Cdm3af |
|---|
| 84 | |
|---|
| 85 | ALLOCATE(m3a_s_prod(mm_nla)) |
|---|
| 86 | |
|---|
| 87 | ! Sanity check for initialization: |
|---|
| 88 | !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 89 | ret = (mm_ini_col.AND.mm_ini_aer) |
|---|
| 90 | if (.NOT.ret) then |
|---|
| 91 | return |
|---|
| 92 | endif |
|---|
| 93 | if (mm_call_clouds.AND.mm_debug) then |
|---|
| 94 | write(*,'(a)') "[MM_DEBUG - muphys_nocld] Clouds microphysics enabled but will not be computed... (wrong interface)" |
|---|
| 95 | endif |
|---|
| 96 | |
|---|
| 97 | ! Reverse vectors so they go from top to ground |
|---|
| 98 | ! @note: mm_dzlev is already from top to ground |
|---|
| 99 | m3a_s_prod = m3as_prod(mm_nla:1:-1) / mm_dzlev(:) |
|---|
| 100 | |
|---|
| 101 | ! Initialize latent heat |
|---|
| 102 | dtlc(:) = 0._mm_wp |
|---|
| 103 | |
|---|
| 104 | ! Calls haze microphysics (/!\ tendencies in X/m-3): |
|---|
| 105 | !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 106 | call mm_haze_microphysics(m3a_s_prod,Hdm0as,Hdm3as,Hdm0af,Hdm3af) |
|---|
| 107 | |
|---|
| 108 | ! Calls cloud microphysics (/!\ tendencies in X/m-3): |
|---|
| 109 | !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 110 | if (mm_call_clouds) then |
|---|
| 111 | call mm_cloud_microphysics(Hdm0as,Hdm3as,Hdm0af,Hdm3af,& |
|---|
| 112 | Cdm0as,Cdm3as,Cdm0af,Cdm3af,& |
|---|
| 113 | dm0ccn,dm3ccn,dm3ices,dmugases) |
|---|
| 114 | |
|---|
| 115 | ! Multiply by altitude thickness and reverse vectors so they go from ground to top (--> m-2) |
|---|
| 116 | dm0ccn = dm0ccn(mm_nla:1:-1) * mm_dzlev(mm_nla:1:-1) |
|---|
| 117 | dm3ccn = dm3ccn(mm_nla:1:-1) * mm_dzlev(mm_nla:1:-1) |
|---|
| 118 | do i = 1, mm_nesp |
|---|
| 119 | dm3ices(:,i) = dm3ices(mm_nla:1:-1,i) * mm_dzlev(mm_nla:1:-1) |
|---|
| 120 | dmugases(:,i) = dmugases(mm_nla:1:-1,i) |
|---|
| 121 | |
|---|
| 122 | ! Compute condensation heating rate (/!\ dmugases = - dm3ices) |
|---|
| 123 | dtlc(:) = dtlc(:) - (dmugases(:,i) * mm_xESPS(i)%fmol2fmas * mm_LheatX(mm_temp,mm_xESPS(i))) |
|---|
| 124 | enddo |
|---|
| 125 | |
|---|
| 126 | else |
|---|
| 127 | Cdm0as(:) = 0._mm_wp ; Cdm3as(:) = 0._mm_wp ; Cdm0af(:) = 0._mm_wp ; Cdm3af(:) = 0._mm_wp |
|---|
| 128 | dm0ccn(:) = 0._mm_wp ; dm3ccn(:) = 0._mm_wp ; dm3ices(:,:) = 0._mm_wp ; dmugases(:,:) = 0._mm_wp |
|---|
| 129 | dtlc(:) = 0._mm_wp |
|---|
| 130 | endif ! end of mm_call_clouds |
|---|
| 131 | |
|---|
| 132 | ! Multiply by altitude thickness and reverse vectors so they go from ground to top (--> m-2) |
|---|
| 133 | dm0as = (Hdm0as(mm_nla:1:-1) + Cdm0as(mm_nla:1:-1)) * mm_dzlev(mm_nla:1:-1) |
|---|
| 134 | dm3as = (Hdm3as(mm_nla:1:-1) + Cdm3as(mm_nla:1:-1)) * mm_dzlev(mm_nla:1:-1) |
|---|
| 135 | dm0af = (Hdm0af(mm_nla:1:-1) + Cdm0af(mm_nla:1:-1)) * mm_dzlev(mm_nla:1:-1) |
|---|
| 136 | dm3af = (Hdm3af(mm_nla:1:-1) + Cdm3af(mm_nla:1:-1)) * mm_dzlev(mm_nla:1:-1) |
|---|
| 137 | |
|---|
| 138 | RETURN |
|---|
| 139 | END FUNCTION muphys_all |
|---|
| 140 | |
|---|
| 141 | |
|---|
| 142 | FUNCTION muphys_nocld(m3as_prod,dm0as,dm3as,dm0af,dm3af) RESULT(ret) |
|---|
| 143 | !! Compute the evolution of moments tracers through haze microphysics processes. |
|---|
| 144 | !! |
|---|
| 145 | !! This method computes the evolution of all the microphysics tracers, given under the form |
|---|
| 146 | !! of moments during a time step. |
|---|
| 147 | !! |
|---|
| 148 | !! The method requires that global variables of the model (i.e. variables declared in mm_globals |
|---|
| 149 | !! module) are initialized/updated correctly (see mm_global_init, mm_column_init, and mm_aerosols_init). |
|---|
| 150 | !! |
|---|
| 151 | !! The tendencies returned by the method are defined on the vertical __layers__ of the model from the __GROUND__ to |
|---|
| 152 | !! the __TOP__ of the atmosphere. They should be added to the input variables used in the initialization methods |
|---|
| 153 | !! before the latter are called to initialize a new step. |
|---|
| 154 | !! |
|---|
| 155 | ! Production of the 3rd order moment of the spherical mode distribution (m3.m-2). |
|---|
| 156 | REAL(kind=mm_wp), INTENT(in), DIMENSION(:) :: m3as_prod |
|---|
| 157 | ! Tendency of the 0th order moment of the spherical mode distribution (m-2). |
|---|
| 158 | REAL(kind=mm_wp), INTENT(inout), DIMENSION(:) :: dm0as |
|---|
| 159 | ! Tendency of the 3rd order moment of the spherical mode distribution (m3.m-2). |
|---|
| 160 | REAL(kind=mm_wp), INTENT(inout), DIMENSION(:) :: dm3as |
|---|
| 161 | ! Tendency of the 0th order moment of the fractal mode distribution (m-2). |
|---|
| 162 | REAL(kind=mm_wp), INTENT(inout), DIMENSION(:) :: dm0af |
|---|
| 163 | ! Tendency of the 3rd order moment of the fractal mode distribution (m3.m-2). |
|---|
| 164 | REAL(kind=mm_wp), INTENT(inout), DIMENSION(:) :: dm3af |
|---|
| 165 | |
|---|
| 166 | ! .true. on succes (i.e. model has been initialized at least once previously), .false. otherwise. |
|---|
| 167 | LOGICAL :: ret |
|---|
| 168 | |
|---|
| 169 | ! Local variables: |
|---|
| 170 | !~~~~~~~~~~~~~~~~~ |
|---|
| 171 | ! Production of the spherical aerosols (m3.m-3). |
|---|
| 172 | REAL(kind=mm_wp), DIMENSION(:), ALLOCATABLE :: m3a_s_prod |
|---|
| 173 | ALLOCATE(m3a_s_prod(mm_nla)) |
|---|
| 174 | |
|---|
| 175 | ! Sanity check for initialization: |
|---|
| 176 | !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 177 | ret = (mm_ini_col.AND.mm_ini_aer) |
|---|
| 178 | if (.NOT.ret) then |
|---|
| 179 | return |
|---|
| 180 | endif |
|---|
| 181 | if (mm_call_clouds.AND.mm_debug) then |
|---|
| 182 | write(*,'(a)') "[MM_DEBUG - muphys_nocld] Clouds microphysics enabled but will not be computed... (wrong interface)" |
|---|
| 183 | endif |
|---|
| 184 | |
|---|
| 185 | ! Reverse vectors so they go from top to ground |
|---|
| 186 | ! @note: mm_dzlev is already from top to ground |
|---|
| 187 | m3a_s_prod = m3as_prod(mm_nla:1:-1) / mm_dzlev(:) |
|---|
| 188 | |
|---|
| 189 | ! Calls haze microphysics (/!\ tendencies in X/m-3): |
|---|
| 190 | !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 191 | call mm_haze_microphysics(m3a_s_prod,dm0as,dm3as,dm0af,dm3af) |
|---|
| 192 | |
|---|
| 193 | ! Multiply by altitude thickness and reverse vectors so they go from ground to top (--> m-2) |
|---|
| 194 | dm0as = dm0as(mm_nla:1:-1) * mm_dzlev(mm_nla:1:-1) |
|---|
| 195 | dm3as = dm3as(mm_nla:1:-1) * mm_dzlev(mm_nla:1:-1) |
|---|
| 196 | dm0af = dm0af(mm_nla:1:-1) * mm_dzlev(mm_nla:1:-1) |
|---|
| 197 | dm3af = dm3af(mm_nla:1:-1) * mm_dzlev(mm_nla:1:-1) |
|---|
| 198 | |
|---|
| 199 | RETURN |
|---|
| 200 | END FUNCTION muphys_nocld |
|---|
| 201 | |
|---|
| 202 | |
|---|
| 203 | SUBROUTINE mm_diagnostics(dt,aer_s_prec,aer_f_prec,aer_s_w,aer_f_w,aer_s_flux,aer_f_flux,rc_sph,rc_fra,& |
|---|
| 204 | ccn_prec,ice_prec,cld_w,ccn_flux,ice_fluxes,rcld,gas_sat,n_rate,g_rate) |
|---|
| 205 | !! Get various diagnostic fields of the microphysics. |
|---|
| 206 | !! |
|---|
| 207 | !! @note |
|---|
| 208 | !! Fluxes values are always negative as they account for sedimentation fluxes. They are set as |
|---|
| 209 | !! vector and are ordered from __GROUND__ to __TOP__. |
|---|
| 210 | !! |
|---|
| 211 | !! @note |
|---|
| 212 | !! Precipitation are always positive and defined in kg.m-2.s-1. |
|---|
| 213 | !! |
|---|
| 214 | ! Physics timestep (s). |
|---|
| 215 | REAL(kind=8), INTENT(IN) :: dt |
|---|
| 216 | |
|---|
| 217 | ! Haze related: |
|---|
| 218 | !~~~~~~~~~~~~~~ |
|---|
| 219 | ! Aerosol precipitation (kg.m-2.s-1). |
|---|
| 220 | REAL(kind=mm_wp), INTENT(inout), OPTIONAL :: aer_s_prec |
|---|
| 221 | REAL(kind=mm_wp), INTENT(inout), OPTIONAL :: aer_f_prec |
|---|
| 222 | ! Aerosol settling velocity (m.s-1). |
|---|
| 223 | REAL(kind=mm_wp), INTENT(inout), DIMENSION(:), OPTIONAL :: aer_s_w |
|---|
| 224 | REAL(kind=mm_wp), INTENT(inout), DIMENSION(:), OPTIONAL :: aer_f_w |
|---|
| 225 | ! Aerosol mass flux (kg.m-2.s-1). |
|---|
| 226 | REAL(kind=mm_wp), INTENT(inout), DIMENSION(:), OPTIONAL :: aer_s_flux |
|---|
| 227 | REAL(kind=mm_wp), INTENT(inout), DIMENSION(:), OPTIONAL :: aer_f_flux |
|---|
| 228 | ! Aerosol characteristic radius (m). |
|---|
| 229 | REAL(kind=mm_wp), INTENT(inout), DIMENSION(:), OPTIONAL :: rc_sph |
|---|
| 230 | REAL(kind=mm_wp), INTENT(inout), DIMENSION(:), OPTIONAL :: rc_fra |
|---|
| 231 | |
|---|
| 232 | ! Clouds related: |
|---|
| 233 | !~~~~~~~~~~~~~~~~ |
|---|
| 234 | ! Cloud condensation nuclei precipitation (kg.m-2.s-1). |
|---|
| 235 | REAL(kind=mm_wp), INTENT(inout), OPTIONAL :: ccn_prec |
|---|
| 236 | ! Ice precipitation (kg.m-2.s-1). |
|---|
| 237 | REAL(kind=mm_wp), INTENT(inout), DIMENSION(:), OPTIONAL :: ice_prec |
|---|
| 238 | ! Cloud drop (CCN + ices) settling velocity (m.s-1). |
|---|
| 239 | REAL(kind=mm_wp), INTENT(inout), DIMENSION(:), OPTIONAL :: cld_w |
|---|
| 240 | ! Cloud condensation nuclei mass flux (kg.m-2.s-1). |
|---|
| 241 | REAL(kind=mm_wp), INTENT(inout), DIMENSION(:), OPTIONAL :: ccn_flux |
|---|
| 242 | ! Ice mass fluxes (kg.m-2.s-1). |
|---|
| 243 | REAL(kind=mm_wp), INTENT(inout), DIMENSION(:,:), OPTIONAL :: ice_fluxes |
|---|
| 244 | ! Cloud drop (CCN + ices) radius (m). |
|---|
| 245 | REAL(kind=mm_wp), INTENT(inout), DIMENSION(:), OPTIONAL :: rcld |
|---|
| 246 | ! Cloud related diagnostics. |
|---|
| 247 | REAL(kind=mm_wp), INTENT(inout), DIMENSION(:,:), OPTIONAL :: gas_sat ! Condensible gaz saturation ratios. |
|---|
| 248 | REAL(kind=mm_wp), INTENT(inout), DIMENSION(:,:), OPTIONAL :: n_rate ! Condensible gaz nucleation rates (m-2.s-1). |
|---|
| 249 | REAL(kind=mm_wp), INTENT(inout), DIMENSION(:,:), OPTIONAL :: g_rate ! Ice growth rates (m2.s-1). |
|---|
| 250 | |
|---|
| 251 | ! Haze related: |
|---|
| 252 | !~~~~~~~~~~~~~~ |
|---|
| 253 | IF (PRESENT(aer_s_prec)) aer_s_prec = ABS(mm_aers_prec) / dt |
|---|
| 254 | IF (PRESENT(aer_f_prec)) aer_f_prec = ABS(mm_aerf_prec) / dt |
|---|
| 255 | IF (PRESENT(aer_s_w)) aer_s_w = -mm_m3as_vsed(mm_nla:1:-1) |
|---|
| 256 | IF (PRESENT(aer_f_w)) aer_f_w = -mm_m3af_vsed(mm_nla:1:-1) |
|---|
| 257 | IF (PRESENT(aer_s_flux)) aer_s_flux = -mm_aer_s_flux(mm_nla:1:-1) |
|---|
| 258 | IF (PRESENT(aer_f_flux)) aer_f_flux = -mm_aer_f_flux(mm_nla:1:-1) |
|---|
| 259 | |
|---|
| 260 | IF (mm_ini_aer) THEN |
|---|
| 261 | IF (PRESENT(rc_sph)) rc_sph = mm_rcs(mm_nla:1:-1) |
|---|
| 262 | IF (PRESENT(rc_fra)) rc_fra = mm_rcf(mm_nla:1:-1) |
|---|
| 263 | ELSE |
|---|
| 264 | IF (PRESENT(rc_sph)) rc_sph = 0._mm_wp |
|---|
| 265 | IF (PRESENT(rc_fra)) rc_fra = 0._mm_wp |
|---|
| 266 | ENDIF |
|---|
| 267 | |
|---|
| 268 | ! Clouds related: |
|---|
| 269 | !~~~~~~~~~~~~~~~~ |
|---|
| 270 | IF (mm_call_clouds) THEN |
|---|
| 271 | IF (PRESENT(ccn_prec)) ccn_prec = ABS(mm_ccn_prec) / dt |
|---|
| 272 | IF (PRESENT(ice_prec)) ice_prec = ABS(mm_ice_prec) / dt |
|---|
| 273 | IF (PRESENT(cld_w)) cld_w = mm_cld_vsed(mm_nla:1:-1) |
|---|
| 274 | IF (PRESENT(ccn_flux)) ccn_flux = mm_ccn_flux(mm_nla:1:-1) |
|---|
| 275 | IF (PRESENT(ice_fluxes)) ice_fluxes = mm_ice_fluxes(mm_nla:1:-1,:) |
|---|
| 276 | IF (PRESENT(rcld)) rcld = mm_drad(mm_nla:1:-1) |
|---|
| 277 | IF (PRESENT(gas_sat)) gas_sat = mm_gas_sat(mm_nla:1:-1,:) |
|---|
| 278 | IF (PRESENT(n_rate)) n_rate = mm_nrate(mm_nla:1:-1,:) |
|---|
| 279 | IF (PRESENT(g_rate)) g_rate = mm_grate(mm_nla:1:-1,:) |
|---|
| 280 | ELSE |
|---|
| 281 | IF (PRESENT(ccn_prec)) ccn_prec = 0._mm_wp |
|---|
| 282 | IF (PRESENT(ice_prec)) ice_prec = 0._mm_wp |
|---|
| 283 | IF (PRESENT(cld_w)) cld_w = 0._mm_wp |
|---|
| 284 | IF (PRESENT(ccn_flux)) ccn_flux = 0._mm_wp |
|---|
| 285 | IF (PRESENT(ice_fluxes)) ice_fluxes = 0._mm_wp |
|---|
| 286 | IF (PRESENT(rcld)) rcld = 0._mm_wp |
|---|
| 287 | IF (PRESENT(gas_sat)) gas_sat = 0._mm_wp |
|---|
| 288 | IF (PRESENT(n_rate)) n_rate = 0._mm_wp |
|---|
| 289 | IF (PRESENT(g_rate)) g_rate = 0._mm_wp |
|---|
| 290 | ENDIF ! end of mm_call_clouds |
|---|
| 291 | |
|---|
| 292 | END SUBROUTINE mm_diagnostics |
|---|
| 293 | |
|---|
| 294 | END MODULE MP2M_MICROPHYSICS |
|---|