source: trunk/LMDZ.TITAN/libf/muphytitan/mm_haze.f90 @ 1862

Last change on this file since 1862 was 1819, checked in by jvatant, 7 years ago

Commit various bugs leading to negative tracer tendencies
Also deleted some useless cfg files
--JVO

File size: 38.1 KB
RevLine 
[1793]1! Copyright 2013-2015 Université de Reims Champagne-Ardenne
2! Contributor: J. Burgalat (GSMA, URCA)
3! email of the author : jeremie.burgalat@univ-reims.fr
4!
5! This software is a computer program whose purpose is to compute
6! microphysics processes using a two-moments scheme.
7!
8! This library is governed by the CeCILL-B license under French law and
9! abiding by the rules of distribution of free software.  You can  use,
10! modify and/ or redistribute the software under the terms of the CeCILL-B
11! license as circulated by CEA, CNRS and INRIA at the following URL
12! "http://www.cecill.info".
13!
14! As a counterpart to the access to the source code and  rights to copy,
15! modify and redistribute granted by the license, users are provided only
16! with a limited warranty  and the software's author,  the holder of the
17! economic rights,  and the successive licensors  have only  limited
18! liability.
19!
20! In this respect, the user's attention is drawn to the risks associated
21! with loading,  using,  modifying and/or developing or reproducing the
22! software by the user in light of its specific status of free software,
23! that may mean  that it is complicated to manipulate,  and  that  also
24! therefore means  that it is reserved for developers  and  experienced
25! professionals having in-depth computer knowledge. Users are therefore
26! encouraged to load and test the software's suitability as regards their
27! requirements in conditions enabling the security of their systems and/or
28! data to be ensured and,  more generally, to use and operate it in the
29! same conditions as regards security.
30!
31! The fact that you are presently reading this means that you have had
32! knowledge of the CeCILL-B license and that you accept its terms.
33
34!! file: mm_haze.f90
35!! summary: Haze microphysics module.
36!! author: J. Burgalat
37!! date: 2013-2015
38
39MODULE MM_HAZE
40  !! Haze microphysics module.
41  !!
42  !! This module contains all definitions of the microphysics processes related to aerosols:
43  !!
44  !! - [coagulation](page/haze.html#coagulation)
45  !! - [sedimentation](page/haze.html#sedimentation)
46  !! - [production](page/haze.html#production)
47  !!
48  !! @note
49  !! The production function is specific to Titan, where aerosols are created above the detached
50  !! haze layer. No other source is taken into account.  This process is controled by two parameters,
51  !! the pressure level of production and the production rate. Then both M0 and M3 of the aerosols
52  !! distribution are updated in the production zone by addition of the production rate along a
53  !! gaussian shape.
54  !!
55  !! @note
56  !! The interface methods always uses the global variables defined in [[mm_globals(module)]] when
57  !! values (any kind, temperature, pressure, moments...) over the vertical grid are required.
58  !!
59  !! @warning
60  !! The tendencies returned by the method are always defined over the vertical grid from __TOP__
61  !! to __GROUND__.
62  !!
63  !! @todo
64  !! Modify tests on tendencies vectors to get sure that allocation is done:
65  !! Currently, we assume the compiler handles automatic allocation of arrays.
66  USE MM_MPREC
67  USE MM_GLOBALS
68  USE MM_INTERFACES
69  USE MM_METHODS
70  IMPLICIT NONE
71
72  PRIVATE
73
74  PUBLIC :: mm_haze_microphysics, mm_haze_coagulation, mm_haze_sedimentation, &
75            mm_haze_production
76
77  CONTAINS
78
79  !============================================================================
80  ! HAZE MICROPHYSICS INTERFACE SUBROUTINE
81  !============================================================================
82
83  SUBROUTINE mm_haze_microphysics(dm0a_s,dm3a_s,dm0a_f,dm3a_f)
84    !! Get the evolution of moments tracers through haze microphysics processes.
85    !!
86    !! The subroutine is a wrapper to the haze microphysics methods. It computes the tendencies
87    !! of moments tracers for coagulation, sedimentation and production processes for the
88    !! atmospheric column.
89    REAL(kind=mm_wp), INTENT(out), DIMENSION(:) :: dm0a_s
90      !! Tendency of the 0th order moment of the spherical mode distribution (\(m^{-3}\)).
91    REAL(kind=mm_wp), INTENT(out), DIMENSION(:) :: dm3a_s
92      !! Tendency of the 3rd order moment of the spherical mode distribution (\(m^{3}.m^{-3}\)).
93    REAL(kind=mm_wp), INTENT(out), DIMENSION(:) :: dm0a_f
94      !! Tendency of the 0th order moment of the fractal mode distribution (\(m^{-3}\)).
95    REAL(kind=mm_wp), INTENT(out), DIMENSION(:) :: dm3a_f
96      !! Tendency of the 3rd order moment of the fractal mode distribution (\(m^{3}.m^{-3}\)).
97    REAL(kind=mm_wp), DIMENSION(:), ALLOCATABLE :: zdm0as
98    REAL(kind=mm_wp), DIMENSION(:), ALLOCATABLE :: zdm3as
99    REAL(kind=mm_wp), DIMENSION(:), ALLOCATABLE :: zdm0af
100    REAL(kind=mm_wp), DIMENSION(:), ALLOCATABLE :: zdm3af
101
102    dm0a_s = 0._mm_wp ; dm3a_s = 0._mm_wp ; dm0a_f = 0._mm_wp ; dm3a_f = 0._mm_wp
103
104    ALLOCATE(zdm0as(mm_nla),zdm3as(mm_nla),zdm0af(mm_nla),zdm3af(mm_nla))
105    zdm0as(1:mm_nla) = 0._mm_wp
106    zdm3as(1:mm_nla) = 0._mm_wp
107    zdm0af(1:mm_nla) = 0._mm_wp
108    zdm3af(1:mm_nla) = 0._mm_wp
109
110    IF (mm_w_haze_coag) THEN
111      ! Calls coagulation
112      call mm_haze_coagulation(dm0a_s,dm3a_s,dm0a_f,dm3a_f)
113    ENDIF
114
115    IF (mm_w_haze_sed) THEN
116      ! Calls sedimentation
117      call mm_haze_sedimentation(zdm0as,zdm3as,zdm0af,zdm3af)
118
119      ! Computes precipitations
120      mm_aer_prec = SUM(zdm3as*mm_dzlev) + SUM(zdm3af*mm_dzlev)
121
122      ! Updates tendencies
123      dm0a_s=dm0a_s+zdm0as ; dm3a_s=dm3a_s+zdm3as
124      dm0a_f=dm0a_f+zdm0af ; dm3a_f=dm3a_f+zdm3af
125    ENDIF
126
127    IF (mm_w_haze_prod) THEN
128      call mm_haze_production(zdm0as,zdm3as)
129      ! We only produce fractal aerosols
130      dm0a_s=dm0a_s+zdm0as ; dm3a_s=dm3a_s+zdm3as
131    ENDIF
132
133    RETURN
134  END SUBROUTINE mm_haze_microphysics
135
136
137  !============================================================================
138  ! COAGULATION PROCESS RELATED METHODS
139  !============================================================================
140 
141  SUBROUTINE mm_haze_coagulation(dM0s,dM3s,dM0f,dM3f)
142    !! Get the evolution of the aerosols moments vertical column due to coagulation process.
143    !!
144    !! This is main method of the coagulation process:
145    !!
146    !! 1. Computes gamma pre-factor for each parts of the coagulation equation(s)
147    !! 2. Applies the electic correction on the gamma pre-factor
148    !! 3. Computes the specific flow regime "kernels"
149    !! 4. Computes the harmonic mean of the kernels
150    !! 5. Finally computes the tendencies of the moments.
151    !!
152    !! All arguments are assumed vectors of __N__ elements where __N__ is the total number of
153    !! vertical __layers__.
154    !!
155    !! @note
156    !! The method uses directly the global variables related to the vertical atmospheric structure
157    !! stored in [[mm_globals(module)]]. Consequently they must be updated before calling the subroutine.
158    !!
159    !! @bug
160    !! If the transfert probabilities are set to 1 for the two flow regimes (pco and pfm),
161    !! a floating point exception occured (i.e. a NaN) as we perform a division by zero
162    !!
163    !! @todo
164    !! Get rid of the fu\*\*\*\* STOP statement...
165    REAL(kind=mm_wp), INTENT(out), DIMENSION(:) :: dM0s
166      !! Tendency of the 0th order moment of the spherical size-distribution over a time step (\(m^{-3}\)).
167    REAL(kind=mm_wp), INTENT(out), DIMENSION(:) :: dM3s
168      !! Tendency of the 3rd order moment of the spherical size-distribution (\(m^{3}.m^{-3}\)).
169    REAL(kind=mm_wp), INTENT(out), DIMENSION(:) :: dM0f
170      !! Tendency of the 0th order moment of the fractal size-distribution over a time step (\(m^{-3}\)).
171    REAL(kind=mm_wp), INTENT(out), DIMENSION(:) :: dM3f
172      !! Tendency of the 3rd order moment of the fractal size-distribution over a time step (\(m^{3}.m^{-3}\)).
173    REAL(kind=mm_wp), DIMENSION(:), ALLOCATABLE :: c_kco,c_kfm,c_slf,tmp, &
174                                                   kco,kfm,pco,pfm,mq
175    REAL(kind=mm_wp), DIMENSION(:), ALLOCATABLE :: a_ss,a_sf,b_ss,b_ff,c_ss,c_sf
176    INTEGER                                     :: i
177
178    IF (mm_coag_choice < 0 .OR. mm_coag_choice > mm_coag_ss+mm_coag_sf+mm_coag_ff) &
179      STOP "invalid choice for coagulation mode interaction activation"
180
181    ! Alloctes local arrays
182    ALLOCATE(kco(mm_nla),kfm(mm_nla),c_slf(mm_nla), &
183             c_kco(mm_nla),c_kfm(mm_nla),mq(mm_nla), &
184             pco(mm_nla),pfm(mm_nla))
185    ALLOCATE(a_ss(mm_nla),a_sf(mm_nla), &
186             b_ss(mm_nla),b_ff(mm_nla), &
187             c_ss(mm_nla),c_sf(mm_nla))
188             
189    a_ss(:) = 0._mm_wp ; a_sf(:) = 0._mm_wp
190    b_ss(:) = 0._mm_wp ; b_ff(:) = 0._mm_wp
191    c_ss(:) = 0._mm_wp ; c_sf(:) = 0._mm_wp
192
193    ! gets kco, kfm pre-factors
194    c_kco(:) = mm_get_kco(mm_temp) ; c_kfm(:) = mm_get_kfm(mm_temp)
195    ! get slf (slip-flow factor)
196    c_slf(:) = mm_akn * mm_lambda_g(mm_temp,mm_play)
197
198    DO i=1,mm_nla
199      ! SS interactions
200      IF (mm_rcs(i) > mm_rc_min .AND. IAND(mm_coag_choice,mm_coag_ss) /= 0) THEN
201        ! compute probability for M0/CO and M0/FM (resp.)
202        pco(i) = mm_ps2s(mm_rcs(i),0,0,mm_temp(i),mm_play(i))
203        pfm(i) = mm_ps2s(mm_rcs(i),0,1,mm_temp(i),mm_play(i))
204        ! (A_SS_CO x A_SS_FM) / (A_SS_CO + A_SS_FM)
205        kco(i) = g0ssco(mm_rcs(i),c_slf(i),c_kco(i))
206        kfm(i) = g0ssfm(mm_rcs(i),c_kfm(i))
207        IF (kco(i)*(pco(i)-2._mm_wp)+kfm(i)*(pfm(i)-2._mm_wp) /=0) THEN
208          a_ss(i) = (kco(i)*(pco(i)-2._mm_wp)*kfm(i)*(pfm(i)-2._mm_wp))/(kco(i)*(pco(i)-2._mm_wp)+kfm(i)*(pfm(i)-2._mm_wp))
209        ENDIF
210        ! (B_SS_CO x B_SS_FM) / (B_SS_CO + B_SS_FM)
211        kco(i) = kco(i) * (1._mm_wp-pco(i)) ; kfm(i) = kfm(i) * (1._mm_wp-pfm(i))
212        IF (kco(i) + kfm(i) /= 0._mm_wp) THEN
213          b_ss(i) = kco(i)*kfm(i)/(kco(i)+kfm(i))
214        ENDIF
215        ! compute and apply eletric charge correction for M0/SS interactions
216        mq(i) = mm_qmean(mm_rcs(i),mm_rcs(i),0,'SS',mm_temp(i),mm_play(i))
217
218        a_ss(i) = a_ss(i) * mq(i)
219        b_ss(i) = b_ss(i) * mq(i)
220        kco(i) = 0._mm_wp ; kfm(i) = 0._mm_wp ; mq(i) = 1._mm_wp
221        ! compute probability for M3/CO and M3/FM (resp.)
222        pco(i) = mm_ps2s(mm_rcs(i),3,0,mm_temp(i),mm_play(i))
223        pfm(i) = mm_ps2s(mm_rcs(i),3,1,mm_temp(i),mm_play(i))
224        ! (C_SS_CO x C_SS_FM) / (C_SS_CO + C_SS_FM)
225        kco(i) = g3ssco(mm_rcs(i),c_slf(i),c_kco(i))*(pco(i)-1._mm_wp)
226        kfm(i) = g3ssfm(mm_rcs(i),c_kfm(i))*(pfm(i)-1._mm_wp)
227        IF (kco(i) + kfm(i) /= 0._mm_wp) THEN
228          c_ss(i) = (kco(i)*kfm(i))/(kco(i)+kfm(i))
229        ENDIF
230        IF (b_ss(i) <= 0._mm_wp) c_ss(i) = 0._mm_wp
231        ! compute and apply eletric charge correction for M3/SS interactions
232        mq(i) = mm_qmean(mm_rcs(i),mm_rcs(i),3,'SS',mm_temp(i),mm_play(i))
233        c_ss(i) = c_ss(i) * mq(i)
234      ENDIF
235      kco(i) = 0._mm_wp ; kfm(i) = 0._mm_wp ; mq(i) = 1._mm_wp
236
237      ! SF interactions
238      IF (mm_rcs(i) > mm_rc_min .AND. mm_rcf(i) > mm_rc_min .AND. IAND(mm_coag_choice,mm_coag_sf) /= 0) THEN
239        ! (A_SF_CO x A_SF_FM) / (A_SF_CO + A_SF_FM)
240        kco(i) = g0sfco(mm_rcs(i),mm_rcf(i),c_slf(i),c_kco(i))
241        kfm(i) = g0sffm(mm_rcs(i),mm_rcf(i),c_kfm(i))
242        IF(kco(i)+kfm(i) /= 0._mm_wp) THEN
243          a_sf(i) = (kco(i)*kfm(i))/(kco(i)+kfm(i))
244        ENDIF
245        ! compute and apply eletric charge correction for M0/SF interactions
246        mq(i) = mm_qmean(mm_rcs(i),mm_rcf(i),0,'SF',mm_temp(i),mm_play(i))
247        a_sf(i) = a_sf(i) * mq(i)
248        ! (C_SF_CO x C_SF_FM) / (C_SF_CO + C_SF_FM)
249        kco(i) = g3sfco(mm_rcs(i),mm_rcf(i),c_slf(i),c_kco(i))
250        kfm(i) = g3sffm(mm_rcs(i),mm_rcf(i),c_kfm(i))
251        IF (kco(i)+kfm(i) /= 0._mm_wp) THEN
252          c_sf(i) = (kco(i)*kfm(i))/(kco(i)+kfm(i))
253        ENDIF
254        ! compute and apply eletric charge correction for M3/SF interactions
255        mq(i) = mm_qmean(mm_rcs(i),mm_rcf(i),3,'SF',mm_temp(i),mm_play(i))
256        c_sf(i) = c_sf(i) * mq(i)
257      ENDIF
258      kco(i) = 0._mm_wp ; kfm(i) = 0._mm_wp ; mq(i) = 1._mm_wp
259      ! FF interactions
260      IF(mm_rcf(i) > mm_rc_min .AND. IAND(mm_coag_choice,mm_coag_sf) /= 0) THEN
261        ! (B_FF_CO x B_FF_FM) / (B_FF_CO + B_FF_FM)
262        kco(i) = g0ffco(mm_rcf(i),c_slf(i),c_kco(i))
263        kfm(i) = g0fffm(mm_rcf(i),c_kfm(i))
264        b_ff(i) = (kco(i)*kfm(i))/(kco(i)+kfm(i))
265        ! compute and apply eletric charge correction for M0/FF interactions
266        mq(i) = mm_qmean(mm_rcf(i),mm_rcf(i),0,'FF',mm_temp(i),mm_play(i))
267        b_ff(i) = b_ff(i) * mq(i)
268      ENDIF
269    ENDDO
270   
271    DEALLOCATE(kco,kfm,c_kco,c_kfm,pco,pfm,c_slf)
272
273    ! Now we will use the kharm two by two to compute :
274    ! dm_0_S/mm_dt = kharm(1) * m_0_S^2 - kharm(2) * m_0_S * m_0_F
275    ! dm_0_F/mm_dt = kharm(3) * m_0_S^2 - kharm(4) * m_0_F^2
276    ! dm_3_S/mm_dt = kharm(5) * m_3_S^2 - kharm(6) * m_3_S * m_3_F
277    ! ... and finally :
278    ! dm_3_F/mm_dt = - dm_3_S/mm_dt
279    !
280    ! We use a (semi) implicit scheme : when X appears as square we set one X
281    ! at t+1, the other a t
282    ALLOCATE(tmp(mm_nla))
283    ! --- dm0s
284    tmp(:) = mm_dt*(a_ss*mm_m0aer_s - a_sf*mm_m0aer_f)
285    dm0s(:) =  mm_m0aer_s * (tmp/(1._mm_wp - tmp))
286    ! --- dm0f
287    tmp(:) = b_ff*mm_dt*mm_m0aer_f
288    dm0f(:) = (b_ss*mm_dt*mm_m0aer_s**2 - tmp*mm_m0aer_f)/(1._mm_wp + tmp)
289    ! --- dm3s
290    tmp(:) = mm_dt*(c_ss*mm_m3aer_s - c_sf*mm_m3aer_f)
291    dm3s(:) =  mm_m3aer_s * (tmp/(1._mm_wp - tmp))
292    ! --- dmm3f
293    dm3f(:) = -dm3s
294
295    ! Deallocates memory explicitly ... another obsolete statement :)
296    DEALLOCATE(a_ss,a_sf,b_ss,b_ff,c_ss,c_sf,tmp)
297
298    ! Time to do something else !
299    RETURN
300  END SUBROUTINE mm_haze_coagulation
301
302  ELEMENTAL FUNCTION g0ssco(rcs,c_slf,c_kco) RESULT(res)
303    !! Get &gamma; pre-factor for the 0th order moment with SS interactions in the continuous flow regime.
304    !!
305    !! @note
306    !! If __rcs__ is 0, the function returns 0.
307    REAL(kind=mm_wp), INTENT(in) :: rcs   !! Characteristic radius of the spherical size-distribution.
308    REAL(kind=mm_wp), INTENT(in) :: c_slf !! Slip-Flow correction pre-factor.
309    REAL(kind=mm_wp), INTENT(in) :: c_kco !! Thermodynamic continuous flow regime pre-factor.
310    REAL(kind=mm_wp) :: res               !! &gamma; coagulation kernel pre-factor.
311    REAL(kind=mm_wp) :: a1, a2, a3
312    res = 0._mm_wp ; IF (rcs <= 0._mm_wp) RETURN
313    ! computes mm_alpha coefficients
314    a1=mm_alpha_s(1._mm_wp) ; a2=mm_alpha_s(-1._mm_wp) ; a3=mm_alpha_s(-2._mm_wp)
315    ! Computes gamma pre-factor
316    res = (1._mm_wp + a1*a2 + c_slf/rcs *(a2+a1*a3))*c_kco
317    RETURN
318  END FUNCTION g0ssco
319
320  ELEMENTAL FUNCTION g0sfco(rcs,rcf,c_slf,c_kco) RESULT(res)
321    !! Get &gamma; pre-factor for the 0th order moment with SF interactions in the continuous flow regime.
322    !!
323    !! @note
324    !! If __rcs__ or __rcf__ is 0, the function returns 0.
325    REAL(kind=mm_wp), INTENT(in) :: rcs   !! Characteristic radius of the spherical size-distribution.
326    REAL(kind=mm_wp), INTENT(in) :: rcf   !! Characteristic radius of the fractal size-distribution.
327    REAL(kind=mm_wp), INTENT(in) :: c_slf !! Slip-Flow correction pre-factor.
328    REAL(kind=mm_wp), INTENT(in) :: c_kco !! Thermodynamic continuous flow regime pre-factor.
329    REAL(kind=mm_wp) :: res               !! &gamma; coagulation kernel pre-factor.
330    REAL(kind=mm_wp) :: a1, a2, a3, a4, a5, a6, e, rcff
331    res = 0._mm_wp ; IF (rcs <= 0._mm_wp .OR. rcf <= 0._mm_wp) RETURN
332    e=3._mm_wp/mm_df ; rcff = rcf**e*mm_rb2ra
333    ! computes mm_alpha coefficients
334    a1=mm_alpha_s(1._mm_wp)   ; a2=mm_alpha_f(-e)   ; a3=mm_alpha_f(e)
335    a4=mm_alpha_s(-1._mm_wp) ; a5=mm_alpha_s(-2._mm_wp) ; a6=mm_alpha_f(-2._mm_wp*e)
336    ! Computes gamma pre-factor
337    res = c_kco*( 2._mm_wp + a1*a2*rcs/rcff + a4*a3*rcff/rcs + c_slf*( a4/rcs + &
338                         a2/rcff + a5*a3*rcff/rcs**2 + a1*a6*rcs/rcff**2))
339    RETURN
340  END FUNCTION g0sfco
341
342  ELEMENTAL FUNCTION g0ffco(rcf,c_slf,c_kco) RESULT(res)
343    !! Get &gamma; pre-factor for the 0th order moment with FF interactions in the continuous flow regime.
344    !!
345    !! @note
346    !! If __rcf__ is 0, the function returns 0.
347    REAL(kind=mm_wp), INTENT(in) :: rcf   !! Characteristic radius of the fractal size-distribution.
348    REAL(kind=mm_wp), INTENT(in) :: c_slf !! Slip-Flow correction pre-factor.
349    REAL(kind=mm_wp), INTENT(in) :: c_kco !! Thermodynamic continuous flow regime pre-factor.
350    REAL(kind=mm_wp) :: res               !! &gamma; coagulation kernel pre-factor.
351    REAL(kind=mm_wp) :: a1, a2, a3, e, rcff
352    res = 0._mm_wp ; IF (rcf <= 0._mm_wp) RETURN
353    ! computes mm_alpha coefficients
354    e = 3._mm_wp/mm_df ; rcff = rcf**e*mm_rb2ra
355    a1=mm_alpha_f(e) ; a2=mm_alpha_f(-e) ; a3=mm_alpha_s(-2._mm_wp*e)
356    ! Computes gamma pre-factor
357    res = (1._mm_wp + a1*a2 + c_slf/rcff *(a2+a1*a3))*c_kco
358    RETURN
359  END FUNCTION g0ffco
360
361  ELEMENTAL FUNCTION g3ssco(rcs, c_slf, c_kco) RESULT(res)
362    !! Get &gamma; pre-factor for the 3rd order moment with SS interactions in the continuous flow regime.
363    !!
364    !! @note
365    !! If __rcs__ is 0, the function returns 0.
366    REAL(kind=mm_wp), INTENT(in) :: rcs   !! Characteristic radius of the spherical size-distribution.
367    REAL(kind=mm_wp), INTENT(in) :: c_slf !! Slip-Flow correction pre-factor.
368    REAL(kind=mm_wp), INTENT(in) :: c_kco !! Thermodynamic continuous flow regime pre-factor.
369    REAL(kind=mm_wp) :: res               !! &gamma; coagulation kernel pre-factor.
370    REAL(kind=mm_wp) :: a1, a2, a3, a4, a5, a6
371    res = 0._mm_wp ; IF (rcs <= 0._mm_wp) RETURN
372    ! computes mm_alpha coefficients
373    a1=mm_alpha_s(3._mm_wp) ; a2=mm_alpha_s(2._mm_wp)  ; a3=mm_alpha_s(1._mm_wp)
374    a4=mm_alpha_s(4._mm_wp) ; a5=mm_alpha_s(-1._mm_wp) ; a6=mm_alpha_s(-2._mm_wp)
375
376    ! Computes gamma pre-factor
377    res = (2._mm_wp*a1 + a2*a3 + a4*a5 + c_slf/rcs*(a3**2 + a4*a6 + a1*a5 + a2))* &
378          c_kco/(a1**2*rcs**3)
379    RETURN
380  END FUNCTION g3ssco
381
382  ELEMENTAL FUNCTION g3sfco(rcs, rcf, c_slf, c_kco) RESULT(res)
383    !! Get &gamma; pre-factor for the 3rd order moment with SF interactions in the continuous flow regime.
384    !!
385    !! @note
386    !! If __rcs__ or __rcf__ is 0, the function returns 0.
387    REAL(kind=mm_wp), INTENT(in) :: rcs   !! Characteristic radius of the spherical size-distribution.
388    REAL(kind=mm_wp), INTENT(in) :: rcf   !! Characteristic radius of the fractal size-distribution.
389    REAL(kind=mm_wp), INTENT(in) :: c_slf !! Slip-Flow correction pre-factor.
390    REAL(kind=mm_wp), INTENT(in) :: c_kco !! Thermodynamic continuous flow regime pre-factor.
391    REAL(kind=mm_wp) :: res               !! &gamma; coagulation kernel pre-factor.
392    REAL(kind=mm_wp) :: a1, a2, a3, a4, a5, a6, a7, a8, e, rcff
393    res = 0._mm_wp ; IF (rcs <= 0._mm_wp .OR. rcf <= 0._mm_wp) RETURN
394    ! computes mm_alpha coefficients
395    e=3._mm_wp/mm_df ; rcff = rcf**e*mm_rb2ra
396    a1=mm_alpha_s(3._mm_wp)    ; a2=mm_alpha_s(4._mm_wp) ; a3=mm_alpha_f(-e)
397    a4=mm_alpha_s(2._mm_wp)    ; a5=mm_alpha_f(e)    ; a6=mm_alpha_s(1._mm_wp)
398    a7=mm_alpha_f(-2._mm_wp*e) ; a8=mm_alpha_f(3._mm_wp)
399    ! Computes gamma pre-factor
400    res = (2._mm_wp*a1*rcs**3 + a2*rcs**4*a3/rcff + a4*rcs**2*a5*rcff + &
401                c_slf *( a4*rcs**2 + a1*rcs**3*a3/rcff + a6*rcs*a5*rcff + &
402                a2*rcs**4*a7/rcff**2))* c_kco/(a1*a8*(rcs*rcf)**3)
403    RETURN
404  END FUNCTION g3sfco
405
406  ELEMENTAL FUNCTION g0ssfm(rcs, c_kfm) RESULT(res)
407    !! Get &gamma; pre-factor for the 0th order moment with SS interactions in the Free Molecular flow regime.
408    !!
409    !! @note
410    !! If __rcs__ is 0, the function returns 0.
411    REAL(kind=mm_wp), INTENT(in) :: rcs   !! Characteristic radius of the spherical size-distribution.
412    REAL(kind=mm_wp), INTENT(in) :: c_kfm !! Thermodynamic free molecular flow regime pre-factor.
413    REAL(kind=mm_wp) :: res               !! &gamma; coagulation kernel pre-factor.
414    REAL(kind=mm_wp) :: a1, a2, a3, a4, a5
415    res = 0._mm_wp ; IF (rcs <= 0._mm_wp) RETURN
416    ! computes mm_alpha coefficients
417    a1=mm_alpha_s(0.5_mm_wp) ; a2=mm_alpha_s(1._mm_wp) ; a3=mm_alpha_s(-0.5_mm_wp)
418    a4=mm_alpha_s(2._mm_wp)   ; a5=mm_alpha_s(-1.5_mm_wp)
419    ! Computes gamma pre-factor
420    res = (a1 + 2._mm_wp*a2*a3 + a4*a5)*rcs**0.5_mm_wp*mm_get_btk(1,0)*c_kfm
421    RETURN
422  END FUNCTION g0ssfm
423
424  ELEMENTAL FUNCTION g0sffm(rcs, rcf, c_kfm) RESULT(res)
425    !> Get &gamma; pre-factor for the 0th order moment with SF interactions in the Free Molecular flow regime.
426    !!
427    !! @note
428    !! If __rcs__ or __rcf__ is 0, the function returns 0.
429    REAL(kind=mm_wp), INTENT(in) :: rcs   !! Characteristic radius of the spherical size-distribution.
430    REAL(kind=mm_wp), INTENT(in) :: rcf   !! Characteristic radius of the fractal size-distribution.
431    REAL(kind=mm_wp), INTENT(in) :: c_kfm !! Thermodynamic free molecular flow regime pre-factor.
432    REAL(kind=mm_wp) :: res               !! &gamma; coagulation kernel pre-factor.
433    REAL(kind=mm_wp) :: a1, a2, a3, a4, a5, a6, a7, a8, a9, a10
434    REAL(kind=mm_wp) :: e1, e2, e3, e4
435    REAL(kind=mm_wp) :: rcff1, rcff2, rcff3, rcff4
436    res = 0._mm_wp ; IF (rcs <= 0._mm_wp .OR. rcf <= 0._mm_wp) RETURN
437    ! computes mm_alpha coefficients
438    e1 = 3._mm_wp/mm_df
439    e2 = 6._mm_wp/mm_df
440    e3 = (6._mm_wp-3._mm_wp*mm_df)/(2._mm_wp*mm_df)
441    e4 = (12._mm_wp-3._mm_wp*mm_df)/(2._mm_wp*mm_df)
442
443    rcff1 = mm_rb2ra * rcf**e1
444    rcff2 = rcff1**2
445    rcff3 = mm_rb2ra * rcf**e3
446    rcff4 = mm_rb2ra**2 * rcf**e4
447
448    a1=mm_alpha_s(0.5_mm_wp)  ; a2=mm_alpha_s(-0.5_mm_wp) ; a3=mm_alpha_f(e1)
449    a4=mm_alpha_s(-1.5_mm_wp) ; a5=mm_alpha_f(e2)      ; a6=mm_alpha_s(2._mm_wp)
450    a7=mm_alpha_f(-1.5_mm_wp) ; a8=mm_alpha_s(1._mm_wp)   ; a9=mm_alpha_f(e3)
451    a10=mm_alpha_f(e4)
452
453    ! Computes gamma pre-factor
454    res = (a1*rcs**0.5_mm_wp + 2._mm_wp*rcff1*a2*a3/rcs**0.5_mm_wp + a4*a5*rcff2/rcs**1.5_mm_wp + &
455           a6*a7*rcs**2/rcf**1.5_mm_wp + 2._mm_wp*a8*a9*rcs*rcff3 + a10*rcff4 &
456          )*mm_get_btk(4,0)*c_kfm
457    RETURN
458  END FUNCTION g0sffm
459
460  ELEMENTAL FUNCTION g0fffm(rcf, c_kfm) RESULT(res)
461    !! Get &gamma; pre-factor for the 0th order moment with FF interactions in the Free Molecular flow regime.
462    !!
463    !! @note
464    !! If __rcf__ is 0, the function returns 0.
465    REAL(kind=mm_wp), INTENT(in) :: rcf   !! Characteristic radius of the fractal size-distribution.
466    REAL(kind=mm_wp), INTENT(in) :: c_kfm !! Thermodynamic free molecular flow regime pre-factor.
467    REAL(kind=mm_wp) :: res               !! &gamma; coagulation kernel pre-factor.
468    REAL(kind=mm_wp) :: a1, a2, a3, a4, a5, e1, e2, e3, rcff
469    res = 0._mm_wp ; IF (rcf <= 0._mm_wp) RETURN
470    ! computes mm_alpha coefficients
471    e1=3._mm_wp/mm_df ; e2=(6_mm_wp-3._mm_wp*mm_df)/(2._mm_wp*mm_df)
472    e3=(12._mm_wp-3._mm_wp*mm_df)/(2._mm_wp*mm_df)
473    rcff=mm_rb2ra**2*rcf**e3
474    a1=mm_alpha_f(e3)      ; a2=mm_alpha_f(e1) ; a3=mm_alpha_f(e2)
475    a4=mm_alpha_f(-1.5_mm_wp) ; a5=mm_alpha_f(2._mm_wp*e1)
476    ! Computes gamma pre-factor
477    res = (a1 + 2._mm_wp*a2*a3 + a4*a5)*rcff*mm_get_btk(3,0)*c_kfm
478    RETURN
479  END FUNCTION g0fffm
480
481  ELEMENTAL FUNCTION g3ssfm(rcs, c_kfm) RESULT(res)
482    !! Get &gamma; pre-factor for the 3rd order moment with SS interactions in the Free Molecular flow regime.
483    !!
484    !! @note
485    !! If __rcs__ is 0, the function returns 0.
486    REAL(kind=mm_wp), INTENT(in) :: rcs   !! Characteristic radius of the spherical size-distribution.
487    REAL(kind=mm_wp), INTENT(in) :: c_kfm !! Thermodynamic free molecular flow regime pre-factor.
488    REAL(kind=mm_wp) :: res               !! &gamma; coagulation kernel pre-factor.
489    REAL(kind=mm_wp) :: a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11
490    res = 0._mm_wp ; IF (rcs <= 0._mm_wp) RETURN
491    ! computes mm_alpha coefficients
492    a1=mm_alpha_s(3.5_mm_wp)  ; a2=mm_alpha_s(1._mm_wp)  ; a3=mm_alpha_s(2.5_mm_wp)
493    a4=mm_alpha_s(2._mm_wp)   ; a5=mm_alpha_s(1.5_mm_wp) ; a6=mm_alpha_s(5._mm_wp)
494    a7=mm_alpha_s(-1.5_mm_wp) ; a8=mm_alpha_s(4._mm_wp)  ; a9=mm_alpha_s(-0.5_mm_wp)
495    a10=mm_alpha_s(3._mm_wp) ; a11=mm_alpha_s(0.5_mm_wp)
496    ! Computes gamma pre-factor
497    res = (a1 + 2._mm_wp*a2*a3 + a4*a5 + a6*a7 + 2._mm_wp*a8*a9 + a10*a11) &
498          *mm_get_btk(1,3)*c_kfm/(a10**2*rcs**2.5_mm_wp)
499    RETURN
500  END FUNCTION g3ssfm
501
502  ELEMENTAL FUNCTION g3sffm(rcs, rcf, c_kfm) RESULT(res)
503    !! Get &gamma; pre-factor for the 3rd order moment with SF interactions in the Free Molecular flow regime.
504    !!
505    !! @note
506    !! If __rcs__ or __rcf__ is 0, the function returns 0.
507    REAL(kind=mm_wp), INTENT(in) :: rcs   !! Characteristic radius of the spherical size-distribution.
508    REAL(kind=mm_wp), INTENT(in) :: rcf   !! Characteristic radius of the fractal size-distribution.
509    REAL(kind=mm_wp), INTENT(in) :: c_kfm !! Thermodynamic free molecular flow regime pre-factor.
510    REAL(kind=mm_wp) :: res               !! &gamma; coagulation kernel pre-factor.
511    REAL(kind=mm_wp) :: a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12
512    REAL(kind=mm_wp) :: e1, e2, e3, rcff1, rcff2, rcff3
513    res = 0._mm_wp ; IF (rcs <= 0._mm_wp .OR. rcf <= 0._mm_wp) RETURN
514    ! computes mm_alpha coefficients
515    e1=3._mm_wp/mm_df
516    e2=(6._mm_wp-3._mm_wp*mm_df)/(2._mm_wp*mm_df)
517    e3=(12._mm_wp-3._mm_wp*mm_df)/(2._mm_wp*mm_df)
518    rcff1=mm_rb2ra*rcf**e1 ; rcff2=mm_rb2ra*rcf**e2 ; rcff3=mm_rb2ra**2*rcf**e3
519    a1=mm_alpha_s(3.5_mm_wp)  ; a2=mm_alpha_s(2.5_mm_wp)   ; a3=mm_alpha_f(e1)
520    a4=mm_alpha_s(1.5_mm_wp)  ; a5=mm_alpha_f(2._mm_wp*e1) ; a6=mm_alpha_s(5._mm_wp)
521    a7=mm_alpha_f(-1.5_mm_wp) ; a8=mm_alpha_s(4._mm_wp)    ; a9=mm_alpha_f(e2)
522    a10=mm_alpha_s(3._mm_wp)  ; a11=mm_alpha_f(e3)         ; a12=mm_alpha_f(3._mm_wp)
523    ! Computes gamma pre-factor
524    res = (a1*rcs**3.5_mm_wp + 2._mm_wp*a2*a3*rcs**2.5_mm_wp*rcff1 + a4*a5*rcs**1.5_mm_wp*rcff1**2 + &
525          a6*a7*rcs**5/rcf**1.5_mm_wp + 2._mm_wp*a8*a9*rcs**4*rcff2 + &
526          a10*a11*rcs**3*rcff3)*mm_get_btk(4,3)*c_kfm/(a10*a12*(rcs*rcf)**3)
527    RETURN
528  END FUNCTION g3sffm
529
530  !============================================================================
531  ! SEDIMENTATION PROCESS RELATED METHODS
532  !============================================================================
533 
534  SUBROUTINE mm_haze_sedimentation(dm0s,dm3s,dm0f,dm3f)
535    !! Interface to sedimentation algorithm.
536    !!
537    !! The subroutine computes the evolution of each moment of the aerosols tracers
538    !! through sedimentation process and returns their tendencies for a timestep.
539    REAL(kind=mm_wp), INTENT(out), DIMENSION(:) :: dm0s
540      !! Tendency of the 0th order moment of the spherical mode (\(m^{-3}\)).
541    REAL(kind=mm_wp), INTENT(out), DIMENSION(:) :: dm3s
542      !! Tendency of the 3rd order moment of the spherical mode (\(m^{3}.m^{-3}\)).
543    REAL(kind=mm_wp), INTENT(out), DIMENSION(:) :: dm0f
544      !! Tendency of the 0th order moment of the fractal mode (\(m^{-3}\)).
545    REAL(kind=mm_wp), INTENT(out), DIMENSION(:) :: dm3f
546      !! Tendency of the 3rd order moment of the fractal mode (\(m^{3}.m^{-3}\)).
547    REAL(kind=mm_wp), DIMENSION(:), ALLOCATABLE :: ft,fdcor,wth
548    REAL(kind=mm_wp)                            :: m,n,p
549    REAL(kind=mm_wp), PARAMETER                 :: fac = 4._mm_wp/3._mm_wp * mm_pi
550
551    ALLOCATE(ft(mm_nle),wth(mm_nle),fdcor(mm_nle))
552
553    !mm_aer_s_flux(:) = 0._mm_wp ; mm_aer_f_flux(:) = 0._mm_wp
554    IF (mm_wsed_m0) THEN
555      ! Spherical particles
556      ! M0
557      call get_weff(mm_m0aer_s,0._mm_wp,3._mm_wp,mm_rcs,mm_dt,mm_alpha_s,wth,fdcor)
558      ft(:) = wth(:) * fdcor(:)  ; mm_m0as_vsed(:) = ft(1:mm_nla)
559      call let_me_fall_in_peace(mm_m0aer_s,-ft,mm_dt,dm0s)
560      ! M3
561      mm_m3as_vsed(:) = ft(1:mm_nla)
562      call let_me_fall_in_peace(mm_m3aer_s,-ft,mm_dt,dm3s)
563      ! get mass flux
564      mm_aer_s_flux(:) = fac * mm_rhoaer * ft(2:) * mm_m3aer_s
565      ! Fractal particles
566      ! M0
567      call get_weff(mm_m0aer_f,0._mm_wp,mm_df,mm_rcf,mm_dt,mm_alpha_f,wth,fdcor)
568      ft(:) = wth(:) * fdcor(:)  ; mm_m0af_vsed(:) = ft(1:mm_nla)
569      call let_me_fall_in_peace(mm_m0aer_f,-ft,mm_dt,dm0f)
570      ! M3
571      mm_m3af_vsed(:) = ft(1:mm_nla)
572      call let_me_fall_in_peace(mm_m3aer_f,-ft,mm_dt,dm3f)
573      ! get mass flux
574      mm_aer_f_flux(:) = fac * mm_rhoaer * ft(2:) * mm_m3aer_f
575    ELSEIF (mm_wsed_m3) THEN
576      ! Spherical particles
577      ! M3
578      call get_weff(mm_m3aer_s,3._mm_wp,3._mm_wp,mm_rcs,mm_dt,mm_alpha_s,wth,fdcor)
579      ft(:) = wth(:) * fdcor(:)  ; mm_m3as_vsed(:) = ft(1:mm_nla)
580      call let_me_fall_in_peace(mm_m3aer_s,-ft,mm_dt,dm3s)
581      ! get mass flux
582      mm_aer_s_flux(:) = fac * mm_rhoaer * ft(2:) * mm_m3aer_s
583      ! M0
584      mm_m0as_vsed(:) = ft(1:mm_nla)
585      call let_me_fall_in_peace(mm_m0aer_s,-ft,mm_dt,dm0s)
586      ! Fractal particles
587      ! M3
588      call get_weff(mm_m3aer_f,3._mm_wp,mm_df,mm_rcf,mm_dt,mm_alpha_f,wth,fdcor)
589      ft(:) = wth(:) * fdcor(:)  ; mm_m3af_vsed(:) = ft(1:mm_nla)
590      call let_me_fall_in_peace(mm_m3aer_f,-ft,mm_dt,dm3f)
591      ! get mass flux
592      mm_aer_f_flux(:) = fac * mm_rhoaer * ft(2:) * mm_m3aer_f
593      ! M0
594      mm_m0af_vsed(:) = ft(1:mm_nla)
595      call let_me_fall_in_peace(mm_m0aer_f,-ft,mm_dt,dm0f)
596    ELSE
597      ! Spherical particles
598      ! M0
599      call get_weff(mm_m0aer_s,0._mm_wp,3._mm_wp,mm_rcs,mm_dt,mm_alpha_s,wth,fdcor)
600      ft(:) = wth(:) * fdcor(:)  ; mm_m0as_vsed(:) = ft(1:mm_nla)
601      call let_me_fall_in_peace(mm_m0aer_s,-ft,mm_dt,dm0s)
602      ! M3
603      call get_weff(mm_m3aer_s,3._mm_wp,3._mm_wp,mm_rcs,mm_dt,mm_alpha_s,wth,fdcor)
604      ft(:) = wth(:) * fdcor(:)  ; mm_m3as_vsed(:) = ft(1:mm_nla)
605      call let_me_fall_in_peace(mm_m3aer_s,-ft,mm_dt,dm3s)
606      ! get mass flux
607      mm_aer_s_flux(:) = fac * mm_rhoaer * ft(2:) * mm_m3aer_s
608      ! Fractal particles
609      ! M0
610      call get_weff(mm_m0aer_f,0._mm_wp,mm_df,mm_rcf,mm_dt,mm_alpha_f,wth,fdcor)
611      ft(:) = wth(:) * fdcor(:)  ; mm_m0af_vsed(:) = ft(1:mm_nla)
612      call let_me_fall_in_peace(mm_m0aer_f,-ft,mm_dt,dm0f)
613      ! M3
614      call get_weff(mm_m3aer_f,3._mm_wp,mm_df,mm_rcf,mm_dt,mm_alpha_f,wth,fdcor)
615      ft(:) = wth(:) * fdcor(:)  ; mm_m3af_vsed(:) = ft(1:mm_nla)
616      call let_me_fall_in_peace(mm_m3aer_f,-ft,mm_dt,dm3f)
617      ! get mass flux
618      mm_aer_f_flux(:) = fac * mm_rhoaer * ft(2:) * mm_m3aer_f
619    ENDIF
620    DEALLOCATE(ft,wth,fdcor)
621    RETURN
622  END SUBROUTINE mm_haze_sedimentation
623
624  SUBROUTINE let_me_fall_in_peace(mk,ft,dt,dmk)
625    !! Compute the tendency of the moment through sedimentation process.
626    !!
627    !!
628    !! The method computes the time evolution of the \(k^{th}\) order moment through sedimentation:
629    !!
630    !! $$ \dfrac{dM_{k}}{dt} = \dfrac{\Phi_{k}}{dz} $$
631    !!
632    !! The equation is resolved using a [Crank-Nicolson algorithm](http://en.wikipedia.org/wiki/Crank-Nicolson_method).
633    !!
634    !! Sedimentation algorithm is quite messy. It appeals to the dark side of the Force and uses evil black magic spells
635    !! from ancient times. It is based on \cite{toon1988b,fiadeiro1977,turco1979} and is an update of the algorithm
636    !! originally implemented in the LMDZ-Titan 2D GCM.
637    REAL(kind=mm_wp), INTENT(in), DIMENSION(:)  :: mk  !! \(k^{th}\) order moment to sediment (in \(m^{k}\)).
638    REAL(kind=mm_wp), INTENT(in)                :: dt  !! Time step (s).
639    REAL(kind=mm_wp), INTENT(in), DIMENSION(:)  :: ft  !! Downward sedimentation flux  (effective velocity of the moment).
640    REAL(kind=mm_wp), INTENT(out), DIMENSION(:) :: dmk !! Tendency of \(k^{th}\) order moment (in \(m^{k}.m^{-3}\)).
641    INTEGER                                 :: i
642    REAL(kind=mm_wp), DIMENSION(:), ALLOCATABLE :: as,bs,cs,mko
643    ALLOCATE(as(mm_nla), bs(mm_nla), cs(mm_nla), mko(mm_nla))
644    mko(1:mm_nla) = 0._mm_wp
645    cs(1:mm_nla) = ft(2:mm_nla+1) - mm_dzlay(1:mm_nla)/dt
646    IF (ANY(cs > 0._mm_wp)) THEN
647      ! implicit case
648      as(1:mm_nla) = ft(1:mm_nla)
649      bs(1:mm_nla) = -(ft(2:mm_nle)+mm_dzlay(1:mm_nla)/dt)
650      cs(1:mm_nla) = -mm_dzlay(1:mm_nla)/dt*mk(1:mm_nla)
651      ! (Tri)diagonal matrix inversion
652      mko(1) = cs(1)/bs(1)
653      DO i=2,mm_nla ; mko(i) = (cs(i)-mko(i-1)*as(i))/bs(i) ; ENDDO
654    ELSE
655      ! explicit case
656      as(1:mm_nla)=-mm_dzlay(1:mm_nla)/dt
657      bs(1:mm_nla)=-ft(1:mm_nla)
658      ! boundaries
659      mko(1)=cs(1)*mk(1)/as(1)
660      mko(mm_nla)=(bs(mm_nla)*mk(mm_nla-1)+cs(mm_nla)*mk(mm_nla))/as(mm_nla)
661      ! interior
662      mko(2:mm_nla-1)=(bs(2:mm_nla-1)*mk(1:mm_nla-2) + &
663                       cs(2:mm_nla-1)*mk(2:mm_nla-1)   &
664                      )/as(2:mm_nla-1)
665    ENDIF
666    dmk = mko - mk
667    DEALLOCATE(as,bs,cs,mko)
668    RETURN
669  END SUBROUTINE let_me_fall_in_peace
670
671  SUBROUTINE get_weff(mk,k,df,rc,dt,afun,wth,corf)
672    !! Get the effective settling velocity for aerosols moments.
673    !!
674    !! This method computes the effective settling velocity of the \(k^{th}\) order moment of aerosol
675    !! tracers. The basic settling velocity (\(v^{eff}_{M_{k}}\)) is computed using the following
676    !! equation:
677    !!
678    !! $$
679    !! \begin{eqnarray*}
680    !! \Phi^{sed}_{M_{k}} &=& \int_{0}^{\infty} n(r) r^{k} \times w(r) dr
681    !!                     == M_{k}  \times v^{eff}_{M_{k}} \\
682    !!     v^{eff}_{M_{k} &=& \dfrac{2 \rho g r_{c}^{\dfrac{3D_{f}-3}{D_{f}}}}
683    !!     {r_{m}^{D_{f}-3}/D_{f}} \times \alpha(k)} \times \left( \alpha \right(
684    !!     \frac{D_{f}(k+3)-3}{D_{f}}\left) + \dfrac{A_{kn}\lambda_{g}}{r_{c}^{
685    !!     3/D_{f}}} \alpha \right( \frac{D_{f}(k+3)-6}{D_{f}}\left)\left)
686    !! \end{eqnarray*}
687    !! $$
688    !!
689    !! \(v^{eff}_{M_{k}\) is then corrected to reduce numerical diffusion of the sedimentation algorithm
690    !! as defined in \cite{toon1988b}.
691    !!
692    !! @warning
693    !! Both __df__, __rc__ and __afun__ must be consistent with each other otherwise wrong values will
694    !! be computed.
695    REAL(kind=mm_wp), INTENT(in), DIMENSION(mm_nla)            :: mk
696      !! Moment of order __k__ (\(m^{k}.m^{-3}\)) at each layer.
697    REAL(kind=mm_wp), INTENT(in), DIMENSION(mm_nla)            :: rc
698      !! Characteristic radius associated to the moment at each layer.
699    REAL(kind=mm_wp), INTENT(in)                               :: k
700      !! The order of the moment.
701    REAL(kind=mm_wp), INTENT(in)                               :: df
702      !! Fractal dimension of the aersols.
703    REAL(kind=mm_wp), INTENT(in)                               :: dt
704      !! Time step (s).
705    REAL(kind=mm_wp), INTENT(out), DIMENSION(mm_nle)           :: wth
706      !! Theoretical Settling velocity at each vertical __levels__ (\( wth \times corf = weff\)).
707    REAL(kind=mm_wp), INTENT(out), DIMENSION(mm_nle), OPTIONAL :: corf
708      !! _Fiadero_ correction factor applied to the theoretical settling velocity at each vertical __levels__.
709    INTERFACE
710      FUNCTION afun(order)
711        !! Inter-moment relation function (see [[mm_interfaces(module):mm_alpha_s(interface)]]).
712        IMPORT mm_wp
713        REAL(kind=mm_wp), INTENT(in) :: order !! Order of the moment.
714        REAL(kind=mm_wp) :: afun              !! Alpha value.
715      END FUNCTION afun
716    END INTERFACE
717    INTEGER                             :: i
718    REAL(kind=mm_wp)                    :: af1,af2,ar1,ar2
719    REAL(kind=mm_wp)                    :: csto,cslf,ratio,wdt,dzb
720    REAL(kind=mm_wp)                    :: rb2ra
721    REAL(kind=mm_wp), DIMENSION(mm_nle) :: zcorf
722    ! ------------------
723   
724    wth(:) = 0._mm_wp ; zcorf(:) = 1._mm_wp
725
726    ar1 = (3._mm_wp*df -3._mm_wp)/df    ; ar2 = (3._mm_wp*df -6._mm_wp)/df
727    af1 = (df*(k+3._mm_wp)-3._mm_wp)/df ; af2 = (df*(k+3._mm_wp)-6._mm_wp)/df
728    rb2ra = mm_rm**((df-3._mm_wp)/df)
729    DO i=2,mm_nla
730      IF (rc(i-1) <= 0._mm_wp) CYCLE
731      dzb = (mm_dzlay(i)+mm_dzlay(i-1))/2._mm_wp
732      csto = 2._mm_wp*mm_rhoaer*mm_effg(mm_zlev(i))/(9._mm_wp*mm_eta_g(mm_btemp(i)))
733      cslf = mm_akn * mm_lambda_g(mm_btemp(i),mm_plev(i))
734      wth(i) = - csto/(rb2ra*afun(k)) * (rc(i-1)**ar1 * afun(af1) + cslf/rb2ra * rc(i-1)**ar2 * afun(af2))
735      ! now correct velocity to reduce numerical diffusion
736      IF (.NOT.mm_no_fiadero_w) THEN
737        IF (mk(i) <= 0._mm_wp) THEN
738          ratio = mm_fiadero_max
739        ELSE
740          ratio = MAX(MIN(mk(i-1)/mk(i),mm_fiadero_max),mm_fiadero_min)
741        ENDIF
742        ! apply correction
743        IF ((ratio <= 0.9_mm_wp .OR. ratio >= 1.1_mm_wp) .AND. wth(i) /= 0._mm_wp) THEN
744          wdt = wth(i)*dt
[1819]745          ! bugfix: max exponential arg to 30)
746          zcorf(i) = dzb/wdt * (exp(MIN(30._mm_wp,-wdt*log(ratio)/dzb))-1._mm_wp) / (1._mm_wp-ratio)
747          !zcorf(i) = dzb/wdt * (exp(-wdt*log(ratio)/dzb)-1._mm_wp) / (1._mm_wp-ratio)
[1793]748        ENDIF
749      ENDIF
750    ENDDO
751    ! last value (ground) set to first layer value: arbitrary :)
752    wth(i) = wth(i-1)
753    IF (PRESENT(corf)) corf(:) = zcorf(:)
754    RETURN
755  END SUBROUTINE get_weff
756
757  !============================================================================
758  ! PRODUCTION PROCESS RELATED METHOD
759  !============================================================================
760
761  SUBROUTINE mm_haze_production(dm0s,dm3s)
762    !! Compute the production of aerosols moments.
763    !!
764    !! The method computes the tendencies of M0 and M3 for the spherical mode through production process.
765    !! Production values are distributed along a normal law in altitude, centered  at
766    !! [[mm_globals(module):mm_p_prod(variable)]] pressure level with a fixed sigma of 20km.
767    !!
768    !! First M3 tendency is computed and M0 is retrieved using the inter-moments relation a spherical
769    !! characteristic radius set to [[mm_globals(module):mm_rc_prod(variable)]].
770    !!
771    !! If [[mm_globals(module):mm_var_prod(variable)]] is set to .true., the method computes time-dependent
772    !! tendencies using a sine wave of anuglar frequency [[mm_globals(module):mm_w_prod(variable)]]
773    REAL(kind=mm_wp), INTENT(out), DIMENSION(:) :: dm0s !! Tendency of M0 (\(m^{-3}\)).
774    REAL(kind=mm_wp), INTENT(out), DIMENSION(:) :: dm3s !! Tendency of M3 (\(m^{3}.m^{-3}\)).
775    INTEGER                     :: i
776    REAL(kind=mm_wp)            :: zprod,cprod,timefact
777    REAL(kind=mm_wp), PARAMETER :: sigz  = 20e3_mm_wp, &
778                                   fnorm = 1._mm_wp/(dsqrt(2._mm_wp*mm_pi)*sigz), &
779                                   znorm = dsqrt(2._mm_wp)*sigz
780    REAL(kind=mm_wp), SAVE      :: ctime = 0._mm_wp
781    !$OMP THREADPRIVATE (ctime)
782    zprod = -1._mm_wp
783    ! locate production altitude
784    DO i=1, mm_nla-1
785      IF (mm_plev(i) < mm_p_prod.AND.mm_plev(i+1) >= mm_p_prod) THEN
786        zprod = mm_zlay(i) ; EXIT
787      ENDIF
788    ENDDO
789    IF (zprod < 0._mm_wp) THEN
790      WRITE(*,'(a)') "cannot find aerosols production altitude"
791      call EXIT(11)
792    ENDIF
793
794    dm3s(:)= mm_tx_prod *0.75_mm_wp/mm_pi *mm_dt / mm_rhoaer / 2._mm_wp / mm_dzlev(1:mm_nla) * &
795             (erf((mm_zlev(1:mm_nla)-zprod)/znorm) - &
796             erf((mm_zlev(2:mm_nla+1)-zprod)/znorm))
797    dm0s(:) = dm3s(:)/(mm_rc_prod**3*mm_alpha_s(3._mm_wp))
798
799    IF (mm_var_prod) THEN
800      timefact = mm_d_prod*sin(mm_w_prod*ctime)+1._mm_wp
801      dm3s(:) = timefact*dm3s(:)
802      dm0s(:) = timefact*dm0s(:)
803      ctime = ctime + mm_dt
804    ENDIF
805
806
807  END SUBROUTINE mm_haze_production
808
809END MODULE MM_HAZE
Note: See TracBrowser for help on using the repository browser.