Skip to content

Commit

Permalink
Flexible restart write times (restart_fh) (#139)
Browse files Browse the repository at this point in the history
Modify mom_cap.F90 so that restart writes can be triggered at any forecast time via UFS configuration as for other components
  • Loading branch information
NickSzapiro-NOAA authored Dec 11, 2024
1 parent 5e0c21f commit 8cc8b70
Showing 1 changed file with 21 additions and 68 deletions.
89 changes: 21 additions & 68 deletions config_src/drivers/nuopc_cap/mom_cap.F90
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ module MOM_cap_mod
use NUOPC_Model, only: model_label_Finalize => label_Finalize
use NUOPC_Model, only: SetVM

#ifndef CESMCOUPLED
use shr_is_restart_fh_mod, only : init_is_restart_fh, is_restart_fh, is_restart_fh_type
#endif

implicit none; private

public SetServices
Expand Down Expand Up @@ -150,13 +154,12 @@ module MOM_cap_mod
#else
logical :: cesm_coupled = .false.
type(ESMF_GeomType_Flag) :: geomtype
type(is_restart_fh_type) :: restartfh_info ! For flexible restarts in UFS
#endif
character(len=8) :: restart_mode = 'alarms'
character(len=16) :: inst_suffix = ''
real(8) :: timere

type(ESMF_Time), allocatable :: restartFhTimes(:)

contains

!> NUOPC SetService method is the only public entry point.
Expand Down Expand Up @@ -625,7 +628,7 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc)
open(newunit=readunit, file=rpointer_filename, form='formatted', status='old', iostat=iostat)
if (iostat /= 0) then
call ESMF_LogSetError(ESMF_RC_FILE_OPEN, msg=subname//' ERROR opening '//rpointer_filename, &
line=__LINE__, file=u_FILE_u, rcToReturn=rc)
line=__LINE__, file=u_FILE_u, rcToReturn=rc)
return
endif
do
Expand Down Expand Up @@ -1643,11 +1646,9 @@ subroutine ModelAdvance(gcomp, rc)
character(len=:), allocatable :: rpointer_filename
integer :: num_rest_files
real(8) :: MPI_Wtime, timers
logical :: write_restart
logical :: write_restartfh
logical :: write_restart, write_restartfh
logical :: write_restart_eor


rc = ESMF_SUCCESS
if(profile_memory) call ESMF_VMLogMemInfo("Entering MOM Model_ADVANCE: ")
if(write_runtimelog) then
Expand Down Expand Up @@ -1797,16 +1798,6 @@ subroutine ModelAdvance(gcomp, rc)
call ESMF_ClockGetAlarm(clock, alarmname='restart_alarm', alarm=restart_alarm, rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return

write_restartfh = .false.
! check if next time is == to any restartfhtime
if (allocated(RestartFhTimes)) then
do n = 1,size(RestartFhTimes)
call ESMF_ClockGetNextTime(clock, MyTime, rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return
if (MyTime == RestartFhTimes(n)) write_restartfh = .true.
end do
end if

write_restart = .false.
if (ESMF_AlarmIsRinging(restart_alarm, rc=rc)) then
if (ChkErr(rc,__LINE__,u_FILE_u)) return
Expand All @@ -1827,7 +1818,12 @@ subroutine ModelAdvance(gcomp, rc)
end if
end if

if (write_restart .or. write_restartfh .or. write_restart_eor) then
#ifndef CESMCOUPLED
call is_restart_fh(clock, restartfh_info, write_restartfh)
if (write_restartfh) write_restart = .true.
#endif

if (write_restart .or. write_restart_eor) then
! determine restart filename
call ESMF_ClockGetNextTime(clock, MyTime, rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return
Expand All @@ -1850,7 +1846,7 @@ subroutine ModelAdvance(gcomp, rc)
! write restart file(s)
call ocean_model_restart(ocean_state, restartname=restartname, num_rest_files=num_rest_files)
if (localPet == 0) then
! Write name of restart file in the rpointer file - this is currently hard-coded for the ocean
! Write name of restart file in the rpointer file - this is currently hard-coded for the ocean
open(newunit=writeunit, file=rpointer_filename, form='formatted', status='unknown', iostat=iostat)
if (iostat /= 0) then
call ESMF_LogSetError(ESMF_RC_FILE_OPEN, &
Expand Down Expand Up @@ -1927,34 +1923,26 @@ end subroutine ModelAdvance


subroutine ModelSetRunClock(gcomp, rc)

use ESMF, only : ESMF_TimeIntervalSet

type(ESMF_GridComp) :: gcomp
integer, intent(out) :: rc

! local variables
type(ESMF_VM) :: vm
type(ESMF_Clock) :: mclock, dclock
type(ESMF_Time) :: mcurrtime, dcurrtime
type(ESMF_Time) :: mstoptime, dstoptime
type(ESMF_TimeInterval) :: mtimestep, dtimestep
type(ESMF_TimeInterval) :: fhInterval
character(len=128) :: mtimestring, dtimestring
character(len=256) :: timestr
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)
integer :: dt_cpl ! coupling timestep
integer :: dt_cpl
type(ESMF_Alarm) :: restart_alarm
type(ESMF_Alarm) :: stop_alarm
logical :: isPresent, isSet
logical :: first_time = .true.
integer :: localPet
integer :: n, nfh
integer, allocatable :: restart_fh(:)
character(len=*),parameter :: subname='(MOM_cap:ModelSetRunClock) '
character(len=*),parameter :: subname='MOM_cap:(ModelSetRunClock) '
character(len=256) :: timestr
!--------------------------------

rc = ESMF_SUCCESS
Expand All @@ -1970,11 +1958,6 @@ subroutine ModelSetRunClock(gcomp, rc)
call ESMF_ClockGet(mclock, currTime=mcurrtime, timeStep=mtimestep, rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return

call ESMF_GridCompGet(gcomp, vm=vm, rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return
call ESMF_VMGet(vm, localPet=localPet, rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return

!--------------------------------
! check that the current time in the model and driver are the same
!--------------------------------
Expand Down Expand Up @@ -2073,6 +2056,9 @@ subroutine ModelSetRunClock(gcomp, rc)
call ESMF_LogWrite(subname//" Restarts will be written at finalize only", ESMF_LOGMSG_INFO)
endif
endif
call ESMF_TimeIntervalGet(dtimestep, s=dt_cpl, rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return
call init_is_restart_fh(mcurrTime, dt_cpl, is_root_pe(), restartfh_info)
endif

if (restart_mode == 'alarms') then
Expand All @@ -2098,41 +2084,8 @@ subroutine ModelSetRunClock(gcomp, rc)
call ESMF_TimeGet(dstoptime, timestring=timestr, rc=rc)
call ESMF_LogWrite("Stop Alarm will ring at : "//trim(timestr), ESMF_LOGMSG_INFO)

! set up Times to write non-interval restarts
call NUOPC_CompAttributeGet(gcomp, name='restart_fh', isPresent=isPresent, isSet=isSet, rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return
if (isPresent .and. isSet) then

call ESMF_TimeIntervalGet(dtimestep, s=dt_cpl, rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return
call NUOPC_CompAttributeGet(gcomp, name='restart_fh', value=cvalue, rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return

! convert string to a list of integer restart_fh values
nfh = 1 + count(transfer(trim(cvalue), 'a', len(cvalue)) == ",")
allocate(restart_fh(1:nfh))
allocate(restartFhTimes(1:nfh))
read(cvalue,*)restart_fh(1:nfh)

! create a list of times at each restart_fh
do n = 1,nfh
call ESMF_TimeIntervalSet(fhInterval, h=restart_fh(n), rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return
restartFhTimes(n) = mcurrtime + fhInterval
call ESMF_TimePrint(restartFhTimes(n), options="string", preString="Restart_Fh at ", unit=timestr, rc=rc)
if (ChkErr(rc,__LINE__,u_FILE_u)) return
if (localPet == 0) then
if (mod(3600*restart_fh(n),dt_cpl) /= 0) then
write(stdout,'(A)')trim(subname)//trim(timestr)//' will not be written'
else
write(stdout,'(A)')trim(subname)//trim(timestr)//' will be written'
end if
end if
end do
deallocate(restart_fh)
end if

first_time = .false.

endif

!--------------------------------
Expand Down

0 comments on commit 8cc8b70

Please sign in to comment.