diff --git a/components/mpas-albany-landice/src/Registry.xml b/components/mpas-albany-landice/src/Registry.xml index 279d7fb3c0a0..1c6e0f632985 100644 --- a/components/mpas-albany-landice/src/Registry.xml +++ b/components/mpas-albany-landice/src/Registry.xml @@ -145,9 +145,9 @@ description="Selection of the method for bedrock uplift calculation." possible_values="'none', 'data', 'sealevelmodel'" /> - \brief Perform various checks on the SLM coupling interval setting +!> \author Matt Hoffman +!> \date Feb 2024 +!> \details +!> This routine checks that the SLM coupling interval is an even multiple +!> of the adaptive timestep force inverval and divides evenly into the +!> restart interval. It also checks that the coupling interval in the MALI +!> matches the value in the SLM namelist. +! +!----------------------------------------------------------------------- + + subroutine check_SLM_coupling_interval(slm_dt1, meshPool, err) + + use mpas_timekeeping + use mpas_stream_manager + use mpas_derived_types, only : MPAS_STREAM_PROPERTY_RECORD_INTV + + integer, intent (in) :: slm_dt1 + type (mpas_pool_type), intent(in) :: meshPool !< mesh information + integer, intent(out) :: err + + ! local variables + integer, pointer :: config_slm_coupling_interval + logical, pointer :: config_adaptive_timestep + character (len=StrKIND), pointer :: config_adaptive_timestep_force_interval, config_dt + type (MPAS_TimeInterval_Type) :: coupling_interval, force_interval, dt_interval, zero_interval + type (MPAS_Time_Type) :: start_time + character (len=StrKIND), pointer :: simulationStartTime + integer :: YYYY, MM, DD, H, M, S ! time components + integer (kind=I8KIND) :: n_intervals + type (MPAS_TimeInterval_type) :: remainder + integer :: err_tmp + + err = 0 + err_tmp = 0 + + call mpas_log_write("") + call mpas_log_write("-- Checking consistency of config_slm_coupling_interval and other settings --") + + ! First, check consistency in coupling interval set up in MALI and SLM + call mpas_pool_get_config(liConfigs, "config_slm_coupling_interval", config_slm_coupling_interval) + if (config_slm_coupling_interval == slm_dt1) then + call mpas_log_write("The coupling interval in MALI ($i yr) and SLM ($i yr) are consistent - check passes", & + intArgs=(/config_slm_coupling_interval, slm_dt1/)) + else + call mpas_log_write("The coupling interval in MALI ($i yr) and SLM ($i yr) are inconsistent", MPAS_LOG_ERR, & + intArgs=(/config_slm_coupling_interval, slm_dt1/)) + err = ior(err, 1) + endif + + ! define zero interval for comparing against below + call mpas_set_timeInterval(zero_interval, dt = 0.0_RKIND) + ! get start time as a reference time + call mpas_pool_get_array(meshPool, 'simulationStartTime', simulationStartTime) + call mpas_set_time(start_time, dateTimeString=simulationStartTime) + ! define SLM coupling interval as a timeInterval type + call mpas_set_timeInterval(coupling_interval, YY=config_slm_coupling_interval, MM=0, DD=0, H=0, M=0, S=0, ierr=err_tmp) + err = ior(err, err_tmp) + + call mpas_pool_get_config(liConfigs, "config_adaptive_timestep", config_adaptive_timestep) + if (config_adaptive_timestep) then + ! for adaptive dt, check that config_adaptive_timestep_force_interval divides evenly into config_slm_coupling_interval + call mpas_pool_get_config(liConfigs, "config_adaptive_timestep_force_interval", config_adaptive_timestep_force_interval) + call mpas_set_timeInterval(force_interval, timeString=config_adaptive_timestep_force_interval, ierr=err_tmp) + err = ior(err, err_tmp) + call mpas_interval_division(start_time, coupling_interval, force_interval, n_intervals, remainder) + if (remainder .EQ. zero_interval) then + call mpas_log_write("config_adaptive_timestep_force_interval divides into config_slm_coupling_interval $i times " // & + "with no remainder - check passes", intArgs=(/int(n_intervals)/)) + else + call mpas_log_write("config_adaptive_timestep_force_interval divides into config_slm_coupling_interval $i times " // & + "with nonzero remainder", MPAS_LOG_ERR, intArgs=(/int(n_intervals)/)) + err = ior(err, 1) + endif + else + ! For fixed dt, check that dt divides evenly into config_slm_coupling_interval + call mpas_pool_get_config(liConfigs, "config_dt", config_dt) + call mpas_set_timeInterval(dt_interval, timeString=config_dt, ierr=err_tmp) + err = ior(err, err_tmp) + call mpas_interval_division(start_time, coupling_interval, dt_interval, n_intervals, remainder) + if (remainder .EQ. zero_interval) then + call mpas_log_write("config_dt divides into config_slm_coupling_interval $i times " // & + "with no remainder - check passes", intArgs=(/int(n_intervals)/)) + else + call mpas_log_write("config_dt divides into config_slm_coupling_interval $i times " // & + "with nonzero remainder", MPAS_LOG_ERR, intArgs=(/int(n_intervals)/)) + err = ior(err, 1) + endif + endif + + ! No need to compare restart interval and coupling interval because restarts with SLM are supported for + ! any restart interval now + + call mpas_log_write("") + + !-------------------------------------------------------------------- + end subroutine check_SLM_coupling_interval + + +!*********************************************************************** +! +! routine find_slm_restart_timestep +! +!> \brief Perform various checks on the SLM coupling interval setting +!> \author Matt Hoffman +!> \date Feb 2024 +!> \details +!> This routine checks that the SLM coupling interval is an even multiple +!> of the adaptive timestep force inverval and divides evenly into the +!> restart interval. It also checks that the coupling interval in the MALI +!> matches the value in the SLM namelist. +! +!----------------------------------------------------------------------- + + subroutine find_slm_restart_timestep(meshPool, slmTimeStep, err) + + use mpas_timekeeping + + type (mpas_pool_type), intent(in) :: meshPool !< mesh information + integer, intent(out) :: slmTimeStep + integer, intent(out) :: err + + ! local vars + integer, pointer :: config_slm_coupling_interval + character (len=StrKIND), pointer :: xtime, simulationStartTime + type (MPAS_TimeInterval_Type) :: coupling_interval + type (MPAS_Time_Type) :: start_time, curr_time + integer (kind=I8KIND) :: n_intervals + type (MPAS_TimeInterval_type) :: remainder + character (len=StrKIND) :: remainder_string + integer :: err_tmp + + err = 0 + err_tmp = 0 + + call mpas_pool_get_config(liConfigs, "config_slm_coupling_interval", config_slm_coupling_interval) + ! define SLM coupling interval as a timeInterval type + call mpas_set_timeInterval(coupling_interval, YY=config_slm_coupling_interval, MM=0, DD=0, H=0, M=0, S=0, ierr=err_tmp) + err = ior(err, err_tmp) + + call mpas_pool_get_array(meshPool, 'simulationStartTime', simulationStartTime) + call mpas_pool_get_array(meshPool, 'xtime', xtime) + call mpas_set_time(start_time, dateTimeString=simulationStartTime, ierr=err_tmp) + err = ior(err, err_tmp) + call mpas_set_time(curr_time, dateTimeString=xtime, ierr=err_tmp) + err = ior(err, err_tmp) + + call mpas_interval_division(start_time, curr_time - start_time, coupling_interval, n_intervals, remainder) + slmTimeStep = int(n_intervals) + call mpas_get_timeInterval(remainder, start_time, timeString=remainder_string, ierr=err_tmp) + err = ior(err, err_tmp) + call mpas_log_write("SLM Restart: Using SLM time level $i because config_slm_coupling_interval divides into " // & + "elapsed time that many times ", intArgs=(/int(slmTimeStep)/)) + call mpas_log_write(" That calculation implies it has been " // trim(remainder_string) // " since last SLM coupling. " // & + "If that interval seems wrong, there may be an error in your configuration.") + call mpas_log_write("") + + !-------------------------------------------------------------------- + end subroutine find_slm_restart_timestep + !*********************************************************************** end module li_bedtopo diff --git a/components/mpas-albany-landice/src/mode_forward/mpas_li_core.F b/components/mpas-albany-landice/src/mode_forward/mpas_li_core.F index 10ee1e94b305..16c7c7807200 100644 --- a/components/mpas-albany-landice/src/mode_forward/mpas_li_core.F +++ b/components/mpas-albany-landice/src/mode_forward/mpas_li_core.F @@ -338,8 +338,8 @@ function li_core_init(domain, startTimeStamp) result(err) ! === call li_velocity_external_write_albany_mesh(domain) - call mpas_dmpar_max_int(domain % dminfo, err, globalErr) ! Find out if any blocks got an error - if (globalErr > 0) then + call mpas_dmpar_max_int(domain % dminfo, abs(err), globalErr) ! Find out if any blocks got an error + if (globalErr /= 0) then call mpas_log_write("An error has occurred in li_core_init. Aborting...", MPAS_LOG_CRIT) endif @@ -1105,13 +1105,12 @@ subroutine li_simulation_clock_init(core_clock, configs, ierr) type (MPAS_Time_Type) :: startTime, stopTime, alarmStartTime type (MPAS_TimeInterval_type) :: runDuration, timeStep, alarmTimeStep type (MPAS_TimeInterval_type) :: adaptDtForceInterval - type (MPAS_TimeInterval_type) :: slm_coupling_interval character (len=StrKIND), pointer :: config_start_time, config_run_duration, config_stop_time, & config_output_interval, config_restart_interval ! MPAS standard configs character (len=StrKIND), pointer :: config_dt ! MPAS LI-specific config option character (len=StrKIND), pointer :: config_adaptive_timestep_force_interval ! MPAS LI-specific config option character (len=StrKIND), pointer :: config_restart_timestamp_name - character (len=StrKIND), pointer :: config_uplift_method, config_slm_coupling_interval + integer, pointer :: config_slm_coupling_interval character (len=StrKIND) :: restartTimeStamp !< string to be read from file integer, pointer :: config_year_digits integer :: err_tmp @@ -1130,7 +1129,6 @@ subroutine li_simulation_clock_init(core_clock, configs, ierr) call mpas_pool_get_config(configs, 'config_stop_time', config_stop_time) call mpas_pool_get_config(configs, 'config_restart_timestamp_name', config_restart_timestamp_name) call mpas_pool_get_config(configs, 'config_adaptive_timestep_force_interval', config_adaptive_timestep_force_interval) - call mpas_pool_get_config(configs, 'config_uplift_method', config_uplift_method) call mpas_pool_get_config(configs, 'config_slm_coupling_interval', config_slm_coupling_interval) @@ -1195,22 +1193,8 @@ subroutine li_simulation_clock_init(core_clock, configs, ierr) endif ierr = ior(ierr, err_tmp) - ! Set up the coupling time interval if MALI is coupled to sea-level model - if (trim(config_uplift_method) == "sealevelmodel") then - call mpas_set_timeInterval(slm_coupling_interval, timeString=config_slm_coupling_interval, ierr=err_tmp) - ierr = ior(ierr,err_tmp) - call mpas_add_clock_alarm(core_clock, 'slmCouplingInterval', alarmTime=startTime, & - alarmTimeInterval=slm_coupling_interval, ierr=err_tmp) - ierr = ior(ierr,err_tmp) - if (mpas_is_alarm_ringing(core_clock, 'slmCouplingInterval', ierr=err_tmp)) then - ierr = ior(ierr, err_tmp) - call mpas_reset_clock_alarm(core_clock, 'slmCouplingInterval', ierr=err_tmp) - ierr = ior(ierr, err_tmp) - endif - endif - ! === error check - if (ierr > 0) then + if (ierr /= 0) then call mpas_log_write("An error has occurred in li_simulation_clock_init.", MPAS_LOG_ERR) endif