Skip to content

Commit

Permalink
Merge pull request #460 from nmizukami/cesm-coupling_timestamp
Browse files Browse the repository at this point in the history
allow more flexible time stamp in forcing input
  • Loading branch information
nmizukami authored Mar 29, 2024
2 parents 379f99a + a0bc722 commit 6212c25
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 41 deletions.
14 changes: 11 additions & 3 deletions route/build/src/historyFile.f90
Original file line number Diff line number Diff line change
Expand Up @@ -310,23 +310,31 @@ SUBROUTINE write_loc_rch(this, reach_id, ierr, message)
! ---------------------------------
! writing time variables
! ---------------------------------
SUBROUTINE write_time(this, hvars_local, ierr, message)
SUBROUTINE write_time(this, hVars_local, time_stamp_Local, ierr, message)

implicit none
! Argument variables
class(histFile), intent(inout) :: this
type(histVars), intent(in) :: hVars_local
type(histVars), intent(in) :: hVars_local ! history variable structure
character(len=strLen), intent(in) :: time_stamp_local ! time stamp for time variable: front, end, or middle
integer(i4b), intent(out) :: ierr ! error code
character(*), intent(out) :: message ! error message
! local variables
real(dp) :: timeVar_write ! time variable [time_unit]
character(len=strLen) :: cmessage ! error message of downwind routine

ierr=0; message='write_time/'

this%iTime = this%iTime + 1 ! this is only line to increment time step index

! write time -- note time is just carried across from the input
call write_netcdf(this%pioFileDesc, 'time', [hVars_local%timeVar(1)], [this%iTime], [1], ierr, cmessage)
select case(trim(time_stamp_local))
case('front'); timeVar_write = hVars_local%timeVar(1)
case('end'); timeVar_write = hVars_local%timeVar(2)
case('middle'); timeVar_write = (hVars_local%timeVar(1)+hVars_local%timeVar(2))/2.0
end select

call write_netcdf(this%pioFileDesc, 'time', [timeVar_write], [this%iTime], [1], ierr, cmessage)
if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif

call write_netcdf(this%pioFileDesc, 'time_bounds', hVars_local%timeVar, [1,this%iTime], [2,1], ierr, cmessage)
Expand Down
2 changes: 1 addition & 1 deletion route/build/src/mc_route.f90
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ SUBROUTINE muskingum_cunge(rch_param, & ! input: river parameter data struct
C2 = (1-X-Cn*Y)/(1-X+Cn*(1-Y))

QoutLocal(ix) = C0* QinLocal(ix)+ C1* QinLocal(ix-1)+ C2* QoutLocal(ix-1)
QoutLocal(ix) = max(0.0, QoutLocal(ix))
QoutLocal(ix) = max(0.0_dp, QoutLocal(ix))

! -- EBK 06/26/2023 -- comment out isnan check, doesn't seem to be needed.
!if (isnan(QoutLocal(ix))) then
Expand Down
2 changes: 1 addition & 1 deletion route/build/src/nr_utils.f90
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ pure SUBROUTINE unique_i8b(array, unq, idx)
integer(i4b),allocatable,intent(out) :: idx(:) ! integer array including unique element index
! local
integer(i4b) :: ranked(size(array)) !
integer(i4b) :: unq_tmp(size(array)) !
integer(i8b) :: unq_tmp(size(array)) !
logical(lgt) :: flg_tmp(size(array)) !
integer(i4b) :: ix ! loop index, counter
integer(i8b) :: last_unique ! last unique element
Expand Down
1 change: 1 addition & 0 deletions route/build/src/public_var.f90
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ MODULE public_var
real(dp) ,public :: input_fillvalue = realMissing ! fillvalue used for input variables (runoff, precipitation, evaporation)
character(len=strLen),public :: ro_time_units = charMissing ! time units used in ro netcdf. format should be <unit> since yyyy-mm-dd (hh:mm:ss). () can be omitted
character(len=strLen),public :: ro_calendar = charMissing ! calendar used in ro netcdf
character(len=strLen),public :: ro_time_stamp = 'front' ! time stamp used for I/O - front (default), middle, or end, otherwise error
! Water-management input netCDF - water abstraction/infjection or lake target volume
character(len=strLen),public :: fname_wm = '' ! the txt file name that includes nc files holesing the abstraction, injection, target volume values
character(len=strLen),public :: vname_flux_wm = '' ! variable name for abstraction or injection from or to a river segment
Expand Down
15 changes: 14 additions & 1 deletion route/build/src/read_control.f90
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ SUBROUTINE read_control(ctl_fname, err, message)
case('<continue_run>'); read(cData,*,iostat=io_error) continue_run ! logical; T-> append output in existing history files. F-> write output in new history file
case('<route_opt>'); routOpt = trim(cData) ! routing scheme options 0-> accumRunoff, 1->IRF, 2->KWT, 3-> KW, 4->MC, 5->DW
case('<doesBasinRoute>'); read(cData,*,iostat=io_error) doesBasinRoute ! basin routing options 0-> no, 1->IRF, otherwise error
case('<dt_qsim>'); read(cData,*,iostat=io_error) dt ! time interval of the simulation [sec] (To-do: change dt to dt_sim)
case('<is_lake_sim>'); read(cData,*,iostat=io_error) is_lake_sim ! logical; lakes are simulated
case('<is_flux_wm>'); read(cData,*,iostat=io_error) is_flux_wm ! logical; provided fluxes to or from seg/lakes should be considered
case('<is_vol_wm>'); read(cData,*,iostat=io_error) is_vol_wm ! logical; provided target volume for managed lakes are considered
Expand All @@ -135,7 +136,6 @@ SUBROUTINE read_control(ctl_fname, err, message)
case('<is_Ep_upward_negative>'); read(cData,*,iostat=io_error) is_Ep_upward_negative ! logical; flip evaporation in case upward direction is negative in input values convention
case('<scale_factor_prec>'); read(cData,*,iostat=io_error) scale_factor_prec ! float; factor to scale the precipitation values
case('<offset_value_prec>'); read(cData,*,iostat=io_error) offset_value_prec ! float; offset for precipitation values
case('<dt_qsim>'); read(cData,*,iostat=io_error) dt ! time interval of the simulation [sec] (To-do: change dt to dt_sim)
! RIVER NETWORK TOPOLOGY
case('<fname_ntopOld>'); fname_ntopOld = trim(cData) ! name of file containing stream network topology information
case('<ntopAugmentMode>'); read(cData,*,iostat=io_error) ntopAugmentMode ! option for river network augmentation mode. terminate the program after writing augmented ntopo.
Expand All @@ -158,6 +158,7 @@ SUBROUTINE read_control(ctl_fname, err, message)
case('<input_fillvalue>'); read(cData,*,iostat=io_error) input_fillvalue ! fillvalue used for input variable
case('<ro_calendar>'); ro_calendar = trim(cData) ! name of calendar used in runoff input netcdfs
case('<ro_time_units>'); ro_time_units = trim(cData) ! time units used in runoff input netcdfs
case('<ro_time_stamp>'); ro_time_stamp = trim(cData) ! time stamp used input - front, middle, or end, otherwise error
! Water-management input netCDF - water abstraction/infjection or lake target volume
case('<fname_wm>'); fname_wm = trim(cData) ! name of text file containing ordered nc file names
case('<vname_flux_wm>'); vname_flux_wm = trim(cData) ! name of varibale for fluxes to and from seg (reachs/lakes)
Expand Down Expand Up @@ -434,6 +435,18 @@ SUBROUTINE read_control(ctl_fname, err, message)
err=81; return
end select

! ---------- I/O time stamp -------
if (masterproc) then
write(iulog,'(2a)') new_line('a'), '---- input time stamp --- '
write(iulog,'(2A)') ' Input time stamp <ro_time_stamp>: ', trim(ro_time_stamp)
if (trim(ro_time_stamp)=='front' .or. trim(ro_time_stamp)=='end' .or. trim(ro_time_stamp)=='middle') then
write(iulog,'(2A)') ' The same time stamp is used for history output'
else
write(message, '(2A)') trim(message), 'ERROR: Input time stamp <ro_time_stamp> must be front, end, or middle'
err=81; return
end if
end if

! ---------- simulation time step, output frequency, file frequency -------
if (masterproc) then
write(iulog,'(2a)') new_line('a'), '---- output/simulation time steps --- '
Expand Down
2 changes: 1 addition & 1 deletion route/build/src/standalone/get_basin_runoff.f90
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ SUBROUTINE get_hru_runoff(ierr, message)
runoff_data%basinRunoff = 0._dp ! replacing with zeros
else
! time step mapping from runoff time step to simulation time step
call timeMap_sim_forc(tmap_sim_ro, begDatetime, robegDatetime, dt_ro, iTime, inFileInfo_ro, ierr, cmessage)
call timeMap_sim_forc(tmap_sim_ro, begDatetime, roBegDatetime, dt_ro, iTime, inFileInfo_ro, ierr, cmessage)
if(ierr/=0) then; message=trim(message)//trim(cmessage); return; endif

! get the simulated runoff for the current time step - runoff_data%sim(:) or %sim2D(:,:)
Expand Down
50 changes: 32 additions & 18 deletions route/build/src/standalone/model_setup.f90
Original file line number Diff line number Diff line change
Expand Up @@ -319,13 +319,18 @@ END SUBROUTINE inFile_pop
! private subroutine: initialize time data
! *********************************************************************
SUBROUTINE init_time(ierr, message)

! purpose: Save the following time related global variables
! - time_units
! - calendar
! - timeVar
! - iTime
! - begDatetime, endDatetime: simulationg start and end datetime
! - restDatetime, dropDatetime
! - dt_ro: forcing time step [sec]
! - dt_wm: water-management data time step [sec]
! - time_units: time units used for simulation datetime. format="<units> since yyyy-mm-dd hh:mm:ss"
! - calendar: calendar used for simulation datetime
! - timeVar: time variable [sec] for simulation (since referece datetime
! - iTime: time index of simulation time step
! - begDatetime: datetime at front of 1st simulation time step period
! - endDatetime: datetime at front of last simulation time step period
! - restDatetime: datetime at front of restart simulation time step period
! - dropDatetime: datetime at front of simulation time step period when restart file is written

USE ascii_utils, ONLY: lower ! convert string to lower case
USE datetime_data, ONLY: datetime ! datetime data
Expand All @@ -346,15 +351,16 @@ SUBROUTINE init_time(ierr, message)
USE public_var, ONLY: restart_day ! periodic restart day
USE public_var, ONLY: restart_hour ! periodic restart hr
USE public_var, ONLY: maxTimeDiff ! time difference tolerance for input checks
USE public_var, ONLY: ro_time_stamp ! time stamp for runoff input: front, end or middle of time step
USE globalData, ONLY: timeVar ! time variables at time step endpoints (unit given by runoff data)
USE globalData, ONLY: iTime ! time index at simulation time step
USE globalData, ONLY: sec2tunit ! seconds per time unit
USE globalData, ONLY: simDatetime ! model time data (yyyy:mm:dd:hh:mm:ss)
USE globalData, ONLY: begDatetime ! simulation begin datetime data (yyyy:mm:dd:hh:mm:sec)
USE globalData, ONLY: endDatetime ! simulation end datetime data (yyyy:mm:dd:hh:mm:sec)
USE globalData, ONLY: restDatetime ! restart time data (yyyy:mm:dd:hh:mm:sec)
USE globalData, ONLY: dropDatetime ! restart dropoff calendar date/time
USE globalData, ONLY: roBegDatetime ! forcing data start datetime data (yyyy:mm:dd:hh:mm:sec)
USE globalData, ONLY: begDatetime ! simulation begin datetime data (yyyy:mm:dd:hh:mm:sec). front of time step
USE globalData, ONLY: endDatetime ! simulation end datetime data (yyyy:mm:dd:hh:mm:sec). front of time step
USE globalData, ONLY: restDatetime ! restart time data (yyyy:mm:dd:hh:mm:sec). front of time step
USE globalData, ONLY: dropDatetime ! restart dropoff calendar date/time. front of time step
USE globalData, ONLY: roBegDatetime ! forcing data start datetime data (yyyy:mm:dd:hh:mm:sec) front of time step
USE globalData, ONLY: wmBegDatetime ! water-managment data start datetime data (yyyy:mm:dd:hh:mm:sec)
USE globalData, ONLY: infileinfo_ro ! the information of the input files
USE globalData, ONLY: infileinfo_wm ! the information of the input files
Expand Down Expand Up @@ -433,14 +439,22 @@ SUBROUTINE init_time(ierr, message)
end if
endif

! runoff data time step [sec]
! runoff data time step [sec]- dt_ro is saved
dt_ro = roTimeVar_diff(1)

! datetime at end of last runoff data time step
roDatetime_end = roCal(nTime)%add_sec(dt_ro, ierr, cmessage)

! datetime at start of first runoff data time step
roBegDatetime = roCal(1)
! datetime of runoff time at front of the 1st time step: roBegDatetime (global data)
! datetime of runoff time at end of last time step: roDatetime_end (local data)
select case(trim(ro_time_stamp))
case('front')
roBegDatetime = roCal(1)
roDatetime_end = roCal(nTime)%add_sec(dt_ro, ierr, cmessage)
case('end')
roBegDatetime = roCal(1)%add_sec(-dt_ro, ierr, cmessage)
roDatetime_end = roCal(nTime)
case('middle')
roBegDatetime = roCal(1)%add_sec(-dt_ro/2.0, ierr, cmessage)
roDatetime_end = roCal(nTime)%add_sec(dt_ro/2.0, ierr, cmessage)
end select

call begDatetime%str2datetime(simStart, calendar, ierr, cmessage)
if(ierr/=0) then; message=trim(message)//trim(cmessage)//' [begDatetime]'; return; endif
Expand All @@ -463,7 +477,7 @@ SUBROUTINE init_time(ierr, message)
endif

! Compare sim_start vs. time at first time step in runoff data
if (begDatetime < roCal(1)) then
if (begDatetime < roBegDatetime) then
write(iulog,'(2a)') new_line('a'),'WARNING: <sim_start> is before the first time step in input runoff'
write(iulog,fmt1) ' runoff_start: ', roCal(1)%year(),'-',roCal(1)%month(),'-',roCal(1)%day(), roCal(1)%hour(),':', roCal(1)%minute(),':',roCal(1)%sec()
write(iulog,fmt1) ' <sim_start> : ', begDatetime%year(),'-',begDatetime%month(),'-',begDatetime%day(), begDatetime%hour(),':', begDatetime%minute(),':',begDatetime%sec()
Expand Down
33 changes: 17 additions & 16 deletions route/build/src/write_simoutput_pio.f90
Original file line number Diff line number Diff line change
Expand Up @@ -131,20 +131,21 @@ END FUNCTION newFileAlarm
! *********************************************************************
SUBROUTINE output(ierr, message)

USE public_var, ONLY: outputAtGage ! ascii containing last restart and history files
USE public_var, ONLY: nOutFreq !
USE public_var, ONLY: outputFrequency !
USE globalData, ONLY: simDatetime ! previous,current and next model datetime
USE globalData, ONLY: timeVar ! current simulation time variable
USE globalData, ONLY: sec2tunit ! seconds per time unit
USE globalData, ONLY: RCHFLX_trib ! reach flux data structure containing current flux variables
USE globalData, ONLY: rch_per_proc ! number of reaches assigned to each proc (size = num of procs+1)
USE globalData, ONLY: nRch_mainstem ! number of mainstem reach
USE globalData, ONLY: nTribOutlet ! number of
USE globalData, ONLY: index_write_gage ! reach index (w.r.t. global domain) corresponding gauge location
USE globalData, ONLY: ioDesc_hru_float ! pio decomposition descriptor for hru
USE globalData, ONLY: ioDesc_rch_float ! pio decomposition descriptor for reaches
USE globalData, ONLY: ioDesc_gauge_float ! pio decomposition descriptor for gauges
USE public_var, ONLY: outputAtGage ! ascii containing last restart and history files
USE public_var, ONLY: nOutFreq ! integer output frequency, i.e, written at every "nOutFreq" of simulation step
USE public_var, ONLY: outputFrequency ! writing frequency
USE public_var, ONLY: time_stamp => ro_time_stamp !
USE globalData, ONLY: simDatetime ! previous,current and next model datetime
USE globalData, ONLY: timeVar ! current simulation time variable
USE globalData, ONLY: sec2tunit ! seconds per time unit
USE globalData, ONLY: RCHFLX_trib ! reach flux data structure containing current flux variables
USE globalData, ONLY: rch_per_proc ! number of reaches assigned to each proc (size = num of procs+1)
USE globalData, ONLY: nRch_mainstem ! number of mainstem reach
USE globalData, ONLY: nTribOutlet ! number of
USE globalData, ONLY: index_write_gage ! reach index (w.r.t. global domain) corresponding gauge location
USE globalData, ONLY: ioDesc_hru_float ! pio decomposition descriptor for hru
USE globalData, ONLY: ioDesc_rch_float ! pio decomposition descriptor for reaches
USE globalData, ONLY: ioDesc_gauge_float ! pio decomposition descriptor for gauges
USE nr_utils, ONLY: arth

implicit none
Expand Down Expand Up @@ -203,7 +204,7 @@ SUBROUTINE output(ierr, message)
end if

! write time variables (time and time bounds)
call hist_all_network%write_time(hVars, ierr, cmessage)
call hist_all_network%write_time(hVars, time_stamp, ierr, cmessage)
if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif

! write out output variables in history files
Expand All @@ -220,7 +221,7 @@ SUBROUTINE output(ierr, message)

if (outputAtGage) then
! write time variables (time and time bounds)
call hist_gage%write_time(hVars, ierr, cmessage)
call hist_gage%write_time(hVars, time_stamp, ierr, cmessage)
if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif

call hist_gage%write_flux_rch(hVars, ioDesc_gauge_float, index_write_gage, ierr, cmessage)
Expand Down

0 comments on commit 6212c25

Please sign in to comment.