| 1 | PROGRAM pem |
|---|
| 2 | !----------------------------------------------------------------------- |
|---|
| 3 | ! NAME |
|---|
| 4 | ! pem |
|---|
| 5 | ! |
|---|
| 6 | ! DESCRIPTION |
|---|
| 7 | ! Main entry point for the Planetary Evolution Model (PEM). |
|---|
| 8 | ! |
|---|
| 9 | ! AUTHORS & DATE |
|---|
| 10 | ! R. Vandemeulebrouck, 22/07/2022 |
|---|
| 11 | ! L. Lange, 22/07/2022 |
|---|
| 12 | ! JB Clement, 2023-2025 |
|---|
| 13 | ! |
|---|
| 14 | ! NOTES |
|---|
| 15 | ! |
|---|
| 16 | !----------------------------------------------------------------------- |
|---|
| 17 | |
|---|
| 18 | ! DEPENDENCIES |
|---|
| 19 | ! ------------ |
|---|
| 20 | ! Common modules |
|---|
| 21 | use job_timelimit_mod, only: timelimit, antetime, timewall |
|---|
| 22 | use parse_args_mod, only: parse_args |
|---|
| 23 | ! PEM modules |
|---|
| 24 | use allocation, only: ini_allocation, end_allocation |
|---|
| 25 | use atmosphere, only: ps_PCM, evolve_pressure, CO2cond_ps_PCM |
|---|
| 26 | use backup, only: save_clim_state, backup_rate |
|---|
| 27 | use clim_state_init, only: read_start, read_startfi, read_startpem |
|---|
| 28 | use config, only: read_rundef, read_display_config |
|---|
| 29 | use display, only: print_ini, print_end, print_msg, LVL_NFO, LVL_WRN |
|---|
| 30 | use evolution, only: n_yr_run, n_yr_sim, ntot_yr_sim, nmax_yr_run, dt, idt, r_plnt2earth_yr, pem_ini_date |
|---|
| 31 | use geometry, only: ngrid, nslope, nday, nsoil_PCM, nsoil, cell_area, total_surface, nlayer |
|---|
| 32 | use glaciers, only: h2oice_flow, co2ice_flow, flow_co2glaciers, flow_h2oglaciers |
|---|
| 33 | use ice_table, only: icetable_equilibrium, icetable_dynamic, icetable_depth, icetable_thickness, ice_porefilling, evolve_ice_table |
|---|
| 34 | use layered_deposits, only: layering, do_layering, del_layering, evolve_layering, ptrarray, layering2surfice, surfice2layering, print_layering |
|---|
| 35 | use maths, only: pi |
|---|
| 36 | use numerics, only: dp, qp, di, li, k4, minieps, minieps_qp |
|---|
| 37 | use orbit, only: evo_orbit, read_orbitpm, compute_maxyr_orbit, update_orbit |
|---|
| 38 | use output, only: write_diagevo, dim_ngrid, dim_nsoil |
|---|
| 39 | use physics, only: g |
|---|
| 40 | use slopes, only: subslope_dist, def_slope_mean |
|---|
| 41 | use soil, only: do_soil, set_soil, TI |
|---|
| 42 | use soil_temp, only: tsoil_PCM, shift_tsoil2surf, evolve_soil_temp |
|---|
| 43 | use soil_therm_inertia, only: update_soil_TI |
|---|
| 44 | use sorption, only: do_sorption, compute_totmass_adsorbed, evolve_regolith_adsorption |
|---|
| 45 | use stopping_crit, only: stopFlags, stopping_crit_pressure, stopping_crit_h2o, stopping_crit_h2oice, stopping_crit_co2ice |
|---|
| 46 | use surface, only: emissivity_PCM |
|---|
| 47 | use surf_ice, only: evolve_co2ice, evolve_h2oice, balance_h2oice_reservoirs |
|---|
| 48 | use surf_temp, only: tsurf_PCM, adapt_tsurf2disappearedice |
|---|
| 49 | use tendencies, only: compute_tendice, evolve_tend_co2ice, evolve_tend_h2oice |
|---|
| 50 | use tracers, only: adapt_tracers2pressure |
|---|
| 51 | use utility, only: real2str |
|---|
| 52 | use workflow_status, only: i_pem_run, read_workflow_status, update_workflow_status |
|---|
| 53 | use xios_data, only: load_xios_data |
|---|
| 54 | |
|---|
| 55 | ! DECLARATION |
|---|
| 56 | ! ----------- |
|---|
| 57 | implicit none |
|---|
| 58 | |
|---|
| 59 | ! LOCAL VARIABLES |
|---|
| 60 | ! --------------- |
|---|
| 61 | ! Utility-related: |
|---|
| 62 | integer(li) :: cr ! Number of clock ticks per second (count rate) |
|---|
| 63 | integer(li) :: c1, c2 ! Counts of processor clock |
|---|
| 64 | character(:), allocatable :: num ! To write slope variables |
|---|
| 65 | integer(di) :: i, islope |
|---|
| 66 | ! Pressure-related: |
|---|
| 67 | real(dp), dimension(:), allocatable :: ps_avg ! Average surface pressure [Pa] |
|---|
| 68 | real(dp), dimension(:), allocatable :: ps_dev ! Deviation of surface pressure [Pa] |
|---|
| 69 | real(dp), dimension(:,:), allocatable :: ps_ts ! Surface pressure timeseries [Pa] |
|---|
| 70 | real(dp) :: ps_avg_glob_ini ! Global average pressure at initialization [Pa] |
|---|
| 71 | real(dp) :: ps_avg_glob_old ! Global average pressure of previous time step [Pa] |
|---|
| 72 | real(dp) :: ps_avg_glob ! Global average pressure of current time step [Pa] |
|---|
| 73 | ! Ice-related: |
|---|
| 74 | real(dp), dimension(:,:), allocatable :: h2o_ice ! H2O ice [kg.m-2] |
|---|
| 75 | real(dp), dimension(:,:), allocatable :: co2_ice ! CO2 ice [kg.m-2] |
|---|
| 76 | real(dp) :: h2oice_sublim_coverage_ini ! Initial surface area of sublimating H2O ice [m2] |
|---|
| 77 | real(dp) :: co2ice_sublim_coverage_ini ! Initial surface area of sublimating CO2 ice [m2] |
|---|
| 78 | logical(k4), dimension(:,:), allocatable :: is_h2oice_ini ! Initial location of H2O ice |
|---|
| 79 | logical(k4), dimension(:,:), allocatable :: is_co2ice_ini ! Initial location of CO2 ice |
|---|
| 80 | logical(k4), dimension(:,:), allocatable :: is_co2ice_flow ! Flag for location of CO2 glacier flow |
|---|
| 81 | logical(k4), dimension(:,:), allocatable :: is_h2oice_flow ! Flag for location of H2O glacier flow |
|---|
| 82 | real(dp), dimension(:,:,:), allocatable :: minPCM_h2operice ! Minimum of H2O perennial ice over the last PCM year [kg.m-2] |
|---|
| 83 | real(dp), dimension(:,:,:), allocatable :: minPCM_co2perice ! Minimum of CO2 perennial ice over the last PCM year [kg.m-2] |
|---|
| 84 | real(dp), dimension(:,:,:), allocatable :: minPCM_h2ofrost ! Minimum of H2O frost over the last PCM year [kg.m-2] |
|---|
| 85 | real(dp), dimension(:,:,:), allocatable :: minPCM_co2frost ! Minimum of CO2 frost over the last PCM year [kg.m-2] |
|---|
| 86 | logical(k4), dimension(:,:), allocatable :: is_co2ice_disappeared ! Flag to check if CO2 ice disappeared at the previous timestep |
|---|
| 87 | ! Surface-related: |
|---|
| 88 | real(dp), dimension(:,:), allocatable :: tsurf_avg ! Average surface temperature [K] |
|---|
| 89 | real(dp), dimension(:,:), allocatable :: tsurf_avg_yr1 ! Average surface temperature of the second to last PCM run [K] |
|---|
| 90 | real(dp), dimension(:,:), allocatable :: tsurf_dev ! Deviation of surface temperature [K] |
|---|
| 91 | real(dp), dimension(:,:), allocatable :: h2o_surfdensity_avg ! Average water surface density [kg/m^3] |
|---|
| 92 | real(dp), dimension(:,:), allocatable :: zshift_surf ! Elevation shift for the surface [m] |
|---|
| 93 | real(dp), dimension(:,:), allocatable :: zlag ! Newly built lag thickness [m] |
|---|
| 94 | ! Soil-related: |
|---|
| 95 | real(dp), dimension(:,:,:), allocatable :: tsoil_avg ! Average soil temperature [K] |
|---|
| 96 | real(dp), dimension(:,:,:), allocatable :: tsoil_dev ! Deviation pf soil temperature [K] |
|---|
| 97 | real(dp), dimension(:,:,:,:), allocatable :: tsoil_ts ! Soil temperature timeseries [K] |
|---|
| 98 | real(dp), dimension(:,:,:,:), allocatable :: tsoil_ts_old ! Soil temperature timeseries at the previous time step [K] |
|---|
| 99 | real(dp), dimension(:,:,:), allocatable :: h2o_soildensity_avg ! Average of soil water soil density [kg/m^3] |
|---|
| 100 | real(dp), dimension(:), allocatable :: delta_co2_ads ! Quantity of CO2 exchanged due to adsorption/desorption [kg/m^2] |
|---|
| 101 | real(dp), dimension(:), allocatable :: delta_h2o_ads ! Quantity of H2O exchanged due to adsorption/desorption [kg/m^2] |
|---|
| 102 | real(qp) :: totmass_adsh2o ! Total mass of H2O exchanged because of adsorption/desorption [kg] |
|---|
| 103 | real(dp), dimension(:,:,:), allocatable :: h2o_ads_reg ! H2O adsorbed in the regolith [kg/m^2] |
|---|
| 104 | real(dp), dimension(:,:,:), allocatable :: co2_ads_reg ! CO2 adsorbed in the regolith [kg/m^2] |
|---|
| 105 | real(dp), dimension(:,:), allocatable :: icetable_depth_old ! Old depth of the ice table [m] |
|---|
| 106 | real(dp), dimension(:), allocatable :: delta_icetable ! Total mass of the H2O that has sublimated / condenses from the ice table [kg] |
|---|
| 107 | ! Tracer-related: |
|---|
| 108 | real(dp), dimension(:,:), allocatable :: q_co2_ts ! CO2 mass mixing ratio in the first layer [kg/kg] |
|---|
| 109 | real(dp), dimension(:,:), allocatable :: q_co2_ts_ini ! Initial CO2 mass mixing ratio in the first layer [kg/kg] |
|---|
| 110 | real(dp), dimension(:,:), allocatable :: q_h2o_ts ! H2O mass mixing ratio in the first layer [kg/kg] |
|---|
| 111 | ! Tendency-related: |
|---|
| 112 | real(dp), dimension(:,:), allocatable :: d_co2ice ! Tendency of perennial CO2 ice [kg/m2/y] |
|---|
| 113 | real(dp), dimension(:,:), allocatable :: d_co2ice_ini ! Tendency of perennial CO2 ice at the beginning [kg/m2/y] |
|---|
| 114 | real(dp), dimension(:,:), allocatable :: d_h2oice ! Tendency of perennial H2O ice [kg/m2/y] |
|---|
| 115 | real(dp), dimension(:,:), allocatable :: d_h2oice_new ! Adjusted tendency of perennial H2O ice to keep balance between donor and recipient [kg/m2/y] |
|---|
| 116 | ! Layering-related: |
|---|
| 117 | type(layering), dimension(:,:), allocatable :: layerings_map ! Layering for each grid point and slope |
|---|
| 118 | type(ptrarray), dimension(:,:), allocatable :: current ! Current active stratum in the layering |
|---|
| 119 | real(dp), dimension(:,:), allocatable :: h2oice_depth ! Depth of subsurface ice layer |
|---|
| 120 | real(dp), dimension(:,:), allocatable :: h2oice_depth_old ! Old depth of subsurface ice layer |
|---|
| 121 | logical(k4), dimension(:,:), allocatable :: new_str, new_lag ! Flags for the layering algorithm |
|---|
| 122 | ! Evolution-related: |
|---|
| 123 | real(dp) :: nmax_yr_runorb ! Maximum number of years for the run due to orbital parameters |
|---|
| 124 | type(stopFlags) :: stopcrit ! Stopping criteria |
|---|
| 125 | ! Balance-related |
|---|
| 126 | real(qp) :: totmass_co2ice, totmass_atmco2, totmass_adsco2 ! Current total CO2 masses (surface ice|atmospheric|adsorbed) |
|---|
| 127 | real(qp) :: totmass_co2ice_ini, totmass_atmco2_ini, totmass_adsco2_ini ! Initial total CO2 masses (surface ice|atmospheric|adsorbed) |
|---|
| 128 | real(qp) :: totmass_ini ! Initial total CO2 mass [kg] |
|---|
| 129 | real(qp) :: S_atm_2_h2o, S_h2o_2_atm, S_atm_2_h2oice, S_h2oice_2_atm ! Variables to balance H2O ice reservoirs |
|---|
| 130 | |
|---|
| 131 | ! CODE |
|---|
| 132 | ! ---- |
|---|
| 133 | ! Pre-processing step |
|---|
| 134 | !~~~~~~~~~~~~~~~~~~~~ |
|---|
| 135 | ! Elapsed time with system clock |
|---|
| 136 | call system_clock(count_rate = cr) |
|---|
| 137 | call system_clock(c1) |
|---|
| 138 | |
|---|
| 139 | ! Parse command-line options |
|---|
| 140 | call parse_args() |
|---|
| 141 | |
|---|
| 142 | ! Initialization |
|---|
| 143 | ! ~~~~~~~~~~~~~~ |
|---|
| 144 | ! Header |
|---|
| 145 | call read_display_config() |
|---|
| 146 | call print_ini() |
|---|
| 147 | |
|---|
| 148 | ! Allocate module arrays |
|---|
| 149 | call ini_allocation() |
|---|
| 150 | |
|---|
| 151 | ! Read the duration information of the workflow |
|---|
| 152 | call read_workflow_status() |
|---|
| 153 | |
|---|
| 154 | ! Read the PEM parameters |
|---|
| 155 | call read_rundef() |
|---|
| 156 | |
|---|
| 157 | ! Read the orbital parameters |
|---|
| 158 | call read_orbitpm(n_yr_sim) |
|---|
| 159 | |
|---|
| 160 | ! Read the "start.nc" |
|---|
| 161 | call read_start() |
|---|
| 162 | |
|---|
| 163 | ! Read the "startfi.nc" |
|---|
| 164 | call read_startfi() |
|---|
| 165 | |
|---|
| 166 | ! Read the PCM data given by XIOS |
|---|
| 167 | allocate(ps_avg(ngrid),ps_ts(ngrid,nday)) |
|---|
| 168 | allocate(tsurf_avg(ngrid,nslope),tsurf_avg_yr1(ngrid,nslope),h2o_surfdensity_avg(ngrid,nslope)) |
|---|
| 169 | allocate(tsoil_avg(ngrid,nsoil,nslope),tsoil_ts(ngrid,nsoil,nslope,nday),h2o_soildensity_avg(ngrid,nsoil,nslope)) |
|---|
| 170 | allocate(q_h2o_ts(ngrid,nday),q_co2_ts(ngrid,nday)) |
|---|
| 171 | allocate(minPCM_h2operice(ngrid,nslope,2),minPCM_co2perice(ngrid,nslope,2),minPCM_h2ofrost(ngrid,nslope,2),minPCM_co2frost(ngrid,nslope,2)) |
|---|
| 172 | |
|---|
| 173 | call load_xios_data(ps_avg,ps_ts,tsurf_avg,tsurf_avg_yr1,tsoil_avg,tsoil_ts,h2o_surfdensity_avg,h2o_soildensity_avg, & |
|---|
| 174 | q_h2o_ts,q_co2_ts,minPCM_h2operice,minPCM_co2perice,minPCM_h2ofrost,minPCM_co2frost) |
|---|
| 175 | |
|---|
| 176 | ! Initiate soil settings and TI |
|---|
| 177 | if (do_soil) call set_soil(TI) |
|---|
| 178 | |
|---|
| 179 | ! Compute the deviation from the average |
|---|
| 180 | allocate(ps_dev(ngrid),tsurf_dev(ngrid,nslope),tsoil_dev(ngrid,nsoil_PCM,nslope)) |
|---|
| 181 | ps_dev(:) = ps_PCM(:) - ps_avg(:) |
|---|
| 182 | tsurf_dev(:,:) = tsurf_PCM(:,:) - tsurf_avg(:,:) |
|---|
| 183 | tsoil_dev(:,:,:) = tsoil_PCM(:,:,:) - tsoil_avg(:,1:nsoil_PCM,:) |
|---|
| 184 | |
|---|
| 185 | ! Compute global surface pressure |
|---|
| 186 | ps_avg_glob = sum(cell_area*ps_avg)/total_surface |
|---|
| 187 | |
|---|
| 188 | ! Compute the accepted maximum number of years due to orbital parameters (if needed) |
|---|
| 189 | call compute_maxyr_orbit(n_yr_sim,nmax_yr_runorb) |
|---|
| 190 | |
|---|
| 191 | ! Read the "startevo.nc" |
|---|
| 192 | allocate(h2o_ice(ngrid,nslope),co2_ice(ngrid,nslope)) |
|---|
| 193 | allocate(h2o_ads_reg(ngrid,nsoil,nslope),co2_ads_reg(ngrid,nsoil,nslope),delta_h2o_ads(ngrid),delta_co2_ads(ngrid)) |
|---|
| 194 | allocate(layerings_map(ngrid,nslope)) |
|---|
| 195 | delta_h2o_ads(:) = 0._dp |
|---|
| 196 | delta_co2_ads(:) = 0._dp |
|---|
| 197 | call read_startpem(tsurf_avg_yr1,tsurf_avg,ps_avg_glob_ini,ps_ts,q_co2_ts,q_h2o_ts,h2o_surfdensity_avg,h2o_ice,co2_ice, & |
|---|
| 198 | tsoil_avg,h2o_soildensity_avg,icetable_depth,icetable_thickness,ice_porefilling,layerings_map, & |
|---|
| 199 | h2o_ads_reg,co2_ads_reg,delta_h2o_ads,delta_co2_ads) |
|---|
| 200 | deallocate(tsurf_avg_yr1) |
|---|
| 201 | |
|---|
| 202 | ! Compute ice tendencies from yearly minima |
|---|
| 203 | allocate(d_h2oice(ngrid,nslope),d_co2ice(ngrid,nslope)) |
|---|
| 204 | call print_msg('> Computing surface ice tendencies',LVL_NFO) |
|---|
| 205 | call compute_tendice(minPCM_h2operice + minPCM_h2ofrost,h2o_ice(:,:) > 0._dp,d_h2oice) |
|---|
| 206 | call print_msg('H2O ice tendencies [kg/m2/yr] (min|max): '//real2str(minval(d_h2oice))//' | '//real2str(maxval(d_h2oice)),LVL_NFO) |
|---|
| 207 | call compute_tendice(minPCM_co2perice + minPCM_co2frost,co2_ice(:,:) > 0._dp,d_co2ice) |
|---|
| 208 | call print_msg('CO2 ice tendencies [kg/m2/yr] (min|max): '//real2str(minval(d_co2ice))//' | '//real2str(maxval(d_co2ice)),LVL_NFO) |
|---|
| 209 | deallocate(minPCM_h2operice,minPCM_co2perice,minPCM_h2ofrost,minPCM_co2frost) |
|---|
| 210 | |
|---|
| 211 | ! Save initial set-up useful for the next computations |
|---|
| 212 | call print_msg('> Saving some initial climate state variables',LVL_NFO) |
|---|
| 213 | allocate(d_co2ice_ini(ngrid,nslope),q_co2_ts_ini(ngrid,nday)) |
|---|
| 214 | allocate(is_h2oice_ini(ngrid,nslope),is_co2ice_ini(ngrid,nslope)) |
|---|
| 215 | ps_avg_glob_ini = ps_avg_glob |
|---|
| 216 | d_co2ice_ini(:,:) = d_co2ice(:,:) |
|---|
| 217 | q_co2_ts_ini(:,:) = q_co2_ts(:,:) |
|---|
| 218 | h2oice_sublim_coverage_ini = 0._dp |
|---|
| 219 | co2ice_sublim_coverage_ini = 0._dp |
|---|
| 220 | is_h2oice_ini(:,:) = .false. |
|---|
| 221 | is_co2ice_ini(:,:) = .false. |
|---|
| 222 | totmass_co2ice_ini = 0._qp |
|---|
| 223 | totmass_atmco2_ini = 0._qp |
|---|
| 224 | totmass_adsco2_ini = 0._qp |
|---|
| 225 | totmass_adsh2o = 0._qp |
|---|
| 226 | do i = 1,ngrid |
|---|
| 227 | totmass_atmco2_ini = totmass_atmco2_ini + cell_area(i)*ps_avg(i)/g |
|---|
| 228 | do islope = 1,nslope |
|---|
| 229 | totmass_co2ice_ini = totmass_co2ice_ini + co2_ice(i,islope)*cell_area(i)*subslope_dist(i,islope)/cos(pi*def_slope_mean(islope)/180._dp) |
|---|
| 230 | if (co2_ice(i,islope) > 0._dp) then |
|---|
| 231 | is_co2ice_ini(i,islope) = .true. |
|---|
| 232 | if (d_co2ice(i,islope) < 0._dp) co2ice_sublim_coverage_ini = co2ice_sublim_coverage_ini + cell_area(i)*subslope_dist(i,islope)/cos(pi*def_slope_mean(islope)/180._dp) |
|---|
| 233 | end if |
|---|
| 234 | if (h2o_ice(i,islope) > 0._dp) then |
|---|
| 235 | is_h2oice_ini(i,islope) = .true. |
|---|
| 236 | if (d_h2oice(i,islope) < 0._dp) h2oice_sublim_coverage_ini = h2oice_sublim_coverage_ini + cell_area(i)*subslope_dist(i,islope)/cos(pi*def_slope_mean(islope)/180._dp) |
|---|
| 237 | end if |
|---|
| 238 | end do |
|---|
| 239 | end do |
|---|
| 240 | call print_msg("Initial global average pressure [Pa] = "//real2str(ps_avg_glob_ini),LVL_NFO) |
|---|
| 241 | call print_msg("Initial surface area of sublimating CO2 ice [m2] = "//real2str(co2ice_sublim_coverage_ini),LVL_NFO) |
|---|
| 242 | call print_msg("Initial surface area of sublimating H2O ice [m2] = "//real2str(h2oice_sublim_coverage_ini),LVL_NFO) |
|---|
| 243 | if (do_sorption) call compute_totmass_adsorbed(h2o_ads_reg,co2_ads_reg,totmass_adsco2_ini,totmass_adsh2o) |
|---|
| 244 | |
|---|
| 245 | ! Main evolution loop |
|---|
| 246 | ! ~~~~~~~~~~~~~~~~~~~ |
|---|
| 247 | call print_msg('',LVL_NFO) |
|---|
| 248 | call print_msg('********* Evolution *********',LVL_NFO) |
|---|
| 249 | if (do_layering) then |
|---|
| 250 | allocate(h2oice_depth(ngrid,nslope),h2oice_depth_old(ngrid,nslope),new_str(ngrid,nslope),new_lag(ngrid,nslope),current(ngrid,nslope)) |
|---|
| 251 | new_str = .true. |
|---|
| 252 | new_lag = .true. |
|---|
| 253 | do islope = 1,nslope |
|---|
| 254 | do i = 1,ngrid |
|---|
| 255 | current(i,islope)%p => layerings_map(i,islope)%top |
|---|
| 256 | end do |
|---|
| 257 | end do |
|---|
| 258 | ! Conversion to surface ice |
|---|
| 259 | call layering2surfice(layerings_map,h2o_ice,co2_ice,h2oice_depth) |
|---|
| 260 | ! We put the sublimating tendency coming from subsurface ice into the overall tendency |
|---|
| 261 | !where (h2oice_depth > 0. .and. zdqsdif_ssi_tot < -minieps) d_h2oice = zdqsdif_ssi_tot |
|---|
| 262 | end if |
|---|
| 263 | if (nslope == 1) then ! No slope |
|---|
| 264 | allocate(character(0) :: num) |
|---|
| 265 | else ! Using slopes |
|---|
| 266 | allocate(character(8) :: num) |
|---|
| 267 | end if |
|---|
| 268 | allocate(delta_icetable(ngrid),icetable_depth_old(ngrid,nslope),is_co2ice_disappeared(ngrid,nslope),tsoil_ts_old(ngrid,nsoil,nslope,nday)) |
|---|
| 269 | is_co2ice_disappeared(:,:) = .false. |
|---|
| 270 | delta_icetable(:) = 0._dp |
|---|
| 271 | n_yr_run = 0 |
|---|
| 272 | idt = 0 |
|---|
| 273 | do while (n_yr_run < min(nmax_yr_runorb,nmax_yr_run) .and. n_yr_sim < ntot_yr_sim) |
|---|
| 274 | call print_msg('**** Iteration of the PEM run [Planetary years]: '//real2str(n_yr_run + dt),LVL_NFO) |
|---|
| 275 | ! Evolve global surface pressure |
|---|
| 276 | call evolve_pressure(d_co2ice,delta_co2_ads,do_sorption,ps_avg_glob_old,ps_avg_glob,ps_avg) |
|---|
| 277 | |
|---|
| 278 | ! Adapt tracers according to global surface pressure |
|---|
| 279 | call adapt_tracers2pressure(ps_avg_glob_old,ps_avg_glob,ps_ts,q_h2o_ts,q_co2_ts) |
|---|
| 280 | |
|---|
| 281 | ! Evolve surface ice |
|---|
| 282 | allocate(zshift_surf(ngrid,nslope),zlag(ngrid,nslope)) |
|---|
| 283 | if (do_layering) then |
|---|
| 284 | h2oice_depth_old(:,:) = h2oice_depth(:,:) |
|---|
| 285 | do islope = 1,nslope |
|---|
| 286 | do i = 1,ngrid |
|---|
| 287 | call evolve_layering(layerings_map(i,islope),d_co2ice(i,islope),d_h2oice_new(i,islope),new_str(i,islope),zshift_surf(i,islope),new_lag(i,islope),zlag(i,islope),current(i,islope)%p) |
|---|
| 288 | call print_layering(layerings_map(i,islope)) |
|---|
| 289 | end do |
|---|
| 290 | end do |
|---|
| 291 | ! Conversion to surface ice |
|---|
| 292 | call layering2surfice(layerings_map,h2o_ice,co2_ice,h2oice_depth) |
|---|
| 293 | ! Balance H2O ice reservoirs |
|---|
| 294 | allocate(d_h2oice_new(ngrid,nslope)) |
|---|
| 295 | call stopping_crit_h2o(delta_h2o_ads,delta_icetable,h2o_ice,d_h2oice,S_atm_2_h2o,S_h2o_2_atm,S_atm_2_h2oice,S_h2oice_2_atm,stopcrit) |
|---|
| 296 | call balance_h2oice_reservoirs(S_atm_2_h2o,S_h2o_2_atm,S_atm_2_h2oice,S_h2oice_2_atm,h2o_ice,d_h2oice,d_h2oice_new) |
|---|
| 297 | deallocate(d_h2oice_new) |
|---|
| 298 | else |
|---|
| 299 | zlag(:,:) = 0._dp |
|---|
| 300 | call evolve_h2oice(delta_h2o_ads,delta_icetable,h2o_ice,d_h2oice,zshift_surf,stopcrit) |
|---|
| 301 | call evolve_co2ice(co2_ice,d_co2ice,zshift_surf) |
|---|
| 302 | end if |
|---|
| 303 | |
|---|
| 304 | ! Flow glaciers according to surface ice |
|---|
| 305 | if (co2ice_flow) then |
|---|
| 306 | allocate(is_co2ice_flow(ngrid,nslope)) |
|---|
| 307 | call flow_co2glaciers(q_co2_ts,ps_ts,ps_avg_glob_old,ps_avg_glob,co2_ice,is_co2ice_flow) |
|---|
| 308 | end if |
|---|
| 309 | if (h2oice_flow) then |
|---|
| 310 | allocate(is_h2oice_flow(ngrid,nslope)) |
|---|
| 311 | call flow_h2oglaciers(tsurf_avg,h2o_ice,is_h2oice_flow) |
|---|
| 312 | end if |
|---|
| 313 | if (do_layering) call surfice2layering(h2o_ice,co2_ice,layerings_map) |
|---|
| 314 | |
|---|
| 315 | ! Adapt surface temperature if surface ice disappeared |
|---|
| 316 | call adapt_tsurf2disappearedice(co2_ice,is_co2ice_ini,is_co2ice_disappeared,tsurf_avg) |
|---|
| 317 | !call adapt_tsurf2disappearedice(h2o_ice,is_h2oice_ini,tsurf_avg) |
|---|
| 318 | |
|---|
| 319 | if (do_soil) then |
|---|
| 320 | ! Shift soil temperature to surface |
|---|
| 321 | call shift_tsoil2surf(ngrid,nsoil,nslope,zshift_surf,zlag,tsurf_avg,tsoil_avg) |
|---|
| 322 | |
|---|
| 323 | ! Evolve soil temperature |
|---|
| 324 | call evolve_soil_temp(tsoil_avg,tsurf_avg,tsoil_ts,tsoil_ts_old,h2o_soildensity_avg) |
|---|
| 325 | |
|---|
| 326 | ! Evolve ice table |
|---|
| 327 | call evolve_ice_table(h2o_ice,h2o_surfdensity_avg,h2o_soildensity_avg,tsoil_avg,tsurf_avg,delta_icetable,q_h2o_ts, & |
|---|
| 328 | ps_avg,icetable_depth,icetable_thickness,ice_porefilling,icetable_depth_old) |
|---|
| 329 | |
|---|
| 330 | ! Update soil thermal properties according to ice table and soil temperature |
|---|
| 331 | call update_soil_TI(h2o_ice,ps_avg_glob,icetable_depth,icetable_thickness,ice_porefilling,icetable_equilibrium,icetable_dynamic,TI) |
|---|
| 332 | |
|---|
| 333 | ! Evolve adsorbed species |
|---|
| 334 | if (do_sorption) then |
|---|
| 335 | call evolve_regolith_adsorption(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) |
|---|
| 336 | call compute_totmass_adsorbed(h2o_ads_reg,co2_ads_reg,totmass_adsco2,totmass_adsh2o) |
|---|
| 337 | else |
|---|
| 338 | totmass_adsh2o = 0._dp |
|---|
| 339 | totmass_adsco2 = 0._dp |
|---|
| 340 | end if |
|---|
| 341 | end if ! do_soil |
|---|
| 342 | deallocate(zshift_surf,zlag) |
|---|
| 343 | |
|---|
| 344 | ! Output the results |
|---|
| 345 | call print_msg('> Standard outputs',LVL_NFO) |
|---|
| 346 | call write_diagevo('ps_avg_glob','Global average pressure','Pa',ps_avg_glob) |
|---|
| 347 | do islope = 1,nslope |
|---|
| 348 | if (nslope /= 1) then |
|---|
| 349 | num = ' ' |
|---|
| 350 | write(num,'(i2.2)') islope |
|---|
| 351 | num = '_slope'//num |
|---|
| 352 | end if |
|---|
| 353 | call write_diagevo('h2oice'//num,'H2O ice','kg.m-2',h2o_ice(:,islope),(/dim_ngrid/)) |
|---|
| 354 | call write_diagevo('co2ice'//num,'CO2 ice','kg.m-2',co2_ice(:,islope),(/dim_ngrid/)) |
|---|
| 355 | call write_diagevo('d_h2oice'//num,'H2O ice tendency','kg.m-2.yr-1',d_h2oice(:,islope),(/dim_ngrid/)) |
|---|
| 356 | call write_diagevo('d_co2ice'//num,'CO2 ice tendency','kg.m-2.yr-1',d_co2ice(:,islope),(/dim_ngrid/)) |
|---|
| 357 | if (co2ice_flow) then |
|---|
| 358 | call write_diagevo('Flow_co2ice'//num,'CO2 ice flow location','T/F',merge(1._dp,0._dp,is_co2ice_flow(:,islope)),(/dim_ngrid/)) |
|---|
| 359 | deallocate(is_co2ice_flow) |
|---|
| 360 | end if |
|---|
| 361 | if (h2oice_flow) then |
|---|
| 362 | call write_diagevo('Flow_h2oice'//num,'H2O ice flow location','T/F',merge(1._dp,0._dp,is_h2oice_flow(:,islope)),(/dim_ngrid/)) |
|---|
| 363 | deallocate(is_h2oice_flow) |
|---|
| 364 | end if |
|---|
| 365 | call write_diagevo('tsurf'//num,'Surface temperature','K',tsurf_avg(:,islope),(/dim_ngrid/)) |
|---|
| 366 | if (do_soil) then |
|---|
| 367 | if (icetable_equilibrium) then |
|---|
| 368 | call write_diagevo('icetable_depth'//num,'Ice table depth','m',icetable_depth(:,islope),(/dim_ngrid/)) |
|---|
| 369 | call write_diagevo('icetable_thick'//num,'Ice table thickness','m',icetable_thickness(:,islope),(/dim_ngrid/)) |
|---|
| 370 | else if (icetable_dynamic) then |
|---|
| 371 | call write_diagevo('icetable_depth'//num,'Ice table depth','m',icetable_depth(:,islope),(/dim_ngrid/)) |
|---|
| 372 | call write_diagevo('ice_porefilling'//num,'Ice pore filling','-',ice_porefilling(:,:,islope),(/dim_ngrid,dim_nsoil/)) |
|---|
| 373 | end if |
|---|
| 374 | call write_diagevo('tsoil_avg'//num,'Soil temperature','K',tsoil_avg(:,:,islope),(/dim_ngrid,dim_nsoil/)) |
|---|
| 375 | call write_diagevo('inertiesoil'//num,'Thermal inertia','SI',TI(:,:,islope),(/dim_ngrid,dim_nsoil/)) |
|---|
| 376 | if (do_sorption) then |
|---|
| 377 | call write_diagevo('co2_ads_reg'//num,'CO2 adsorbed in regolith','kg.m-2',co2_ads_reg(:,:,islope),(/dim_ngrid,dim_nsoil/)) |
|---|
| 378 | call write_diagevo('h2o_ads_reg'//num,'H2O adsorbed in regolith','kg.m-2',h2o_ads_reg(:,:,islope),(/dim_ngrid,dim_nsoil/)) |
|---|
| 379 | end if |
|---|
| 380 | end if |
|---|
| 381 | end do |
|---|
| 382 | |
|---|
| 383 | ! Checking mass balance for CO2 |
|---|
| 384 | if (abs(CO2cond_ps_PCM - 1._dp) < minieps) then |
|---|
| 385 | totmass_co2ice = 0._dp |
|---|
| 386 | totmass_atmco2 = 0._dp |
|---|
| 387 | do i = 1,ngrid |
|---|
| 388 | totmass_atmco2 = totmass_atmco2 + cell_area(i)*ps_avg(i)/g |
|---|
| 389 | do islope = 1,nslope |
|---|
| 390 | totmass_co2ice = totmass_co2ice + co2_ice(i,islope)*cell_area(i)*subslope_dist(i,islope)/cos(pi*def_slope_mean(islope)/180.) |
|---|
| 391 | end do |
|---|
| 392 | end do |
|---|
| 393 | totmass_ini = max(totmass_atmco2_ini + totmass_co2ice_ini + totmass_adsco2_ini,minieps_qp) ! To avoid division by 0 |
|---|
| 394 | call print_msg(" > Relative total CO2 mass balance = "//real2str(100._qp*(totmass_atmco2 + totmass_co2ice + totmass_adsco2 - totmass_atmco2_ini - totmass_co2ice_ini - totmass_adsco2_ini)/totmass_ini)//' %',LVL_NFO) |
|---|
| 395 | if (abs((totmass_atmco2 + totmass_co2ice + totmass_adsco2 - totmass_atmco2_ini - totmass_co2ice_ini - totmass_adsco2_ini)/totmass_ini) > 0.01_qp) then |
|---|
| 396 | call print_msg('Mass balance is not conserved!',LVL_WRN) |
|---|
| 397 | totmass_ini = max(totmass_atmco2_ini,minieps_qp) ! To avoid division by 0 |
|---|
| 398 | call print_msg(' Atmospheric CO2 mass balance = '//real2str(100._qp*(totmass_atmco2 - totmass_atmco2_ini)/totmass_ini)//' %',LVL_WRN) |
|---|
| 399 | totmass_ini = max(totmass_co2ice_ini,minieps_qp) ! To avoid division by 0 |
|---|
| 400 | call print_msg(' CO2 ice mass balance = '//real2str(100._qp*(totmass_co2ice - totmass_co2ice_ini)/totmass_ini)//' %',LVL_WRN) |
|---|
| 401 | totmass_ini = max(totmass_adsco2_ini,minieps_qp) ! To avoid division by 0 |
|---|
| 402 | call print_msg(' Adsorbed CO2 mass balance = '//real2str(100._qp*(totmass_adsco2 - totmass_adsco2_ini)/totmass_ini)//' %',LVL_WRN) |
|---|
| 403 | end if |
|---|
| 404 | end if |
|---|
| 405 | |
|---|
| 406 | ! Evolve the tendencies |
|---|
| 407 | call evolve_tend_co2ice(d_co2ice_ini,co2_ice,emissivity_PCM,q_co2_ts_ini,q_co2_ts,ps_ts,ps_avg_glob_ini,ps_avg_glob,d_co2ice) |
|---|
| 408 | !~ if (do_layering) then |
|---|
| 409 | !~ do i = 1,ngrid |
|---|
| 410 | !~ do islope = 1,nslope |
|---|
| 411 | !~ if (is_h2oice_sublim_ini(i,islope) .and. h2oice_depth(i,islope) > 0._dp) call evolve_tend_h2oice(h2oice_depth_old(i,islope),h2oice_depth(i,islope),tsurf_avg(i,islope),tsoil_ts_old(i,:,islope,:),tsoil_ts(i,:,islope,:),d_h2oice(i,islope)) |
|---|
| 412 | !~ end do |
|---|
| 413 | !~ end do |
|---|
| 414 | ! else |
|---|
| 415 | ! do i = 1,ngrid |
|---|
| 416 | ! do islope = 1,nslope |
|---|
| 417 | ! call evolve_tend_h2oice(icetable_depth_old(i,islope),icetable_depth(i,islope),tsurf_avg(i,islope),tsoil_ts_old(i,:,islope,:),tsoil_ts(i,:,islope,:),d_h2oice(i,islope)) |
|---|
| 418 | ! end do |
|---|
| 419 | ! end do |
|---|
| 420 | !~ end if |
|---|
| 421 | |
|---|
| 422 | ! Increment time |
|---|
| 423 | n_yr_run = n_yr_run + dt |
|---|
| 424 | n_yr_sim = n_yr_sim + dt |
|---|
| 425 | idt = idt + 1 |
|---|
| 426 | |
|---|
| 427 | ! Save periodic backups of restart files |
|---|
| 428 | if (backup_rate > 0 .and. mod(idt,backup_rate) == 0) then |
|---|
| 429 | call save_clim_state(h2o_ice,co2_ice,tsurf_avg,tsurf_dev,tsoil_avg,tsoil_dev,ps_avg,ps_dev,ps_avg_glob,ps_avg_glob_ini, & |
|---|
| 430 | icetable_depth,icetable_thickness,ice_porefilling,h2o_ads_reg,co2_ads_reg,layerings_map,idt) |
|---|
| 431 | end if |
|---|
| 432 | |
|---|
| 433 | ! Check the stopping criteria |
|---|
| 434 | call print_msg("> Checking the stopping criteria",LVL_NFO) |
|---|
| 435 | call stopping_crit_pressure(ps_avg_glob_ini,ps_avg_glob,stopcrit) |
|---|
| 436 | call stopping_crit_h2oice(h2oice_sublim_coverage_ini,h2o_ice,d_h2oice,stopcrit) |
|---|
| 437 | call stopping_crit_co2ice(co2ice_sublim_coverage_ini,co2_ice,d_co2ice,stopcrit) |
|---|
| 438 | call system_clock(c2) |
|---|
| 439 | if (stopcrit%stop_code() == 0 .and. n_yr_run >= nmax_yr_run) stopcrit%nmax_yr_run_reached = .true. |
|---|
| 440 | if (stopcrit%stop_code() == 0 .and. n_yr_run >= nmax_yr_runorb) stopcrit%nmax_yr_runorb_reached = .true. |
|---|
| 441 | if (stopcrit%stop_code() == 0 .and. n_yr_sim >= ntot_yr_sim) stopcrit%nmax_yr_sim_reached = .true. |
|---|
| 442 | if (stopcrit%stop_code() == 0 .and. timewall .and. real(c2 - c1,dp)/real(cr,dp) >= timelimit - antetime) stopcrit%time_limit_reached = .true. |
|---|
| 443 | if (stopcrit%is_any_set()) then |
|---|
| 444 | call print_msg(stopcrit%stop_message(),LVL_NFO) |
|---|
| 445 | exit |
|---|
| 446 | else |
|---|
| 447 | call print_msg('**** This run has achieved '//real2str(n_yr_run)//' Planetary years.',LVL_NFO) |
|---|
| 448 | call print_msg('**** The workflow has achieved '//real2str(n_yr_sim)//' Planetary years.',LVL_NFO) |
|---|
| 449 | call print_msg('**** This run is continuing!',LVL_NFO) |
|---|
| 450 | call print_msg('****',LVL_NFO) |
|---|
| 451 | end if |
|---|
| 452 | end do ! End of the evolution loop |
|---|
| 453 | deallocate(is_co2ice_disappeared) |
|---|
| 454 | |
|---|
| 455 | ! Finalization |
|---|
| 456 | ! ~~~~~~~~~~~~ |
|---|
| 457 | call print_msg('',LVL_NFO) |
|---|
| 458 | call print_msg('********* Finalization *********',LVL_NFO) |
|---|
| 459 | ! Update orbital parameters |
|---|
| 460 | if (evo_orbit) call update_orbit(n_yr_sim,n_yr_run) |
|---|
| 461 | |
|---|
| 462 | call save_clim_state(h2o_ice,co2_ice,tsurf_avg,tsurf_dev,tsoil_avg,tsoil_dev,ps_avg,ps_dev,ps_avg_glob,ps_avg_glob_ini, & |
|---|
| 463 | icetable_depth,icetable_thickness,ice_porefilling,h2o_ads_reg,co2_ads_reg,layerings_map) |
|---|
| 464 | |
|---|
| 465 | ! Update the duration information of the workflow |
|---|
| 466 | call update_workflow_status(n_yr_run,stopcrit%stop_code(),n_yr_sim,ntot_yr_sim) |
|---|
| 467 | |
|---|
| 468 | ! Deallocation |
|---|
| 469 | deallocate(num) |
|---|
| 470 | if (do_layering) then |
|---|
| 471 | deallocate(h2oice_depth,h2oice_depth_old,new_str,new_lag,current) |
|---|
| 472 | do islope = 1,nslope |
|---|
| 473 | do i = 1,ngrid |
|---|
| 474 | call del_layering(layerings_map(i,islope)) |
|---|
| 475 | end do |
|---|
| 476 | end do |
|---|
| 477 | end if |
|---|
| 478 | deallocate(layerings_map) |
|---|
| 479 | deallocate(h2o_ads_reg,co2_ads_reg) |
|---|
| 480 | deallocate(h2o_ice,co2_ice,is_h2oice_ini,is_co2ice_ini) |
|---|
| 481 | deallocate(ps_avg,ps_dev,ps_ts) |
|---|
| 482 | deallocate(tsurf_avg,tsurf_dev,h2o_surfdensity_avg) |
|---|
| 483 | deallocate(tsoil_avg,tsoil_dev,tsoil_ts,tsoil_ts_old,h2o_soildensity_avg) |
|---|
| 484 | deallocate(q_h2o_ts,q_co2_ts,q_co2_ts_ini) |
|---|
| 485 | deallocate(d_h2oice,d_co2ice,d_co2ice_ini) |
|---|
| 486 | deallocate(delta_h2o_ads,delta_co2_ads,delta_icetable,icetable_depth_old) |
|---|
| 487 | call end_allocation() |
|---|
| 488 | |
|---|
| 489 | ! Footer |
|---|
| 490 | call system_clock(c2) |
|---|
| 491 | call print_end(i_pem_run,n_yr_run,n_yr_sim,real((c2 - c1),dp)/real(cr,dp),pem_ini_date,r_plnt2earth_yr) |
|---|
| 492 | |
|---|
| 493 | END PROGRAM pem |
|---|