Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow more flexible time stamp in forcing input #460

Merged
merged 5 commits into from
Mar 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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