Ignore:
Timestamp:
Apr 8, 2026, 11:36:16 AM (2 days ago)
Author:
jbclement
Message:

PEM:
Refactor of H2O flux balancing:

  • centralizes flux balancing logic;
  • removes intermediate variables, especially related to of H2O mass bookkeeping;
  • adds new stopping criterion when H2O flux balance fails8 (sanity check);
  • introduces configurable weighting strategies for H2O flux balancing.

JBC

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/LMDZ.COMMON/libf/evolution/stopping_crit.F90

    r4170 r4174  
    3131! ---------
    3232type :: stopFlags
    33     logical(k4) :: surface_h2oice_change  = .false.
    34     logical(k4) :: zero_dh2oice          = .false.
    35     logical(k4) :: surface_co2ice_change  = .false.
    36     logical(k4) :: pressure_change        = .false.
    37     logical(k4) :: nmax_yr_run_reached    = .false.
    38     logical(k4) :: nmax_yr_runorb_reached = .false.
    39     logical(k4) :: nmax_yr_sim_reached    = .false.
    40     logical(k4) :: time_limit_reached     = .false.
     33    logical(k4) :: surface_h2oice_change     = .false.
     34    logical(k4) :: h2o_flux_balance_unclosed = .false.
     35    logical(k4) :: surface_co2ice_change     = .false.
     36    logical(k4) :: pressure_change           = .false.
     37    logical(k4) :: nmax_yr_run_reached       = .false.
     38    logical(k4) :: nmax_yr_runorb_reached    = .false.
     39    logical(k4) :: nmax_yr_sim_reached       = .false.
     40    logical(k4) :: time_limit_reached        = .false.
    4141contains
    4242    procedure :: is_any_set
     
    120120! CODE
    121121! ----
    122 stopPEM = this%surface_h2oice_change  .or. &
    123           this%zero_dh2oice          .or. &
    124           this%surface_co2ice_change  .or. &
    125           this%pressure_change        .or. &
    126           this%nmax_yr_run_reached    .or. &
    127           this%nmax_yr_runorb_reached .or. &
    128           this%nmax_yr_sim_reached    .or. &
     122stopPEM = this%surface_h2oice_change     .or. &
     123          this%h2o_flux_balance_unclosed .or. &
     124          this%surface_co2ice_change     .or. &
     125          this%pressure_change           .or. &
     126          this%nmax_yr_run_reached       .or. &
     127          this%nmax_yr_runorb_reached    .or. &
     128          this%nmax_yr_sim_reached       .or. &
    129129          this%time_limit_reached
    130130
     
    160160! ----
    161161code = 0
    162 if     (this%surface_h2oice_change)  then; code = 1
    163 elseif (this%zero_dh2oice)          then; code = 2
    164 elseif (this%surface_co2ice_change)  then; code = 3
    165 elseif (this%pressure_change)        then; code = 4
    166 elseif (this%nmax_yr_run_reached)    then; code = 5
    167 elseif (this%nmax_yr_runorb_reached) then; code = 6
    168 elseif (this%nmax_yr_sim_reached)    then; code = 7
    169 elseif (this%time_limit_reached)     then; code = 8
     162if     (this%surface_h2oice_change)     then; code = 1
     163elseif (this%h2o_flux_balance_unclosed) then; code = 2
     164elseif (this%surface_co2ice_change)     then; code = 3
     165elseif (this%pressure_change)           then; code = 4
     166elseif (this%nmax_yr_run_reached)       then; code = 5
     167elseif (this%nmax_yr_runorb_reached)    then; code = 6
     168elseif (this%nmax_yr_sim_reached)       then; code = 7
     169elseif (this%time_limit_reached)        then; code = 8
    170170end if
    171171
     
    200200! CODE
    201201! ----
    202 if     (this%surface_h2oice_change)  then; msg = "**** STOPPING because surface of H2O ice has changed too much (see message above)."
    203 elseif (this%zero_dh2oice)           then; msg = "**** STOPPING because tendencies on H2O ice = 0 (see message above)."
    204 elseif (this%surface_co2ice_change)  then; msg = "**** STOPPING because surface of CO2 ice has changed too much (see message above)."
    205 elseif (this%pressure_change)        then; msg = "**** STOPPING because surface global pressure has changed too much (see message above)."
    206 elseif (this%nmax_yr_run_reached)    then; msg = "**** STOPPING because maximum number of years is reached."
    207 elseif (this%nmax_yr_runorb_reached) then; msg = "**** STOPPING because maximum number of years due to orbital parameters is reached."
    208 elseif (this%nmax_yr_sim_reached)    then; msg = "**** STOPPING because the number of years to be simulated is reached."
    209 elseif (this%time_limit_reached)     then; msg = "**** STOPPING because the job time limit is going to be reached."
     202if     (this%surface_h2oice_change)     then; msg = "**** STOPPING because surface of H2O ice has changed too much (see message above)."
     203elseif (this%h2o_flux_balance_unclosed) then; msg = "**** STOPPING because H2O flux imbalance cannot be closed under physical bounds (see message above)."
     204elseif (this%surface_co2ice_change)     then; msg = "**** STOPPING because surface of CO2 ice has changed too much (see message above)."
     205elseif (this%pressure_change)           then; msg = "**** STOPPING because surface global pressure has changed too much (see message above)."
     206elseif (this%nmax_yr_run_reached)       then; msg = "**** STOPPING because maximum number of years is reached."
     207elseif (this%nmax_yr_runorb_reached)    then; msg = "**** STOPPING because maximum number of years due to orbital parameters is reached."
     208elseif (this%nmax_yr_sim_reached)       then; msg = "**** STOPPING because the number of years to be simulated is reached."
     209elseif (this%time_limit_reached)        then; msg = "**** STOPPING because the job time limit is going to be reached."
     210else
     211    msg = "**** STOPPING for unknown reason (this should not happen!)."
    210212end if
    211213
     
    388390!=======================================================================
    389391
    390 !=======================================================================
    391 SUBROUTINE 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)
    392 !-----------------------------------------------------------------------
    393 ! NAME
    394 !     stopping_crit_h2o
    395 !
    396 ! DESCRIPTION
    397 !     Check if PEM oscillates infinitely with H2O (no net exchange).
    398 !
    399 ! AUTHORS & DATE
    400 !     L. Lange, 2024
    401 !     JB Clement, 2025
    402 !
    403 ! NOTES
    404 !
    405 !-----------------------------------------------------------------------
    406 
    407 ! DEPENDENCIES
    408 ! ------------
    409 use geometry,  only: ngrid, nslope, cell_area
    410 use evolution, only: dt
    411 use slopes,    only: subslope_dist, def_slope_mean
    412 use maths,     only: pi
    413 use display,   only: print_msg, LVL_WRN
    414 use utility,   only: real2str
    415 
    416 ! DECLARATION
    417 ! -----------
    418 implicit none
    419 
    420 ! ARGUMENTS
    421 ! ---------
    422 real(dp), dimension(:),   intent(in)    :: delta_h2o_ads            ! Mass of H2O adsorbed/desorbded in the soil (kg/m^2)
    423 real(dp), dimension(:),   intent(in)    :: delta_icetable ! Mass of H2O that condensed/sublimated at the ice table
    424 real(dp), dimension(:,:), intent(in)    :: h2o_ice, d_h2oice
    425 real(qp),                 intent(out)   :: S_atm_2_h2o, S_h2o_2_atm, S_atm_2_h2oice, S_h2oice_2_atm
    426 type(stopFlags),          intent(inout) :: stopcrit
    427 
    428 ! LOCAL VARIABLES
    429 ! ---------------
    430 integer(di) :: i, islope
    431 
    432 ! CODE
    433 ! ----
    434 ! Check to escape the subroutine (not relevant in 1D or if the PEM should stop already)
    435 if (ngrid == 1 .or. stopcrit%stop_code() > 0) then
    436     S_atm_2_h2o = 1._qp
    437     S_h2o_2_atm = S_atm_2_h2o
    438     S_atm_2_h2oice = 1._qp
    439     S_h2oice_2_atm = S_atm_2_h2oice
    440     return
    441 end if
    442 
    443 ! We compute the amount of water going out from the atmosphere (S_atm_2_h2o) and going into the atmophere (S_h2o_2_atm)
    444 S_atm_2_h2o = 0._qp
    445 S_h2o_2_atm = 0._qp
    446 S_atm_2_h2oice = 0._qp
    447 S_h2oice_2_atm = 0._qp
    448 do i = 1,ngrid
    449     if (delta_h2o_ads(i) > 0._dp) then
    450         S_atm_2_h2o = S_atm_2_h2o + delta_h2o_ads(i)*cell_area(i)
    451     else
    452         S_h2o_2_atm = S_h2o_2_atm - delta_h2o_ads(i)*cell_area(i)
    453     end if
    454     if (delta_icetable(i) > 0._dp) then
    455         S_atm_2_h2o = S_atm_2_h2o + delta_icetable(i)*cell_area(i)
    456     else
    457         S_h2o_2_atm = S_h2o_2_atm - delta_icetable(i)*cell_area(i)
    458     end if
    459     do islope = 1,nslope
    460         if (d_h2oice(i,islope) > 0._dp) then
    461             S_atm_2_h2o = S_atm_2_h2o + d_h2oice(i,islope)*dt*cell_area(i)*subslope_dist(i,islope)/cos(def_slope_mean(islope)*pi/180._dp)
    462             S_atm_2_h2oice = S_atm_2_h2oice + d_h2oice(i,islope)*dt*cell_area(i)*subslope_dist(i,islope)/cos(def_slope_mean(islope)*pi/180._dp)
    463         else if (d_h2oice(i,islope) < 0._dp .and. h2o_ice(i,islope) > 0._dp) then
    464             S_h2o_2_atm = S_h2o_2_atm - d_h2oice(i,islope)*dt*cell_area(i)*subslope_dist(i,islope)/cos(def_slope_mean(islope)*pi/180._dp)
    465             S_h2oice_2_atm = S_h2oice_2_atm - d_h2oice(i,islope)*dt*cell_area(i)*subslope_dist(i,islope)/cos(def_slope_mean(islope)*pi/180._dp)
    466         end if
    467     end do
    468 end do
    469 
    470 ! Since relative atmospheric water is kept constant, we need to equate condensing reservoirs to the sublimating ones.
    471 ! It is not possible if one of them is missing.
    472 if ((abs(S_atm_2_h2oice) < minieps_qp .or. abs(S_h2oice_2_atm) < minieps_qp)) then
    473     call print_msg("There is no sublimating or condensing H2O ice! This can be due to the absence of H2O ice in the PCM run.",LVL_WRN)
    474     call print_msg("Amount of condensing ice  [kg] = "//real2str(S_atm_2_h2oice),LVL_WRN)
    475     call print_msg("Amount of sublimating ice [kg] = "//real2str(S_h2oice_2_atm),LVL_WRN)
    476     stopcrit%zero_dh2oice = .true.
    477 end if
    478 
    479 END SUBROUTINE stopping_crit_h2o
    480 !=======================================================================
    481 
    482392END MODULE stopping_crit
Note: See TracChangeset for help on using the changeset viewer.