[3090] | 1 | ! Copyright (2017,2022-2023) Université de Reims Champagne-Ardenne |
---|
| 2 | ! Contributors : J. Burgalat (GSMA, URCA), B. de Batz de Trenquelléon (GSMA, URCA) |
---|
[1897] | 3 | ! email of the author : jeremie.burgalat@univ-reims.fr |
---|
[3083] | 4 | ! |
---|
[1897] | 5 | ! This software is a computer program whose purpose is to compute |
---|
| 6 | ! microphysics processes using a two-moments scheme. |
---|
[3083] | 7 | ! |
---|
[1897] | 8 | ! This library is governed by the CeCILL license under French law and |
---|
[3083] | 9 | ! abiding by the rules of distribution of free software. You can use, |
---|
[1897] | 10 | ! modify and/ or redistribute the software under the terms of the CeCILL |
---|
| 11 | ! license as circulated by CEA, CNRS and INRIA at the following URL |
---|
[3083] | 12 | ! "http://www.cecill.info". |
---|
| 13 | ! |
---|
[1897] | 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 |
---|
[3083] | 18 | ! liability. |
---|
| 19 | ! |
---|
[1897] | 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 |
---|
[3083] | 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 | ! |
---|
[1897] | 31 | ! The fact that you are presently reading this means that you have had |
---|
| 32 | ! knowledge of the CeCILL license and that you accept its terms. |
---|
| 33 | |
---|
| 34 | !! file: mmp_gcm.f90 |
---|
| 35 | !! summary: YAMMS interfaces for the LMDZ GCM. |
---|
| 36 | !! author: J. Burgalat |
---|
[3090] | 37 | !! date: 2017,2022,2023 |
---|
| 38 | !! modifications: B. de Batz de Trenquelléon |
---|
[1793] | 39 | MODULE MMP_GCM |
---|
| 40 | !! Interface to YAMMS for the LMDZ GCM. |
---|
[1897] | 41 | USE MMP_GLOBALS |
---|
[1793] | 42 | USE MM_LIB |
---|
| 43 | USE CFGPARSE |
---|
| 44 | USE DATASETS |
---|
| 45 | IMPLICIT NONE |
---|
| 46 | |
---|
[3083] | 47 | CONTAINS |
---|
| 48 | |
---|
[1897] | 49 | SUBROUTINE mmp_initialize(dt,p_prod,tx_prod,rc_prod,rplanet,g0, air_rad,air_mmol,clouds,cfgpath) |
---|
[1793] | 50 | !! Initialize global parameters of the model. |
---|
[3083] | 51 | !! |
---|
[1793] | 52 | !! The function initializes all the global parameters of the model from direct input. |
---|
[3083] | 53 | !! Boolean (and Fiadero) parameters are optional as they are rather testing parameters. Their |
---|
| 54 | !! default values are suitable for production runs. |
---|
[1793] | 55 | !! @note |
---|
[1897] | 56 | !! If the subroutine fails to initialize parameters, the run is aborted. |
---|
[1793] | 57 | !! |
---|
| 58 | !! @warning |
---|
[3083] | 59 | !! If OpenMP is activated, this subroutine must be called in an $OMP SINGLE statement as it |
---|
[1793] | 60 | !! initializes global variable that are not thread private. |
---|
| 61 | !! |
---|
[1897] | 62 | !! ``` |
---|
[1793] | 63 | !! !$OMP SINGLE |
---|
| 64 | !! call mmp_initialize(...) |
---|
| 65 | !! !$OMP END SINGLE |
---|
[1897] | 66 | !! ``` |
---|
[1793] | 67 | !! |
---|
| 68 | REAL(kind=mm_wp), INTENT(in) :: dt |
---|
| 69 | !! Microphysics timestep in seconds. |
---|
| 70 | REAL(kind=mm_wp), INTENT(in) :: p_prod |
---|
| 71 | !! Aerosol production pressure level in Pa. |
---|
| 72 | REAL(kind=mm_wp), INTENT(in) :: tx_prod |
---|
| 73 | !! Spherical aerosol mode production rate in \(kg.m^{-2}.s^{-1}\). |
---|
| 74 | REAL(kind=mm_wp), INTENT(in) :: rc_prod |
---|
| 75 | !! Spherical mode characteristic radius for production in meter. |
---|
| 76 | REAL(kind=mm_wp), INTENT(in) :: rplanet |
---|
| 77 | !! Planet radius in meter |
---|
| 78 | REAL(kind=mm_wp), INTENT(in) :: g0 |
---|
| 79 | !! Planet gravity acceleration at ground level in \(m.s^{-2}\). |
---|
| 80 | REAL(kind=mm_wp), INTENT(in) :: air_rad |
---|
| 81 | !! Air molecules mean radius in meter. |
---|
| 82 | REAL(kind=mm_wp), INTENT(in) :: air_mmol |
---|
| 83 | !! Air molecules mean molar mass in \(kg.mol^{-1}\). |
---|
| 84 | LOGICAL, INTENT(in) :: clouds |
---|
| 85 | !! Clouds microphysics control flag. |
---|
| 86 | CHARACTER(len=*), INTENT(in), OPTIONAL :: cfgpath |
---|
| 87 | !! Internal microphysic configuration file. |
---|
| 88 | |
---|
[1897] | 89 | INTEGER :: coag_choice |
---|
[3083] | 90 | REAL(kind=mm_wp) :: fiad_max,fiad_min,df,rm,rho_aer |
---|
| 91 | LOGICAL :: w_h_prod,w_h_sed,w_h_coag,w_c_sed,w_c_nucond, & |
---|
| 92 | no_fiadero,fwsed_m0,fwsed_m3 |
---|
[1897] | 93 | TYPE(error) :: err |
---|
[1793] | 94 | INTEGER :: i |
---|
| 95 | TYPE(cfgparser) :: cparser |
---|
[1926] | 96 | CHARACTER(len=st_slen) :: spcpath,pssfile,mqfile,opt_file |
---|
[1793] | 97 | CHARACTER(len=st_slen), DIMENSION(:), ALLOCATABLE :: species |
---|
| 98 | REAL(kind=mm_wp), DIMENSION(:), ALLOCATABLE :: tmp |
---|
[3083] | 99 | REAL(kind=mm_wp) :: m0as_min,rcs_min,m0af_min,rcf_min,m0n_min |
---|
| 100 | LOGICAL :: wdebug |
---|
[1793] | 101 | |
---|
| 102 | w_h_prod = .true. |
---|
| 103 | w_h_sed = .true. |
---|
| 104 | w_h_coag = .true. |
---|
| 105 | w_c_sed = clouds |
---|
| 106 | w_c_nucond = clouds |
---|
| 107 | fwsed_m0 = .true. |
---|
| 108 | fwsed_m3 = .false. |
---|
[3083] | 109 | no_fiadero = .true. |
---|
[1793] | 110 | fiad_min = 0.1_mm_wp |
---|
| 111 | fiad_max = 10._mm_wp |
---|
| 112 | coag_choice = 7 |
---|
[3083] | 113 | wdebug = .false. |
---|
| 114 | m0as_min = 1e-10_mm_wp |
---|
| 115 | rcs_min = 1e-9_mm_wp |
---|
| 116 | m0af_min = 1e-10_mm_wp |
---|
| 117 | rcf_min = 1e-9_mm_wp |
---|
| 118 | m0n_min = 1e-10_mm_wp |
---|
[1793] | 119 | |
---|
| 120 | WRITE(*,'(a)') "##### MMP_GCM SPEAKING #####" |
---|
[3083] | 121 | WRITE(*,'(a)') "I will initialize the microphysics model in moments YAMMS" |
---|
[1793] | 122 | WRITE(*,'(a)') "On error I will simply abort the program. Stay near your computer !" |
---|
| 123 | WRITE(*,*) |
---|
| 124 | WRITE(*,'(a)') "Reading muphys configuration file ("//trim(cfgpath)//")..." |
---|
[3083] | 125 | err = cfg_read_config(cparser,TRIM(cfgpath),.true.) |
---|
[1793] | 126 | IF (err /= 0) THEN |
---|
| 127 | ! RETURN AN ERROR !! |
---|
| 128 | call abort_program(err) |
---|
| 129 | ENDIF |
---|
[3083] | 130 | |
---|
[1793] | 131 | ! YAMMS internal parameters: |
---|
[1897] | 132 | err = mm_check_opt(cfg_get_value(cparser,"rm",rm),rm,50e-9_mm_wp,mm_log) |
---|
| 133 | err = mm_check_opt(cfg_get_value(cparser,"df",df),df,2._mm_wp,mm_log) |
---|
| 134 | err = mm_check_opt(cfg_get_value(cparser,"rho_aer",rho_aer),rho_aer,1000._mm_wp,mm_log) |
---|
[1793] | 135 | ! the following parameters are primarily used to test and debug YAMMS. |
---|
| 136 | ! They are set in an optional configuration file and default to suitable values for production runs. |
---|
[3083] | 137 | err = mm_check_opt(cfg_get_value(cparser,"haze_production",w_h_prod) ,w_h_prod ,.true. ,mm_log) |
---|
| 138 | err = mm_check_opt(cfg_get_value(cparser,"haze_sedimentation",w_h_sed) ,w_h_sed ,.true. ,mm_log) |
---|
| 139 | err = mm_check_opt(cfg_get_value(cparser,"haze_coagulation",w_h_coag) ,w_h_coag ,.true. ,mm_log) |
---|
| 140 | err = mm_check_opt(cfg_get_value(cparser,"clouds_sedimentation",w_c_sed) ,w_c_sed ,clouds ,mm_log) |
---|
| 141 | err = mm_check_opt(cfg_get_value(cparser,"clouds_nucl_cond",w_c_nucond) ,w_c_nucond ,clouds ,mm_log) |
---|
| 142 | err = mm_check_opt(cfg_get_value(cparser,"wsed_m0",fwsed_m0) ,fwsed_m0 ,.true. ,mm_log) |
---|
| 143 | err = mm_check_opt(cfg_get_value(cparser,"wsed_m3",fwsed_m3) ,fwsed_m3 ,.false. ,mm_log) |
---|
| 144 | err = mm_check_opt(cfg_get_value(cparser,"no_fiadero",no_fiadero) ,no_fiadero ,.true. ,mm_log) |
---|
| 145 | err = mm_check_opt(cfg_get_value(cparser,"fiadero_min_ratio",fiad_min) ,fiad_min ,0.1_mm_wp ,mm_log) |
---|
| 146 | err = mm_check_opt(cfg_get_value(cparser,"fiadero_max_ratio",fiad_max) ,fiad_max ,10._mm_wp ,mm_log) |
---|
| 147 | err = mm_check_opt(cfg_get_value(cparser,"haze_coag_interactions",coag_choice),coag_choice,7 ,mm_log) |
---|
| 148 | err = mm_check_opt(cfg_get_value(cparser,"m0as_min",m0as_min) ,m0as_min ,1e-10_mm_wp,mm_log) |
---|
| 149 | err = mm_check_opt(cfg_get_value(cparser,"rcs_min",rcs_min) ,rcs_min ,1e-9_mm_wp ,mm_log) |
---|
| 150 | err = mm_check_opt(cfg_get_value(cparser,"m0af_min",m0af_min) ,m0af_min ,1e-10_mm_wp,mm_log) |
---|
| 151 | err = mm_check_opt(cfg_get_value(cparser,"rcf_min",rcf_min) ,rcf_min ,rm ,mm_log) |
---|
| 152 | err = mm_check_opt(cfg_get_value(cparser,"m0n_min",m0n_min) ,m0n_min ,1e-10_mm_wp,mm_log) |
---|
| 153 | err = mm_check_opt(cfg_get_value(cparser,"debug",wdebug) ,wdebug ,.false. ,mm_log) |
---|
[1793] | 154 | |
---|
| 155 | ! Retrieve clouds species configuration file |
---|
| 156 | spcpath = '' |
---|
| 157 | IF (clouds) THEN |
---|
| 158 | err = mm_check_opt(cfg_get_value(cparser,"specie_cfg",spcpath), spcpath, wlog=mm_log) |
---|
| 159 | IF (err/=0) call abort_program(err) |
---|
| 160 | ENDIF |
---|
| 161 | |
---|
[3083] | 162 | ! Setup alpha function: THEY ARE REQUIRED IN YAMMS global initialization ! |
---|
| 163 | ! spherical mode inter-moments function parameters |
---|
| 164 | IF (.NOT.cfg_has_section(cparser,'alpha_s')) call abort_program(error("Cannot find [alpha_s] section",-1)) |
---|
| 165 | err = read_aprm(cparser,'alpha_s',mmp_asp) |
---|
| 166 | IF (err /= 0) call abort_program(error("alpha_s: "//TRIM(err%msg),-1)) |
---|
| 167 | ! fractal mode inter-moments function parameters |
---|
| 168 | IF (.NOT.cfg_has_section(cparser,'alpha_f')) call abort_program(error("Cannot find [alpha_f] section",-1)) |
---|
| 169 | err = read_aprm(cparser,'alpha_f',mmp_afp) |
---|
| 170 | IF (err /= 0) call abort_program(error("alpha_s: "//TRIM(err%msg),-1)) |
---|
| 171 | |
---|
[1793] | 172 | ! YAMMS initialization. |
---|
| 173 | err = mm_global_init_0(dt,df,rm,rho_aer,p_prod,tx_prod,rc_prod,rplanet,g0, & |
---|
| 174 | air_rad,air_mmol,coag_choice,clouds,spcpath, & |
---|
| 175 | w_h_prod,w_h_sed,w_h_coag,w_c_nucond, & |
---|
| 176 | w_c_sed,fwsed_m0,fwsed_m3, & |
---|
[3083] | 177 | no_fiadero,fiad_min,fiad_max, & |
---|
| 178 | m0as_min,rcs_min,m0af_min,rcf_min,m0n_min,wdebug) |
---|
[1793] | 179 | IF (err /= 0) call abort_program(err) |
---|
| 180 | |
---|
| 181 | ! Extra initialization (needed for YAMMS method interfaces) |
---|
| 182 | err = mm_check_opt(cfg_get_value(cparser, "transfert_probability", mmp_w_ps2s), mmp_w_ps2s, wlog=mm_log) |
---|
| 183 | IF (err/=0) call abort_program(err) |
---|
| 184 | err = mm_check_opt(cfg_get_value(cparser, "electric_charging" , mmp_w_qe ), mmp_w_qe, wlog=mm_log) |
---|
| 185 | IF (err/=0) call abort_program(err) |
---|
| 186 | |
---|
| 187 | ! initialize transfert probabilities look-up tables |
---|
| 188 | IF (mm_w_haze_coag .AND. mmp_w_ps2s) THEN |
---|
| 189 | err = mm_check_opt(cfg_get_value(cparser, "ps2s_file", pssfile), pssfile) |
---|
| 190 | IF (err /= 0) call abort_program(err) |
---|
| 191 | |
---|
| 192 | IF (.NOT.read_dset(pssfile,'p_m0_co',mmp_pco0p)) THEN |
---|
[3083] | 193 | call abort_program(error("Cannot get 'p_m0_co' from "//pssfile,-1)) |
---|
[1793] | 194 | ENDIF |
---|
| 195 | IF (.NOT.read_dset(pssfile,'p_m3_co',mmp_pco3p)) THEN |
---|
[3083] | 196 | call abort_program(error("Cannot get 'p_m3_co' from "//pssfile,-1)) |
---|
[1793] | 197 | ENDIF |
---|
| 198 | IF (.NOT.read_dset(pssfile,'p_m0_fm',mmp_pfm0p)) THEN |
---|
| 199 | call abort_program(error("Cannot get 'p_m0_fm' from "//pssfile,-1)) |
---|
| 200 | ENDIF |
---|
| 201 | IF (.NOT.read_dset(pssfile,'p_m3_fm',mmp_pfm3p)) THEN |
---|
| 202 | call abort_program(error("Cannot get 'p_m3_fm' from "//pssfile,-1)) |
---|
| 203 | ENDIF |
---|
| 204 | ENDIF |
---|
| 205 | ! initialize mean electric correction look-up tables |
---|
| 206 | IF (mm_w_haze_coag .AND. mmp_w_qe) THEN |
---|
| 207 | err = mm_check_opt(cfg_get_value(cparser, "mq_file", mqfile), mqfile) |
---|
| 208 | IF (err /= 0) call abort_program(err) |
---|
| 209 | |
---|
| 210 | IF (.NOT.read_dset(mqfile,'qbsf0',mmp_qbsf0)) THEN |
---|
| 211 | call abort_program(error("Cannot get 'qbsf0' from "//mqfile,-1)) |
---|
| 212 | ELSE |
---|
[3083] | 213 | mmp_qbsf0_e(1,1) = MINVAL(mmp_qbsf0%x) |
---|
[1793] | 214 | mmp_qbsf0_e(1,2) = MAXVAL(mmp_qbsf0%x) |
---|
| 215 | mmp_qbsf0_e(2,1) = MINVAL(mmp_qbsf0%y) |
---|
| 216 | mmp_qbsf0_e(2,2) = MAXVAL(mmp_qbsf0%y) |
---|
| 217 | ENDIF |
---|
| 218 | IF (.NOT.read_dset(mqfile,'qbsf3',mmp_qbsf3)) THEN |
---|
| 219 | call abort_program(error("Cannot get 'qbsf3' from "//mqfile,-1)) |
---|
| 220 | ELSE |
---|
[3083] | 221 | mmp_qbsf3_e(1,1) = MINVAL(mmp_qbsf3%x) |
---|
[1793] | 222 | mmp_qbsf3_e(1,2) = MAXVAL(mmp_qbsf3%x) |
---|
| 223 | mmp_qbsf3_e(2,1) = MINVAL(mmp_qbsf3%y) |
---|
| 224 | mmp_qbsf3_e(2,2) = MAXVAL(mmp_qbsf3%y) |
---|
| 225 | ENDIF |
---|
| 226 | IF (.NOT.read_dset(mqfile,'qbff0',mmp_qbff0)) THEN |
---|
| 227 | call abort_program(error("Cannot get 'qbff0' from "//mqfile,-1)) |
---|
| 228 | ELSE |
---|
[3083] | 229 | mmp_qbff0_e(1,1) = MINVAL(mmp_qbff0%x) |
---|
[1793] | 230 | mmp_qbff0_e(1,2) = MAXVAL(mmp_qbff0%x) |
---|
| 231 | mmp_qbff0_e(2,1) = MINVAL(mmp_qbff0%y) |
---|
| 232 | mmp_qbff0_e(2,2) = MAXVAL(mmp_qbff0%y) |
---|
| 233 | ENDIF |
---|
| 234 | ENDIF |
---|
[1819] | 235 | |
---|
[1793] | 236 | ! btk coefficients |
---|
| 237 | IF (.NOT.cfg_has_section(cparser,'btks')) call abort_program(error("Cannot find [btks] section",-1)) |
---|
| 238 | err = cfg_get_value(cparser,"btks/bt0",tmp) ; IF (err/=0) call abort_program(error("bt0: "//TRIM(err%msg),-1)) |
---|
| 239 | IF (SIZE(tmp) /= 5) call abort_program(error("bt0: Inconsistent number of coefficients",-1)) |
---|
| 240 | mmp_bt0 = tmp |
---|
| 241 | err = cfg_get_value(cparser,"btks/bt3",tmp) ; IF (err/=0) call abort_program(error("bt3: "//TRIM(err%msg),-1)) |
---|
| 242 | IF (SIZE(tmp) /= 5) call abort_program(error("bt3: Inconsistent number of coefficients",-1)) |
---|
| 243 | mmp_bt3 = tmp |
---|
| 244 | |
---|
| 245 | ! dump parameters ... |
---|
| 246 | WRITE(*,'(a)') "========= MUPHYS PARAMETERS ===========" |
---|
| 247 | WRITE(*,'(a,L2)') "transfert_probability: ", mmp_w_ps2s |
---|
| 248 | WRITE(*,'(a,L2)') "electric_charging : ", mmp_w_qe |
---|
| 249 | call mm_dump_parameters() |
---|
[3083] | 250 | IF (clouds) THEN |
---|
| 251 | DO i=1, size(mm_xESPS) |
---|
| 252 | print*, TRIM(mm_xESPS(i)%name), " fmol2fmas = ", mm_xESPS(i)%fmol2fmas |
---|
| 253 | ENDDO |
---|
| 254 | ENDIF |
---|
| 255 | |
---|
[1793] | 256 | END SUBROUTINE mmp_initialize |
---|
| 257 | |
---|
| 258 | FUNCTION read_aprm(parser,sec,pp) RESULT(err) |
---|
[3083] | 259 | !! Read and store [[mmp_gcm(module):aprm(type)]] parameters. |
---|
| 260 | TYPE(cfgparser), INTENT(in) :: parser !! Configuration parser |
---|
[1793] | 261 | CHARACTER(len=*), INTENT(in) :: sec !! Name of the section that contains the parameters. |
---|
[1819] | 262 | TYPE(aprm), INTENT(out) :: pp !! [[mmp_gcm(module):aprm(type)]] object that stores the parameters values. |
---|
[1793] | 263 | TYPE(error) :: err !! Error status of the function. |
---|
| 264 | err = cfg_get_value(parser,TRIM(sec)//'/a',pp%a) ; IF (err /= 0) RETURN |
---|
| 265 | err = cfg_get_value(parser,TRIM(sec)//'/b',pp%b) ; IF (err /= 0) RETURN |
---|
| 266 | err = cfg_get_value(parser,TRIM(sec)//'/c',pp%c) ; IF (err /= 0) RETURN |
---|
| 267 | IF (SIZE(pp%a) /= SIZE(pp%b) .OR. SIZE(pp%a) /= SIZE(pp%c)) & |
---|
| 268 | err = error("Inconsistent number of coefficients (a,b, and c must have the same size)",-1) |
---|
| 269 | RETURN |
---|
| 270 | END FUNCTION read_aprm |
---|
| 271 | |
---|
| 272 | END MODULE MMP_GCM |
---|
| 273 | |
---|