source: trunk/LMDZ.TITAN/libf/muphytitan/mm_methods.f90 @ 1793

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

Making Titan's hazy again, part I
+ Added the source folder libf/muphytitan which contains

YAMMS ( Titan's microphysical model ) from J. Burgalat

+ Modif. compilation files linked to this change
JVO

File size: 16.4 KB
Line 
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_methods.f90
35!! summary: Model miscellaneous methods module.
36!! author: J. Burgalat
37!! date: 2013-2015
38
39MODULE MM_METHODS
40  !! Model miscellaneous methods module.
41  !!
42  !! The module contains miscellaneous methods used either in the haze and clouds parts of the model.
43  !!
44  !! All thermodynamic functions related to cloud microphysics (i.e. [[mm_methods(module):mm_lHeatX(interface)]],
45  !! [[mm_methods(module):mm_sigX(interface)]] and [[mm_methods(module):mm_psatX(interface)]]) compute related equations
46  !! from \cite{reid1986}. A version of the book is freely available [here](http://f3.tiera.ru/3/Chemistry/References/Poling%20B.E.,%20Prausnitz%20J.M.,%20O'Connell%20J.P.%20The%20Properties%20of%20Gases%20and%20Liquids%20(5ed.,%20MGH,%202000)(ISBN%200070116822)(803s).pdf).
47  !!
48  !! The module defines the following functions/subroutines/interfaces:
49  !!
50  !! | name        | description
51  !! | :---------: | :-------------------------------------------------------------------------------------
52  !! | mm_lheatx   | Compute latent heat released
53  !! | mm_sigx     | Compute surface tension
54  !! | mm_psatx    | Compute saturation vapor pressure
55  !! | mm_qsatx    | Compute saturation mass mixing ratio
56  !! | mm_fshape   | Compute shape factor
57  !! | mm_lambda_g | Compute air mean free path
58  !! | mm_eta_g    | Compute air viscosity
59  !! | mm_get_kfm  | Compute the thermodynamic pre-factor of coagulation kernel in free-molecular regime
60  !! | mm_get_kco  | Compute the thermodynamic pre-factor of coagulation kernel in continuous regime
61  USE MM_MPREC
62  USE MM_GLOBALS
63  USE MM_INTERFACES
64  IMPLICIT NONE
65
66  PRIVATE
67
68  PUBLIC  :: mm_sigX, mm_LheatX, mm_psatX, mm_qsatx, mm_fshape, &
69             mm_get_kco, mm_get_kfm, mm_eta_g, mm_lambda_g
70
71  ! ---- INTERFACES
72
73  !> Interface to surface tension computation functions.
74  !!
75  !! The method computes the surface tension of a given specie at given temperature(s).
76  !!
77  !! ```fortran
78  !! FUNCTION mm_sigX(temp,xESP)
79  !! ```
80  !!
81  !! __xESP__ must always be given as a scalar. If __temp__ is given as a vector, then the method
82  !! computes the result for all the temperatures and returns a vector of same size than __temp__.
83  INTERFACE mm_sigX
84    MODULE PROCEDURE sigx_sc,sigx_ve
85  END INTERFACE
86
87  !> Interface to Latent heat computation functions.
88  !!
89  !! The method computes the latent heat released of a given specie at given temperature(s).
90  !!
91  !! ```fortran
92  !! FUNCTION mm_lheatX(temp,xESP)
93  !! ```
94  !!
95  !! __xESP__ must always be given as a scalar. If __temp__ is given as a vector, then the method
96  !! computes the result for all the temperatures and returns a vector of same size than __temp__.
97  INTERFACE mm_LheatX
98    MODULE PROCEDURE lheatx_sc,lheatx_ve
99  END INTERFACE
100
101  !> Interface to saturation vapor pressure computation functions.
102  !!
103  !! ```fortran
104  !! FUNCTION mm_psatX(temp,xESP)
105  !! ```
106  !!
107  !! The method computes the saturation vapor pressure of a given specie at given temperature(s).
108  !!
109  !! __xESP__ must always be given as a scalar. If __temp__ is given as a vector, then the method
110  !! computes the result for all the temperatures and returns a vector of same size than __temp__.
111  INTERFACE mm_psatX
112    MODULE PROCEDURE psatx_sc,psatx_ve
113  END INTERFACE
114
115  !! Interface to saturation mass mixing ratio computaiton functions.
116  !!
117  !! The method computes the mass mixing ratio at saturation of a given specie at given temperature(s)
118  !! and pressure level(s).
119  !!
120  !! ```fortran
121  !! FUNCTION mm_qsatX(temp,pres,xESP)
122  !! ```
123  !!
124  !! __xESP__ must always be given as a scalar. If __temp__ and __pres__  are given as a vector (of same
125  !! size !), then the method computes the result for each couple of (temperature, pressure) and returns
126  !! a vector of same size than __temp__.
127  INTERFACE mm_qsatx
128    MODULE PROCEDURE qsatx_sc,qsatx_ve
129  END INTERFACE
130
131  !> Interface to shape factor computation functions.
132  !!
133  !! The method computes the shape factor for the heterogeneous nucleation.
134  !!
135  !! ```fortran
136  !! FUNCTION mm_fshape(m,x)
137  !! ```
138  !!
139  !! Where __m__ is cosine of the contact angle and __x__ the curvature radius. __m__ must always be
140  !! given as a scalar. If __x__ is given as a vector, then the method compute the result for each
141  !! value of __x__ and and returns a vector of same size than __x__.
142  INTERFACE mm_fshape
143    MODULE PROCEDURE fshape_sc,fshape_ve
144  END INTERFACE
145
146  CONTAINS
147
148  FUNCTION fshape_sc(cost,rap) RESULT(res)
149    !! Get the shape factor of a ccn (scalar).
150    !!
151    !! The method computes the shape factor for the heterogeneous nucleation on a fractal particle.
152    !! Details about the shape factor can be found in \cite{prup1978}.
153    REAL(kind=mm_wp), INTENT(in) :: cost !! Cosine of the contact angle.
154    REAL(kind=mm_wp), INTENT(in) :: rap  !! Curvature radius (\(r_{particle}/r^{*}\)).
155    REAL(kind=mm_wp) :: res              !! Shape factor value.
156    REAL(kind=mm_wp) :: phi,a,b,c
157    IF (rap > 3000._mm_wp) THEN
158      res = ((2._mm_wp+cost)*(1._mm_wp-cost)**2)/4._mm_wp
159    ELSE
160      phi = dsqrt(1._mm_wp-2._mm_wp*cost*rap+rap**2)
161      a = 1._mm_wp + ( (1._mm_wp-cost*rap)/phi )**3
162      b = (rap**3) * (2._mm_wp-3._mm_wp*(rap-cost)/phi+((rap-cost)/phi)**3)
163      c = 3._mm_wp * cost * (rap**2) * ((rap-cost)/phi-1._mm_wp)
164      res = 0.5_mm_wp*(a+b+c)
165    ENDIF
166    RETURN
167  END FUNCTION fshape_sc
168
169  FUNCTION fshape_ve(cost,rap) RESULT(res)
170    !! Get the shape factor of a ccn (vector).
171    !!
172    !! See [[mm_methods(module):fshape_sc(function)]].
173    REAL(kind=mm_wp), INTENT(in)               :: cost !! Cosine of the contact angle.
174    REAL(kind=mm_wp), INTENT(in), DIMENSION(:) :: rap  !! Curvature radii (\(r_{particle}/r^{*}\)).
175    REAL(kind=mm_wp), DIMENSION(SIZE(rap)) :: res      !! Shape factor value.
176    REAL(kind=mm_wp), DIMENSION(SIZE(rap)) :: phi,a,b,c
177    WHERE(rap > 3000._mm_wp)
178      res = ((2._mm_wp+cost)*(1._mm_wp-cost)**2)/4._mm_wp
179    ELSEWHERE
180      phi = dsqrt(1._mm_wp-2._mm_wp*cost*rap+rap**2)
181      a = 1._mm_wp + ((1._mm_wp-cost*rap)/phi )**3
182      b = (rap**3)*(2._mm_wp-3._mm_wp*(rap-cost)/phi+((rap-cost)/phi)**3)
183      c = 3._mm_wp*cost*(rap**2)*((rap-cost)/phi-1._mm_wp)
184      res = 0.5_mm_wp*(a+b+c)
185    ENDWHERE
186    RETURN
187  END FUNCTION fshape_ve
188
189  FUNCTION LHeatX_sc(temp,xESP) RESULT(res)
190    !! Compute latent heat of a given specie at given temperature (scalar).
191    !!
192    !! The method computes the latent heat equation as given in \cite{reid1986} p. 220 (eq. 7-9.4).
193    IMPLICIT NONE
194    ! - DUMMY
195    REAL(kind=mm_wp), INTENT(in) :: temp !! temperature (K).
196    TYPE(mm_esp), INTENT(in)     :: xESP !! Specie properties.
197    REAL(kind=mm_wp) :: res              !! Latent heat of given specie at given temperature (\(J.kg^{-1}\)).
198    REAL(kind=mm_wp) :: ftm
199    ftm=MIN(1._mm_wp-temp/xESP%tc,1.e-3_mm_wp)
200    res = mm_rgas*xESP%tc*(7.08_mm_wp*ftm**0.354_mm_wp+10.95_mm_wp*xESP%w*ftm**0.456_mm_wp)/xESP%masmol
201  END FUNCTION LHeatX_sc
202   
203  FUNCTION LHeatX_ve(temp,xESP) RESULT(res)
204    !! Compute latent heat of a given specie at given temperature (vector).
205    !!
206    !! See [[mm_methods(module):lheatx_sc(function)]].
207    REAL(kind=mm_wp), INTENT(in), DIMENSION(:) :: temp !! temperatures (K).
208    TYPE(mm_esp), INTENT(in)                   :: xESP !! Specie properties.
209    REAL(kind=mm_wp), DIMENSION(SIZE(temp))    :: res  !! Latent heat of given specie at given temperatures (\(J.kg^{-1}\)).
210    REAL(kind=mm_wp) :: ftm
211    INTEGER      :: i
212    DO i=1,SIZE(temp)
213      ftm=MIN(1._mm_wp-temp(i)/xESP%tc,1.e-3_mm_wp)
214      res(i) = mm_rgas*xESP%tc*(7.08_mm_wp*ftm**0.354_mm_wp+10.95_mm_wp*xESP%w*ftm**0.456_mm_wp) / &
215               xESP%masmol
216    ENDDO
217  END FUNCTION LHeatX_ve
218
219  FUNCTION sigX_sc(temp,xESP) RESULT(res)
220    !! Get the surface tension between a given specie and the air (scalar).
221    !!
222    !! The method computes the surface tension equation as given in \cite{reid1986} p. 637 (eq. 12-3.6).
223    REAL(kind=mm_wp), INTENT(in) :: temp !! temperature (K).
224    TYPE(mm_esp), INTENT(in)     :: xESP !! Specie properties.
225    REAL(kind=mm_wp) :: res              !! Surface tension (\(N.m^{-1}\)).
226    REAL(kind=mm_wp) :: tr,tbr,sig
227    tr=MIN(temp/xESP%tc,0.99_mm_wp)
228    tbr=xESP%tb/xESP%tc
229    sig = 0.1196_mm_wp*(1._mm_wp+(tbr*dlog(xESP%pc/1.01325_mm_wp))/(1._mm_wp-tbr))-0.279_mm_wp
230    sig = xESP%pc**(2._mm_wp/3._mm_wp)*xESP%tc**(1._mm_wp/3._mm_wp)*sig*(1._mm_wp-tr)**(11._mm_wp/9._mm_wp)
231    res = sig*1e3_mm_wp ! dyn/cm2 -> N/m
232  END FUNCTION sigX_sc
233 
234  FUNCTION sigX_ve(temp,xESP) RESULT(res)
235    !! Get the surface tension between a given specie and the air (vector).
236    !!
237    !! See [[mm_methods(module):sigx_sc(function)]].
238    REAL(kind=mm_wp), INTENT(in), DIMENSION(:) :: temp !! temperatures (K).
239    TYPE(mm_esp), INTENT(in)                   :: xESP !! Specie properties.
240    REAL(kind=mm_wp), DIMENSION(SIZE(temp)) :: res     !! Surface tensions (\(N.m^{-1}\)).
241    INTEGER      :: i
242    REAL(kind=mm_wp) :: tr,tbr,sig
243    tbr = xESP%tb/xESP%tc
244    sig = 0.1196_mm_wp*(1._mm_wp+(tbr*dlog(xESP%pc/1.01325_mm_wp))/(1._mm_wp-tbr))-0.279_mm_wp
245    DO i=1,SIZE(temp)
246      tr     = MIN(temp(i)/xESP%tc,0.99_mm_wp)
247      sig    = xESP%pc**(2._mm_wp/3._mm_wp)*xESP%tc**(1._mm_wp/3._mm_wp)*sig*(1._mm_wp-tr)**(11._mm_wp/9._mm_wp)
248      res(i) = sig*1e3_mm_wp ! dyn/cm2 -> N/m
249    ENDDO
250  END FUNCTION sigX_ve
251
252  FUNCTION psatX_sc(temp,xESP) RESULT(res)
253    !! Get saturation vapor pressure for a given specie at given temperature (scalar).
254    !!
255    !! The method computes the saturation vapor pressure equation given in \cite{reid1986} p. 657 (eq. 1).
256    !!
257    !! @warning
258    !! This subroutine accounts for a specific Titan feature:
259    !! If __xESP__ corresponds to \(CH_{4}\), the saturation vapor presure is multiplied by 0.85
260    !! to take into account its dissolution in \(N_{2}\).
261    REAL(kind=mm_wp), INTENT(in) :: temp !! Temperature (K).
262    TYPE(mm_esp), INTENT(in)     :: xESP !! Specie properties.
263    REAL(kind=mm_wp) :: res              !! Saturation vapor pressure (Pa).
264    REAL(kind=mm_wp) :: x,qsat
265    x = 1._mm_wp-temp/xESP%tc
266    IF (x > 0._mm_wp) THEN
267      qsat = (1._mm_wp-x)**(-1) * &
268      (xESP%a_sat*x + xESP%b_sat*x**1.5_mm_wp + xESP%c_sat*x**3 + xESP%d_sat*x**6)
269    ELSE
270      qsat = XESP%a_sat*x/abs(1._mm_wp-x)     ! approx for  t > tc
271    ENDIF
272    !  Special case : ch4 : x0.85 (dissolution in N2)
273    IF (xESP%name == "ch4") THEN
274      res = xESP%pc*dexp(qsat)*0.85_mm_wp
275    ELSE
276      res = xESP%pc*dexp(qsat)
277    ENDIF
278    ! now convert bar to Pa
279    res = res * 1e5_mm_wp
280  END FUNCTION psatX_sc
281
282  FUNCTION psatX_ve(temp,xESP) RESULT(res)
283    !! Get saturation vapor pressure for a given specie at given temperature (vector).
284    !!
285    !! See [[mm_methods(module):psatX_sc(function)]].
286    REAL(kind=mm_wp), INTENT(in), DIMENSION(:) :: temp !! Temperatures (K).
287    TYPE(mm_esp), INTENT(in)                   :: xESP !! Specie properties.
288    REAL(kind=mm_wp), DIMENSION(SIZE(temp)) :: res     !! Saturation vapor pressures (Pa).
289    INTEGER      :: i
290    REAL(kind=mm_wp) :: x,qsat
291    DO i=1, SIZE(temp)
292      x = 1._mm_wp-temp(i)/xESP%tc
293      IF (x > 0._mm_wp) THEN
294        qsat = (1._mm_wp-x)**(-1) * &
295        (xESP%a_sat*x + xESP%b_sat*x**1.5_mm_wp + xESP%c_sat*x**3 + xESP%d_sat*x**6)
296      ELSE
297        qsat = XESP%a_sat*x/abs(1._mm_wp-x)     ! approx for  t > tc
298      ENDIF
299      res(i) = xESP%pc*dexp(qsat)
300      !  Peculiar case : ch4 : x0.85 (dissolution in N2)
301      IF (xESP%name == "ch4") res(i) = res(i)* 0.85_mm_wp
302    ENDDO
303    res = res * 1e5_mm_wp  ! bar -> Pa
304  END FUNCTION psatX_ve
305
306  FUNCTION qsatX_sc(temp,pres,xESP) RESULT(res)
307    !! Get the mass mixing ratio of a given specie at saturation (scalar).
308    REAL(kind=mm_wp), INTENT(in) :: temp !! Temperature (K).
309    REAL(kind=mm_wp), INTENT(in) :: pres !! Pressure level (Pa).
310    TYPE(mm_esp), INTENT(in)    :: xESP  !! Specie properties.
311    REAL(kind=mm_wp) :: res              !! Mass mixing ratio of the specie.
312    REAL(kind=mm_wp) :: x,psat
313    psat = mm_psatX(temp,xESP)
314    res = (psat / pres) * xESP%fmol2fmas
315  END FUNCTION qsatX_sc
316
317  FUNCTION qsatX_ve(temp,pres,xESP) RESULT(res)
318    !! Get the mass mixing ratio of a given specie at saturation (vector).
319    REAL(kind=mm_wp), INTENT(in), DIMENSION(:) :: temp !! Temperatures (K).
320    REAL(kind=mm_wp), INTENT(in), DIMENSION(:) :: pres !! Pressure levels (Pa).
321    TYPE(mm_esp), INTENT(in)                   :: xESP !! Specie properties.
322    REAL(kind=mm_wp), DIMENSION(SIZE(temp)) :: res     !! Mass mixing ratios of the specie.
323    REAL(kind=mm_wp), DIMENSION(SIZE(temp)) :: psat
324    psat = mm_psatX(temp,xESP)
325    res = (psat / pres) * xESP%fmol2fmas
326  END FUNCTION qsatX_ve
327
328  ELEMENTAL FUNCTION mm_get_kco(t) RESULT(res)
329    !! Get the Continuous regime thermodynamics pre-factor of the coagulation kernel.
330    REAL(kind=mm_wp), INTENT(in) :: t !! Temperature (K).
331    REAL(kind=mm_wp) :: res           !! Continuous regime thermodynamics pre-factor (\(m^{3}.s^{-1}\)).
332    res = 2._mm_wp*mm_kboltz*t / (3._mm_wp*mm_eta_g(t))
333    RETURN
334  END FUNCTION mm_get_kco
335
336  ELEMENTAL FUNCTION mm_get_kfm(t) RESULT(res)
337    !! Get the Free Molecular regime thermodynamics pre-factor of the coagulation kernel.
338    REAL(kind=mm_wp), INTENT(in) :: t !! Temperature (K).
339    REAL(kind=mm_wp) :: res           !! Free Molecular regime thermodynamics pre-factor (\(m^{5/2}.s^{-1}\)).
340    res = (6._mm_wp*mm_kboltz*t/mm_rhoaer)**(0.5_mm_wp)
341    RETURN
342  END FUNCTION mm_get_kfm
343
344!  ELEMENTAL FUNCTION mm_eta_g(t) RESULT (res)
345!    !! Get the air viscosity at a given temperature.
346!    !!
347!    !! The function computes the air viscosity at temperature __t__ using Sutherland method.
348!    REAL(kind=mm_wp), INTENT(in) :: t !! Temperature (K).
349!    REAL(kind=mm_wp) :: res           !! Air viscosity at given temperature (\(Pa.s^{-1}\)).
350!    REAL (kind=mm_wp), PARAMETER :: eta0 = 1.75e-5_mm_wp, &
351!                                    tsut = 109._mm_wp,    &
352!                                    tref = 293._mm_wp
353!    res = eta0 *dsqrt(t/tref)*(1._mm_wp+tsut/tref)/(1._mm_wp+tsut/t)
354!    RETURN
355!  END FUNCTION mm_eta_g
356!
357!  ELEMENTAL FUNCTION mm_lambda_g(t,p) RESULT(res)
358!    !! Get the air mean free path at given temperature and pressure.
359!    !!
360!    !! The method computes the air mean free path:
361!    !!
362!    !! $$ \lambda_{g} = \dfrac{k_{b}T}{4\sqrt{2}\pi r_{a}^2 P} $$
363!    !!
364!    !! Where \(\lambda_{g}\), is the air mean free path, \(k_{b}\) the Boltzmann constant, T the
365!    !! temperature, P the pressure level and \(r_{a}\) the radius of an _air molecule_.
366!    REAL(kind=mm_wp), INTENT(in) :: t !! Temperature (K).
367!    REAL(kind=mm_wp), INTENT(in) :: p !! Pressure level (Pa).
368!    REAL(kind=mm_wp) :: res           !! Air mean free path (m).
369!    res = mm_kboltz*t/(4._mm_wp*dsqrt(2._mm_wp)*mm_pi*(mm_air_rad**2)*p)
370!    RETURN
371!  END FUNCTION mm_lambda_g
372
373END MODULE MM_METHODS
Note: See TracBrowser for help on using the repository browser.