diff --git a/datm/atm_comp_nuopc.F90 b/datm/atm_comp_nuopc.F90 index b4491ff2f..ffb640454 100644 --- a/datm/atm_comp_nuopc.F90 +++ b/datm/atm_comp_nuopc.F90 @@ -34,7 +34,7 @@ module cdeps_datm_comp use dshr_strdata_mod , only : shr_strdata_get_stream_pointer, shr_strdata_setOrbs use dshr_mod , only : dshr_model_initphase, dshr_init use dshr_mod , only : dshr_state_setscalar, dshr_set_runclock, dshr_log_clock_advance - use dshr_mod , only : dshr_restart_read, dshr_restart_write, dshr_mesh_init + use dshr_mod , only : dshr_mesh_init, dshr_check_restart_alarm use dshr_mod , only : dshr_orbital_init, dshr_orbital_update use dshr_dfield_mod , only : dfield_type, dshr_dfield_add, dshr_dfield_copy use dshr_fldlist_mod , only : fldlist_type, dshr_fldlist_add, dshr_fldlist_realize @@ -448,7 +448,7 @@ subroutine ModelAdvance(gcomp, rc) type(ESMF_Time) :: nextTime type(ESMF_TimeInterval) :: timeStep real(r8) :: nextsw_cday - logical :: restart_write ! restart alarm is ringing + logical :: restart_write ! restart alarm is ringing integer :: next_ymd ! model date integer :: next_tod ! model sec into model date integer :: yr, mon, day ! year, month, day @@ -485,18 +485,9 @@ subroutine ModelAdvance(gcomp, rc) orbEccen, orbObliqr, orbLambm0, orbMvelpp, rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return - ! determine if will write restart - call ESMF_ClockGetAlarm(clock, alarmname='alarm_restart', alarm=alarm, rc=rc) + restart_write = dshr_check_restart_alarm(clock, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return - if (ESMF_AlarmIsRinging(alarm, rc=rc)) then - if (ChkErr(rc,__LINE__,u_FILE_u)) return - call ESMF_AlarmRingerOff( alarm, rc=rc ) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - restart_write = .true. - else - restart_write = .false. - endif - + ! Run datm call ESMF_TraceRegionEnter('datm_run') call datm_comp_run(importstate, exportstate, next_ymd, next_tod, mon, & diff --git a/dice/ice_comp_nuopc.F90 b/dice/ice_comp_nuopc.F90 index a28d52428..5eb37ad1f 100644 --- a/dice/ice_comp_nuopc.F90 +++ b/dice/ice_comp_nuopc.F90 @@ -28,7 +28,7 @@ module cdeps_dice_comp use shr_sys_mod , only : shr_sys_abort use shr_cal_mod , only : shr_cal_ymd2date, shr_cal_ymd2julian use shr_mpi_mod , only : shr_mpi_bcast - use dshr_mod , only : dshr_model_initphase, dshr_init, dshr_mesh_init + use dshr_mod , only : dshr_model_initphase, dshr_init, dshr_mesh_init, dshr_check_restart_alarm use dshr_mod , only : dshr_state_setscalar, dshr_set_runclock, dshr_log_clock_advance use dshr_methods_mod , only : dshr_state_diagnose, chkerr, memcheck use dshr_strdata_mod , only : shr_strdata_type, shr_strdata_init_from_config, shr_strdata_advance @@ -415,16 +415,8 @@ subroutine ModelAdvance(gcomp, rc) cosArg = 2.0_R8*shr_const_pi*(jday - jday0)/365.0_R8 ! Determine if will write restarts - call ESMF_ClockGetAlarm(clock, alarmname='alarm_restart', alarm=alarm, rc=rc) + restart_write = dshr_check_restart_alarm(clock, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return - if (ESMF_AlarmIsRinging(alarm, rc=rc)) then - if (ChkErr(rc,__LINE__,u_FILE_u)) return - call ESMF_AlarmRingerOff( alarm, rc=rc ) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - restart_write = .true. - else - restart_write = .false. - endif ! Run dice call dice_comp_run(importState, exportState, next_ymd, next_tod, cosarg, restart_write, rc) diff --git a/dlnd/lnd_comp_nuopc.F90 b/dlnd/lnd_comp_nuopc.F90 index 5bb6d73dc..ea88469a3 100644 --- a/dlnd/lnd_comp_nuopc.F90 +++ b/dlnd/lnd_comp_nuopc.F90 @@ -29,7 +29,7 @@ module cdeps_dlnd_comp use dshr_methods_mod , only : dshr_state_getfldptr, dshr_state_diagnose, chkerr, memcheck use dshr_strdata_mod , only : shr_strdata_type, shr_strdata_advance, shr_strdata_get_stream_domain use dshr_strdata_mod , only : shr_strdata_init_from_config - use dshr_mod , only : dshr_model_initphase, dshr_init + use dshr_mod , only : dshr_model_initphase, dshr_init, dshr_check_restart_alarm use dshr_mod , only : dshr_state_setscalar, dshr_set_runclock, dshr_log_clock_advance use dshr_mod , only : dshr_restart_read, dshr_restart_write, dshr_mesh_init use dshr_dfield_mod , only : dfield_type, dshr_dfield_add, dshr_dfield_copy @@ -325,6 +325,7 @@ subroutine ModelAdvance(gcomp, rc) integer :: yr ! year integer :: mon ! month integer :: day ! day in month + logical :: write_restart character(len=*),parameter :: subname=trim(modName)//':(ModelAdvance) ' !------------------------------------------------------------------------------- @@ -351,19 +352,16 @@ subroutine ModelAdvance(gcomp, rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return ! write_restart if alarm is ringing - call ESMF_ClockGetAlarm(clock, alarmname='alarm_restart', alarm=alarm, rc=rc) + write_restart = dshr_check_restart_alarm(clock, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return - if (ESMF_AlarmIsRinging(alarm, rc=rc)) then - if (ChkErr(rc,__LINE__,u_FILE_u)) return - call ESMF_AlarmRingerOff( alarm, rc=rc ) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - + if (write_restart) then call ESMF_TraceRegionEnter('dlnd_restart') call dshr_restart_write(rpfile, case_name, 'dlnd', inst_suffix, next_ymd, next_tod, & logunit, my_task, sdat) call ESMF_TraceRegionExit('dlnd_restart') endif + ! write diagnostics if (diagnose_data) then call dshr_state_diagnose(exportState, flds_scalar_name, subname//':ES',rc=rc) diff --git a/docn/ocn_comp_nuopc.F90 b/docn/ocn_comp_nuopc.F90 index 0887f9746..d155c30fb 100644 --- a/docn/ocn_comp_nuopc.F90 +++ b/docn/ocn_comp_nuopc.F90 @@ -30,7 +30,7 @@ module cdeps_docn_comp use dshr_methods_mod , only : dshr_state_diagnose, chkerr, memcheck use dshr_strdata_mod , only : shr_strdata_type, shr_strdata_advance, shr_strdata_init_from_config use dshr_mod , only : dshr_model_initphase, dshr_init, dshr_mesh_init - use dshr_mod , only : dshr_state_setscalar, dshr_set_runclock + use dshr_mod , only : dshr_state_setscalar, dshr_set_runclock, dshr_check_restart_alarm use dshr_dfield_mod , only : dfield_type, dshr_dfield_add, dshr_dfield_copy use dshr_fldlist_mod , only : fldlist_type, dshr_fldlist_realize @@ -422,16 +422,7 @@ subroutine ModelAdvance(gcomp, rc) call shr_cal_ymd2date(yr, mon, day, next_ymd) ! determine if will write restart - call ESMF_ClockGetAlarm(clock, alarmname='alarm_restart', alarm=alarm, rc=rc) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - if (ESMF_AlarmIsRinging(alarm, rc=rc)) then - if (ChkErr(rc,__LINE__,u_FILE_u)) return - call ESMF_AlarmRingerOff( alarm, rc=rc ) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - restart_write = .true. - else - restart_write = .false. - end if + restart_write = dshr_check_restart_alarm(clock, rc=rc) ! run docn call docn_comp_run(importState, exportState, clock, next_ymd, next_tod, restart_write, rc=rc) diff --git a/drof/rof_comp_nuopc.F90 b/drof/rof_comp_nuopc.F90 index 396f8f3ae..0d35b5fab 100644 --- a/drof/rof_comp_nuopc.F90 +++ b/drof/rof_comp_nuopc.F90 @@ -32,7 +32,7 @@ module cdeps_drof_comp use dshr_strdata_mod , only : shr_strdata_type, shr_strdata_advance, shr_strdata_get_stream_domain use dshr_strdata_mod , only : shr_strdata_init_from_config use dshr_mod , only : dshr_model_initphase, dshr_init - use dshr_mod , only : dshr_state_setscalar, dshr_set_runclock + use dshr_mod , only : dshr_state_setscalar, dshr_set_runclock, dshr_check_restart_alarm use dshr_mod , only : dshr_restart_read, dshr_restart_write, dshr_mesh_init use dshr_dfield_mod , only : dfield_type, dshr_dfield_add, dshr_dfield_copy use dshr_fldlist_mod , only : fldlist_type, dshr_fldlist_add, dshr_fldlist_realize @@ -339,17 +339,9 @@ subroutine ModelAdvance(gcomp, rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return call shr_cal_ymd2date(yr, mon, day, next_ymd) - ! write_restart if alarm is ringing - call ESMF_ClockGetAlarm(clock, alarmname='alarm_restart', alarm=alarm, rc=rc) + ! write restart if alarm is ringing + restart_write = dshr_check_restart_alarm(clock, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return - if (ESMF_AlarmIsRinging(alarm, rc=rc)) then - if (ChkErr(rc,__LINE__,u_FILE_u)) return - call ESMF_AlarmRingerOff( alarm, rc=rc ) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - restart_write = .true. - else - restart_write = .false. - endif ! run drof call drof_comp_run(exportState, next_ymd, next_tod, restart_write, rc=rc) diff --git a/dshr/dshr_mod.F90 b/dshr/dshr_mod.F90 index 5a6e71516..a8b219828 100644 --- a/dshr/dshr_mod.F90 +++ b/dshr/dshr_mod.F90 @@ -77,6 +77,7 @@ module dshr_mod character(len=*) , parameter :: orb_fixed_year = 'fixed_year' character(len=*) , parameter :: orb_variable_year = 'variable_year' character(len=*) , parameter :: orb_fixed_parameters = 'fixed_parameters' + logical :: write_restart_at_endofrun integer , parameter :: master_task = 0 character(*), parameter :: u_FILE_u = & @@ -213,6 +214,12 @@ subroutine dshr_init(gcomp, compname, sdat, mpicom, my_task, inst_index, inst_su inst_index=1 endif + call NUOPC_CompAttributeGet(gcomp, name="write_restart_at_endofrun", value=cvalue, isPresent=isPresent, isSet=isSet, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + if (isPresent .and. isSet) then + if (trim(cvalue) .eq. '.true.') write_restart_at_endofrun = .true. + end if + #ifdef CESMCOUPLED sdat%pio_subsystem => shr_pio_getiosys(trim(compname)) sdat%io_type = shr_pio_getiotype(trim(compname)) @@ -453,10 +460,14 @@ subroutine dshr_set_runclock(gcomp, rc) type(ESMF_Time) :: mstoptime type(ESMF_TimeInterval) :: mtimestep, dtimestep character(len=256) :: cvalue - character(len=256) :: restart_option ! Restart option units - integer :: restart_n ! Number until restart interval - integer :: restart_ymd ! Restart date (YYYYMMDD) + character(len=256) :: restart_option ! Restart option units + integer :: restart_n ! Number until restart interval + integer :: restart_ymd ! Restart date (YYYYMMDD) type(ESMF_ALARM) :: restart_alarm + character(len=256) :: stop_option ! Stop option units + integer :: stop_n ! Number until stop interval + integer :: stop_ymd ! Stop date (YYYYMMDD) + type(ESMF_ALARM) :: stop_alarm character(len=128) :: name integer :: alarmcount character(len=*),parameter :: subname='dshr_mod:(ModelSetRunClock) ' @@ -510,6 +521,30 @@ subroutine dshr_set_runclock(gcomp, rc) call ESMF_AlarmSet(restart_alarm, clock=mclock, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return + !---------------- + ! Stop alarm + !---------------- + call NUOPC_CompAttributeGet(gcomp, name="stop_option", value=stop_option, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + call NUOPC_CompAttributeGet(gcomp, name="stop_n", value=cvalue, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + read(cvalue,*) stop_n + + call NUOPC_CompAttributeGet(gcomp, name="stop_ymd", value=cvalue, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + read(cvalue,*) stop_ymd + + call dshr_alarm_init(mclock, stop_alarm, stop_option, & + opt_n = stop_n, & + opt_ymd = stop_ymd, & + RefTime = mcurrTime, & + alarmname = 'alarm_stop', rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + call ESMF_AlarmSet(stop_alarm, clock=mclock, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + end if ! Advance model clock to trigger alarms then reset model clock back to currtime @@ -577,6 +612,7 @@ subroutine dshr_alarm_init( clock, alarm, option, & optMonthly = "monthly" , & optYearly = "yearly" , & optDate = "date" , & + optEnd = "end" , & optIfdays0 = "ifdays0" character(len=*), parameter :: subname = '(dshr_alarm_init): ' !------------------------------------------------------------------------------- @@ -623,6 +659,13 @@ subroutine dshr_alarm_init( clock, alarm, option, & if (chkerr(rc,__LINE__,u_FILE_u)) return update_nextalarm = .false. + case (optEnd) + call ESMF_TimeIntervalSet(AlarmInterval, yy=9999, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_TimeSet( NextAlarm, yy=9999, mm=12, dd=1, s=0, calendar=cal, rc=rc ) + if (chkerr(rc,__LINE__,u_FILE_u)) return + update_nextalarm = .false. + case (optDate) if (.not. present(opt_ymd)) then call shr_sys_abort(subname//trim(option)//' requires opt_ymd') @@ -1844,5 +1887,56 @@ subroutine dshr_pio_init(gcomp, sdat, logunit, rc) pio_rearr_comm_max_pend_req_io2comp) end subroutine dshr_pio_init +! +! Returns trun if the restart alarm is ringing or its the end of the run and +! REST_OPTION is not none or never +! + logical function dshr_check_restart_alarm(clock, rc) + use ESMF, only : ESMF_ClockGetAlarm, ESMF_AlarmIsRinging, ESMF_AlarmRingerOff + integer, intent(out) :: rc + type(ESMF_CLOCK), intent(in) :: clock + + type(ESMF_ALARM) :: alarm + logical :: nlend, rstwr + !-------------------------------- + ! Determine if time to stop + !-------------------------------- + + rc = ESMF_SUCCESS + + call ESMF_ClockGetAlarm(clock, alarmname='alarm_stop', alarm=alarm, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + if (ESMF_AlarmIsRinging(alarm, rc=rc)) then + if (ChkErr(rc,__LINE__,u_FILE_u)) return + nlend = .true. + call ESMF_AlarmRingerOff( alarm, rc=rc ) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + else + nlend = .false. + endif + + !-------------------------------- + ! Determine if time to write restart + !-------------------------------- + + if (nlend .and. write_restart_at_endofrun) then + rstwr = .true. + else + call ESMF_ClockGetAlarm(clock, alarmname='alarm_restart', alarm=alarm, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + + if (ESMF_AlarmIsRinging(alarm, rc=rc)) then + if (ChkErr(rc,__LINE__,u_FILE_u)) return + rstwr = .true. + call ESMF_AlarmRingerOff( alarm, rc=rc ) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + else + rstwr = .false. + endif + end if + dshr_check_restart_alarm = rstwr + end function dshr_check_restart_alarm + end module dshr_mod diff --git a/dwav/wav_comp_nuopc.F90 b/dwav/wav_comp_nuopc.F90 index 6975b534e..c9b8f9291 100644 --- a/dwav/wav_comp_nuopc.F90 +++ b/dwav/wav_comp_nuopc.F90 @@ -29,7 +29,7 @@ module cdeps_dwav_comp use dshr_methods_mod , only : dshr_state_getfldptr, chkerr, memcheck, dshr_state_diagnose use dshr_strdata_mod , only : shr_strdata_type, shr_strdata_advance use dshr_strdata_mod , only : shr_strdata_init_from_config - use dshr_mod , only : dshr_model_initphase, dshr_init + use dshr_mod , only : dshr_model_initphase, dshr_init, dshr_check_restart_alarm use dshr_mod , only : dshr_state_setscalar, dshr_set_runclock, dshr_log_clock_advance use dshr_mod , only : dshr_restart_read, dshr_restart_write, dshr_mesh_init use dshr_dfield_mod , only : dfield_type, dshr_dfield_add, dshr_dfield_copy @@ -307,6 +307,7 @@ subroutine ModelAdvance(gcomp, rc) integer :: day ! day in month integer :: next_ymd ! model date integer :: next_tod ! model sec into model date + logical :: write_restart character(len=*),parameter :: subname=trim(modName)//':(ModelAdvance) ' !------------------------------------------------------------------------------- @@ -334,13 +335,9 @@ subroutine ModelAdvance(gcomp, rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return ! write_restart if alarm is ringing - call ESMF_ClockGetAlarm(clock, alarmname='alarm_restart', alarm=alarm, rc=rc) + write_restart = dshr_check_restart_alarm(clock, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return - if (ESMF_AlarmIsRinging(alarm, rc=rc)) then - if (ChkErr(rc,__LINE__,u_FILE_u)) return - call ESMF_AlarmRingerOff( alarm, rc=rc ) - if (ChkErr(rc,__LINE__,u_FILE_u)) return - + if (write_restart) then call ESMF_TraceRegionEnter('dwav_restart') call NUOPC_CompAttributeGet(gcomp, name='case_name', value=case_name, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return