source: trunk/LMDZ.TITAN/libf/muphytitan/mmp_gcm.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: 15.8 KB
Line 
1MODULE MMP_GCM
2  !! Interface to YAMMS for the LMDZ GCM.
3  USE MM_LIB
4  USE CFGPARSE
5  USE DATASETS
6  IMPLICIT NONE
7
8  PUBLIC
9
10  !> Alpha function parameters.
11  !!
12  !! It stores the parameters of the inter-moments relation functions.
13  !!
14  !! The inter-moments relation function is represented by the sum of exponential
15  !! quadratic expressions:
16  !!
17  !! $$
18  !! \displaystyle \alpha(k) = \sum_{i=1}^{n} \exp\left( a_{i}\times k^{2} +
19  !! b_{i}\times k^{2} +c_{i}\right)
20  !! $$
21  TYPE, PUBLIC :: aprm
22    !> Quadratic coefficients of the quadratic expressions.
23    REAL(kind=mm_wp), DIMENSION(:), ALLOCATABLE :: a
24    !> Linear coefficients of the quadratic expressions.
25    REAL(kind=mm_wp), DIMENSION(:), ALLOCATABLE :: b
26    !> Free term of the quadratic expressions.
27    REAL(kind=mm_wp), DIMENSION(:), ALLOCATABLE :: c
28  END TYPE
29
30  !> Size distribution parameters derived type.
31  !!
32  !! It stores the parameters of the size distribution law for Titan.
33  !!
34  !! The size distribution law is represented by the minimization of a sum of
35  !! power law functions:
36  !!
37  !! $$
38  !! \displaystyle n\left(r\right) = \frac{A_{0}}{C+\sum_{i=1}^{n} A_{i}\times
39  !!                                    \left(\frac{r}{r_{c}}\right)^{-b_{i}}}
40  !! $$
41  TYPE, PUBLIC :: nprm
42    !> Scaling factor.
43    REAL(kind=mm_wp)                            :: a0
44    !> Characterisitic radius.
45    REAL(kind=mm_wp)                            :: rc
46    !> Additional constant to the sum of power law.
47    REAL(kind=mm_wp)                            :: c
48    !> Scaling factor of each power law.
49    REAL(kind=mm_wp), DIMENSION(:), ALLOCATABLE :: a
50    !> Power of each power law.
51    REAL(kind=mm_wp), DIMENSION(:), ALLOCATABLE :: b
52  END TYPE
53
54  !> Inter-moment relation set of parameters for the spherical mode.
55  TYPE(aprm), PUBLIC, SAVE :: mmp_asp
56  !> Inter-moment relation set of parameters for the fractal mode.
57  TYPE(aprm), PUBLIC, SAVE :: mmp_afp
58
59  !> Size-distribution law parameters of the spherical mode.
60  TYPE(nprm), PUBLIC, SAVE :: mmp_pns
61  !> Size-distribution law parameters of the fractal mode.
62  TYPE(nprm), PUBLIC, SAVE :: mmp_pnf
63
64  !> Data set for @f$<Q>_{SF}^{M0}@f$.
65  TYPE(dset2d), PUBLIC, SAVE, TARGET             :: mmp_qbsf0
66  !> Extended values of [[mmp_gcm(module):mmp_qbsf0(variable)]] dataset.
67  REAL(kind=mm_wp), PUBLIC, SAVE, DIMENSION(2,2) :: mmp_qbsf0_e
68  !> Data set for @f$<Q>_{SF}^{M3}@f$.
69  TYPE(dset2d), PUBLIC, SAVE, TARGET             :: mmp_qbsf3
70  !> Extended values of [[mmp_gcm(module):mmp_qbsf3(variable)]] dataset.
71  REAL(kind=mm_wp), PUBLIC, SAVE, DIMENSION(2,2) :: mmp_qbsf3_e
72  !> Data set for @f$<Q>_{FF}^{M0}@f$.
73  TYPE(dset2d), PUBLIC, SAVE, TARGET             :: mmp_qbff0
74  !> Extended values of [[mmp_gcm(module):mmp_qbff0(variable)]] dataset.
75  REAL(kind=mm_wp), PUBLIC, SAVE, DIMENSION(2,2) :: mmp_qbff0_e
76 
77  !> Data set for linear interpolation of transfert probability (M0/CO).
78  TYPE(dset1d), PUBLIC, SAVE, TARGET :: mmp_pco0p
79  !> Data set for linear interpolation of transfert probability (M3/CO).
80  TYPE(dset1d), PUBLIC, SAVE, TARGET :: mmp_pco3p
81  !> Data set for linear interpolation of transfert probability (M0/FM).
82  TYPE(dset1d), PUBLIC, SAVE, TARGET :: mmp_pfm0p
83  !> Data set for linear interpolation of transfert probability (M3/FM).
84  TYPE(dset1d), PUBLIC, SAVE, TARGET :: mmp_pfm3p
85
86  !> \(b_{0}^{t}\) coefficients for Free-molecular regime kernel approximation.
87  REAL(kind=mm_wp), PUBLIC, SAVE, DIMENSION(5) :: mmp_bt0 = (/1._mm_wp,1._mm_wp,1._mm_wp,1._mm_wp,1._mm_wp/)
88  !> \(b_{3}^{t}\) coefficients for Free-molecular regime kernel approximation.
89  REAL(kind=mm_wp), PUBLIC, SAVE, DIMENSION(5) :: mmp_bt3 = (/1._mm_wp,1._mm_wp,1._mm_wp,1._mm_wp,1._mm_wp/)
90
91  !> Spherical probability transfert control flag.
92  LOGICAL, SAVE :: mmp_w_ps2s = .true.
93  !> Aerosol electric charge correction control flag.
94  LOGICAL, SAVE :: mmp_w_qe   = .true.
95
96
97  CONTAINS
98   
99  SUBROUTINE abort_program(err)
100    !! Dump error message and abort the program.
101    TYPE(error), INTENT(in) :: err !! Error object.
102    WRITE(stderr,'(a)') "ERROR: "//TRIM(err%msg)
103    CALL EXIT(err%id)
104  END SUBROUTINE abort_program
105
106
107  SUBROUTINE mmp_initialize(dt,df,rm,rho_aer,p_prod,tx_prod,rc_prod,rplanet,g0, air_rad,air_mmol,clouds,cfgpath)
108    !! Initialize global parameters of the model.
109    !!
110    !! The function initializes all the global parameters of the model from direct input.
111    !! Boolean (and Fiadero) parameters are optional as they are rather testing parameters. Their
112    !! default values are suitable for production runs. 
113    !! @note
114    !! If the method fails to initialize parameters (i.e. returned error is not 0). Then the model
115    !! should probably be aborted as the global variables of the model will not be correctly setup.
116    !!
117    !! @warning
118    !! If OpenMP is activated, this subroutine must be called in an $OMP SINGLE statement as it
119    !! initializes global variable that are not thread private.
120    !!
121    !! '''
122    !! !$OMP SINGLE
123    !! call mmp_initialize(...)
124    !! !$OMP END SINGLE
125    !!
126    REAL(kind=mm_wp), INTENT(in)           :: dt
127      !! Microphysics timestep in seconds.
128    REAL(kind=mm_wp), INTENT(in)           :: df
129      !! Fractal dimension of fractal aerosol.
130    REAL(kind=mm_wp), INTENT(in)           :: rm
131      !! Monomer radius in meter.
132    REAL(kind=mm_wp), INTENT(in)           :: rho_aer
133      !! Aerosol density in \(kg.m^{-3}\).
134    REAL(kind=mm_wp), INTENT(in)           :: p_prod
135      !!  Aerosol production pressure level in Pa.
136    REAL(kind=mm_wp), INTENT(in)           :: tx_prod
137      !! Spherical aerosol mode production rate in \(kg.m^{-2}.s^{-1}\).
138    REAL(kind=mm_wp), INTENT(in)           :: rc_prod
139      !! Spherical mode characteristic radius for production in meter.
140    REAL(kind=mm_wp), INTENT(in)           :: rplanet
141      !! Planet radius in meter
142    REAL(kind=mm_wp), INTENT(in)           :: g0
143      !! Planet gravity acceleration at ground level in \(m.s^{-2}\).
144    REAL(kind=mm_wp), INTENT(in)           :: air_rad
145      !! Air molecules mean radius in meter.
146    REAL(kind=mm_wp), INTENT(in)           :: air_mmol
147      !! Air molecules mean molar mass in \(kg.mol^{-1}\).
148    LOGICAL, INTENT(in)                    :: clouds
149      !! Clouds microphysics control flag.
150    CHARACTER(len=*), INTENT(in), OPTIONAL :: cfgpath
151      !! Internal microphysic configuration file.
152
153    INTEGER          :: coag_choice
154    REAL(kind=mm_wp) :: fiad_max, fiad_min
155    LOGICAL          :: w_h_prod, w_h_sed, w_h_coag, w_c_sed, w_c_nucond, &
156                        no_fiadero, fwsed_m0, fwsed_m3
157    TYPE(error)      :: err
158    INTEGER                                           :: i
159    TYPE(cfgparser)                                   :: cparser
160    CHARACTER(len=st_slen)                            :: spcpath,pssfile,mqfile
161    CHARACTER(len=st_slen), DIMENSION(:), ALLOCATABLE :: species
162    REAL(kind=mm_wp), DIMENSION(:), ALLOCATABLE       :: tmp
163
164    w_h_prod    = .true.
165    w_h_sed     = .true.
166    w_h_coag    = .true.
167    w_c_sed     = clouds
168    w_c_nucond  = clouds
169    fwsed_m0    = .true.
170    fwsed_m3    = .false.
171    no_fiadero  = .false.
172    fiad_min    = 0.1_mm_wp
173    fiad_max    = 10._mm_wp
174    coag_choice = 7
175
176    WRITE(*,'(a)') "##### MMP_GCM SPEAKING #####"
177    WRITE(*,'(a)') "I will initialize ze microphysics model in moments YAMMS"
178    WRITE(*,'(a)') "On error I will simply abort the program. Stay near your computer !"
179    WRITE(*,*)
180    WRITE(*,'(a)') "Reading muphys configuration file ("//trim(cfgpath)//")..."
181    err = cfg_read_config(cparser,TRIM(cfgpath),.true.)
182    IF (err /= 0) THEN
183      ! RETURN AN ERROR !!
184      call abort_program(err)
185    ENDIF
186   
187    ! YAMMS internal parameters:
188    ! the following parameters are primarily used to test and debug YAMMS.
189    ! They are set in an optional configuration file and default to suitable values for production runs.
190    err = mm_check_opt(cfg_get_value(cparser,"haze_production",w_h_prod)    ,w_h_prod   ,.true.   ,mm_log)
191    err = mm_check_opt(cfg_get_value(cparser,"haze_sedimentation",w_h_sed)  ,w_h_sed    ,.true.   ,mm_log)
192    err = mm_check_opt(cfg_get_value(cparser,"haze_coagulation",w_h_coag)   ,w_h_coag   ,.true.   ,mm_log)
193    err = mm_check_opt(cfg_get_value(cparser,"clouds_sedimentation",w_c_sed),w_c_sed    ,clouds   ,mm_log)
194    err = mm_check_opt(cfg_get_value(cparser,"clouds_nucl_cond",w_c_nucond) ,w_c_nucond ,clouds   ,mm_log)
195    err = mm_check_opt(cfg_get_value(cparser,"wsed_m0",fwsed_m0)            ,fwsed_m0   ,.true.   ,mm_log)
196    err = mm_check_opt(cfg_get_value(cparser,"wsed_m3",fwsed_m3)            ,fwsed_m3   ,.false.  ,mm_log)
197    err = mm_check_opt(cfg_get_value(cparser,"no_fiadero",no_fiadero)       ,no_fiadero ,.false.  ,mm_log)
198    err = mm_check_opt(cfg_get_value(cparser,"fiadero_min_ratio",fiad_min)  ,fiad_min   ,0.1_mm_wp,mm_log)
199    err = mm_check_opt(cfg_get_value(cparser,"fiadero_max_ratio",fiad_max)  ,fiad_max   ,10._mm_wp,mm_log)
200    err = mm_check_opt(cfg_get_value(cparser,"haze_coag_interactions",coag_choice),coag_choice,7,mm_log)
201
202    ! Retrieve clouds species configuration file
203    spcpath = ''
204    IF (clouds) THEN
205      err = mm_check_opt(cfg_get_value(cparser,"specie_cfg",spcpath), spcpath, wlog=mm_log)
206      IF (err/=0) call abort_program(err)
207    ENDIF
208
209    ! YAMMS initialization.
210    err = mm_global_init_0(dt,df,rm,rho_aer,p_prod,tx_prod,rc_prod,rplanet,g0, &
211                           air_rad,air_mmol,coag_choice,clouds,spcpath,  &
212                           w_h_prod,w_h_sed,w_h_coag,w_c_nucond,  &
213                           w_c_sed,fwsed_m0,fwsed_m3, &
214                           no_fiadero,fiad_min,fiad_max)
215    IF (err /= 0) call abort_program(err)
216
217    ! Extra initialization (needed for YAMMS method interfaces)
218    err = mm_check_opt(cfg_get_value(cparser, "transfert_probability", mmp_w_ps2s), mmp_w_ps2s, wlog=mm_log)
219    IF (err/=0) call abort_program(err)
220    err = mm_check_opt(cfg_get_value(cparser, "electric_charging"    , mmp_w_qe  ), mmp_w_qe, wlog=mm_log)
221    IF (err/=0) call abort_program(err)
222
223    ! initialize transfert probabilities look-up tables
224    IF (mm_w_haze_coag .AND. mmp_w_ps2s) THEN
225      err = mm_check_opt(cfg_get_value(cparser, "ps2s_file", pssfile), pssfile)
226      IF (err /= 0) call abort_program(err)
227
228      IF (.NOT.read_dset(pssfile,'p_m0_co',mmp_pco0p)) THEN
229        call abort_program(error("Cannot get 'p_m0_co' from "//pssfile,-1))
230      ENDIF
231      IF (.NOT.read_dset(pssfile,'p_m3_co',mmp_pco3p)) THEN
232        call abort_program(error("Cannot get 'p_m3_co' from "//pssfile,-1))
233      ENDIF
234      IF (.NOT.read_dset(pssfile,'p_m0_fm',mmp_pfm0p)) THEN
235        call abort_program(error("Cannot get 'p_m0_fm' from "//pssfile,-1))
236      ENDIF
237      IF (.NOT.read_dset(pssfile,'p_m3_fm',mmp_pfm3p)) THEN
238        call abort_program(error("Cannot get 'p_m3_fm' from "//pssfile,-1))
239      ENDIF
240    ENDIF
241    ! initialize mean electric correction look-up tables
242    IF (mm_w_haze_coag .AND. mmp_w_qe) THEN
243      err = mm_check_opt(cfg_get_value(cparser, "mq_file", mqfile), mqfile)
244      IF (err /= 0) call abort_program(err)
245
246      IF (.NOT.read_dset(mqfile,'qbsf0',mmp_qbsf0)) THEN
247        call abort_program(error("Cannot get 'qbsf0' from "//mqfile,-1))
248      ELSE
249        mmp_qbsf0_e(1,1) = MINVAL(mmp_qbsf0%x)
250        mmp_qbsf0_e(1,2) = MAXVAL(mmp_qbsf0%x)
251        mmp_qbsf0_e(2,1) = MINVAL(mmp_qbsf0%y)
252        mmp_qbsf0_e(2,2) = MAXVAL(mmp_qbsf0%y)
253      ENDIF
254      IF (.NOT.read_dset(mqfile,'qbsf3',mmp_qbsf3)) THEN
255        call abort_program(error("Cannot get 'qbsf3' from "//mqfile,-1))
256      ELSE
257        mmp_qbsf3_e(1,1) = MINVAL(mmp_qbsf3%x)
258        mmp_qbsf3_e(1,2) = MAXVAL(mmp_qbsf3%x)
259        mmp_qbsf3_e(2,1) = MINVAL(mmp_qbsf3%y)
260        mmp_qbsf3_e(2,2) = MAXVAL(mmp_qbsf3%y)
261      ENDIF
262      IF (.NOT.read_dset(mqfile,'qbff0',mmp_qbff0)) THEN
263        call abort_program(error("Cannot get 'qbff0' from "//mqfile,-1))
264      ELSE
265        mmp_qbff0_e(1,1) = MINVAL(mmp_qbff0%x)
266        mmp_qbff0_e(1,2) = MAXVAL(mmp_qbff0%x)
267        mmp_qbff0_e(2,1) = MINVAL(mmp_qbff0%y)
268        mmp_qbff0_e(2,2) = MAXVAL(mmp_qbff0%y)
269      ENDIF
270    ENDIF
271    ! spherical mode inter-moments function parameters
272    IF (.NOT.cfg_has_section(cparser,'alpha_s')) call abort_program(error("Cannot find [alpha_s] section",-1))
273    err = read_aprm(cparser,'alpha_s',mmp_asp)
274    IF (err /= 0) call abort_program(error("alpha_s: "//TRIM(err%msg),-1))
275    ! fractal mode inter-moments function parameters
276    IF (.NOT.cfg_has_section(cparser,'alpha_f')) call abort_program(error("Cannot find [alpha_f] section",-1))
277    err = read_aprm(cparser,'alpha_f',mmp_afp)
278    IF (err /= 0) call abort_program(error("alpha_s: "//TRIM(err%msg),-1))
279
280    ! get size-distribution laws parameters
281    IF (.NOT.cfg_has_section(cparser,'dndr_s')) call abort_program(error("Cannot find [dndr_s] section",-2))
282    err = read_nprm(cparser,'dndr_s',mmp_pns)
283    IF (err /= 0) call abort_program(error("dndr_s: "//TRIM(err%msg),-2))
284    IF (.NOT.cfg_has_section(cparser,'dndr_f')) call abort_program(error("Cannot find [dndr_f] section",-2))
285    err = read_nprm(cparser,'dndr_f',mmp_pnf)
286    IF (err /= 0) call abort_program(error("dndr_f: "//TRIM(err%msg),-2))
287
288    ! btk coefficients
289    IF (.NOT.cfg_has_section(cparser,'btks')) call abort_program(error("Cannot find [btks] section",-1))
290    err = cfg_get_value(cparser,"btks/bt0",tmp) ; IF (err/=0) call abort_program(error("bt0: "//TRIM(err%msg),-1))
291    IF (SIZE(tmp) /= 5)  call abort_program(error("bt0: Inconsistent number of coefficients",-1))
292    mmp_bt0 = tmp
293    err = cfg_get_value(cparser,"btks/bt3",tmp) ; IF (err/=0) call abort_program(error("bt3: "//TRIM(err%msg),-1))
294    IF (SIZE(tmp) /= 5)  call abort_program(error("bt3: Inconsistent number of coefficients",-1))
295    mmp_bt3 = tmp
296
297    ! dump parameters ...
298    WRITE(*,'(a)')        "========= MUPHYS PARAMETERS ==========="
299    WRITE(*,'(a,L2)')     "transfert_probability: ", mmp_w_ps2s
300    WRITE(*,'(a,L2)')     "electric_charging    : ", mmp_w_qe
301    call mm_dump_parameters()
302     
303  END SUBROUTINE mmp_initialize
304
305  FUNCTION read_aprm(parser,sec,pp) RESULT(err)
306    !! Read and store [[mmp_gcm(module):aprm(type)]] parameters.
307    TYPE(cfgparser), INTENT(in)  :: parser !! Configuration parser
308    CHARACTER(len=*), INTENT(in) :: sec    !! Name of the section that contains the parameters.
309    TYPE(aprm), INTENT(out)      :: pp     !! [[mmp_gcm(module):aprm(type)]] object that stores the parameters values.
310    TYPE(error) :: err                     !! Error status of the function.
311    err = cfg_get_value(parser,TRIM(sec)//'/a',pp%a) ; IF (err /= 0) RETURN
312    err = cfg_get_value(parser,TRIM(sec)//'/b',pp%b) ; IF (err /= 0) RETURN
313    err = cfg_get_value(parser,TRIM(sec)//'/c',pp%c) ; IF (err /= 0) RETURN
314    IF (SIZE(pp%a) /= SIZE(pp%b) .OR. SIZE(pp%a) /= SIZE(pp%c)) &
315    err = error("Inconsistent number of coefficients (a,b, and c must have the same size)",-1)
316    RETURN
317  END FUNCTION read_aprm
318
319  FUNCTION read_nprm(parser,sec,pp) RESULT(err)
320    !! Read and store [[mmp_gcm(module):nprm(type)]] parameters.
321    TYPE(cfgparser), INTENT(in)  :: parser !! Configuration parser
322    CHARACTER(len=*), INTENT(in) :: sec    !! Name of the section that contains the parameters.
323    TYPE(nprm), INTENT(out)      :: pp     !! [[mmp_gcm(module):nprm(type)]] object that stores the parameters values.
324    TYPE(error) :: err                     !! Error status of the function.
325    err = cfg_get_value(parser,TRIM(sec)//'/rc',pp%rc) ; IF (err /= 0) RETURN
326    err = cfg_get_value(parser,TRIM(sec)//'/a0',pp%a0) ; IF (err /= 0) RETURN
327    err = cfg_get_value(parser,TRIM(sec)//'/c',pp%c)   ; IF (err /= 0) RETURN
328    err = cfg_get_value(parser,TRIM(sec)//'/a',pp%a)   ; IF (err /= 0) RETURN
329    err = cfg_get_value(parser,TRIM(sec)//'/b',pp%b)   ; IF (err /= 0) RETURN
330    IF (SIZE(pp%a) /= SIZE(pp%b)) &
331      err = error("Inconsistent number of coefficients (a and b must have the same size)",3)
332    RETURN
333  END FUNCTION read_nprm
334
335END MODULE MMP_GCM
336
Note: See TracBrowser for help on using the repository browser.