source: trunk/LMDZ.COMMON/libf/evolution/config.F90 @ 4074

Last change on this file since 4074 was 4074, checked in by jbclement, 10 days ago

PEM:

  • Correct management of H2O ice tendency in 1D when there is not enough ice anymore.
  • Clean initialization of allocatable module arrays (especially needed when no slope)
  • One more renaming for consistency + few small updates thoughout the code.

JBC

File size: 13.4 KB
Line 
1MODULE config
2!-----------------------------------------------------------------------
3! NAME
4!     config
5!
6! DESCRIPTION
7!     Read and apply parameters for a PEM run from run_pem.def.
8!
9! AUTHORS & DATE
10!     R. Vandemeulebrouck
11!     JB Clement, 2023-2025
12!
13! NOTES
14!
15!-----------------------------------------------------------------------
16
17! DEPENDENCIES
18! ------------
19use numerics, only: dp, di, k4, minieps
20
21! DECLARATION
22! -----------
23implicit none
24
25character(7),  parameter :: rundef_name = 'run.def'
26character(11), parameter :: runPCMdef_name = 'run_pcm.def'
27character(12), parameter :: callphys_name = 'callphys.def'
28
29contains
30!+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
31
32!=======================================================================
33SUBROUTINE read_rundef()
34!-----------------------------------------------------------------------
35! NAME
36!     read_rundef
37!
38! DESCRIPTION
39!     Read PEM runtime configuration from getin keys, then set
40!     module-scoped parameters accordingly.
41!
42! AUTHORS & DATE
43!     R. Vandemeulebrouck
44!     JB Clement, 2023-2025
45!
46! NOTES
47!
48!-----------------------------------------------------------------------
49
50! DEPENDENCIES
51! ------------
52#ifdef CPP_IOIPSL
53use IOIPSL,           only: getin
54#else
55! If not using IOIPSL, we still need to use (a local version of) getin
56use ioipsl_getincom,  only: getin
57#endif
58use evolution,        only: set_evolution_config
59use stopping_crit,    only: set_stopping_crit_config
60use soil,             only: set_soil_config
61use sorption,         only: set_sorption_config
62use glaciers,         only: set_glaciers_config
63use surf_ice,         only: set_surf_ice_config
64use ice_table,        only: set_ice_table_config
65use layered_deposits, only: set_layered_deposits_config
66use output,           only: set_output_config
67use orbit,            only: set_orbit_config
68use atmosphere,       only: set_atmosphere_config
69use stoppage,         only: stop_clean
70use display,          only: print_msg
71
72! DECLARATION
73! -----------
74implicit none
75
76! LOCAL VARIABLES
77! ---------------
78logical(k4) :: here, evol_orbit_l, evol_obl_l, evol_ecc_l, evol_lsp_l, do_soil_l, reg_thprop_dependp_l, do_sorption_l, hybrid
79logical(k4) :: icetable_equilibrium_l, icetable_dynamic_l, h2oice_flow_l, co2ice_flow_l, do_layering_l, impose_dust_ratio_l
80integer(di) :: output_rate_l
81integer(di) :: pem_ini_earth_date ! Initial year (in Earth years) of the PEM workflow defined in "run.def"
82real(dp)    :: dt_l, nmax_yr_run_l, h2oice_crit_l, co2ice_crit_l, ps_crit_l, max_change_obl_l, max_change_ecc_l, max_change_lsp_l
83real(dp)    :: flux_geo_l, depth_breccia_l, depth_bedrock_l, threshold_h2oice_cap_l, h2oice_huge_ini_l, d_dust_l, dust2ice_ratio_l
84
85! CODE
86! ----
87inquire(file = rundef_name,exist = here)
88if (.not. here) call stop_clean(__FILE__,__LINE__,'cannot find required file "'//rundef_name//'" (PEM)!',1)
89call print_msg('> Reading "'//rundef_name//'"')
90
91! Output
92! ~~~~~~
93output_rate_l = 1_di ! Default value: every year
94call getin('output_rate',output_rate_l)
95
96! Orbital parameters
97! ~~~~~~~~~~~~~~~~~~
98evol_orbit_l = .false.
99call getin('evol_orbit',evol_orbit_l)
100
101pem_ini_earth_date = 0_di
102call getin('pem_ini_earth_date',pem_ini_earth_date)
103
104evol_obl_l = .true.
105call getin('evol_obl',evol_obl_l)
106
107evol_ecc_l = .true.
108call getin('evol_ecc',evol_ecc_l)
109
110evol_lsp_l = .true.
111call getin('evol_lsp',evol_lsp_l)
112
113dt_l = 1._dp
114call getin('dt',dt_l)
115
116! Stopping criteria
117! ~~~~~~~~~~~~~~~~~
118nmax_yr_run_l = 100000000._dp
119call getin('nmax_yr_run',nmax_yr_run_l)
120
121h2oice_crit_l = 0.2_dp
122call getin('h2oice_crit',h2oice_crit_l)
123
124co2ice_crit_l = 0.2_dp
125call getin('co2ice_crit',co2ice_crit_l)
126
127ps_crit_l = 0.15_dp
128call getin('ps_crit',ps_crit_l)
129
130max_change_obl_l = 1._dp
131call getin('max_change_obl',max_change_obl_l)
132
133max_change_ecc_l = 5.e-3_dp
134call getin('max_change_ecc',max_change_ecc_l)
135
136max_change_lsp_l = 20._dp
137call getin('max_change_lsp',max_change_lsp_l)
138
139! Subsurface
140! ~~~~~~~~~~
141do_soil_l = .true.
142call getin('do_soil',do_soil_l)
143
144do_sorption_l = .false.
145call getin('do_sorption',do_sorption_l)
146
147reg_thprop_dependp_l = .false.
148call getin('reg_thprop_dependp',reg_thprop_dependp_l)
149
150flux_geo_l = 0._dp
151call getin('flux_geo',flux_geo_l)
152
153depth_breccia_l = 10._dp
154call getin('depth_breccia',depth_breccia_l)
155
156depth_bedrock_l = 1000._dp
157call getin('depth_bedrock',depth_bedrock_l)
158
159icetable_equilibrium_l = .true.
160call getin('icetable_equilibrium',icetable_equilibrium_l)
161
162icetable_dynamic_l = .false.
163call getin('icetable_dynamic',icetable_dynamic_l)
164
165! Ice management
166! ~~~~~~~~~~~~~~
167h2oice_huge_ini_l = 9200._dp ! [kg/m^2]; Default = 10 m
168call getin('h2oice_huge_ini',h2oice_huge_ini_l)
169
170threshold_h2oice_cap_l = 460._dp ! kg.m-2 (= 0.5 m)
171call getin('threshold_h2oice_cap',threshold_h2oice_cap_l)
172
173h2oice_flow_l = .true.
174call getin('h2oice_flow',h2oice_flow_l)
175
176co2ice_flow_l = .true.
177call getin('co2ice_flow',co2ice_flow_l)
178
179! Layering
180! ~~~~~~~~
181do_layering_l = .false.
182call getin('do_layering',do_layering_l)
183
184d_dust_l = 5.78e-2_dp ! kg.m-2.y-1 (= 1.e-9 kg.m-2.s-1)
185call getin('d_dust',d_dust_l)
186
187impose_dust_ratio_l = .false.
188call getin('impose_dust_ratio',impose_dust_ratio_l)
189
190dust2ice_ratio_l = 0.01_dp
191call getin('dust2ice_ratio',dust2ice_ratio_l)
192
193! Setters
194call set_output_config(output_rate_l)
195call set_orbit_config(evol_orbit_l,evol_obl_l,evol_ecc_l,evol_lsp_l,max_change_obl_l,max_change_ecc_l,max_change_lsp_l)
196call set_evolution_config(pem_ini_earth_date,dt_l,nmax_yr_run_l)
197call set_stopping_crit_config(h2oice_crit_l,co2ice_crit_l,ps_crit_l)
198call set_soil_config(do_soil_l,reg_thprop_dependp_l,flux_geo_l,depth_breccia_l,depth_bedrock_l)
199call set_sorption_config(do_sorption_l)
200call set_ice_table_config(icetable_equilibrium_l,icetable_dynamic_l)
201call set_surf_ice_config(threshold_h2oice_cap_l,h2oice_huge_ini_l)
202call set_glaciers_config(h2oice_flow_l,co2ice_flow_l)
203call set_layered_deposits_config(do_layering_l,impose_dust_ratio_l,d_dust_l,dust2ice_ratio_l)
204
205! Read "run_pcm.def" parameters
206hybrid = .true. ! Default
207call get_hybrid(hybrid)
208call set_atmosphere_config(hybrid)
209
210! Check incompatibilities
211call check_config_incompatibility()
212
213END SUBROUTINE read_rundef
214!=======================================================================
215
216!=======================================================================
217SUBROUTINE check_config_incompatibility()
218!-----------------------------------------------------------------------
219! NAME
220!     check_config_incompatibility
221!
222! DESCRIPTION
223!     Check incompatibilities in the PEM runtime configuration.
224!
225! AUTHORS & DATE
226!     JB Clement, 02/2026
227!
228! NOTES
229!
230!-----------------------------------------------------------------------
231
232! DEPENDENCIES
233! ------------
234use stoppage,  only: stop_clean
235use soil,      only: do_soil, reg_thprop_dependp, flux_geo
236use sorption,  only: do_sorption
237use orbit,     only: evol_orbit
238use evolution, only: pem_ini_date
239use ice_table, only: icetable_equilibrium, icetable_dynamic
240use display,   only: print_msg
241
242! DECLARATION
243! -----------
244implicit none
245
246! CODE
247! ----
248! Warnings (possible incompatibilities)
249if (evol_orbit .and. abs(pem_ini_date) < minieps) call print_msg('Warning: evol_orbit = .true. but the initial date of the PEM is set to 0!')
250
251! Errors (true incompatibilities)
252if (.not. do_soil) then
253    if (icetable_equilibrium .or. icetable_dynamic) call stop_clean(__FILE__,__LINE__,'ice table must be used when do_soil = true!',1)
254    if (abs(flux_geo) > minieps) call stop_clean(__FILE__,__LINE__,'soil is not activated but flux_geo /= 0!',1)
255    if (reg_thprop_dependp) call stop_clean(__FILE__,__LINE__,'regolith properties vary according to Ps only when soil = true!',1)
256    if (do_sorption) call stop_clean(__FILE__,__LINE__,'do_soil must be true when do_sorption = true!',1)
257end if
258
259END SUBROUTINE check_config_incompatibility
260!=======================================================================
261
262!=======================================================================
263SUBROUTINE read_callphys()
264!-----------------------------------------------------------------------
265! NAME
266!     read_callphys
267!
268! DESCRIPTION
269!     Read physics runtime configuration from getin keys, then set
270!     module-scoped parameters accordingly.
271!
272! AUTHORS & DATE
273!     JB Clement, 01/2026
274!
275! NOTES
276!     To work, it needs that "run_pem.def" hols a line with
277!     "INCLUDEDEF=callphys.def".
278!-----------------------------------------------------------------------
279
280! DEPENDENCIES
281! ------------
282#ifdef CPP_IOIPSL
283use IOIPSL,          only: getin
284#else
285! If not using IOIPSL, we still need to use (a local version of) getin
286use ioipsl_getincom, only: getin
287#endif
288use atmosphere,      only: CO2cond_ps_PCM
289use stoppage,        only: stop_clean
290use display,         only: print_msg
291
292! DECLARATION
293! -----------
294implicit none
295
296! LOCAL VARIABLES
297! ---------------
298logical(k4) :: here
299
300! CODE
301! ----
302inquire(file = callphys_name,exist = here)
303if (.not. here) call stop_clean(__FILE__,__LINE__,'cannot find required file "'//callphys_name//'"!',1)
304call print_msg('> Reading "'//callphys_name//'"')
305
306CO2cond_ps_PCM = 1._dp ! Default value
307call getin("CO2cond_ps",CO2cond_ps_PCM)
308if (CO2cond_ps_PCM < 0._dp .or. CO2cond_ps_PCM > 1._dp) call stop_clean(__FILE__,__LINE__,'Value for ''CO2cond_ps'' is not between 0 and 1. Please, specify a correct value in "'//callphys_name//'"!',1)
309
310END SUBROUTINE read_callphys
311!=======================================================================
312
313!=======================================================================
314SUBROUTINE get_hybrid(hybrid)
315!-----------------------------------------------------------------------
316! NAME
317!     get_hybrid
318!
319! DESCRIPTION
320!     Get the key definition in "run_pcm.def".
321!
322! AUTHORS & DATE
323!     JB Clement, 12/2025
324!
325! NOTES
326!
327!-----------------------------------------------------------------------
328
329! DEPENDENCIES
330! ------------
331use stoppage, only: stop_clean
332use display,  only: print_msg
333use utility,  only: bool2str
334
335! DECLARATION
336! -----------
337implicit none
338
339! ARGUMENTS
340! ---------
341logical(k4), intent(inout) :: hybrid
342
343! LOCAL VARIABLES
344! ---------------
345integer(di)    :: ierr, funit, eq_pos
346logical(k4)    :: here, found, hybrid_in
347character(256) :: line
348character(128) :: key, res
349
350! CODE
351! ----
352inquire(file = runPCMdef_name,exist = here)
353if (.not. here) call stop_clean(__FILE__,__LINE__,'cannot find required file "'//runPCMdef_name//'"!',1)
354call print_msg('> Reading "'//runPCMdef_name//'"')
355open(newunit = funit,file = runPCMdef_name,status = 'old',form = 'formatted',action = 'read',iostat = ierr)
356if (ierr /= 0) call stop_clean(__FILE__,__LINE__,'error opening file "'//runPCMdef_name//'"!',ierr)
357
358found = .false.
359hybrid_in = hybrid
360do
361    ! Read the line
362    read(funit,'(a)',iostat = ierr) line
363    if (ierr /= 0) exit
364
365    ! Skip empty lines and comments
366    if (trim(line) == '') cycle
367    if (line(1:1) == '#' .or. line(1:1) == '!') cycle
368
369    ! Get the position of equal sign
370    eq_pos = index(line,'=')
371    if (eq_pos == 0) cycle
372
373    ! Get the key and its value/result
374    key = adjustl(trim(line(:eq_pos - 1)))
375    res = adjustl(trim(line(eq_pos + 1:)))
376
377    ! Check the key
378    if (trim(key) == 'hybrid') then
379        read(res,*,iostat = ierr) hybrid
380        if (ierr == 0) found = .true.
381        exit
382    end if
383end do
384
385close(funit)
386
387if (.not. found) call print_msg('Warning: key ''hybrid'' not found in the file "'//runPCMdef_name//'"!')
388if (hybrid .eqv. hybrid_in) call print_msg('USING DEFAULTS : hybrid = '//bool2str(hybrid_in))
389
390END SUBROUTINE get_hybrid
391!=======================================================================
392
393!=======================================================================
394SUBROUTINE read_controldata()
395!-----------------------------------------------------------------------
396! NAME
397!     read_controldata
398!
399! DESCRIPTION
400!     Read 'controle' data in "startfi.nc".
401!
402! AUTHORS & DATE
403!     JB Clement, 01/2026
404!
405! NOTES
406!
407!-----------------------------------------------------------------------
408
409! DEPENDENCIES
410! ------------
411use io_netcdf, only: open_nc, close_nc, startfi_name, get_dim_nc, get_var_nc
412use physics,   only: init_physics
413use orbit,     only: init_orbit
414use soil,      only: volcapa
415use stoppage,  only: stop_clean
416use display,   only: print_msg
417
418! DECLARATION
419! -----------
420implicit none
421
422! LOCAL VARIABLES
423! ---------------
424integer(di)                         :: nindex ! Size of dimension 'index'
425real(dp), dimension(:), allocatable :: controle
426
427! CODE
428! ----
429call print_msg('> Reading control data ("'//startfi_name//'")')
430! Open the "startfi.nc" file
431call open_nc(startfi_name,'read')
432
433! Get the dimension size of 'index'
434call get_dim_nc('index',nindex)
435
436! Get 'controle'
437allocate(controle(nindex))
438call get_var_nc('controle',controle)
439
440! Close the file
441call close_nc(startfi_name)
442
443! Initialize physical data
444!     Arguments order: rad, g, mugaz, rcp
445call print_msg('    > Initializing physical constants')
446call init_physics(controle(5),controle(7),controle(8),controle(9))
447
448! Initialize soil data
449call print_msg('    > Initializing soil parameters')
450volcapa = controle(35)
451if (abs(volcapa) < minieps) call stop_clean(__FILE__,__LINE__,'volcapa is 0 in "'//startfi_name//'"!',1)
452
453! Initialize orbital data
454!     Arguments order: Obliquity, Perihelion, Aphelion, Date of perihelion, Year length, Sol length
455call print_msg('    > Initializing orbital characteristics of the planet')
456call init_orbit(controle(18),controle(15),controle(16),controle(17),controle(14),controle(10))
457
458deallocate(controle)
459
460END SUBROUTINE read_controldata
461!=======================================================================
462
463END MODULE config
Note: See TracBrowser for help on using the repository browser.