source: trunk/LMDZ.PLUTO/libf/muphypluto/mp2m_microphysics.F90 @ 3992

Last change on this file since 3992 was 3965, checked in by debatzbr, 5 weeks ago

Pluto PCM: add tendency of condensation heating rate (latent heat).
BBR

File size: 14.3 KB
Line 
1MODULE 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
294END MODULE MP2M_MICROPHYSICS 
Note: See TracBrowser for help on using the repository browser.