source: trunk/LMDZ.COMMON/libf/evolution/clim_state_init.F90 @ 4066

Last change on this file since 4066 was 4065, checked in by jbclement, 3 weeks ago

PEM:
Major refactor following the previous ones (r3989 and r3991) completing the large structural reorganization and cleanup of the PEM codebase. This revision introduces newly designed modules, standardizes interfaces with explicit ini/end APIs and adds native NetCDF I/O together with explicit PCM/PEM adapters. In detail:

  • Some PEM models were corrected or improved:
    • Frost/perennial ice semantics are clarified via renaming;
    • Soil temperature remapping clarified, notably by removing the rescaling of temperature deviation;
    • Geothermal flux for the PCM is computed based on the PEM state;
  • New explicit PEM/PCM adapters ("set_*"/"build4PCM_*") to decouple PEM internal representation from PCM file layouts and reconstruct consistent fields returned to the PCM;
  • New explicit build/teardown routines that centralize allocation and initialization ordering, reducing accidental use of uninitialized data and making the model lifecycle explicit;
  • Add native read/write helpers for NetCDF that centralize all low-level NetCDF interactions with major improvements (and more simplicity) compared to legacy PEM/PCM I/O (see the modules "io_netcdf" and "output"). They support reading, creation and writing of "diagevol.nc" (renamed from "diagpem.nc") and start/restart files;
  • Provide well-focused modules ("numerics"/"maths"/"utility"/"display") to host commonly-used primitives:
    • "numerics" defines numerical types and constants for reproducibility, portability across compilers and future transitions (e.g. quadruple precision experiments);
    • "display" provides a single controlled interface for runtime messages, status output and diagnostics, avoiding direct 'print'/'write' to enable silent mode, log redirection, and MPI-safe output in the future.
    • "utility" (new module) hosts generic helpers used throughout the code (e.g. "int2str" or "real2str");
  • Add modules "clim_state_init"/"clim_state_rec" which provide robust read/write logic for "start/startfi/startpem", including 1D fallbacks, mesh conversions and dimension checks. NetCDF file creation is centralized and explicit. Restart files are now self-consistent and future-proof, requiring changes only to affected variables;
  • Add module "atmosphere" which computes pressure fields, reconstructs potential temperature and air mass. It also holds the whole logic to define sigma or hybrid coordinates for altitudes;
  • Add module "geometry" to centrilize dimensions logic and grid conversions routines (including 2 new ones "dyngrd2vect"/"vect2dyngrd");
  • Add module "slopes" to isolate slopes handling;
  • Add module "surface" to isolate surface management. Notably, albedo and emissivity are now fully reconstructed following the PCM settings;
  • Add module "allocation" to check the dimension initialization and centrilize allocation/deallocation;
  • Finalize module decomposition and renaming to consolidate domain-based modules, purpose-based routines and physics/process-based variables;
  • The main program now drives a clearer sequence of conceptual steps (initialization / reading / evolution / update / build / writing) and fails explicitly instead of silently defaulting;
  • Ice table logic is made restart-safe;
  • 'Open'/'read' intrinsic logic is made safe and automatic;
  • Improve discoverability and standardize the data handling (private vs protected vs public);
  • Apply consistent documentation/header style already introduced;
  • Update deftank scripts to reflect new names and launch wrappers;

This revision is a structural milestone aiming to be behavior-preserving where possible. It has been tested via compilation and short integration runs. However, due to extensive renames, moves, and API changes, full validation is still ongoing.
Note: the revision includes one (possibly two) easter egg hidden in the code for future archaeologists of the PEM. No physics were harmed.
JBC

File size: 22.2 KB
RevLine 
[4065]1MODULE clim_state_init
2!-----------------------------------------------------------------------
3! NAME
4!     clim_state_init
5!
6! DESCRIPTION
7!     Read the start files to initialize the climate state.
8!
9! AUTHORS & DATE
10!     JB Clement, 12/2025
11!
12! NOTES
13!
14!-----------------------------------------------------------------------
15
16! DEPENDENCIES
17! ------------
18use numerics,  only: dp, di, k4
19use io_netcdf, only: open_nc, close_nc, get_var_nc, get_dim_nc, put_var_nc, start_name, start1D_name, startfi_name, startpem_name
20
21! DECLARATION
22! -----------
23implicit none
24
25contains
26!+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
27
28!=======================================================================
29SUBROUTINE read_start()
30!-----------------------------------------------------------------------
31! NAME
32!     read_start
33!
34! DESCRIPTION
35!     Read the file "start.nc".
36!
37! AUTHORS & DATE
38!     JB Clement, 12/2025
39!
40! NOTES
41!
42!-----------------------------------------------------------------------
43
44! DEPENDENCIES
45! ------------
46use geometry,   only: nlayer, nlon, nlat, ngrid
47use atmosphere, only: set_ap, set_bp, set_ps_PCM, set_teta_PCM
48use tracers,    only: nq, qnames, set_q_PCM
49use stoppage,   only: stop_clean
50use display,    only: print_msg
51
52! DECLARATION
53! -----------
54implicit none
55
56! LOCAL VARIABLES
57! ---------------
58real(dp), dimension(nlayer + 1)           :: tmp1d
59real(dp), dimension(nlon + 1,nlat)        :: tmp2d
60real(dp), dimension(nlon + 1,nlat,nlayer) :: tmp3d
61logical(k4)                               :: here
62integer(di)                               :: i
63
64! CODE
65! ----
66! In case of 1D
67! ~~~~~~~~~~~~~
68if (ngrid == 1) then
69    call read_start1D()
70    return
71end if
72
73! In case of 3D
74! ~~~~~~~~~~~~~
75! Open
76inquire(file = start_name,exist = here)
77if (.not. here) call stop_clean(__FILE__,__LINE__,'cannot find required file "'//start_name//'"!',1)
78call print_msg('> Reading "'//start_name//'"')
79call open_nc(start_name,'read')
80
81! Get the variables
82call get_var_nc('ap',tmp1d)
83call set_ap(tmp1d)
84
85call get_var_nc('bp',tmp1d)
86call set_bp(tmp1d)
87
88call get_var_nc('ps',tmp2d)
89call set_ps_PCM(tmp2d)
90
91call get_var_nc('teta',tmp3d)
92call set_teta_PCM(tmp3d)
93
94do i = 1,nq
95    call get_var_nc(trim(qnames(i)),tmp3d)
96    call set_q_PCM(tmp3d,i)
97end do
98
99! Close
100call close_nc(start_name)
101
102END SUBROUTINE read_start
103!=======================================================================
104
105!=======================================================================
106SUBROUTINE read_start1D()
107!-----------------------------------------------------------------------
108! NAME
109!     read_start1D
110!
111! DESCRIPTION
112!     Read the file "start1D.txt".
113!
114! AUTHORS & DATE
115!     JB Clement, 12/2025
116!
117! NOTES
118!
119!-----------------------------------------------------------------------
120
121! DEPENDENCIES
122! ------------
123use geometry,   only: nlayer, nslope
124use atmosphere, only: set_ap, set_bp, set_ps_PCM, set_teta_PCM, set_u_PCM, set_v_PCM, compute_alt_coord, set_ap, set_bp
125use tracers,    only: nq, set_q_PCM
126use stoppage,   only: stop_clean
127use config,     only: read_callphys
128use display,    only: print_msg
129
130! DECLARATION
131! -----------
132implicit none
133
134! LOCAL VARIABLES
135! ---------------
136integer(di)                     :: i, j, k, ierr, funit
137character(30)                   :: header
138real(dp), dimension(1,1)        :: tmp
139real(dp), dimension(nslope)     :: tmp_1d
140real(dp), dimension(1,1,nlayer) :: q_tmp, teta_tmp, wind_tmp
141real(dp), dimension(nlayer + 1) :: ap_tmp, bp_tmp
142real(dp)                        :: pa, preff
143logical(k4)                     :: here
144
145! CODE
146! ----
147! Open "start1D.txt"
148inquire(file = start1D_name,exist = here)
149if (.not. here) call stop_clean(__FILE__,__LINE__,'cannot find required file "'//start1D_name//'"!',1)
150call print_msg('> Reading "'//start1D_name//'"')
151open(newunit = funit,file = start1D_name,status = "old",action = "read",iostat = ierr)
152if (ierr /= 0) call stop_clean(__FILE__,__LINE__,'error opening file "'//start1D_name//'"!',ierr)
153
154! Get the variables
155read(funit,*) header, tmp, pa, preff
156call set_ps_PCM(tmp)
157
158do i = 1,nq
159    read(funit,*,iostat = ierr) header, (tmp_1d(j),j = 1,nslope), (q_tmp(1,1,k),k = 1,nlayer)
160    if (ierr /= 0) call stop_clean(__FILE__,__LINE__,'not enough atmospheric layers defined in the file "'//start1D_name//'" for the tracer "'//trim(header)//'"!',1)
161    call set_q_PCM(q_tmp,i)
162end do
163read(funit,*,iostat = ierr) header, (wind_tmp(1,1,k),k = 1,nlayer)
164call set_u_PCM(wind_tmp)
165read(funit,*,iostat = ierr) header, (wind_tmp(1,1,k),k = 1,nlayer)
166call set_v_PCM(wind_tmp)
167read(funit,*,iostat = ierr) header, (tmp_1d(j),j = 1,nslope), (teta_tmp(1,1,k),k = 1,nlayer)
168call set_teta_PCM(teta_tmp)
169
170! Close
171close(funit)
172
173! Construct altitude coordinates (not stored in "start1D.txt")
174call compute_alt_coord(pa,preff,ap_tmp,bp_tmp)
175call set_ap(ap_tmp)
176call set_bp(bp_tmp)
177
178! Read the "callphys.def"
179call read_callphys() ! To get 'CO2cond_ps'
180
181END SUBROUTINE read_start1D
182!=======================================================================
183
184!=======================================================================
185SUBROUTINE read_startfi()
186!-----------------------------------------------------------------------
187! NAME
188!     read_startfi
189!
190! DESCRIPTION
191!     Read the file "startfi.nc".
192!
193! AUTHORS & DATE
194!     JB Clement, 12/2025
195!
196! NOTES
197!
198!-----------------------------------------------------------------------
199
200! DEPENDENCIES
201! ------------
202use geometry,  only: ngrid, nslope, nsoil_PCM
203use stoppage,  only: stop_clean
204use config,    only: read_controldata
205use slopes,    only: set_def_slope_mean, set_subslope_dist, set_iflat
206use surface,   only: set_albedodat_PCM, set_albedo_PCM, set_emissivity_PCM
207use surf_temp, only: set_tsurf_PCM
208use soil_temp, only: set_tsoil_PCM, set_flux_geo_PCM
209use frost,     only: set_h2ofrost_PCM, set_co2frost_PCM
210use surf_ice,  only: set_is_h2o_perice_PCM, set_co2_perice_PCM
211use soil,      only: set_TI_PCM, set_inertiedat_PCM
212use display,   only: print_msg
213
214! DECLARATION
215! -----------
216implicit none
217
218! LOCAL VARIABLES
219! ---------------
220real(dp), dimension(:),   allocatable       :: tmp1d
221real(dp), dimension(:,:), allocatable       :: tmp2d
222real(dp), dimension(ngrid,nsoil_PCM,nslope) :: tmp3d
223logical(k4)                                 :: here
224
225! CODE
226! ----
227inquire(file = startfi_name,exist = here)
228if (.not. here) call stop_clean(__FILE__,__LINE__,'cannot find required file "'//startfi_name//'"!',1)
229
230! Allocate the array to store the variables
231call print_msg('> Reading "'//startfi_name//'"')
232allocate(tmp1d(nslope + 1),tmp2d(ngrid,nslope))
233
234! Get control data
235call read_controldata()
236
237! Open
238call open_nc(startfi_name,'read')
239
240! Get the variables
241if (nslope > 1) then
242    call get_var_nc('def_slope_mean',tmp1d)
243    call set_def_slope_mean(tmp1d)
244
245    call get_var_nc('subslope_dist',tmp2d)
246    call set_subslope_dist(tmp2d)
247end if
248
249call get_var_nc('flux_geo',tmp2d)
250call set_flux_geo_PCM(tmp2d)
251
252call get_var_nc('h2o_ice',tmp2d)
253where (tmp2d < 0.) tmp2d = 0._dp ! Remove unphysical values of surface tracer
254call set_h2ofrost_PCM(tmp2d)
255
256call get_var_nc('co2',tmp2d)
257where (tmp2d < 0.) tmp2d = 0._dp ! Remove unphysical values of surface tracer
258call set_co2frost_PCM(tmp2d)
259
260call get_var_nc('perennial_co2ice',tmp2d)
261where (tmp2d < 0.) tmp2d = 0._dp ! Remove unphysical values of surface tracer
262call set_co2_perice_PCM(tmp2d)
263
264deallocate(tmp1d); allocate(tmp1d(ngrid))
265call get_var_nc('watercaptag',tmp1d)
266call set_is_h2o_perice_PCM(tmp1d)
267
268call get_var_nc('albedodat',tmp1d)
269call set_albedodat_PCM(tmp1d)
270
271call get_var_nc('albedo',tmp2d)
272call set_albedo_PCM(tmp2d)
273
274call get_var_nc('emis',tmp2d)
275call set_emissivity_PCM(tmp2d)
276
277call get_var_nc('tsurf',tmp2d)
278call set_tsurf_PCM(tmp2d)
279
280call get_var_nc('tsoil',tmp3d)
281call set_tsoil_PCM(tmp3d)
282
283deallocate(tmp2d); allocate(tmp2d(ngrid,nsoil_PCM))
284call get_var_nc('inertiedat',tmp2d)
285call set_inertiedat_PCM(tmp2d)
286
287call get_var_nc('inertiesoil',tmp3d)
288call set_TI_PCM(tmp3d)
289
290! To do?
291!   h2oice_depth
292!   d_coef
293!   lag_co2_ice
294
295! Close/Deallocate
296call close_nc(startfi_name)
297deallocate(tmp1d,tmp2d)
298
299END SUBROUTINE read_startfi
300!=======================================================================
301
302!=======================================================================
303SUBROUTINE read_startpem(tsurf_avg_yr1,tsurf_avg_yr2,ps_avg_glob,ps_ts,q_co2_ts,q_h2o_ts,h2o_surfdensity_avg,d_h2oice,d_co2ice,h2o_ice,co2_ice, &
304                         tsoil_avg,h2o_soildensity_avg,icetable_depth,icetable_thickness,ice_porefilling,layerings_map,                         &
305                         h2o_ads_reg,co2_ads_reg,delta_h2o_ads,delta_co2_ads)
306!-----------------------------------------------------------------------
307! NAME
308!     read_startpem
309!
310! DESCRIPTION
311!     Read the file "startpem.nc" which stores the PEM state.
312!
313! AUTHORS & DATE
314!     L. Lange, 2023
315!     JB Clement, 2023-2026
316!
317! NOTES
318!
319!-----------------------------------------------------------------------
320
321! DEPENDENCIES
322! ------------
323use stoppage,           only: stop_clean
324use geometry,           only: ngrid, nslope, nsoil, nsoil_PCM
325use evolution,          only: dt
326use physics,            only: mugaz, r
327use planet,             only: TI_breccia, TI_bedrock, alpha_clap_h2o, beta_clap_h2o
328use frost,              only: h2ofrost_PCM, h2o_frost4PCM, co2frost_PCM, co2_frost4PCM
329use surf_ice,           only: is_h2o_perice_PCM, h2oice_huge_ini, co2_perice_PCM
330use soil,               only: do_soil, TI, depth_breccia, depth_bedrock, index_breccia, index_bedrock, inertiedat, layer, inertiedat_PCM
331use soil_temp,          only: ini_tsoil_pem, compute_tsoil
332use soil_therm_inertia, only: update_soil_TI
333use ice_table,          only: icetable_equilibrium, icetable_dynamic, computeice_table_equilibrium
334use sorption,           only: do_sorption, evolve_regolith_adsorption
335use tracers,            only: mmol, iPCM_qh2o
336use layered_deposits,   only: layering, do_layering, array2map, ini_layering, add_stratum
337use surf_ice,           only: rho_co2ice, rho_h2oice
338use display,            only: print_msg
339use utility,            only: int2str
340
341! DECLARATION
342! -----------
343implicit none
344
345! ARGUMENTS
346! ---------
347real(dp), dimension(:,:),       intent(in)    :: tsurf_avg_yr1, tsurf_avg_yr2 ! Surface temperature at the last but one PCM run and at the last PCM run
348real(dp),                       intent(in)    :: ps_avg_glob                  ! Mean average pressure on the planet
349real(dp), dimension(:,:),       intent(in)    :: ps_ts                        ! Surface pressure timeseries
350real(dp), dimension(:,:),       intent(in)    :: q_co2_ts, q_h2o_ts           ! MMR of CO2 and H2O
351real(dp), dimension(:,:),       intent(in)    :: h2o_surfdensity_avg          ! Average of surface water density
352real(dp), dimension(:,:),       intent(in)    :: d_h2oice, d_co2ice           ! Tendencies on ice
353real(dp), dimension(:,:),       intent(inout) :: h2o_ice, co2_ice             ! Surface ice
354real(dp), dimension(:,:,:),     intent(inout) :: tsoil_avg                    ! Soil temperature
355real(dp), dimension(:,:,:),     intent(inout) :: h2o_soildensity_avg          ! Average of soil water soil density
356real(dp), dimension(:,:),       intent(inout) :: icetable_depth               ! Ice table depth
357real(dp), dimension(:,:),       intent(inout) :: icetable_thickness           ! Ice table thickness
358real(dp), dimension(:,:,:),     intent(inout) :: ice_porefilling              ! Subsurface ice pore filling
359real(dp), dimension(:,:,:),     intent(inout) :: h2o_ads_reg, co2_ads_reg     ! Mass of H2O and CO2 adsorbed
360type(layering), dimension(:,:), intent(inout) :: layerings_map                ! Layerings
361real(dp), dimension(:),         intent(inout) :: delta_h2o_ads, delta_co2_ads ! Mass of H2O and CO2 exchanged due to adsorption/desorption
362
363! LOCAL VARIABLES
364! ---------------
365logical(k4)                               :: here
366integer(di)                               :: i, islope, k, nb_str_max, nsoil_startpem
367real(dp)                                  :: delta           ! Depth of the interface regolith/breccia, breccia/bedrock [m]
368real(dp), dimension(ngrid,nsoil,nslope)   :: TI_startpem     ! Soil thermal inertia saved in the startpem [SI]
369real(dp), dimension(ngrid,nsoil,nslope)   :: tsoil_startpem  ! Soil temperature saved in the startpem [K]
370real(dp), dimension(:,:,:,:), allocatable :: layerings_array ! Array for layerings
371
372! CODE
373! ----
374! Check if the file exists
375inquire(file = startpem_name,exist = here)
376
377! If the file is not here
378! ~~~~~~~~~~~~~~~~~~~~~~~
379if (.not. here) then
380    ! It is possibly because it is the very first PEM run so everything needs to be initalized
381    call print_msg('> The file "'//startpem_name//'" was not found (possibly because this is the first PEM run)')
382
383    ! H2O ice
384    call print_msg("'h2o_ice' is initialized with default value 'h2oice_huge_ini' where 'watercaptag' is true.")
385    h2o_ice(:,:) = 0._dp
386    do i = 1,ngrid
387        if (is_h2o_perice_PCM(i)) h2o_ice(i,:) = h2oice_huge_ini + h2ofrost_PCM(i,:) - h2o_frost4PCM(i,:)
388    end do
389
390    ! CO2 ice
391    call print_msg("'co2_ice' is initialized with 'perennial_co2ice' found in the PCM.")
392    co2_ice(:,:) = co2_perice_PCM(:,:) + co2frost_PCM(:,:) - co2_frost4PCM(:,:)
393
394    if (do_soil) then
395        ! Thermal inertia
396        do islope = 1,nslope
397            do i = 1,ngrid
398                if (TI(i,index_breccia,islope) < TI_breccia) then
399                    !!! transition
400                    delta = depth_breccia
401                    TI(i,index_breccia + 1,islope) = sqrt((layer(index_breccia + 1) - layer(index_breccia))/                       &
402                                                               (((delta - layer(index_breccia))/(TI(i,index_breccia,islope)**2)) + &
403                                                               ((layer(index_breccia + 1) - delta)/(TI_breccia**2))))
404                    do k = index_breccia + 2,index_bedrock
405                        TI(i,k,islope) = TI_breccia
406                    end do
407                else ! we keep the high ti values
408                    do k = index_breccia + 1,index_bedrock
409                        TI(i,k,islope) = TI(i,index_breccia,islope)
410                    end do
411                end if
412                !! transition
413                delta = depth_bedrock
414                TI(i,index_bedrock + 1,islope) = sqrt((layer(index_bedrock + 1) - layer(index_bedrock))/                   &
415                                                       (((delta - layer(index_bedrock))/(TI(i,index_bedrock,islope)**2)) + &
416                                                       ((layer(index_bedrock + 1) - delta)/(TI_breccia**2))))
417                do k = index_bedrock + 2,nsoil
418                    TI(i,k,islope) = TI_bedrock
419                end do
420            end do
421        end do
422
423        do k = 1,nsoil_PCM
424            inertiedat(:,k) = inertiedat_PCM(:,k)
425        end do
426        !!! zone de transition
427        delta = depth_breccia
428        do i = 1,ngrid
429            if (inertiedat(i,index_breccia) < TI_breccia) then
430                inertiedat(i,index_breccia + 1) = sqrt((layer(index_breccia + 1) - layer(index_breccia))/                    &
431                                                        (((delta - layer(index_breccia))/(inertiedat(i,index_breccia)**2)) + &
432                                                        ((layer(index_breccia + 1) - delta)/(TI_breccia**2))))
433                do k = index_breccia + 2,index_bedrock
434                    inertiedat(i,k) = TI_breccia
435                end do
436            else
437                do k = index_breccia + 1,index_bedrock
438                    inertiedat(i,k) = inertiedat(i,index_breccia)
439                end do
440            end if
441        end do
442        !!! zone de transition
443        delta = depth_bedrock
444        do i = 1,ngrid
445            inertiedat(i,index_bedrock + 1) = sqrt((layer(index_bedrock + 1) - layer(index_bedrock))/                    &
446                                                    (((delta - layer(index_bedrock))/(inertiedat(i,index_bedrock)**2)) + &
447                                                    ((layer(index_bedrock + 1) - delta)/(TI_bedrock**2))))
448        end do
449
450        do k = index_bedrock + 2,nsoil
451            do i = 1,ngrid
452                inertiedat(i,k) = TI_bedrock
453            end do
454        end do
455
456        ! Soil temperature
457        do islope = 1,nslope
458            call ini_tsoil_pem(ngrid,nsoil,TI(:,:,islope),tsurf_avg_yr2(:,islope),tsoil_avg(:,:,islope))
459            call compute_tsoil(ngrid,nsoil,.true.,TI(:,:,islope),dt,tsurf_avg_yr2(:,islope),tsoil_avg(:,:,islope))
460
461            ! First raw initialization
462            h2o_soildensity_avg(:,nsoil_PCM + 1:nsoil,islope) = exp(beta_clap_h2o/tsoil_avg(:,nsoil_PCM + 1:nsoil,islope) + alpha_clap_h2o)/tsoil_avg(:,nsoil_PCM + 1:nsoil,islope)**mmol(iPCM_qh2o)/(mugaz*r)
463        end do
464
465        ! Ice table
466        if (icetable_equilibrium) then
467            call computeice_table_equilibrium(is_h2o_perice_PCM,h2o_surfdensity_avg,h2o_soildensity_avg,TI(:,1,:),icetable_depth,icetable_thickness)
468            call update_soil_TI(d_h2oice,h2o_ice,ps_avg_glob,icetable_depth,icetable_thickness,ice_porefilling,icetable_equilibrium,icetable_dynamic,TI)
469            do islope = 1,nslope
470                call ini_tsoil_pem(ngrid,nsoil,TI(:,:,islope),tsurf_avg_yr2(:,islope),tsoil_avg(:,:,islope))
471            end do
472        else if (icetable_dynamic) then
473            call update_soil_TI(d_h2oice,h2o_ice,ps_avg_glob,icetable_depth,icetable_thickness,ice_porefilling,icetable_equilibrium,icetable_dynamic,TI)
474            do islope = 1,nslope
475                call ini_tsoil_pem(ngrid,nsoil,TI(:,:,islope),tsurf_avg_yr2(:,islope),tsoil_avg(:,:,islope))
476            end do
477        end if
478
479        ! Absorption in regolith
480        if (do_sorption) then
481            h2o_ads_reg = 0._dp
482            co2_ads_reg = 0._dp
483            call evolve_regolith_adsorption(d_h2oice,d_co2ice,h2o_ice,co2_ice,tsoil_avg,TI,ps_ts,q_h2o_ts,q_co2_ts,h2o_ads_reg,co2_ads_reg,delta_h2o_ads,delta_co2_ads)
484            delta_co2_ads = 0._dp
485            delta_h2o_ads = 0._dp
486        end if ! do_sorption
487    end if ! do_soil
488
489    ! Layering
490    if (do_layering) then
491        call print_msg('layerings_map is initialized with sub-surface strata.')
492        call print_msg("Ice is added with 'h2oice_huge_ini' where 'watercaptag' is true and otherwise with 'perennial_co2ice' found in the PCM.")
493        do i = 1,ngrid
494            if (is_h2o_perice_PCM(i)) then
495                do islope = 1,nslope
496                    call ini_layering(layerings_map(i,islope))
497                    call add_stratum(layerings_map(i,islope),1.05_dp*h2oice_huge_ini/rho_h2oice,0._dp,h2oice_huge_ini/rho_h2oice,0.05_dp*h2oice_huge_ini/rho_h2oice,0._dp,0._dp)
498                end do
499            else
500                do islope = 1,nslope
501                    call ini_layering(layerings_map(i,islope))
502                    if (co2_perice_PCM(i,islope) > 0.) call add_stratum(layerings_map(i,islope),1.05_dp*co2_perice_PCM(i,islope)/rho_co2ice,co2_perice_PCM(i,islope)/rho_co2ice,0._dp,0.05_dp*co2_perice_PCM(i,islope)/rho_co2ice,0._dp,0._dp)
503                end do
504            end if
505        end do
506    end if ! do_layering
507
508    return
509end if
510
511! If the file is present
512! ~~~~~~~~~~~~~~~~~~~~~~
513call print_msg('> Reading "'//startpem_name//'"')
514call open_nc(startpem_name,'read')
515
516! H2O ice
517h2o_ice(:,:) = 0._dp
518call get_var_nc('h2o_ice',h2o_ice(:,:))
519
520! CO2 ice
521co2_ice(:,:) = 0._dp
522call get_var_nc('co2_ice',co2_ice(:,:))
523
524if (do_soil) then
525    ! Check if the number of soil layers is compatible
526    call get_dim_nc('subsurface_layers',nsoil_startpem)
527    if (nsoil_startpem /= nsoil) then
528        call print_msg('nsoil (PEM) = '//int2str(nsoil)//' | nsoil ("'//startpem_name//'") = '//int2str(nsoil_startpem))
529        call stop_clean(__FILE__,__LINE__,'nsoil defined in the PEM is different from the one read in "'//startpem_name//'"!',1)
530    end if
531
532    do islope = 1,nslope
533        ! Soil temperature
534        call get_var_nc('tsoil',tsoil_startpem(:,:,islope))
535        ! Predictor-corrector: due to changes of surface temperature in the PCM, the tsoil_startpem is adapted firstly
536        !                      for PCM year 1 and then for PCM year 2 in order to build the evolution of the profile at depth
537        call compute_tsoil(ngrid,nsoil,.true.,TI(:,:,islope),dt,tsurf_avg_yr1(:,islope),tsoil_startpem(:,:,islope))
538        call compute_tsoil(ngrid,nsoil,.false.,TI(:,:,islope),dt,tsurf_avg_yr1(:,islope),tsoil_startpem(:,:,islope))
539        call compute_tsoil(ngrid,nsoil,.false.,TI(:,:,islope),dt,tsurf_avg_yr2(:,islope),tsoil_startpem(:,:,islope))
540    end do
541    tsoil_avg(:,nsoil_PCM + 1:nsoil,:) = tsoil_startpem(:,nsoil_PCM + 1:nsoil,:)
542    if (any(isnan(tsoil_avg(:,:,:)))) call stop_clean(__FILE__,__LINE__,"NaN detected in 'tsoil_avg'",1)
543
544    ! Thermal inertia
545    call get_var_nc('TI',TI_startpem(:,:,:))
546    TI(:,nsoil_PCM + 1:nsoil,:) = TI_startpem(:,nsoil_PCM + 1:nsoil,:) ! 1st layers can change because of the presence of ice at the surface, so we don't change it here
547    call get_var_nc('inertiedat',inertiedat(:,:))
548
549    ! Ice table
550    call get_var_nc('icetable_depth',icetable_depth(:,:))
551    if (icetable_dynamic) call get_var_nc('ice_porefilling',ice_porefilling(:,:,:))
552    if (icetable_equilibrium) then
553        call get_var_nc('icetable_thickness',icetable_thickness(:,:))
554    else if (icetable_dynamic) then
555        call get_var_nc('ice_porefilling',ice_porefilling(:,:,:))
556    end if
557
558    ! Absorption in regolith
559    if (do_sorption) then
560        call get_var_nc('co2_ads_reg',co2_ads_reg(:,:,:))
561        call get_var_nc('h2o_ads_reg',h2o_ads_reg(:,:,:))
562        call evolve_regolith_adsorption(d_h2oice,d_co2ice,h2o_ice,co2_ice,tsoil_avg,TI,ps_ts,q_h2o_ts,q_co2_ts,h2o_ads_reg,co2_ads_reg,delta_h2o_ads,delta_co2_ads)
563    end if ! do_sorption
564end if ! do_soil
565
566! Layering
567if (do_layering) then
568    call get_dim_nc('nb_str_max',nb_str_max)
569    allocate(layerings_array(ngrid,nslope,nb_str_max,6))
570    layerings_array = 0.
571    call get_var_nc('stratif_top_elevation',layerings_array(:,:,:,1))
572    call get_var_nc('stratif_h_co2ice',layerings_array(:,:,:,2))
573    call get_var_nc('stratif_h_h2oice',layerings_array(:,:,:,3))
574    call get_var_nc('stratif_h_dust',layerings_array(:,:,:,4))
575    call get_var_nc('stratif_h_pore',layerings_array(:,:,:,5))
576    call get_var_nc('stratif_poreice_volfrac',layerings_array(:,:,:,6))
577    call array2map(layerings_array,layerings_map)
578    deallocate(layerings_array)
579end if
580
581! Close
582call close_nc(startpem_name)
583
584END SUBROUTINE read_startpem
585!=======================================================================
586
587END MODULE clim_state_init
Note: See TracBrowser for help on using the repository browser.