From 7a0137edd3b46aa73eb854dd1e1f28688aca15ae Mon Sep 17 00:00:00 2001 From: ShervanGharari Date: Sat, 8 Aug 2020 21:30:29 -0400 Subject: [PATCH 01/29] new strcuture, global varibaribles and modified model set up in stand alone to read the second netcdf file that inclue flux to or from river segment or target volume for lakes --- route/build/src/dataTypes.f90 | 12 + route/build/src/globalData.f90 | 8 + route/build/src/public_var.f90 | 13 +- route/build/src/read_control.f90 | 19 +- .../build/src/standalone/get_basin_runoff.f90 | 70 ++- route/build/src/standalone/model_setup.f90 | 432 ++++++++++++------ route/build/src/standalone/read_runoff.f90 | 170 ++++--- 7 files changed, 495 insertions(+), 229 deletions(-) diff --git a/route/build/src/dataTypes.f90 b/route/build/src/dataTypes.f90 index a303e26f..637dc8ad 100644 --- a/route/build/src/dataTypes.f90 +++ b/route/build/src/dataTypes.f90 @@ -174,6 +174,18 @@ MODULE dataTypes real(dp) , allocatable :: basinPrecip(:)! remapped river network catchment runoff (size: number of nHRU) end type runoff + ! water management data; fluxes to/from reaches or target volume + type, public :: wm + integer(i4b) :: nTime ! number of time steps + integer(i4b) :: nSpace ! number of spatial dimension, in this case only one dimentonal + real(dp) :: time ! time variable at one time step + real(dp) , allocatable :: sim(:) ! user specified flux add/subtract, or volume at one time step (size: nSpace) + integer(i4b) , allocatable :: seg_id(:) ! id of reach in data (size: nSpace) + integer(i4b) , allocatable :: seg_ix(:) ! Index of river network reach IDs corresponding reach ID in data + real(dp) , allocatable :: flux_wm(:) ! allocated flux to existing river network using sort_flux (size: number of nRCH) + real(dp) , allocatable :: vol_wm(:) ! allocated target vol to existing river network using sort_flux (size: number of nRCH) +end type + ! ---------- reach parameters ---------------------------------------------------------------------------- ! Reach Parameters diff --git a/route/build/src/globalData.f90 b/route/build/src/globalData.f90 index e39ca2df..eeea738e 100644 --- a/route/build/src/globalData.f90 +++ b/route/build/src/globalData.f90 @@ -88,6 +88,7 @@ module globalData ! ---------- input file information ------------------------------------------------------------------- type(infileinfo) , allocatable , public :: infileinfo_data(:) ! conversion factor to convert time to units of days + type(infileinfo) , allocatable , public :: infileinfo_data_wm(:)! conversion factor to convert time to units of days ! ---------- Misc. data ------------------------------------------------------------------------- @@ -186,6 +187,13 @@ module globalData real(dp) , allocatable , public :: basinPrecip_trib(:) ! HRU precipitation array (m/s) for tributaries real(dp) , allocatable , public :: basinPrecip_main(:) ! HRU precipitation array (m/s) for mainstem + ! seg water management fluxes and target volume + type(wm) , public :: wm_data ! SEG flux and target vol data structure for one time step for river network + real(dp) , allocatable , public :: flux_wm_trib(:) ! SEG flux array (m3/s) for tributaries + real(dp) , allocatable , public :: flux_wm_main(:) ! SEG flux array (m3/s) for mainstem + real(dp) , allocatable , public :: vol_wm_trib(:) ! SEG target volume (for lakes) (m3) for tributaries + real(dp) , allocatable , public :: vol_wm_main(:) ! SEG target volume (for lakes) (m3) for mainstem + ! domain data ! MPI type(subbasin_mpi) , public :: domains(maxDomain) ! domain decomposition data structure (maximum domain is set to maxDomain) diff --git a/route/build/src/public_var.f90 b/route/build/src/public_var.f90 index f82352e9..b13df4ca 100644 --- a/route/build/src/public_var.f90 +++ b/route/build/src/public_var.f90 @@ -93,7 +93,8 @@ module public_var integer(i4b) ,public :: doesBasinRoute = 1 ! basin routing options 0-> no, 1->IRF, otherwise error integer(i4b) ,public :: doesAccumRunoff = 1 ! option to delayed runoff accumulation over all the upstream reaches logical(lgt),public :: is_lake_sim = .false. ! logical whether or not lakes are activated in simulation - logical(lgt),public :: is_wm_sim = .false. ! logical whether or not water management componenets, abstraction, injections and target volums are provided and will be used in the simulation + logical(lgt),public :: is_flux_wm = .false. ! logical whether or not water management componenets, abstraction, injections and target volums are provided and will be used in the simulation + logical(lgt),public :: is_vol_wm = .false. ! logical whether or not water management componenets, abstraction, injections and target volums are provided and will be used in the simulation ! RIVER NETWORK TOPOLOGY character(len=strLen),public :: fname_ntopOld = '' ! old filename containing stream network topology information logical(lgt) ,public :: ntopAugmentMode = .false. ! option for river network augmentation mode. terminate the program after writing augmented ntopo. @@ -101,7 +102,7 @@ module public_var character(len=strLen),public :: dname_sseg = '' ! dimension name of segment in river network data character(len=strLen),public :: dname_nhru = '' ! dimension name of hru in river network data integer(i4b) ,public :: idSegOut = integerMissing ! id of outlet stream segment - ! RUNOFF FILE + ! RUNOFF, EVAPORATION AND PRECIPITATION FILE character(len=strLen),public :: fname_qsim = '' ! simulated runoff netCDF name character(len=strLen),public :: vname_qsim = '' ! variable name for simulated runoff character(len=strLen),public :: vname_evapo = '' ! variable name for actual evapoartion @@ -115,6 +116,14 @@ module public_var character(len=strLen),public :: units_qsim = '' ! units of simulated runoff data real(dp) ,public :: dt = realMissing ! time step (seconds) real(dp) ,public :: input_fillvalue = realMissing ! fillvalue used for input variables (runoff, precipitation, evaporation) + ! FLUXES TO/FROM REACHES AND LAKES STATES FILE + 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 + character(len=strLen),public :: vname_vol_wm = '' ! variable name for target volume when lake is_lake_sim is on + character(len=strLen),public :: vname_time_wm = '' ! variable name for time + character(len=strLen),public :: vname_segid_wm = '' ! variable name for runoff hru id + character(len=strLen),public :: dname_time_wm = '' ! dimension name for time + character(len=strLen),public :: dname_segid_wm = '' ! dimension name for hru in runoff data ! RUNOFF REMAPPING logical(lgt),public :: is_remap = .false. ! logical whether or not runnoff needs to be mapped to river network HRU character(len=strLen),public :: fname_remap = '' ! runoff mapping netCDF name diff --git a/route/build/src/read_control.f90 b/route/build/src/read_control.f90 index 68b941ae..a15c6e25 100644 --- a/route/build/src/read_control.f90 +++ b/route/build/src/read_control.f90 @@ -114,16 +114,17 @@ SUBROUTINE read_control(ctl_fname, err, message) case(''); read(cData,*,iostat=io_error) doesBasinRoute ! basin routing options 0-> no, 1->IRF, otherwise error case(''); read(cData,*,iostat=io_error) doesAccumRunoff ! option to delayed runoff accumulation over all the upstream reaches. 0->no, 1->yes case('' ); read(cData,*,iostat=io_error) idSegOut ! desired outlet reach id (if -9999 --> route over the entire network) - case(''); read(cData,*,iostat=io_error) is_lake_sim ! logical whether or not lakes are simulated - case(''); read(cData,*,iostat=io_error) is_wm_sim ! logical whether or not water balance components, abstraction, injection and target volumes should be used in simulation + case(''); read(cData,*,iostat=io_error) is_lake_sim ! logical; lakes are simulated + case(''); read(cData,*,iostat=io_error) is_flux_wm ! logical; provided fluxes to or from seg/lakes should be considered + case(''); read(cData,*,iostat=io_error) is_vol_wm ! logical; provided target volume for managed lakes are considered ! RIVER NETWORK TOPOLOGY case(''); fname_ntopOld = trim(cData) ! name of file containing stream network topology information case(''); read(cData,*,iostat=io_error) ntopAugmentMode ! option for river network augmentation mode. terminate the program after writing augmented ntopo. case(''); fname_ntopNew = trim(cData) ! name of file containing stream segment information case(''); dname_nhru = trim(cData) ! dimension name of the HRUs case(''); dname_sseg = trim(cData) ! dimension name of the stream segments - ! RUNOFF FILE - case(''); fname_qsim = trim(cData) ! name of text file containing nc file names and their order for runoff + ! RUNOFF, EVAPORATION AND PRECIPITATION FILE + case(''); fname_qsim = trim(cData) ! name of text file containing ordered nc file names case(''); vname_qsim = trim(cData) ! name of runoff variable case(''); vname_evapo = trim(cData) ! name of actual evapoartion variable case(''); vname_precip = trim(cData) ! name of precipitation variable @@ -136,8 +137,16 @@ SUBROUTINE read_control(ctl_fname, err, message) case(''); units_qsim = trim(cData) ! units of runoff case(''); read(cData,*,iostat=io_error) dt ! time interval of the gridded runoff case(''); read(cData,*,iostat=io_error) input_fillvalue ! fillvalue used for input variable + ! FLUXES TO/FROM REACHES AND LAKE STATES FILE + case(''); fname_wm = trim(cData) ! name of text file containing ordered nc file names + case(''); vname_flux_wm = trim(cData) ! name of varibale for fluxes to and from seg (reachs/lakes) + case(''); vname_vol_wm = trim(cData) ! name of varibale for target volume for managed lakes + case(''); vname_time_wm = trim(cData) ! name of time variable + case(''); vname_segid_wm = trim(cData) ! name of the segid varibale in nc files + case(''); dname_time_wm = trim(cData) ! name of time dimension + case(''); dname_segid_wm = trim(cData) ! name of the routing HRUs dimension ! RUNOFF REMAPPING - case(''); read(cData,*,iostat=io_error) is_remap ! logical whether or not runnoff needs to be mapped to river network HRU + case(''); read(cData,*,iostat=io_error) is_remap ! logical case runnoff needs to be mapped to river network HRU case(''); fname_remap = trim(cData) ! name of runoff mapping netCDF case(''); vname_hruid_in_remap = trim(cData) ! name of variable containing ID of river network HRU case(''); vname_weight = trim(cData) ! name of variable contating areal weights of runoff HRUs within each river network HRU diff --git a/route/build/src/standalone/get_basin_runoff.f90 b/route/build/src/standalone/get_basin_runoff.f90 index a256a299..7e0ea1b9 100644 --- a/route/build/src/standalone/get_basin_runoff.f90 +++ b/route/build/src/standalone/get_basin_runoff.f90 @@ -20,21 +20,29 @@ SUBROUTINE get_hru_runoff(ierr, message) ! output: error control ! shared data USE public_var, ONLY:input_dir ! directory containing input data USE public_var, ONLY:fname_qsim ! simulated runoff netCDF name + USE public_var, ONLY:fname_wm ! flux and vol netCDF name USE public_var, ONLY:vname_qsim ! varibale runoff in netCDF file USE public_var, ONLY:vname_evapo ! varibale actual evaporation in netCDF file USE public_var, ONLY:vname_precip ! varibale precipitation in netCDF file - USE public_var, ONLY:is_remap ! logical whether or not runnoff needs to be mapped to river network HRU - USE public_var, ONLY:is_lake_sim ! logical whether or not lake should be simulated - USE public_var, ONLY:is_wm_sim ! logical whether or not water management components should be read, abstraction, injection and target volume + USE public_var, ONLY:vname_flux_wm ! varibale precipitation in netCDF file + USE public_var, ONLY:vname_vol_wm ! varibale precipitation in netCDF file + USE public_var, ONLY:is_remap ! logical runnoff needs to be mapped to river network HRU + USE public_var, ONLY:is_lake_sim ! logical lake should be simulated + USE public_var, ONLY:is_flux_wm ! logical water management components fluxes should be read + USE public_var, ONLY:is_vol_wm ! logical water management components target volume should be read USE globalData, ONLY:basinID ! basin ID + USE globalData, ONLY:reachID ! reach ID USE globalData, ONLY:iTime_local ! iTime index for the given netcdf file + USE globalData, ONLY:iTime_local_wm ! iTime index for the given netcdf file USE globalData, ONLY:nHRU ! number of routing sub-basin + USE globalData, ONLY:nRch ! number of routing seg (reaches and lakes) USE globalData, ONLY:runoff_data ! data structure to hru runoff data + USE globalData, ONLY:wm_data ! data structure to hru runoff data USE globalData, ONLY:remap_data ! data structure to remap data ! subroutines USE read_runoff, ONLY:read_runoff_data ! read runoff value into runoff_data data strucuture USE remapping, ONLY:remap_runoff ! mapping HM runoff to river network HRU runoff (HM_HRU /= RN_HRU) - USE remapping, ONLY:sort_flux ! mapping HM runoff to river network HRU runoff (HM_HRU == RN_HRU) + USE remapping, ONLY:sort_flux ! mapping runoff, fluxes based on order of HRUs, Reaches in the network implicit none ! input variables: none @@ -46,7 +54,7 @@ SUBROUTINE get_hru_runoff(ierr, message) ! output: error control ierr=0; message='get_hru_runoff/' - call infile_name(ierr, cmessage) + call infile_name(ierr, cmessage) ! read the infile name for given iTime 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(:,:) @@ -141,37 +149,71 @@ SUBROUTINE get_hru_runoff(ierr, message) ! output: error control END SUBROUTINE get_hru_runoff + ! ********************************************************************* ! private subroutine: get the name of input file based current time ! ********************************************************************* SUBROUTINE infile_name(ierr, message) ! output ! Shared data - USE public_var, ONLY: fname_qsim ! simulated runoff netCDF name - USE globalData, ONLY: iTime ! time index at simulation time step - USE globalData, ONLY: infileinfo_data ! the information of the input files - USE globalData, ONLY: iTime_local ! iTime index for the given netcdf file + USE public_var, ONLY: fname_qsim ! simulated runoff netCDF name + USE public_var, ONLY: fname_wm ! water management netCDF name + USE public_var, ONLY: is_flux_wm ! logical whether or not abstraction or injection should be read + USE public_var, ONLY: is_vol_wm ! logical whether or not target volume should be read + USE globalData, ONLY: iTime ! time index at simulation time step + USE globalData, ONLY: infileinfo_data ! the information of the input files for runoff, evapo and precip + USE globalData, ONLY: infileinfo_data_wm ! the information of the input files + USE globalData, ONLY: iTime_local ! iTime index for the given netcdf file + USE globalData, ONLY: iTime_local_wm ! iTime index for the given netcdf file implicit none ! output: - integer(i4b), intent(out) :: ierr ! error code - character(*), intent(out) :: message ! error message + integer(i4b), intent(out) :: ierr ! error code + character(*), intent(out) :: message ! error message ! local variable - integer(i4b) :: ix - !character(len=strLen) :: cmessage ! error message of downwind routine + integer(i4b) :: ix + integer(i4b) :: counter ! to check if both iTime_local are read properly + !character(len=strLen) :: cmessage ! error message - ierr=0; message='infile_name/' + ! initialize error control + ierr=0; message='infile_name/'; counter = 0 ; ! fast forward time to time index at simStart and save iTime and modJulday ixloop: do ix = 1, size(infileinfo_data) !loop over number of file if ((iTime >= infileinfo_data(ix)%iTimebound(1)).and.(iTime <= infileinfo_data(ix)%iTimebound(2))) then iTime_local = iTime - infileinfo_data(ix)%iTimebound(1) + 1 fname_qsim = trim(infileinfo_data(ix)%infilename) + counter = counter + 1 exit ixloop endif enddo ixloop + ! fast forward time to time index at simStart and save iTime and modJulday for water management nc file + if ((is_flux_wm).or.(is_vol_wm)) then + iyloop: do ix = 1, size(infileinfo_data_wm) !loop over number of file + if ((iTime >= infileinfo_data_wm(ix)%iTimebound(1)).and.(iTime <= infileinfo_data_wm(ix)%iTimebound(2))) then + iTime_local_wm = iTime - infileinfo_data_wm(ix)%iTimebound(1) + 1 + fname_wm = trim(infileinfo_data_wm(ix)%infilename) + counter = counter + 1 + exit iyloop + endif + enddo iyloop + endif + + ! check if the two files are identified in case is flux and vol flags are set to true + if ((counter /= 2).and.((is_flux_wm).or.(is_vol_wm))) then + ierr=20; message=trim(message)//'iTime local is out of bound for the netcdf file inputs based on given simulation time'; print*, ierr ; print*, message ; return ; + endif + + !print*, counter + !print*, ierr + !print*, message + !print*, infileinfo_data_wm(1)%iTimebound(1) + !print*, infileinfo_data_wm(1)%iTimebound(2) + !print*, infileinfo_data(1)%iTimebound(1) + !print*, infileinfo_data(1)%iTimebound(2) + END SUBROUTINE infile_name END MODULE get_runoff diff --git a/route/build/src/standalone/model_setup.f90 b/route/build/src/standalone/model_setup.f90 index 9c8c5aac..8c3b4da9 100644 --- a/route/build/src/standalone/model_setup.f90 +++ b/route/build/src/standalone/model_setup.f90 @@ -23,6 +23,7 @@ MODULE model_setup private public :: init_mpi public :: init_data +public :: infile_name CONTAINS @@ -81,7 +82,7 @@ SUBROUTINE init_data(pid, & ! input: proc id ierr=0; message='init_data/' ! runoff input files initialization - call inFile_pop(ierr, cmessage) + call init_inFile_pop(ierr, message) if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif ! time initialization @@ -109,45 +110,80 @@ SUBROUTINE init_data(pid, & ! input: proc id END SUBROUTINE init_data - ! ******************************************************************************** - ! public subroutine: initialize runoff, and runoff-mapping data - For stand-alone - ! ******************************************************************************** - SUBROUTINE init_runoff_data(pid, & ! input: proc id - ierr, message) ! output: error control + ! ********************************************************************* + ! public subroutine: initiate the reading of the netcdf files for runoff + ! or abstraction or injection + ! ********************************************************************* - USE public_var, ONLY: is_remap ! logical whether or not runnoff needs to be mapped to river network HRU - USE globalData, ONLY: remap_data ! runoff mapping data structure - USE globalData, ONLY: runoff_data ! runoff data structure + SUBROUTINE init_inFile_pop (ierr, message) ! output - implicit none - ! input: - integer(i4b), intent(in) :: pid ! proc id - ! output: error control - integer(i4b), intent(out) :: ierr ! error code - character(*), intent(out) :: message ! error message - ! local: - character(len=strLen) :: cmessage ! error message of downwind routine + ! Shared data + USE public_var, ONLY: input_dir ! directory containing the text files of fname_qsim and fname_wm + USE public_var, ONLY: fname_qsim ! simulated runoff txt file that includes the NetCDF file names + USE public_var, ONLY: vname_time ! variable name for time + USE public_var, ONLY: dname_time ! dimension name for time + USE public_var, ONLY: fname_wm ! simulated runoff txt file that includes the NetCDF file names + USE public_var, ONLY: vname_time_wm ! variable name for time + USE public_var, ONLY: dname_time_wm ! dimension name for time + USE globalData, ONLY: infileinfo_data ! the information of the input files + USE globalData, ONLY: infileinfo_data_wm ! the information of the input files for abstration, injection and target volume + USE public_var, ONLY: is_lake_sim ! logical whether or not lake should be simulated + USE public_var, ONLY: is_flux_wm ! logical whether or not abstraction and injection should be read from the file + USE public_var, ONLY: is_vol_wm ! logical whether or not target volume for lakes should be read - ! initialize error control - ierr=0; message='init_runoff_data/' - if (pid==0) then - ! runoff and remap data initialization (TO DO: split runoff and remap initialization) - call init_runoff(is_remap, & ! input: logical whether or not runnoff needs to be mapped to river network HRU - remap_data, & ! output: data structure to remap data - runoff_data, & ! output: data structure for runoff - ierr, cmessage) ! output: error control - if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif - end if ! if processor=0 (root) + ! output: error control + integer(i4b), intent(out) :: ierr ! error code + character(*), intent(out) :: message ! error message - END SUBROUTINE init_runoff_data + ! local: + character(len=strLen) :: cmessage ! error message of downwind routine + + ! initialize error control + ierr=0; message='init_inFile_pop/' + + call inFile_pop(input_dir, & ! input: name of the directory of the txt file + fname_qsim, & ! input: name of the txt file hold the nc file names + vname_time, & ! input: name of variable time in the nc files + dname_time, & ! input: name of dimention time in the nc files + infileinfo_data, & ! output: input file information + ierr, cmessage) ! output: error control + if(ierr/=0)then; message=trim(message)//trim(cmessage); return; end if + + ! passing the first nc file as global file name to read + fname_qsim = trim(infileinfo_data(1)%infilename) + + if ((is_flux_wm).or.(is_vol_wm)) then ! if either of abstraction injection or target volume is activated + call inFile_pop(input_dir, & ! input: name of the directory of the txt file + fname_wm, & ! input: name of the txt file hold the nc file names + vname_time_wm, & ! input: name of variable time in the nc files + dname_time_wm, & ! input: name of dimention time in the nc files + infileinfo_data_wm, & ! output: input file information + ierr, cmessage) ! output: error control + if(ierr/=0)then; message=trim(message)//trim(cmessage); return; end if + + ! passing the first nc file as global file name to read + fname_wm = trim(infileinfo_data_wm(1)%infilename) + + call inFile_corr_time(infileinfo_data, & ! input: the structure of simulated runoff, evapo and + infileinfo_data_wm, & ! inout: input file information + ierr, cmessage) ! output: error control + + endif + + END SUBROUTINE init_inFile_pop ! ********************************************************************* - ! public subroutine: read the name of the netcdf that is specified + ! private subroutine: read the name of the netcdf that is specified ! in a text file, populates the filed of inFiledata dataType ! ********************************************************************* - SUBROUTINE inFile_pop(ierr, message) ! output + SUBROUTINE inFile_pop(dir_name, & ! input: name of the directory of the txt file + file_name, & ! input: name of the txt file hold the nc file names + time_var_name, & ! input: name of variable time in the nc files + time_dim_name, & ! input: name of dimention time in the nc files + inputfileinfo, & ! output: input file information + ierr, message) ! output: error control ! data types USE dataTypes, ONLY: infileinfo ! the data type for storing the infromation of the nc files and its attributes @@ -160,18 +196,19 @@ SUBROUTINE inFile_pop(ierr, message) ! output USE io_netcdf, ONLY: get_var_attr ! get the attributes interface USE io_netcdf, ONLY: get_nc_dim_len ! get the nc dimension length - ! Shared data - USE public_var, ONLY: input_dir ! directory containing input data - USE public_var, ONLY: fname_qsim ! simulated runoff txt file that includes the NetCDF file names - USE public_var, ONLY: vname_time ! variable name for time - USE public_var, ONLY: dname_time ! - USE public_var, ONLY: time_units ! - USE public_var, ONLY: calendar ! - USE globalData, ONLY: infileinfo_data ! the information of the input files + ! input + character(len=strLen), intent(in) :: dir_name ! the name of the directory that the txt file located + character(len=strLen), intent(in) :: file_name ! the name of the file that include the nc file names + character(len=strLen), intent(in) :: time_var_name ! the name of the time variable + character(len=strLen), intent(in) :: time_dim_name ! the name of dimension time - ! output: error control - integer(i4b), intent(out) :: ierr ! error code - character(*), intent(out) :: message ! error message + ! inoutput + type(infileinfo), intent(inout), allocatable :: inputfileinfo(:) ! the name of structure that hold the infile information + + ! output + !type(infileinfo), intent(out) , allocatable :: inputfileinfo ! the name of structure that hold the infile information + integer(i4b), intent(out) :: ierr ! error code + character(*), intent(out) :: message ! error message ! local varibales integer(i4b) :: unit ! file unit (free unit output from file_open) @@ -189,7 +226,7 @@ SUBROUTINE inFile_pop(ierr, message) ! output ierr=0; message='inFile_pop/' ! build filename and its path containing list of NetCDF files - infilename = trim(input_dir)//trim(fname_qsim) + infilename = trim(dir_name)//trim(file_name) ! open the text file call file_open(trim(infilename),unit,ierr,cmessage) @@ -201,7 +238,7 @@ SUBROUTINE inFile_pop(ierr, message) ! output nFile = size(dataLines) ! get the name of the lines in the file ! allocate space for forcing information - allocate(infileinfo_data(nFile), stat=ierr) + allocate(inputfileinfo(nFile), stat=ierr) if(ierr/=0)then; ierr=20; message=trim(message)//'problem allocating space for forcFileInfo'; return; end if ! poputate the forcingInfo structure with filenames, and time variables/attributes @@ -212,42 +249,34 @@ SUBROUTINE inFile_pop(ierr, message) ! output if(ierr/=0)then; message=trim(message)//'problem reading a line of data from file ['//trim(infilename)//']'; return; end if ! set forcing file name - infileinfo_data(iFile)%infilename = trim(filenameData) + inputfileinfo(iFile)%infilename = trim(filenameData) ! get the time units - if (trim(time_units) == charMissing) then - call get_var_attr(trim(input_dir)//trim(infileinfo_data(iFile)%infilename), & - trim(vname_time), 'units', infileinfo_data(iFile)%unit, ierr, cmessage) - if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif - else - infileinfo_data(iFile)%unit = trim(time_units) - end if + call get_var_attr(trim(dir_name)//trim(inputfileinfo(iFile)%infilename), & + trim(time_var_name), 'units', inputfileinfo(iFile)%unit, ierr, cmessage) + if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif ! get the calendar - if (trim(calendar) == charMissing) then - call get_var_attr(trim(input_dir)//trim(infileinfo_data(iFile)%infilename), & - trim(vname_time), 'calendar', infileinfo_data(iFile)%calendar, ierr, cmessage) - if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif - else - infileinfo_data(iFile)%calendar = trim(calendar) - end if + call get_var_attr(trim(dir_name)//trim(inputfileinfo(iFile)%infilename), & + trim(time_var_name), 'calendar', inputfileinfo(iFile)%calendar, ierr, cmessage) + if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif ! get the dimension of the time to populate nTime and pass it to the get_nc file - call get_nc_dim_len(trim(input_dir)//trim(infileinfo_data(iFile)%infilename), & - trim(dname_time), infileinfo_data(iFile)%nTime, ierr, cmessage) + call get_nc_dim_len(trim(dir_name)//trim(inputfileinfo(iFile)%infilename), & + trim(time_dim_name), inputfileinfo(iFile)%nTime, ierr, cmessage) if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif - nTime = infileinfo_data(iFile)%nTime ! the length of time varibale for each nc file + nTime = inputfileinfo(iFile)%nTime ! the length of time varibale for each nc file ! allocate space for time varibale of each file - allocate(infileinfo_data(iFile)%timeVar(nTime)) - if(ierr/=0)then; ierr=20; message=trim(message)//'problem allocating space for infileinfo_data(:)%timeVar'; return; end if + allocate(inputfileinfo(iFile)%timeVar(nTime)) + if(ierr/=0)then; ierr=20; message=trim(message)//'problem allocating space for inputfileinfo(:)%timeVar'; return; end if ! get the time varibale - call get_nc(trim(input_dir)//trim(infileinfo_data(iFile)%infilename), & - vname_time, infileinfo_data(iFile)%timeVar, 1, nTime, ierr, cmessage) ! does it needs timeVar(:) + call get_nc(trim(dir_name)//trim(inputfileinfo(iFile)%infilename), & + time_var_name, inputfileinfo(iFile)%timeVar, 1, nTime, ierr, cmessage) ! does it needs timeVar(:) ! get the time multiplier needed to convert time to units of days for each nc file - t_unit = trim( infileinfo_data(iFile)%unit(1:index(infileinfo_data(iFile)%unit,' ')) ) + t_unit = trim( inputfileinfo(iFile)%unit(1:index(inputfileinfo(iFile)%unit,' ')) ) select case( trim(t_unit) ) case('seconds','second','sec','s'); convTime2Days=86400._dp case('minutes','minute','min','m'); convTime2Days=1440._dp @@ -256,19 +285,19 @@ SUBROUTINE inFile_pop(ierr, message) ! output case default ierr=20; message=trim(message)//'= '//trim(t_unit)//': must be seconds, minutes, hours or days.'; return end select - infileinfo_data(iFile)%convTime2Days = convTime2Days + inputfileinfo(iFile)%convTime2Days = convTime2Days ! get the reference julian day from the nc file - call process_time(trim(infileinfo_data(iFile)%unit),infileinfo_data(iFile)%calendar,infileinfo_data(iFile)%ncrefjulday,ierr, cmessage) + call process_time(trim(inputfileinfo(iFile)%unit),inputfileinfo(iFile)%calendar,inputfileinfo(iFile)%ncrefjulday,ierr, cmessage) if(ierr/=0) then; message=trim(message)//trim(cmessage)//' [ncrefjulday]'; return; endif ! populated the index of the iTimebound for each nc file if (iFile==1) then - infileinfo_data(iFile)%iTimebound(1) = 1 - infileinfo_data(iFile)%iTimebound(2) = nTime + inputfileinfo(iFile)%iTimebound(1) = 1 + inputfileinfo(iFile)%iTimebound(2) = nTime else ! if multiple files specfied in the txt file - infileinfo_data(iFile)%iTimebound(1) = infileinfo_data(iFile-1)%iTimebound(2) + 1 ! the last index from the perivous nc file + 1 - infileinfo_data(iFile)%iTimebound(2) = infileinfo_data(iFile-1)%iTimebound(2) + nTime ! the last index from the perivous nc file + 1 + inputfileinfo(iFile)%iTimebound(1) = inputfileinfo(iFile-1)%iTimebound(2) + 1 ! the last index from the perivous nc file + 1 + inputfileinfo(iFile)%iTimebound(2) = inputfileinfo(iFile-1)%iTimebound(2) + nTime ! the last index from the perivous nc file + 1 endif enddo @@ -276,22 +305,91 @@ SUBROUTINE inFile_pop(ierr, message) ! output ! close ascii file close(unit=unit,iostat=ierr); if(ierr/=0)then;message=trim(message)//'problem closing forcing file list'; return; end if - ! passing the first nc file as global file name to read - fname_qsim = trim(infileinfo_data(1)%infilename) - END SUBROUTINE inFile_pop + ! ********************************************************************* + ! private subroutine: get the two infiledata and convert the iTimebound of + ! the input_info_wm to match the input_info + ! ********************************************************************* + SUBROUTINE inFile_corr_time(inputfileinfo, & ! input: the structure of simulated runoff, evapo and + inputfileinfo_wm, & ! inout: input file information + ierr, message) ! output: error control + + ! data types + USE dataTypes, ONLY: infileinfo ! the data type for storing the infromation of the nc files and its attributes + + ! public data + USE public_var, ONLY: time_units ! time units (seconds, hours, or days) + USE public_var, ONLY: dt ! simulation time step in seconds + USE public_var, ONLY: secprday ! conversion of steps in days to seconds + + ! input + type(infileinfo), intent(in) :: inputfileinfo(:) ! the name of structure that hold the infile information + + ! inout + type(infileinfo), intent(inout) :: inputfileinfo_wm(:) ! the name of structure that hold the infile information + + ! output + integer(i4b), intent(out) :: ierr ! error code + character(*), intent(out) :: message ! error message + + ! local + integer(i4b) :: nt + integer(i4b) :: nFile ! number of nc files for the simulated runoff + integer(i4b) :: nFile_wm ! number of nc files for the water managent + integer(i4b) :: iFile ! for loop over the nc files + real(dp) :: refJulday_local ! the reference julian day based on the first nc file + real(dp) :: day_start_diff ! conversion of the day to the local time + real(dp) :: day_end_diff ! conversion of the day to the local time + + + ! initialize error control + ierr=0; message='inFile_corr_time/' + + ! set the reference julday based on the first nc file of simulation + refJulday_local = inputfileinfo(1)%ncrefjulday + nFile = size(inputfileinfo) + nFile_wm = size(inputfileinfo_wm) + + do iFile=1,nFile_wm + + nt = inputfileinfo_wm(iFile)%nTime ! get the number of time + + day_start_diff = inputfileinfo_wm(iFile)%timeVar(1) /inputfileinfo_wm(iFile)%convTime2Days+inputfileinfo_wm(iFile)%ncrefjulday - refJulday_local + day_end_diff = inputfileinfo_wm(iFile)%timeVar(nt)/inputfileinfo_wm(iFile)%convTime2Days+inputfileinfo_wm(iFile)%ncrefjulday - refJulday_local + + inputfileinfo_wm(iFile)%iTimebound(1) = day_start_diff*secprday/dt + 1 ! to convert the day difference into time step difference + inputfileinfo_wm(iFile)%iTimebound(2) = day_end_diff *secprday/dt ! to convert the day difference into time step difference + + end do + + ! checks if the staring and ending iTime of the inputfileinfo_wm overlap with the inputfileinfo of simulated runoff, evapo and precip + if (inputfileinfo_wm(1)%iTimebound(1) > inputfileinfo(1)%iTimebound(1)) then + print*, "The first water managment nc file starts later than the first simulted runoff, evapo and precip nc file and may cause crash" + endif + if (inputfileinfo_wm(nFile_wm)%iTimebound(2) < inputfileinfo(nFile)%iTimebound(2)) then + print*, "The last water managment nc file ends earlier than the last simulted runoff, evapo and precip nc file and may cause crash" + endif + if (inputfileinfo_wm(1)%iTimebound(1) < inputfileinfo(1)%iTimebound(1)) then + print*, "The water managment nc file starts earlier than the last simulted runoff, evapo and precip nc file" + endif + if (inputfileinfo_wm(nFile_wm)%iTimebound(2) > inputfileinfo(nFile)%iTimebound(2)) then + print*, "The water managment nc file ends later than the last simulted runoff, evapo and precip nc file" + endif + + + END SUBROUTINE inFile_corr_time + ! ********************************************************************* ! private subroutine: initialize time data ! ********************************************************************* SUBROUTINE init_time(ierr, message) ! output ! subroutines: - USE process_time_module, ONLY: process_time ! process time information - USE process_time_module, ONLY: conv_julian2cal ! compute data and time from julian day - USE process_time_module, ONLY: conv_cal2julian ! compute data and time from julian day - USE time_utils_module, ONLY: ndays_month ! compute number of days in a month + USE process_time_module, ONLY: process_time ! process time information + USE process_time_module, ONLY: process_calday ! compute data and time from julian day + USE io_netcdf, ONLY: get_nc ! netcdf input ! derived datatype USE dataTypes, ONLY: time ! time data type ! public data @@ -299,13 +397,8 @@ SUBROUTINE init_time(ierr, message) ! output USE public_var, ONLY: simStart ! date string defining the start of the simulation USE public_var, ONLY: simEnd ! date string defining the end of the simulation USE public_var, ONLY: calendar ! calendar name - USE public_var, ONLY: dt - USE public_var, ONLY: secprday USE public_var, ONLY: restart_write ! restart write option USE public_var, ONLY: restart_date ! restart date - USE public_var, ONLY: restart_month ! periodic restart month - USE public_var, ONLY: restart_day ! periodic restart day - USE public_var, ONLY: restart_hour ! periodic restart hr ! saved time variables USE globalData, ONLY: timeVar ! time variables (unit given by runoff data) USE globalData, ONLY: iTime ! time index at simulation time step @@ -314,9 +407,8 @@ SUBROUTINE init_time(ierr, message) ! output USE globalData, ONLY: startJulday ! julian day: start of routing simulation USE globalData, ONLY: endJulday ! julian day: end of routing simulation USE globalData, ONLY: modJulday ! julian day: at model time step + USE globalData, ONLY: restartJulday ! julian day: at restart USE globalData, ONLY: modTime ! model time data (yyyy:mm:dd:hh:mm:ss) - USE globalData, ONLY: restCal ! restart time data (yyyy:mm:dd:hh:mm:sec) - USE globalData, ONLY: dropCal ! restart dropoff calendar date/time USE globalData, ONLY: infileinfo_data ! the information of the input files implicit none @@ -333,9 +425,6 @@ SUBROUTINE init_time(ierr, message) ! output integer(i4b) :: iFile ! for loop over the nc files type(time) :: rofCal type(time) :: simCal - integer(i4b) :: nDays ! number of days in a month - real(dp) :: restartJulday - real(dp) :: tempJulday character(len=strLen) :: cmessage ! error message of downwind routine character(len=50) :: fmt1='(a,I4,a,I2.2,a,I2.2,x,I2.2,a,I2.2,a,F5.2)' @@ -383,8 +472,8 @@ SUBROUTINE init_time(ierr, message) ! output ! check sim_start is before the last time step in runoff data if(startJulday>roJulday(nTime)) then - call conv_julian2cal(roJulday(nTime), calendar, rofCal, ierr, cmessage) - call conv_julian2cal(startJulday, calendar, simCal, ierr, cmessage) + call process_calday(roJulday(nTime), calendar, rofCal, ierr, cmessage) + call process_calday(startJulday, calendar, simCal, ierr, cmessage) write(iulog,'(2a)') new_line('a'),'ERROR: is after the first time step in input runoff' write(iulog,fmt1) ' runoff_end : ', rofCal%iy,'-',rofCal%im,'-',rofCal%id, rofCal%ih,':', rofCal%imin,':',rofCal%dsec write(iulog,fmt1) ' : ', simCal%iy,'-',simCal%im,'-',simCal%id, simCal%ih,':', simCal%imin,':',simCal%dsec @@ -393,8 +482,8 @@ SUBROUTINE init_time(ierr, message) ! output ! Compare sim_start vs. time at first time step in runoff data if (startJulday < roJulday(1)) then - call conv_julian2cal(roJulday(1), calendar, rofCal, ierr, cmessage) - call conv_julian2cal(startJulday, calendar, simCal, ierr, cmessage) + call process_calday(roJulday(1), calendar, rofCal, ierr, cmessage) + call process_calday(startJulday, calendar, simCal, ierr, cmessage) write(iulog,'(2a)') new_line('a'),'WARNING: is before the first time step in input runoff' write(iulog,fmt1) ' runoff_start: ', rofCal%iy,'-',rofCal%im,'-',rofCal%id, rofCal%ih,':', rofCal%imin,':',rofCal%dsec write(iulog,fmt1) ' : ', simCal%iy,'-',simCal%im,'-',simCal%id, simCal%ih,':', simCal%imin,':',simCal%dsec @@ -404,8 +493,8 @@ SUBROUTINE init_time(ierr, message) ! output ! Compare sim_end vs. time at last time step in runoff data if (endJulday > roJulday(nTime)) then - call conv_julian2cal(roJulday(nTime), calendar, rofCal, ierr, cmessage) - call conv_julian2cal(endJulday, calendar, simCal, ierr, cmessage) + call process_calday(roJulday(nTime), calendar, rofCal, ierr, cmessage) + call process_calday(endJulday, calendar, simCal, ierr, cmessage) write(iulog,'(2a)') new_line('a'),'WARNING: is after the last time step in input runoff' write(iulog,fmt1) ' runoff_end: ', rofCal%iy,'-',rofCal%im,'-',rofCal%id, rofCal%ih,':', rofCal%imin,':',rofCal%dsec write(iulog,fmt1) ' : ', simCal%iy,'-',simCal%im,'-',simCal%id, simCal%ih,':', simCal%imin,':',simCal%dsec @@ -424,52 +513,60 @@ SUBROUTINE init_time(ierr, message) ! output ! initialize previous model time modTime(0) = time(integerMissing, integerMissing, integerMissing, integerMissing, integerMissing, realMissing) - ! Set restart calendar date/time and dropoff calendar date/time and - ! -- For periodic restart options --------------------------------------------------------------------- - ! Ensure that user-input restart month, day are valid. - ! "Annual" option: if user input day exceed number of days given user input month, set to last day - ! "Monthly" option: use 2000-01 as template calendar yr/month - ! "Daily" option: use 2000-01-01 as template calendar yr/month/day - select case(trim(restart_write)) - case('Annual','annual') - call ndays_month(2000, restart_month, calendar, nDays, ierr, cmessage) - if(ierr/=0) then; message=trim(message)//trim(cmessage); return; endif - if (restart_day > nDays) restart_day=nDays - case('Monthly','monthly'); restart_month = 1 - case('Daily','daily'); restart_month = 1; restart_day = 1 - end select - + ! restart drop off time select case(trim(restart_write)) case('last','Last') - call conv_julian2cal(endJulday, calendar, dropCal, ierr, cmessage) - if(ierr/=0) then; message=trim(message)//trim(cmessage)//' [endJulday->dropCal]'; return; endif - restart_month = dropCal%im; restart_day = dropCal%id; restart_hour = dropCal%ih + call process_time(trim(simEnd), calendar, restartJulday, ierr, cmessage) + if(ierr/=0) then; message=trim(message)//trim(cmessage)//' [restartDate]'; return; endif + case('never','Never') + restartJulday = 0.0_dp case('specified','Specified') if (trim(restart_date) == charMissing) then ierr=20; message=trim(message)//' must be provided when option is "specified"'; return end if call process_time(trim(restart_date),calendar, restartJulday, ierr, cmessage) - if(ierr/=0) then; message=trim(message)//trim(cmessage)//' [restart_date]'; return; endif - restartJulday = restartJulday - dt/secprday - call conv_julian2cal(restartJulday, calendar, dropCal, ierr, cmessage) - if(ierr/=0) then; message=trim(message)//trim(cmessage)//' [restartJulday->dropCal]'; return; endif - restart_month = dropCal%im; restart_day = dropCal%id; restart_hour = dropCal%ih - case('Annual','Monthly','Daily','annual','monthly','daily') - restCal = time(2000, restart_month, restart_day, restart_hour, 0, 0._dp) - call conv_cal2julian(restCal, calendar, tempJulday, ierr, cmessage) - if(ierr/=0)then; message=trim(message)//trim(cmessage)//' [restCal->tempJulday]'; return; endif - tempJulday = tempJulday - dt/secprday - call conv_julian2cal(tempJulday, calendar, dropCal, ierr, cmessage) - if(ierr/=0) then; message=trim(message)//trim(cmessage)//' [tempJulday->dropCal]'; return; endif - restart_month = dropCal%im; restart_day = dropCal%id; restart_hour = dropCal%ih - case('never','Never') - restCal = time(integerMissing, integerMissing, integerMissing, integerMissing, integerMissing, realMissing) + if(ierr/=0) then; message=trim(message)//trim(cmessage)//' [restartDate]'; return; endif case default - ierr=20; message=trim(message)//'Current accepted options: L[l]ast, N[n]ever, S[s]pecified, A[a]nnual, M[m]onthly, D[d]aily'; return + ierr=20; message=trim(message)//'Current accepted options: last[Last], never[Never], specified[Specified]'; return end select END SUBROUTINE init_time + ! ******************************************************************************** + ! public subroutine: initialize runoff, and runoff-mapping data - For stand-alone + ! ******************************************************************************** + SUBROUTINE init_runoff_data(pid, & ! input: proc id + ierr, message) ! output: error control + + USE public_var, ONLY: is_remap ! logical whether or not runnoff needs to be mapped to river network HRU + USE globalData, ONLY: remap_data ! runoff mapping data structure + USE globalData, ONLY: runoff_data ! runoff data structure + USE globalData, ONLY: AbsInj_data ! abstraction injection data structure + + implicit none + ! input: + integer(i4b), intent(in) :: pid ! proc id + ! output: error control + integer(i4b), intent(out) :: ierr ! error code + character(*), intent(out) :: message ! error message + ! local: + character(len=strLen) :: cmessage ! error message of downwind routine + + ! initialize error control + ierr=0; message='init_runoff_data/' + + if (pid==0) then + ! runoff and remap data initialization (TO DO: split runoff and remap initialization) + call init_runoff(is_remap, & ! input: logical whether or not runnoff needs to be mapped to river network HRU + remap_data, & ! output: data structure to remap data + runoff_data, & ! output: data structure for runoff + AbsInj_data, & ! output: data structure for abstraction and injection and target volume + ierr, cmessage) ! output: error control + if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif + end if ! if processor=0 (root) + + END SUBROUTINE init_runoff_data + ! ***** ! private subroutine: get mapping data between runoff hru and river network hru @@ -477,14 +574,33 @@ END SUBROUTINE init_time SUBROUTINE init_runoff(remap_flag, & ! input: logical whether or not runnoff needs to be mapped to river network HRU remap_data_in, & ! output: data structure to remap data runoff_data_in, & ! output: data structure for runoff + AbsInj_data_in, & ! output: data strcuture for abstraction injection and target volume ierr, message) ! output: error control USE public_var, ONLY: ancil_dir ! name of the ancillary directory USE public_var, ONLY: input_dir ! name of the runoff input directory - USE public_var, ONLY: fname_qsim ! name of simulated runoff netCDF + USE public_var, ONLY: fname_qsim ! name of simulated runoff file + USE public_var, ONLY: vname_qsim ! name of simulated runoff varibale + USE public_var, ONLY: vname_evapo ! name of simulated evaporation varibale + USE public_var, ONLY: vname_precip ! name of simulated precipitation varibale + USE public_var, ONLY: vname_hruid ! name of name of varibale hruid + USE public_var, ONLY: vname_time ! name of varibale time + USE public_var, ONLY: dname_time ! name of dimension for variable time + USE public_var, ONLY: dname_hruid ! name of dimension for varibale hruid + USE public_var, ONLY: dname_xlon ! name of dimension for lon + USE public_var, ONLY: dname_ylat ! name of dimension for lat + USE public_var, ONLY: fname_wm ! name of abstraction/injection file name + USE public_var, ONLY: vname_flux_wm ! name of varibale abstraction/injection + USE public_var, ONLY: vname_vol_wm ! name of varibale target volume + USE public_var, ONLY: vname_time_wm ! name of varibale time for abstraction/injection + USE public_var, ONLY: vname_segid_wm ! name of varibale river network hruid for abs/inj + USE public_var, ONLY: dname_time_wm ! name of dimension time for ans/inj + USE public_var, ONLY: dname_segid_wm ! name of dimension hruid USE public_var, ONLY: fname_remap ! name of runoff mapping netCDF name USE public_var, ONLY: calendar ! name of calendar USE public_var, ONLY: time_units ! time units + USE public_var, ONLY: is_AbsInj ! logical whether or not abstraction or injection should be read + USE public_var, ONLY: is_TargVol ! logical whether or not target volume should be read USE globalData, ONLY: basinID ! basin ID USE dataTypes, ONLY: remap ! remapping data type USE dataTypes, ONLY: runoff ! runoff data type @@ -493,9 +609,10 @@ SUBROUTINE init_runoff(remap_flag, & ! input: logical whether or not runno implicit none ! data structures - logical(lgt), intent(in) :: remap_flag ! logical whether or not runnoff needs to be mapped to river network HRU - type(remap) , intent(out) :: remap_data_in ! data structure to remap data from a polygon (e.g., grid) to another polygon (e.g., basin) - type(runoff) , intent(out) :: runoff_data_in ! runoff for one time step for all HRUs + logical(lgt), intent(in) :: remap_flag ! logical whether or not runnoff needs to be mapped to river network HRU + type(remap), intent(out) :: remap_data_in ! data structure to remap data from a polygon (e.g., grid) to another polygon (e.g., basin) + type(runoff), intent(out) :: runoff_data_in ! runoff for one time step for all HRUs + type(wm), intent(out) :: wm_data_in ! abstraction/injection for one time step for all HRUs ! error control integer(i4b), intent(out) :: ierr ! error code character(*), intent(out) :: message ! error message @@ -507,11 +624,18 @@ SUBROUTINE init_runoff(remap_flag, & ! input: logical whether or not runno ! initialize error control ierr=0; message='init_runoff/' - ! get runoff metadata - call read_runoff_metadata(trim(input_dir)//trim(fname_qsim), & ! input: filename - runoff_data_in, & ! output: runoff data structure - time_units, calendar, & ! output: number of time steps, time units, calendar - ierr, cmessage) ! output: error control + ! get runoff metadata for simulated runoff, evaporation and precipitation + call read_runoff_metadata(trim(input_dir)//trim(fname_qsim), & ! input: filename + vname_qsim, & ! input: varibale name for simulated runoff + vname_time, & ! input: varibale name for time + dname_time, & ! input: dimension of variable time + vname_hruid, & ! input: varibale hruid + dname_hruid, & ! input: dimension of varibale hru + dname_ylat, & ! input: dimension of lat + dname_xlon, & ! input: dimension of lon + runoff_data_in, & ! output: runoff data structure + time_units, calendar, & ! output: number of time steps, time units, calendar + ierr, cmessage) ! output: error control if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif !write(*,*) 'runoff_data_in%nSpace, nTime, trim(time_units) = ', runoff_data_in%nSpace(:), runoff_data_in%nTime, trim(time_units) @@ -586,6 +710,36 @@ SUBROUTINE init_runoff(remap_flag, & ! input: logical whether or not runno endif + ! is abstraction and injection flag is active + if ((is_flux_wm).or.(is_vol_wm)) then + + call read_runoff_metadata(trim(input_dir)//trim(fname_wm), & ! input: filename + vname_flux_wm, & ! input: varibale name for simulated runoff + vname_time_wm, & ! input: varibale name for time + dname_time_wm, & ! input: dimension of variable time + vname_segid_wm, & ! input: varibale hruid + dname_segid_wm, & ! input: dimension of varibale hru + dname_ylat, & ! input: dimension of lat + dname_xlon, & ! input: dimension of lon + wm_data_in, & ! output: water management data structure + time_units, calendar, & ! output: number of time steps, time units, calendar + ierr, cmessage) ! output: error control + if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif + + ! allocate the hru_ix based on number of hru_id presented in the + allocate(AbsInj_data_in%hru_ix(size(AbsInj_data_in%hru_id)), stat=ierr) + if(ierr/=0)then; message=trim(message)//'problem allocating runoff_data_in%hru_ix'; return; endif + + ! get indices of the HRU ids in the runoff file in the routing layer + call get_qix(AbsInj_data_in%hru_id, & ! input: vector of ids in mapping file + basinID, & ! input: vector of ids in the routing layer + AbsInj_data_in%hru_ix, & ! output: indices of hru ids in routing layer + ierr, cmessage) ! output: error control + if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif + + endif + + END SUBROUTINE init_runoff @@ -652,7 +806,7 @@ SUBROUTINE get_qix(qid,qidMaster,qix,ierr,message) end do ! looping through the vector - ! check + ! check again do ix=1,size(qid) if(qix(ix) /= integerMissing)then if(qid(ix) /= qidMaster( qix(ix) ) )then diff --git a/route/build/src/standalone/read_runoff.f90 b/route/build/src/standalone/read_runoff.f90 index e90a28d1..a715b248 100644 --- a/route/build/src/standalone/read_runoff.f90 +++ b/route/build/src/standalone/read_runoff.f90 @@ -6,10 +6,10 @@ module read_runoff USE io_netcdf, only:open_nc USE io_netcdf, only:get_nc USE io_netcdf, only:get_var_attr -USE io_netcdf, only:check_attr USE io_netcdf, only:get_nc_dim_len USE dataTypes, only:runoff ! runoff data type + implicit none private @@ -22,17 +22,31 @@ module read_runoff ! public subroutine: get runoff metadata... ! ****************************************** subroutine read_runoff_metadata(& - ! input - fname , & ! filename - ! output - runoff_data_in , & ! runoff data structure - timeUnits , & ! time units - calendar , & ! calendar - ! error control - ierr, message) ! output: error control + ! input + fname , & ! filename including directory + var_name , & ! varibale name + var_time_name , & ! name of varibale time + dim_time_name , & ! name of dimension time + var_hru_name , & ! name of varibale HRUs + dim_hru_name , & ! name of dimension HRUs + dim_ylat_name , & ! name of dimension lat in case of a 2D input varibale + dim_xlon_name , & ! name of dimension lon in case of a 2D input varibale + ! output + runoff_data_in , & ! runoff data structure + timeUnits , & ! time units + calendar , & ! calendar + ! error control + ierr, message) ! output: error control implicit none ! input variables character(*), intent(in) :: fname ! filename + character(*), intent(in) :: var_name ! name of the varibale for simulated runoff or abstraction/injection + character(*), intent(in) :: var_time_name ! name of the varibale time + character(*), intent(in) :: dim_time_name ! name of dimension for time + character(*), intent(in) :: var_hru_name ! name of the varibale hru + character(*), intent(in) :: dim_hru_name ! name of dimension for hydrological HRUs + character(*), intent(in) :: dim_ylat_name ! name of dimension along lat + character(*), intent(in) :: dim_xlon_name ! name of dimension along lon ! output variables type(runoff), intent(out) :: runoff_data_in ! runoff for one time step for all HRUs character(*), intent(out) :: timeUnits ! time units @@ -53,7 +67,7 @@ subroutine read_runoff_metadata(& if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif ! get the ID of runoff variable - ierr = nf90_inq_varid(ncid, trim(vname_qsim), ivarID) + ierr = nf90_inq_varid(ncid, trim(var_name), ivarID) if(ierr/=0)then; message=trim(message)//trim(nf90_strerror(ierr)); return; endif ! get the number of dimensions - must be 2D(hru, time) or 3D(y, x, time) @@ -62,8 +76,24 @@ subroutine read_runoff_metadata(& ! get runoff metadata select case( nDims ) - case(2); call read_1D_runoff_metadata(fname, runoff_data_in, timeUnits, calendar, ierr, cmessage) - case(3); call read_2D_runoff_metadata(fname, runoff_data_in, timeUnits, calendar, ierr, cmessage) + case(2); call read_1D_runoff_metadata(fname, & ! name of dile including its directory + var_time_name, & ! name of varibale time + dim_time_name, & ! dimension of varibale time + var_hru_name, & ! name of varibale hrus + dim_hru_name, & ! dimension of varibales hrus + runoff_data_in, & + timeUnits, & + calendar, & + ierr, cmessage) + case(3); call read_2D_runoff_metadata(fname, & ! name of file including its directory + var_time_name, & ! name of varibale time + dim_time_name, & ! dimension of varibale time + dim_ylat_name, & ! dimesnion of lat + dim_xlon_name, & ! dimension of lon + runoff_data_in, & + timeUnits, & + calendar, & + ierr, cmessage) case default; ierr=20; message=trim(message)//'runoff input must be 2-dimension (e.g, [time, hru]) or 3-dimension (e.g., [time, lat, lon]'; return end select if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif @@ -75,47 +105,55 @@ end subroutine read_runoff_metadata ! ****************************************** subroutine read_1D_runoff_metadata(& ! input - fname , & ! filename + fname , & ! filename + var_time_name , & ! name of varibale time + dim_time_name , & ! name of dimension time + var_hru_name , & ! name of varibale HRUs + dim_hru_name , & ! name of dimension HRUs ! output runoff_data_in , & ! runoff data structure - timeUnits , & ! time units - calendar , & ! calendar + timeUnits , & ! time units + calendar , & ! calendar ! error control - ierr, message) ! output: error control + ierr, message) ! output: error control implicit none ! input variables - character(*), intent(in) :: fname ! filename + character(*), intent(in) :: fname ! filename + character(*), intent(in) :: var_time_name ! name of the varibale time + character(*), intent(in) :: dim_time_name ! name of dimension for time + character(*), intent(in) :: var_hru_name ! name of the varibale hru + character(*), intent(in) :: dim_hru_name ! name of dimension for hydrological HRUs ! output variables - type(runoff), intent(out) :: runoff_data_in ! runoff for one time step for all HRUs - character(*), intent(out) :: timeUnits ! time units - character(*), intent(out) :: calendar ! calendar + type(runoff), intent(out) :: runoff_data_in ! runoff for one time step for all HRUs + character(*), intent(out) :: timeUnits ! time units + character(*), intent(out) :: calendar ! calendar ! error control - integer(i4b), intent(out) :: ierr ! error code - character(*), intent(out) :: message ! error message + integer(i4b), intent(out) :: ierr ! error code + character(*), intent(out) :: message ! error message ! local variables - character(len=strLen) :: cmessage ! error message from subroutine + character(len=strLen) :: cmessage ! error message from subroutine ! initialize error control ierr=0; message='read_1D_runoff_metadata/' runoff_data_in%nSpace(2) = integerMissing ! get the number of HRUs - call get_nc_dim_len(fname, trim(dname_hruid), runoff_data_in%nSpace(1), ierr, cmessage) + call get_nc_dim_len(fname, trim(dim_hru_name), runoff_data_in%nSpace(1), ierr, cmessage) if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif ! get number of time steps from the runoff file - call get_nc_dim_len(fname, trim(dname_time), runoff_data_in%nTime, ierr, cmessage) + call get_nc_dim_len(fname, trim(dim_time_name), runoff_data_in%nTime, ierr, cmessage) if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif ! get the time units if (trim(timeUnits) == charMissing) then - call get_var_attr(fname, trim(vname_time), 'units', timeUnits, ierr, cmessage) + call get_var_attr(fname, trim(var_time_name), 'units', timeUnits, ierr, cmessage) if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif end if ! get the calendar if (trim(calendar) == charMissing) then - call get_var_attr(fname, trim(vname_time), 'calendar', calendar, ierr, cmessage) + call get_var_attr(fname, trim(var_time_name), 'calendar', calendar, ierr, cmessage) if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif end if @@ -128,7 +166,7 @@ subroutine read_1D_runoff_metadata(& if(ierr/=0)then; message=trim(message)//'problem allocating runoff_data_in%sim'; return; endif ! get HRU ids from the runoff file - call get_nc(fname, vname_hruid, runoff_data_in%hru_id, 1, runoff_data_in%nSpace(1), ierr, cmessage) + call get_nc(fname, var_hru_name, runoff_data_in%hru_id, 1, runoff_data_in%nSpace(1), ierr, cmessage) if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif end subroutine read_1D_runoff_metadata @@ -138,50 +176,58 @@ end subroutine read_1D_runoff_metadata ! ****************************************** subroutine read_2D_runoff_metadata(& ! input - fname , & ! filename + fname , & ! filename + var_time_name , & ! name of varibale time + dim_time_name , & ! name of dimension time + dim_ylat_name , & ! name of varibale HRUs + dim_xlon_name , & ! name of dimension HRUs ! output runoff_data_in , & ! runoff data structure - timeUnits , & ! time units - calendar , & ! calendar + timeUnits , & ! time units + calendar , & ! calendar ! error control - ierr, message) ! output: error control + ierr, message) ! output: error control implicit none ! input variables - character(*), intent(in) :: fname ! filename + character(*), intent(in) :: fname ! filename + character(*), intent(in) :: var_time_name ! name of the varibale time + character(*), intent(in) :: dim_time_name ! name of dimension for time + character(*), intent(in) :: dim_ylat_name ! name of dimension along lat + character(*), intent(in) :: dim_xlon_name ! name of dimension along lon ! output variables - type(runoff), intent(out) :: runoff_data_in ! runoff for one time step for all HRUs - character(*), intent(out) :: timeUnits ! time units - character(*), intent(out) :: calendar ! calendar + type(runoff), intent(out) :: runoff_data_in ! runoff for one time step for all HRUs + character(*), intent(out) :: timeUnits ! time units + character(*), intent(out) :: calendar ! calendar ! error control - integer(i4b), intent(out) :: ierr ! error code - character(*), intent(out) :: message ! error message + integer(i4b), intent(out) :: ierr ! error code + character(*), intent(out) :: message ! error message ! local variables - character(len=strLen) :: cmessage ! error message from subroutine + character(len=strLen) :: cmessage ! error message from subroutine ! initialize error control ierr=0; message='read_2D_runoff_metadata/' ! get number of time steps from the runoff file - call get_nc_dim_len(fname, trim(dname_time), runoff_data_in%nTime, ierr, cmessage) + call get_nc_dim_len(fname, trim(dim_time_name), runoff_data_in%nTime, ierr, cmessage) if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif ! get the time units if (trim(timeUnits) == charMissing) then - call get_var_attr(fname, trim(vname_time), 'units', timeUnits, ierr, cmessage) + call get_var_attr(fname, trim(var_time_name), 'units', timeUnits, ierr, cmessage) if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif end if ! get the calendar if (trim(calendar) == charMissing) then - call get_var_attr(fname, trim(vname_time), 'calendar', calendar, ierr, cmessage) + call get_var_attr(fname, trim(var_time_name), 'calendar', calendar, ierr, cmessage) if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif end if ! get size of ylat dimension - call get_nc_dim_len(fname, trim(dname_ylat), runoff_data_in%nSpace(1), ierr, cmessage) + call get_nc_dim_len(fname, trim(dim_ylat_name), runoff_data_in%nSpace(1), ierr, cmessage) if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif ! get size of xlon dimension - call get_nc_dim_len(fname, trim(dname_xlon), runoff_data_in%nSpace(2), ierr, cmessage) + call get_nc_dim_len(fname, trim(dim_xlon_name), runoff_data_in%nSpace(2), ierr, cmessage) if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif ! allocate space for simulated runoff. sim2d = runoff(lon, lat) @@ -246,9 +292,7 @@ subroutine read_1D_runoff(fname, & ! input: filename integer(i4b), intent(out) :: ierr ! error code character(*), intent(out) :: message ! error message ! local variables - integer(i4b) :: iStart(2) - integer(i4b) :: iCount(2) - logical(lgt) :: existFillVal + real(dp) :: fill_value ! fill_value real(dp) :: dummy(nSpace,1) ! data read character(len=strLen) :: cmessage ! error message from subroutine @@ -256,20 +300,15 @@ subroutine read_1D_runoff(fname, & ! input: filename ierr=0; message='read_1D_runoff/' ! get the simulated runoff data - iStart = [1,iTime] - iCount = [nSpace,1] - call get_nc(fname, var_name, dummy, iStart, iCount, ierr, cmessage) + call get_nc(trim(fname), trim(var_name), dummy, (/1,iTime/), (/nSpace,1/), ierr, cmessage) if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif - ! get the _fill_values for runoff variable if exist - existFillVal = check_attr(fname, var_name, '_FillValue') - if (existFillval) then - call get_var_attr(fname, var_name, '_FillValue', input_fillvalue, ierr, cmessage) - if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif - end if + ! get the _fill_values for runoff variable + call get_var_attr(trim(fname), trim(var_name), '_FillValue', fill_value, ierr, cmessage) + if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif ! replace _fill_value with -999 for dummy - where ( abs(dummy - input_fillvalue) < verySmall ) dummy = realMissing + where ( abs(dummy - fill_value) < verySmall ) dummy = realMissing ! reshape runoff_data_in%sim(1:nSpace) = dummy(1:nSpace,1) @@ -297,9 +336,7 @@ subroutine read_2D_runoff(fname, & ! input: filename integer(i4b), intent(out) :: ierr ! error code character(*), intent(out) :: message ! error message ! local variables - logical(lgt) :: existFillVal - integer(i4b) :: iStart(3) - integer(i4b) :: iCount(3) + real(dp) :: fill_value ! fill_value real(dp) :: dummy(nSpace(2),nSpace(1),1) ! data read character(len=strLen) :: cmessage ! error message from subroutine @@ -307,20 +344,15 @@ subroutine read_2D_runoff(fname, & ! input: filename ierr=0; message='read_2D_runoff/' ! get the simulated runoff data - iStart = [1,1,iTime] - iCount = [nSpace(2),nSpace(1),1] - call get_nc(fname, var_name, dummy, iStart, iCount, ierr, cmessage) + call get_nc(trim(fname), trim(var_name), dummy, (/1,1,iTime/), (/nSpace(2), nSpace(1), 1/), ierr, cmessage) if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif ! get the _fill_values for runoff variable - existFillVal = check_attr(fname, var_name, '_FillValue') - if (existFillval) then - call get_var_attr(fname, var_name, '_FillValue', input_fillvalue, ierr, cmessage) - if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif - end if + call get_var_attr(trim(fname), trim(var_name), '_FillValue', fill_value, ierr, cmessage) + if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif ! replace _fill_value with -999 for dummy - where ( abs(dummy - input_fillvalue) < verySmall ) dummy = realMissing + where ( abs(dummy - fill_value) < verySmall ) dummy = realMissing ! reshape runoff_data_in%sim2d(1:nSpace(2),1:nSpace(1)) = dummy(1:nSpace(2),1:nSpace(1),1) From 912bfd6717c0aa486ec05046f5742d5b32600e84 Mon Sep 17 00:00:00 2001 From: ShervanGharari Date: Sat, 8 Aug 2020 22:11:54 -0400 Subject: [PATCH 02/29] changes in global data --- route/build/src/globalData.f90 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/route/build/src/globalData.f90 b/route/build/src/globalData.f90 index eeea738e..16ae458e 100644 --- a/route/build/src/globalData.f90 +++ b/route/build/src/globalData.f90 @@ -32,6 +32,7 @@ module globalData ! remapping structures USE dataTypes, ONLY: remap ! remapping data type USE dataTypes, ONLY: runoff ! runoff data type + USE dataTypes, ONLY: wm ! water management (flux to/from segment, target volume) data type ! basin data structure USE dataTypes, ONLY: subbasin_omp ! mainstem+tributary data structures @@ -74,6 +75,7 @@ module globalData integer(i4b) , public :: iTime ! time index at simulation time step integer(i4b) , public :: iTime_local ! time index at simulation time step for a given input file + integer(i4b) , public :: iTime_local_wm ! time index at simulation time step for a given wm input file real(dp) , public :: startJulday ! julian day: start of routing simulation real(dp) , public :: endJulday ! julian day: end of routing simulation real(dp) , public :: refJulday ! julian day: reference From 6e043da4c6abbd5841aaabb0c5e9c93de7a18397 Mon Sep 17 00:00:00 2001 From: ShervanGharari Date: Sat, 8 Aug 2020 23:38:05 -0400 Subject: [PATCH 03/29] change to wm_data strcuture --- route/build/src/standalone/model_setup.f90 | 88 ++++++++++++++++------ 1 file changed, 63 insertions(+), 25 deletions(-) diff --git a/route/build/src/standalone/model_setup.f90 b/route/build/src/standalone/model_setup.f90 index 8c3b4da9..b788c382 100644 --- a/route/build/src/standalone/model_setup.f90 +++ b/route/build/src/standalone/model_setup.f90 @@ -387,9 +387,10 @@ END SUBROUTINE inFile_corr_time SUBROUTINE init_time(ierr, message) ! output ! subroutines: - USE process_time_module, ONLY: process_time ! process time information - USE process_time_module, ONLY: process_calday ! compute data and time from julian day - USE io_netcdf, ONLY: get_nc ! netcdf input + USE process_time_module, ONLY: process_time ! process time information + USE process_time_module, ONLY: conv_julian2cal ! compute data and time from julian day + USE process_time_module, ONLY: conv_cal2julian ! compute data and time from julian day + USE time_utils_module, ONLY: ndays_month ! compute number of days in a month ! derived datatype USE dataTypes, ONLY: time ! time data type ! public data @@ -397,8 +398,13 @@ SUBROUTINE init_time(ierr, message) ! output USE public_var, ONLY: simStart ! date string defining the start of the simulation USE public_var, ONLY: simEnd ! date string defining the end of the simulation USE public_var, ONLY: calendar ! calendar name + USE public_var, ONLY: dt + USE public_var, ONLY: secprday USE public_var, ONLY: restart_write ! restart write option USE public_var, ONLY: restart_date ! restart date + USE public_var, ONLY: restart_month ! periodic restart month + USE public_var, ONLY: restart_day ! periodic restart day + USE public_var, ONLY: restart_hour ! periodic restart hr ! saved time variables USE globalData, ONLY: timeVar ! time variables (unit given by runoff data) USE globalData, ONLY: iTime ! time index at simulation time step @@ -407,8 +413,9 @@ SUBROUTINE init_time(ierr, message) ! output USE globalData, ONLY: startJulday ! julian day: start of routing simulation USE globalData, ONLY: endJulday ! julian day: end of routing simulation USE globalData, ONLY: modJulday ! julian day: at model time step - USE globalData, ONLY: restartJulday ! julian day: at restart USE globalData, ONLY: modTime ! model time data (yyyy:mm:dd:hh:mm:ss) + USE globalData, ONLY: restCal ! restart time data (yyyy:mm:dd:hh:mm:sec) + USE globalData, ONLY: dropCal ! restart dropoff calendar date/time USE globalData, ONLY: infileinfo_data ! the information of the input files implicit none @@ -425,6 +432,9 @@ SUBROUTINE init_time(ierr, message) ! output integer(i4b) :: iFile ! for loop over the nc files type(time) :: rofCal type(time) :: simCal + integer(i4b) :: nDays ! number of days in a month + real(dp) :: restartJulday + real(dp) :: tempJulday character(len=strLen) :: cmessage ! error message of downwind routine character(len=50) :: fmt1='(a,I4,a,I2.2,a,I2.2,x,I2.2,a,I2.2,a,F5.2)' @@ -472,8 +482,8 @@ SUBROUTINE init_time(ierr, message) ! output ! check sim_start is before the last time step in runoff data if(startJulday>roJulday(nTime)) then - call process_calday(roJulday(nTime), calendar, rofCal, ierr, cmessage) - call process_calday(startJulday, calendar, simCal, ierr, cmessage) + call conv_julian2cal(roJulday(nTime), calendar, rofCal, ierr, cmessage) + call conv_julian2cal(startJulday, calendar, simCal, ierr, cmessage) write(iulog,'(2a)') new_line('a'),'ERROR: is after the first time step in input runoff' write(iulog,fmt1) ' runoff_end : ', rofCal%iy,'-',rofCal%im,'-',rofCal%id, rofCal%ih,':', rofCal%imin,':',rofCal%dsec write(iulog,fmt1) ' : ', simCal%iy,'-',simCal%im,'-',simCal%id, simCal%ih,':', simCal%imin,':',simCal%dsec @@ -482,8 +492,8 @@ SUBROUTINE init_time(ierr, message) ! output ! Compare sim_start vs. time at first time step in runoff data if (startJulday < roJulday(1)) then - call process_calday(roJulday(1), calendar, rofCal, ierr, cmessage) - call process_calday(startJulday, calendar, simCal, ierr, cmessage) + call conv_julian2cal(roJulday(1), calendar, rofCal, ierr, cmessage) + call conv_julian2cal(startJulday, calendar, simCal, ierr, cmessage) write(iulog,'(2a)') new_line('a'),'WARNING: is before the first time step in input runoff' write(iulog,fmt1) ' runoff_start: ', rofCal%iy,'-',rofCal%im,'-',rofCal%id, rofCal%ih,':', rofCal%imin,':',rofCal%dsec write(iulog,fmt1) ' : ', simCal%iy,'-',simCal%im,'-',simCal%id, simCal%ih,':', simCal%imin,':',simCal%dsec @@ -493,8 +503,8 @@ SUBROUTINE init_time(ierr, message) ! output ! Compare sim_end vs. time at last time step in runoff data if (endJulday > roJulday(nTime)) then - call process_calday(roJulday(nTime), calendar, rofCal, ierr, cmessage) - call process_calday(endJulday, calendar, simCal, ierr, cmessage) + call conv_julian2cal(roJulday(nTime), calendar, rofCal, ierr, cmessage) + call conv_julian2cal(endJulday, calendar, simCal, ierr, cmessage) write(iulog,'(2a)') new_line('a'),'WARNING: is after the last time step in input runoff' write(iulog,fmt1) ' runoff_end: ', rofCal%iy,'-',rofCal%im,'-',rofCal%id, rofCal%ih,':', rofCal%imin,':',rofCal%dsec write(iulog,fmt1) ' : ', simCal%iy,'-',simCal%im,'-',simCal%id, simCal%ih,':', simCal%imin,':',simCal%dsec @@ -513,25 +523,53 @@ SUBROUTINE init_time(ierr, message) ! output ! initialize previous model time modTime(0) = time(integerMissing, integerMissing, integerMissing, integerMissing, integerMissing, realMissing) - ! restart drop off time + ! Set restart calendar date/time and dropoff calendar date/time and + ! -- For periodic restart options --------------------------------------------------------------------- + ! Ensure that user-input restart month, day are valid. + ! "Annual" option: if user input day exceed number of days given user input month, set to last day + ! "Monthly" option: use 2000-01 as template calendar yr/month + ! "Daily" option: use 2000-01-01 as template calendar yr/month/day + select case(trim(restart_write)) + case('Annual','annual') + call ndays_month(2000, restart_month, calendar, nDays, ierr, cmessage) + if(ierr/=0) then; message=trim(message)//trim(cmessage); return; endif + if (restart_day > nDays) restart_day=nDays + case('Monthly','monthly'); restart_month = 1 + case('Daily','daily'); restart_month = 1; restart_day = 1 + end select + select case(trim(restart_write)) case('last','Last') - call process_time(trim(simEnd), calendar, restartJulday, ierr, cmessage) - if(ierr/=0) then; message=trim(message)//trim(cmessage)//' [restartDate]'; return; endif - case('never','Never') - restartJulday = 0.0_dp + call conv_julian2cal(endJulday, calendar, dropCal, ierr, cmessage) + if(ierr/=0) then; message=trim(message)//trim(cmessage)//' [endJulday->dropCal]'; return; endif + restart_month = dropCal%im; restart_day = dropCal%id; restart_hour = dropCal%ih case('specified','Specified') if (trim(restart_date) == charMissing) then ierr=20; message=trim(message)//' must be provided when option is "specified"'; return end if call process_time(trim(restart_date),calendar, restartJulday, ierr, cmessage) - if(ierr/=0) then; message=trim(message)//trim(cmessage)//' [restartDate]'; return; endif + if(ierr/=0) then; message=trim(message)//trim(cmessage)//' [restart_date]'; return; endif + restartJulday = restartJulday - dt/secprday + call conv_julian2cal(restartJulday, calendar, dropCal, ierr, cmessage) + if(ierr/=0) then; message=trim(message)//trim(cmessage)//' [restartJulday->dropCal]'; return; endif + restart_month = dropCal%im; restart_day = dropCal%id; restart_hour = dropCal%ih + case('Annual','Monthly','Daily','annual','monthly','daily') + restCal = time(2000, restart_month, restart_day, restart_hour, 0, 0._dp) + call conv_cal2julian(restCal, calendar, tempJulday, ierr, cmessage) + if(ierr/=0)then; message=trim(message)//trim(cmessage)//' [restCal->tempJulday]'; return; endif + tempJulday = tempJulday - dt/secprday + call conv_julian2cal(tempJulday, calendar, dropCal, ierr, cmessage) + if(ierr/=0) then; message=trim(message)//trim(cmessage)//' [tempJulday->dropCal]'; return; endif + restart_month = dropCal%im; restart_day = dropCal%id; restart_hour = dropCal%ih + case('never','Never') + restCal = time(integerMissing, integerMissing, integerMissing, integerMissing, integerMissing, realMissing) case default - ierr=20; message=trim(message)//'Current accepted options: last[Last], never[Never], specified[Specified]'; return + ierr=20; message=trim(message)//'Current accepted options: L[l]ast, N[n]ever, S[s]pecified, A[a]nnual, M[m]onthly, D[d]aily'; return end select END SUBROUTINE init_time + ! ******************************************************************************** ! public subroutine: initialize runoff, and runoff-mapping data - For stand-alone ! ******************************************************************************** @@ -541,7 +579,7 @@ SUBROUTINE init_runoff_data(pid, & ! input: proc id USE public_var, ONLY: is_remap ! logical whether or not runnoff needs to be mapped to river network HRU USE globalData, ONLY: remap_data ! runoff mapping data structure USE globalData, ONLY: runoff_data ! runoff data structure - USE globalData, ONLY: AbsInj_data ! abstraction injection data structure + USE globalData, ONLY: wm_data ! abstraction injection data structure implicit none ! input: @@ -560,7 +598,7 @@ SUBROUTINE init_runoff_data(pid, & ! input: proc id call init_runoff(is_remap, & ! input: logical whether or not runnoff needs to be mapped to river network HRU remap_data, & ! output: data structure to remap data runoff_data, & ! output: data structure for runoff - AbsInj_data, & ! output: data structure for abstraction and injection and target volume + wm_data, & ! output: data structure for abstraction and injection and target volume ierr, cmessage) ! output: error control if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif end if ! if processor=0 (root) @@ -574,7 +612,7 @@ END SUBROUTINE init_runoff_data SUBROUTINE init_runoff(remap_flag, & ! input: logical whether or not runnoff needs to be mapped to river network HRU remap_data_in, & ! output: data structure to remap data runoff_data_in, & ! output: data structure for runoff - AbsInj_data_in, & ! output: data strcuture for abstraction injection and target volume + wm_data_in, & ! output: data strcuture for abstraction injection and target volume ierr, message) ! output: error control USE public_var, ONLY: ancil_dir ! name of the ancillary directory @@ -599,8 +637,8 @@ SUBROUTINE init_runoff(remap_flag, & ! input: logical whether or not runno USE public_var, ONLY: fname_remap ! name of runoff mapping netCDF name USE public_var, ONLY: calendar ! name of calendar USE public_var, ONLY: time_units ! time units - USE public_var, ONLY: is_AbsInj ! logical whether or not abstraction or injection should be read - USE public_var, ONLY: is_TargVol ! logical whether or not target volume should be read + USE public_var, ONLY: is_flux_wm ! logical whether or not abstraction or injection should be read + USE public_var, ONLY: is_vol_wm ! logical whether or not target volume should be read USE globalData, ONLY: basinID ! basin ID USE dataTypes, ONLY: remap ! remapping data type USE dataTypes, ONLY: runoff ! runoff data type @@ -727,13 +765,13 @@ SUBROUTINE init_runoff(remap_flag, & ! input: logical whether or not runno if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif ! allocate the hru_ix based on number of hru_id presented in the - allocate(AbsInj_data_in%hru_ix(size(AbsInj_data_in%hru_id)), stat=ierr) + allocate(wm_data_in%seg_ix(size(wm_data_in%seg_id)), stat=ierr) if(ierr/=0)then; message=trim(message)//'problem allocating runoff_data_in%hru_ix'; return; endif ! get indices of the HRU ids in the runoff file in the routing layer - call get_qix(AbsInj_data_in%hru_id, & ! input: vector of ids in mapping file + call get_qix(wm_data_in%seg_id, & ! input: vector of ids in mapping file basinID, & ! input: vector of ids in the routing layer - AbsInj_data_in%hru_ix, & ! output: indices of hru ids in routing layer + wm_data_in%seg_ix, & ! output: indices of hru ids in routing layer ierr, cmessage) ! output: error control if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif From 685020c8bf8d542a4afe555cd74ea1b683a4bec6 Mon Sep 17 00:00:00 2001 From: Shervan Gharari <28273583+ShervanGharari@users.noreply.github.com> Date: Mon, 10 Aug 2020 17:42:22 -0600 Subject: [PATCH 04/29] Update remap.f90 --- route/build/src/remap.f90 | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/route/build/src/remap.f90 b/route/build/src/remap.f90 index 37dcf4a4..be0133fc 100644 --- a/route/build/src/remap.f90 +++ b/route/build/src/remap.f90 @@ -286,24 +286,6 @@ subroutine sort_flux (ID_in, & ! input: the array of ids for HRU/seg ierr=0; message="sort_flux/" -! ! allocate basin_flux_sort is not allocated -! if (.not.allocated(basin_flux_sort)) then -! ierr = 10 -! if(ierr/=0)then; message=trim(message)//'basin_flux_sort is not allocated'; return; endif -! endif - -! ! the size of basin_flux_sort and ID_total_in -! if (size(basin_flux_sort)/=size(ID_total_in)) then -! ierr = 20 -! if(ierr/=0)then; message=trim(message)//'basin_flux_sort and ID are not the same size'; return; endif -! endif - -! ! check the size of ID_in, IX_in and flux_in -! if ((size(ID_in)/=size(IX_in)).or.(size(IX_in)/=size(flux_in)).or.(size(flux_in)/=size(ID_in))) then -! ierr = 30 -! if(ierr/=0)then; message=trim(message)//'ID_in, IX_in and flux_in not the same size'; return; endif -! endif - ! initializing the basin_flux_sort to zero, assuming non existing elements are all set to zero basin_flux_sort = 0._dp From 3961e5840df5b14907d835979509d18b40ebba96 Mon Sep 17 00:00:00 2001 From: ShervanGharari Date: Tue, 11 Aug 2020 15:29:35 -0400 Subject: [PATCH 05/29] minor changes in the model_setup --- route/build/src/standalone/model_setup.f90 | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/route/build/src/standalone/model_setup.f90 b/route/build/src/standalone/model_setup.f90 index b788c382..50f1bfb7 100644 --- a/route/build/src/standalone/model_setup.f90 +++ b/route/build/src/standalone/model_setup.f90 @@ -23,8 +23,6 @@ MODULE model_setup private public :: init_mpi public :: init_data -public :: infile_name - CONTAINS ! ********************************************************************* @@ -642,6 +640,7 @@ SUBROUTINE init_runoff(remap_flag, & ! input: logical whether or not runno USE globalData, ONLY: basinID ! basin ID USE dataTypes, ONLY: remap ! remapping data type USE dataTypes, ONLY: runoff ! runoff data type + USE dataTypes, ONLY: wm ! wm data type USE read_runoff, ONLY: read_runoff_metadata ! read meta data from runoff data USE read_remap, ONLY: get_remap_data ! read remap data From 613320538d030c7bdf492b38cdff748fe5b66b78 Mon Sep 17 00:00:00 2001 From: ShervanGharari Date: Wed, 12 Aug 2020 12:29:41 -0400 Subject: [PATCH 06/29] the read_runoff_metadata and read_runoff subroutins are generalized so different type of data strcuture such as runoff and water management can be pass in model setup --- route/build/src/dataTypes.f90 | 5 +- .../build/src/standalone/get_basin_runoff.f90 | 12 +- route/build/src/standalone/model_setup.f90 | 30 ++-- route/build/src/standalone/read_runoff.f90 | 168 +++++++++++------- 4 files changed, 131 insertions(+), 84 deletions(-) diff --git a/route/build/src/dataTypes.f90 b/route/build/src/dataTypes.f90 index 637dc8ad..df690695 100644 --- a/route/build/src/dataTypes.f90 +++ b/route/build/src/dataTypes.f90 @@ -177,14 +177,15 @@ MODULE dataTypes ! water management data; fluxes to/from reaches or target volume type, public :: wm integer(i4b) :: nTime ! number of time steps - integer(i4b) :: nSpace ! number of spatial dimension, in this case only one dimentonal + integer(i4b) :: nSpace(1:2) ! number of spatial dimension, in this case only one dimentonal real(dp) :: time ! time variable at one time step real(dp) , allocatable :: sim(:) ! user specified flux add/subtract, or volume at one time step (size: nSpace) + real(dp) , allocatable :: sim2D(:,:) ! to provide modularity for reading data integer(i4b) , allocatable :: seg_id(:) ! id of reach in data (size: nSpace) integer(i4b) , allocatable :: seg_ix(:) ! Index of river network reach IDs corresponding reach ID in data real(dp) , allocatable :: flux_wm(:) ! allocated flux to existing river network using sort_flux (size: number of nRCH) real(dp) , allocatable :: vol_wm(:) ! allocated target vol to existing river network using sort_flux (size: number of nRCH) -end type + end type ! ---------- reach parameters ---------------------------------------------------------------------------- diff --git a/route/build/src/standalone/get_basin_runoff.f90 b/route/build/src/standalone/get_basin_runoff.f90 index c860388c..102ccb9b 100644 --- a/route/build/src/standalone/get_basin_runoff.f90 +++ b/route/build/src/standalone/get_basin_runoff.f90 @@ -61,7 +61,9 @@ SUBROUTINE get_hru_runoff(ierr, message) ! output: error control call read_runoff_data(trim(input_dir)//trim(fname_qsim), & ! input: filename trim(vname_qsim), & ! input: varname iTime_local, & ! input: time index - runoff_data, & ! inout: runoff data structure + runoff_data%nSpace, & ! inout: runoff data structure + runoff_data%sim, & ! inout: runoff data structure + runoff_data%sim2D, & ! inout: runoff data structure ierr, cmessage) ! output: error control if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif @@ -91,7 +93,9 @@ SUBROUTINE get_hru_runoff(ierr, message) ! output: error control call read_runoff_data(trim(input_dir)//trim(fname_qsim), & ! input: filename trim(vname_evapo), & ! input: varname iTime_local, & ! input: time index - runoff_data, & ! inout: runoff data structure + runoff_data%nSpace, & ! inout: runoff data structure + runoff_data%sim, & ! inout: runoff data structure + runoff_data%sim2D, & ! inout: runoff data structure ierr, cmessage) ! output: error control if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif @@ -119,7 +123,9 @@ SUBROUTINE get_hru_runoff(ierr, message) ! output: error control call read_runoff_data(trim(input_dir)//trim(fname_qsim), & ! input: filename trim(vname_precip), & ! input: varname iTime_local, & ! input: time index - runoff_data, & ! inout: runoff data structure + runoff_data%nSpace, & ! inout: runoff data structure + runoff_data%sim, & ! inout: runoff data structure + runoff_data%sim2D, & ! inout: runoff data structure ierr, cmessage) ! output: error control if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif diff --git a/route/build/src/standalone/model_setup.f90 b/route/build/src/standalone/model_setup.f90 index 50f1bfb7..1ca9bf2d 100644 --- a/route/build/src/standalone/model_setup.f90 +++ b/route/build/src/standalone/model_setup.f90 @@ -670,7 +670,11 @@ SUBROUTINE init_runoff(remap_flag, & ! input: logical whether or not runno dname_hruid, & ! input: dimension of varibale hru dname_ylat, & ! input: dimension of lat dname_xlon, & ! input: dimension of lon - runoff_data_in, & ! output: runoff data structure + runoff_data_in%nSpace , & ! nSpace of the input in runoff or wm strcuture + runoff_data_in%nTime , & ! nTime of the input in runoff or wm strcuture + runoff_data_in%sim , & ! 1D simulation + runoff_data_in%sim2D , & ! 2D simulation + runoff_data_in%hru_id , & ! ID of seg or hru in data time_units, calendar, & ! output: number of time steps, time units, calendar ierr, cmessage) ! output: error control if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif @@ -751,16 +755,20 @@ SUBROUTINE init_runoff(remap_flag, & ! input: logical whether or not runno if ((is_flux_wm).or.(is_vol_wm)) then call read_runoff_metadata(trim(input_dir)//trim(fname_wm), & ! input: filename - vname_flux_wm, & ! input: varibale name for simulated runoff - vname_time_wm, & ! input: varibale name for time - dname_time_wm, & ! input: dimension of variable time - vname_segid_wm, & ! input: varibale hruid - dname_segid_wm, & ! input: dimension of varibale hru - dname_ylat, & ! input: dimension of lat - dname_xlon, & ! input: dimension of lon - wm_data_in, & ! output: water management data structure - time_units, calendar, & ! output: number of time steps, time units, calendar - ierr, cmessage) ! output: error control + vname_flux_wm, & ! input: varibale name for simulated runoff + vname_time_wm, & ! input: varibale name for time + dname_time_wm, & ! input: dimension of variable time + vname_segid_wm, & ! input: varibale hruid + dname_segid_wm, & ! input: dimension of varibale hru + dname_ylat, & ! input: dimension of lat + dname_xlon, & ! input: dimension of lon + wm_data_in%nSpace, & ! nSpace of the input in runoff or wm strcuture + wm_data_in%nTime, & ! nTime of the input in runoff or wm strcuture + wm_data_in%sim, & ! 1D simulation + wm_data_in%sim2D, & ! 2D simulation + wm_data_in%seg_id, & ! ID of seg or hru in data + time_units, calendar, & ! output: number of time steps, time units, calendar + ierr, cmessage) ! output: error control if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif ! allocate the hru_ix based on number of hru_id presented in the diff --git a/route/build/src/standalone/read_runoff.f90 b/route/build/src/standalone/read_runoff.f90 index a715b248..bca62932 100644 --- a/route/build/src/standalone/read_runoff.f90 +++ b/route/build/src/standalone/read_runoff.f90 @@ -7,7 +7,6 @@ module read_runoff USE io_netcdf, only:get_nc USE io_netcdf, only:get_var_attr USE io_netcdf, only:get_nc_dim_len -USE dataTypes, only:runoff ! runoff data type implicit none @@ -23,18 +22,22 @@ module read_runoff ! ****************************************** subroutine read_runoff_metadata(& ! input - fname , & ! filename including directory - var_name , & ! varibale name - var_time_name , & ! name of varibale time - dim_time_name , & ! name of dimension time - var_hru_name , & ! name of varibale HRUs - dim_hru_name , & ! name of dimension HRUs - dim_ylat_name , & ! name of dimension lat in case of a 2D input varibale - dim_xlon_name , & ! name of dimension lon in case of a 2D input varibale + fname , & ! filename including directory + var_name , & ! varibale name + var_time_name , & ! name of varibale time + dim_time_name , & ! name of dimension time + var_hru_name , & ! name of varibale HRUs + dim_hru_name , & ! name of dimension HRUs + dim_ylat_name , & ! name of dimension lat in case of a 2D input varibale + dim_xlon_name , & ! name of dimension lon in case of a 2D input varibale ! output - runoff_data_in , & ! runoff data structure - timeUnits , & ! time units - calendar , & ! calendar + nSpace , & ! nSpace of the input in runoff or wm strcuture + nTime , & ! nTime of the input in runoff or wm strcuture + sim , & ! 1D simulation + sim2D , & ! 2D simulation + ID_array , & ! ID of seg or hru in data + timeUnits , & ! time units + calendar , & ! calendar ! error control ierr, message) ! output: error control implicit none @@ -48,7 +51,11 @@ subroutine read_runoff_metadata(& character(*), intent(in) :: dim_ylat_name ! name of dimension along lat character(*), intent(in) :: dim_xlon_name ! name of dimension along lon ! output variables - type(runoff), intent(out) :: runoff_data_in ! runoff for one time step for all HRUs + integer(i4b), intent(out) :: nSpace(1:2) ! nSpace of the input in runoff or wm strcuture + integer(i4b), intent(out) :: nTime ! nTime of the input in runoff or wm strcuture + real(dp), allocatable, intent(out) :: sim(:) ! 1D simulation + real(dp), allocatable, intent(out) :: sim2D(:,:) ! 2D simulation + integer(i4b),allocatable, intent(out) :: ID_array(:) ! ID of seg or hru in data character(*), intent(out) :: timeUnits ! time units character(*), intent(out) :: calendar ! calendar ! error control @@ -81,7 +88,11 @@ subroutine read_runoff_metadata(& dim_time_name, & ! dimension of varibale time var_hru_name, & ! name of varibale hrus dim_hru_name, & ! dimension of varibales hrus - runoff_data_in, & + nSpace , & ! nSpace of the input in runoff or wm strcuture + nTime , & ! nTime of the input in runoff or wm strcuture + sim , & ! 1D simulation + sim2D , & ! 2D simulation + ID_array , & ! ID of seg or hru in data timeUnits, & calendar, & ierr, cmessage) @@ -90,7 +101,11 @@ subroutine read_runoff_metadata(& dim_time_name, & ! dimension of varibale time dim_ylat_name, & ! dimesnion of lat dim_xlon_name, & ! dimension of lon - runoff_data_in, & + nSpace , & ! nSpace of the input in runoff or wm strcuture + nTime , & ! nTime of the input in runoff or wm strcuture + sim , & ! 1D simulation + sim2D , & ! 2D simulation + ID_array , & ! ID of seg or hru in data timeUnits, & calendar, & ierr, cmessage) @@ -105,15 +120,19 @@ end subroutine read_runoff_metadata ! ****************************************** subroutine read_1D_runoff_metadata(& ! input - fname , & ! filename - var_time_name , & ! name of varibale time - dim_time_name , & ! name of dimension time - var_hru_name , & ! name of varibale HRUs - dim_hru_name , & ! name of dimension HRUs + fname , & ! filename + var_time_name , & ! name of varibale time + dim_time_name , & ! name of dimension time + var_hru_name , & ! name of varibale HRUs + dim_hru_name , & ! name of dimension HRUs ! output - runoff_data_in , & ! runoff data structure - timeUnits , & ! time units - calendar , & ! calendar + nSpace , & ! nSpace of the input in runoff or wm strcuture + nTime , & ! nTime of the input in runoff or wm strcuture + sim , & ! 1D simulation + sim2D , & ! 2D simulation + ID_array , & ! ID of seg or hru in data + timeUnits , & ! time units + calendar , & ! calendar ! error control ierr, message) ! output: error control implicit none @@ -124,7 +143,11 @@ subroutine read_1D_runoff_metadata(& character(*), intent(in) :: var_hru_name ! name of the varibale hru character(*), intent(in) :: dim_hru_name ! name of dimension for hydrological HRUs ! output variables - type(runoff), intent(out) :: runoff_data_in ! runoff for one time step for all HRUs + integer(i4b), intent(out) :: nSpace(1:2) ! nSpace of the input in runoff or wm strcuture + integer(i4b), intent(out) :: nTime ! nTime of the input in runoff or wm strcuture + real(dp), allocatable, intent(out) :: sim(:) ! 1D simulation + real(dp), allocatable, intent(out) :: sim2D(:,:) ! 2D simulation + integer(i4b), allocatable, intent(out) :: ID_array(:) ! ID of seg or hru in data character(*), intent(out) :: timeUnits ! time units character(*), intent(out) :: calendar ! calendar ! error control @@ -135,14 +158,14 @@ subroutine read_1D_runoff_metadata(& ! initialize error control ierr=0; message='read_1D_runoff_metadata/' - runoff_data_in%nSpace(2) = integerMissing + nSpace(2) = integerMissing ! get the number of HRUs - call get_nc_dim_len(fname, trim(dim_hru_name), runoff_data_in%nSpace(1), ierr, cmessage) + call get_nc_dim_len(fname, trim(dim_hru_name), nSpace(1), ierr, cmessage) if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif ! get number of time steps from the runoff file - call get_nc_dim_len(fname, trim(dim_time_name), runoff_data_in%nTime, ierr, cmessage) + call get_nc_dim_len(fname, trim(dim_time_name), nTime, ierr, cmessage) if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif ! get the time units @@ -158,15 +181,15 @@ subroutine read_1D_runoff_metadata(& end if ! allocate space for hru_id - allocate(runoff_data_in%hru_id(runoff_data_in%nSpace(1)), stat=ierr) - if(ierr/=0)then; message=trim(message)//'problem allocating runoff_data_in%hruId'; return; endif + allocate(ID_array(nSpace(1)), stat=ierr) + if(ierr/=0)then; message=trim(message)//'problem allocating ID'; return; endif ! allocate space for simulated runoff - allocate(runoff_data_in%sim(runoff_data_in%nSpace(1)), stat=ierr) - if(ierr/=0)then; message=trim(message)//'problem allocating runoff_data_in%sim'; return; endif + allocate(sim(nSpace(1)), stat=ierr) + if(ierr/=0)then; message=trim(message)//'problem allocating read_struct_data%sim'; return; endif ! get HRU ids from the runoff file - call get_nc(fname, var_hru_name, runoff_data_in%hru_id, 1, runoff_data_in%nSpace(1), ierr, cmessage) + call get_nc(fname, var_hru_name, ID_array, 1, nSpace(1), ierr, cmessage) if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif end subroutine read_1D_runoff_metadata @@ -176,15 +199,19 @@ end subroutine read_1D_runoff_metadata ! ****************************************** subroutine read_2D_runoff_metadata(& ! input - fname , & ! filename - var_time_name , & ! name of varibale time - dim_time_name , & ! name of dimension time - dim_ylat_name , & ! name of varibale HRUs - dim_xlon_name , & ! name of dimension HRUs + fname , & ! filename + var_time_name , & ! name of varibale time + dim_time_name , & ! name of dimension time + dim_ylat_name , & ! name of varibale HRUs + dim_xlon_name , & ! name of dimension HRUs ! output - runoff_data_in , & ! runoff data structure - timeUnits , & ! time units - calendar , & ! calendar + nSpace , & ! nSpace of the input in runoff or wm strcuture + nTime , & ! nTime of the input in runoff or wm strcuture + sim , & ! 1D simulation + sim2D , & ! 2D simulation + ID_array , & ! ID of seg or hru in data + timeUnits , & ! time units + calendar , & ! calendar ! error control ierr, message) ! output: error control implicit none @@ -195,7 +222,11 @@ subroutine read_2D_runoff_metadata(& character(*), intent(in) :: dim_ylat_name ! name of dimension along lat character(*), intent(in) :: dim_xlon_name ! name of dimension along lon ! output variables - type(runoff), intent(out) :: runoff_data_in ! runoff for one time step for all HRUs + integer(i4b), intent(out) :: nSpace(1:2) ! nSpace of the input in runoff or wm strcuture + integer(i4b), intent(out) :: nTime ! nTime of the input in runoff or wm strcuture + real(dp), allocatable, intent(out) :: sim(:) ! 1D simulation + real(dp), allocatable, intent(out) :: sim2D(:,:) ! 2D simulation + integer(i4b), allocatable, intent(out) :: ID_array(:) ! ID of seg or hru in data character(*), intent(out) :: timeUnits ! time units character(*), intent(out) :: calendar ! calendar ! error control @@ -207,7 +238,7 @@ subroutine read_2D_runoff_metadata(& ierr=0; message='read_2D_runoff_metadata/' ! get number of time steps from the runoff file - call get_nc_dim_len(fname, trim(dim_time_name), runoff_data_in%nTime, ierr, cmessage) + call get_nc_dim_len(fname, trim(dim_time_name), nTime, ierr, cmessage) if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif ! get the time units @@ -223,15 +254,15 @@ subroutine read_2D_runoff_metadata(& end if ! get size of ylat dimension - call get_nc_dim_len(fname, trim(dim_ylat_name), runoff_data_in%nSpace(1), ierr, cmessage) + call get_nc_dim_len(fname, trim(dim_ylat_name), nSpace(1), ierr, cmessage) if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif ! get size of xlon dimension - call get_nc_dim_len(fname, trim(dim_xlon_name), runoff_data_in%nSpace(2), ierr, cmessage) + call get_nc_dim_len(fname, trim(dim_xlon_name), nSpace(2), ierr, cmessage) if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif ! allocate space for simulated runoff. sim2d = runoff(lon, lat) - allocate(runoff_data_in%sim2d(runoff_data_in%nSpace(2),runoff_data_in%nSpace(1)), stat=ierr) + allocate(sim2d(nSpace(2),nSpace(1)), stat=ierr) if(ierr/=0)then; message=trim(message)//'problem allocating sim'; return; endif end subroutine read_2D_runoff_metadata @@ -240,19 +271,22 @@ end subroutine read_2D_runoff_metadata ! ********************************************************************* ! public subroutine: read runoff data ! ********************************************************************* - subroutine read_runoff_data(fname, & ! input: filename - var_name, & ! input: varibale name - iTime, & ! input: time index - runoff_data_in, & ! inout: runoff data structure - ierr, message) ! output: error control + subroutine read_runoff_data(fname, & ! input: filename + var_name, & ! input: varibale name + iTime, & ! input: time index + nSpace, & ! input: dimension of data to be read + sim, & ! output: read data 1D sim + sim2D, & ! output: read data 2D sim + ierr, message) ! output: error control implicit none ! input variables character(*), intent(in) :: fname ! filename character(*), intent(in) :: var_name ! variable name integer(i4b), intent(in) :: iTime ! index of time element - ! input/output variables - type(runoff), intent(inout) :: runoff_data_in ! runoff for one time step for all spatial dimension + integer(i4b), intent(in) :: nSpace(1:2) ! dimension of data for one time step ! output variables + real(dp), allocatable, intent(out) :: sim(:) ! runoff for one time step for all spatial dimension + real(dp), allocatable, intent(out) :: sim2D(:,:) ! runoff for one time step for all spatial dimension integer(i4b), intent(out) :: ierr ! error code character(*), intent(out) :: message ! error message ! local variables @@ -261,11 +295,11 @@ subroutine read_runoff_data(fname, & ! input: filename ! initialize error control ierr=0; message='read_runoff_data/' - if (runoff_data_in%nSpace(2) == integerMissing) then - call read_1D_runoff(fname, var_name, iTime, runoff_data_in%nSpace(1), runoff_data_in, ierr, cmessage) + if (nSpace(2) == integerMissing) then + call read_1D_runoff(fname, var_name, iTime, nSpace(1), sim, ierr, cmessage) if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif else - call read_2D_runoff(fname, var_name, iTime, runoff_data_in%nSpace, runoff_data_in, ierr, cmessage) + call read_2D_runoff(fname, var_name, iTime, nSpace, sim2D, ierr, cmessage) if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif endif @@ -278,7 +312,7 @@ subroutine read_1D_runoff(fname, & ! input: filename var_name, & ! input: variable name iTime, & ! input: time index nSpace, & ! input: size of HRUs - runoff_data_in, & ! inout: runoff data structure + sim, & ! output: runoff data structure ierr, message) ! output: error control implicit none ! input variables @@ -286,9 +320,8 @@ subroutine read_1D_runoff(fname, & ! input: filename character(*), intent(in) :: var_name ! variable name integer(i4b), intent(in) :: iTime ! index of time element integer(i4b), intent(in) :: nSpace ! size of spatial dimensions - ! input/output variables - type(runoff), intent(inout) :: runoff_data_in ! runoff for one time step for all spatial dimension ! output variables + real(dp), allocatable, intent(out) :: sim(:) integer(i4b), intent(out) :: ierr ! error code character(*), intent(out) :: message ! error message ! local variables @@ -311,28 +344,27 @@ subroutine read_1D_runoff(fname, & ! input: filename where ( abs(dummy - fill_value) < verySmall ) dummy = realMissing ! reshape - runoff_data_in%sim(1:nSpace) = dummy(1:nSpace,1) + sim(1:nSpace) = dummy(1:nSpace,1) end subroutine read_1D_runoff ! ********************************************************************* ! private subroutine: read 2D runoff data ! ********************************************************************* - subroutine read_2D_runoff(fname, & ! input: filename - var_name, & ! input: variable name - iTime, & ! input: time index - nSpace, & ! input: size of HRUs - runoff_data_in, & ! output: runoff data structure - ierr, message) ! output: error control + subroutine read_2D_runoff(fname, & ! input: filename + var_name, & ! input: variable name + iTime, & ! input: time index + nSpace, & ! input: size of HRUs + sim2D, & ! output: runoff data structure + ierr, message) ! output: error control implicit none ! input variables character(*), intent(in) :: fname ! filename character(*), intent(in) :: var_name ! variable name integer(i4b), intent(in) :: iTime ! index of time element integer(i4b), intent(in) :: nSpace(1:2) ! size of spatial dimensions - ! input/output variables - type(runoff), intent(inout) :: runoff_data_in ! runoff for one time step for all spatial dimension ! output variables + real(dp), allocatable, intent(out) :: sim2D(:,:) ! runoff for one time step for all spatial dimension integer(i4b), intent(out) :: ierr ! error code character(*), intent(out) :: message ! error message ! local variables @@ -355,7 +387,7 @@ subroutine read_2D_runoff(fname, & ! input: filename where ( abs(dummy - fill_value) < verySmall ) dummy = realMissing ! reshape - runoff_data_in%sim2d(1:nSpace(2),1:nSpace(1)) = dummy(1:nSpace(2),1:nSpace(1),1) + sim2D(1:nSpace(2),1:nSpace(1)) = dummy(1:nSpace(2),1:nSpace(1),1) end subroutine read_2D_runoff From 49d44e4ffa1b4c61c79a7c1a73c3f8ff89ef6fa7 Mon Sep 17 00:00:00 2001 From: ShervanGharari Date: Wed, 12 Aug 2020 13:33:53 -0400 Subject: [PATCH 07/29] get basin runoff reads the extra files --- route/build/src/read_control.f90 | 4 +- .../build/src/standalone/get_basin_runoff.f90 | 167 ++++++++++++------ route/build/src/standalone/model_setup.f90 | 51 +++--- route/build/src/standalone/read_runoff.f90 | 14 +- 4 files changed, 148 insertions(+), 88 deletions(-) diff --git a/route/build/src/read_control.f90 b/route/build/src/read_control.f90 index a15c6e25..20880731 100644 --- a/route/build/src/read_control.f90 +++ b/route/build/src/read_control.f90 @@ -139,8 +139,8 @@ SUBROUTINE read_control(ctl_fname, err, message) case(''); read(cData,*,iostat=io_error) input_fillvalue ! fillvalue used for input variable ! FLUXES TO/FROM REACHES AND LAKE STATES FILE case(''); fname_wm = trim(cData) ! name of text file containing ordered nc file names - case(''); vname_flux_wm = trim(cData) ! name of varibale for fluxes to and from seg (reachs/lakes) - case(''); vname_vol_wm = trim(cData) ! name of varibale for target volume for managed lakes + case(''); vname_flux_wm = trim(cData) ! name of varibale for fluxes to and from seg (reachs/lakes) + case(''); vname_vol_wm = trim(cData) ! name of varibale for target volume for managed lakes case(''); vname_time_wm = trim(cData) ! name of time variable case(''); vname_segid_wm = trim(cData) ! name of the segid varibale in nc files case(''); dname_time_wm = trim(cData) ! name of time dimension diff --git a/route/build/src/standalone/get_basin_runoff.f90 b/route/build/src/standalone/get_basin_runoff.f90 index 102ccb9b..dff9d2c2 100644 --- a/route/build/src/standalone/get_basin_runoff.f90 +++ b/route/build/src/standalone/get_basin_runoff.f90 @@ -37,6 +37,7 @@ SUBROUTINE get_hru_runoff(ierr, message) ! output: error control USE globalData, ONLY:nHRU ! number of routing sub-basin USE globalData, ONLY:nRch ! number of routing seg (reaches and lakes) USE globalData, ONLY:runoff_data ! data structure to hru runoff data + USE globalData, ONLY:wm_data ! data strcuture for water management USE globalData, ONLY:wm_data ! data structure to hru runoff data USE globalData, ONLY:remap_data ! data structure to remap data ! subroutines @@ -76,78 +77,136 @@ SUBROUTINE get_hru_runoff(ierr, message) ! output: error control ! Get river network HRU runoff into runoff_data data structure if (is_remap) then ! remap LSM simulated flux to the HRUs in the river network - call remap_runoff(runoff_data, remap_data, runoff_data%basinRunoff, ierr, cmessage) - if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif + call remap_runoff(runoff_data, remap_data, runoff_data%basinRunoff, ierr, cmessage) + if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif else ! runoff is already remapped to river network HRUs - call sort_flux (runoff_data%hru_id, & + call sort_flux (runoff_data%hru_id, & runoff_data%hru_ix, & runoff_data%sim, & runoff_data%basinRunoff, & ierr, cmessage) - if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif + if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif end if if (is_lake_sim) then ! if is_lake_sim if true then read actual evaporation and preciptation - ! get the actual evaporation - runoff_data%sim(:) or %sim2D(:,:) - call read_runoff_data(trim(input_dir)//trim(fname_qsim), & ! input: filename - trim(vname_evapo), & ! input: varname - iTime_local, & ! input: time index - runoff_data%nSpace, & ! inout: runoff data structure - runoff_data%sim, & ! inout: runoff data structure - runoff_data%sim2D, & ! inout: runoff data structure - ierr, cmessage) ! output: error control - if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif - - if ( allocated(runoff_data%basinEvapo) ) then - deallocate(runoff_data%basinEvapo, stat=ierr) - if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif - end if - allocate(runoff_data%basinEvapo(nHRU), stat=ierr) - if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif - - ! Get river network HRU runoff into runoff_data data structure - if (is_remap) then ! remap LSM simulated flux to the HRUs in the river network - call remap_runoff(runoff_data, remap_data, runoff_data%basinEvapo, ierr, cmessage) + ! get the actual evaporation - runoff_data%sim(:) or %sim2D(:,:) + call read_runoff_data(trim(input_dir)//trim(fname_qsim), & ! input: filename + trim(vname_evapo), & ! input: varname + iTime_local, & ! input: time index + runoff_data%nSpace, & ! inout: runoff data structure + runoff_data%sim, & ! inout: runoff data structure + runoff_data%sim2D, & ! inout: runoff data structure + ierr, cmessage) ! output: error control if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif - else ! runoff is already remapped to river network HRUs - call sort_flux (runoff_data%hru_id, & - runoff_data%hru_ix, & - runoff_data%sim, & - runoff_data%basinEvapo, & - ierr, cmessage) + + if ( allocated(runoff_data%basinEvapo) ) then + deallocate(runoff_data%basinEvapo, stat=ierr) + if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif + end if + allocate(runoff_data%basinEvapo(nHRU), stat=ierr) if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif - end if - ! get the precepitation - runoff_data%sim(:) or %sim2D(:,:) - call read_runoff_data(trim(input_dir)//trim(fname_qsim), & ! input: filename - trim(vname_precip), & ! input: varname - iTime_local, & ! input: time index - runoff_data%nSpace, & ! inout: runoff data structure - runoff_data%sim, & ! inout: runoff data structure - runoff_data%sim2D, & ! inout: runoff data structure - ierr, cmessage) ! output: error control - if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif + ! Get river network HRU runoff into runoff_data data structure + if (is_remap) then ! remap LSM simulated flux to the HRUs in the river network + call remap_runoff(runoff_data, remap_data, runoff_data%basinEvapo, ierr, cmessage) + if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif + else ! runoff is already remapped to river network HRUs + call sort_flux (runoff_data%hru_id, & + runoff_data%hru_ix, & + runoff_data%sim, & + runoff_data%basinEvapo, & + ierr, cmessage) + if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif + end if + + ! get the precepitation - runoff_data%sim(:) or %sim2D(:,:) + call read_runoff_data(trim(input_dir)//trim(fname_qsim), & ! input: filename + trim(vname_precip), & ! input: varname + iTime_local, & ! input: time index + runoff_data%nSpace, & ! inout: runoff data structure + runoff_data%sim, & ! inout: runoff data structure + runoff_data%sim2D, & ! inout: runoff data structure + ierr, cmessage) ! output: error control + if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif + + if ( allocated(runoff_data%basinPrecip) ) then + deallocate(runoff_data%basinPrecip, stat=ierr) + if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif + end if + allocate(runoff_data%basinPrecip(nHRU), stat=ierr) + if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif - if ( allocated(runoff_data%basinPrecip) ) then - deallocate(runoff_data%basinPrecip, stat=ierr) + ! Get river network HRU runoff into runoff_data data structure + if (is_remap) then ! remap LSM simulated flux to the HRUs in the river network + call remap_runoff(runoff_data, remap_data, runoff_data%basinPrecip, ierr, cmessage) + if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif + else ! runoff is already remapped to river network HRUs + call sort_flux (runoff_data%hru_id, & + runoff_data%hru_ix, & + runoff_data%sim, & + runoff_data%basinPrecip, & + ierr, cmessage) + if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif + end if + end if + + ! reading the abstraction and subtraction to river segment + if (is_flux_wm) then + + ! get the added or subtracted discharge from river segments + call read_runoff_data(trim(input_dir)//trim(fname_wm), & ! input: filename + trim(vname_flux_wm), & ! input: varname + iTime_local_wm, & ! input: time index + wm_data%nSpace, & ! inout: runoff data structure + wm_data%sim, & ! inout: runoff data structure + wm_data%sim2D, & ! inout: runoff data structure + ierr, cmessage) ! output: error control + if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif + + if ( allocated(wm_data%flux_wm) ) then + deallocate(wm_data%flux_wm, stat=ierr) + if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif + end if + allocate(wm_data%flux_wm(nRch), stat=ierr) if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif - end if - allocate(runoff_data%basinPrecip(nHRU), stat=ierr) - if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif - ! Get river network HRU runoff into runoff_data data structure - if (is_remap) then ! remap LSM simulated flux to the HRUs in the river network - call remap_runoff(runoff_data, remap_data, runoff_data%basinPrecip, ierr, cmessage) + ! sorting the read_runoff into wm_data%flux_wm + call sort_flux (wm_data%seg_id, & + wm_data%seg_ix, & + wm_data%sim, & + wm_data%flux_wm, & + ierr, cmessage) if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif - else ! runoff is already remapped to river network HRUs - call sort_flux (runoff_data%hru_id, & - runoff_data%hru_ix, & - runoff_data%sim, & - runoff_data%basinPrecip, & + end if + + ! reading the target volume for lakes if is_lake_sim is activated + if ((is_lake_sim).and.(is_vol_wm)) then + + ! get the added or subtracted discharge from river segments + call read_runoff_data(trim(input_dir)//trim(fname_wm), & ! input: filename + trim(vname_vol_wm), & ! input: varname + iTime_local_wm, & ! input: time index + wm_data%nSpace, & ! inout: runoff data structure + wm_data%sim, & ! inout: runoff data structure + wm_data%sim2D, & ! inout: runoff data structure + ierr, cmessage) ! output: error control + if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif + + if ( allocated(wm_data%vol_wm) ) then + deallocate(wm_data%vol_wm, stat=ierr) + if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif + end if + allocate(wm_data%vol_wm(nRch), stat=ierr) + if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif + + ! sorting the read_runoff into wm_data%vol_wm + call sort_flux (wm_data%seg_id, & + wm_data%seg_ix, & + wm_data%sim, & + wm_data%vol_wm, & ierr, cmessage) if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif - end if end if END SUBROUTINE get_hru_runoff diff --git a/route/build/src/standalone/model_setup.f90 b/route/build/src/standalone/model_setup.f90 index 1ca9bf2d..a9879fa6 100644 --- a/route/build/src/standalone/model_setup.f90 +++ b/route/build/src/standalone/model_setup.f90 @@ -635,6 +635,7 @@ SUBROUTINE init_runoff(remap_flag, & ! input: logical whether or not runno USE public_var, ONLY: fname_remap ! name of runoff mapping netCDF name USE public_var, ONLY: calendar ! name of calendar USE public_var, ONLY: time_units ! time units + USE public_var, ONLY: is_lake_sim ! logical if lakes simulations are activated USE public_var, ONLY: is_flux_wm ! logical whether or not abstraction or injection should be read USE public_var, ONLY: is_vol_wm ! logical whether or not target volume should be read USE globalData, ONLY: basinID ! basin ID @@ -670,11 +671,11 @@ SUBROUTINE init_runoff(remap_flag, & ! input: logical whether or not runno dname_hruid, & ! input: dimension of varibale hru dname_ylat, & ! input: dimension of lat dname_xlon, & ! input: dimension of lon - runoff_data_in%nSpace , & ! nSpace of the input in runoff or wm strcuture - runoff_data_in%nTime , & ! nTime of the input in runoff or wm strcuture - runoff_data_in%sim , & ! 1D simulation - runoff_data_in%sim2D , & ! 2D simulation - runoff_data_in%hru_id , & ! ID of seg or hru in data + runoff_data_in%nSpace, & ! nSpace of the input in runoff or wm strcuture + runoff_data_in%nTime, & ! nTime of the input in runoff or wm strcuture + runoff_data_in%sim, & ! 1D simulation + runoff_data_in%sim2D, & ! 2D simulation + runoff_data_in%hru_id, & ! ID of seg or hru in data time_units, calendar, & ! output: number of time steps, time units, calendar ierr, cmessage) ! output: error control if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif @@ -752,34 +753,34 @@ SUBROUTINE init_runoff(remap_flag, & ! input: logical whether or not runno endif ! is abstraction and injection flag is active - if ((is_flux_wm).or.(is_vol_wm)) then - - call read_runoff_metadata(trim(input_dir)//trim(fname_wm), & ! input: filename - vname_flux_wm, & ! input: varibale name for simulated runoff - vname_time_wm, & ! input: varibale name for time - dname_time_wm, & ! input: dimension of variable time - vname_segid_wm, & ! input: varibale hruid - dname_segid_wm, & ! input: dimension of varibale hru - dname_ylat, & ! input: dimension of lat - dname_xlon, & ! input: dimension of lon - wm_data_in%nSpace, & ! nSpace of the input in runoff or wm strcuture - wm_data_in%nTime, & ! nTime of the input in runoff or wm strcuture - wm_data_in%sim, & ! 1D simulation - wm_data_in%sim2D, & ! 2D simulation - wm_data_in%seg_id, & ! ID of seg or hru in data - time_units, calendar, & ! output: number of time steps, time units, calendar - ierr, cmessage) ! output: error control + if ((is_flux_wm).or.((is_vol_wm).and.(is_lake_sim))) then + + call read_runoff_metadata(trim(input_dir)//trim(fname_wm), & ! input: filename + vname_flux_wm, & ! input: varibale name for simulated runoff + vname_time_wm, & ! input: varibale name for time + dname_time_wm, & ! input: dimension of variable time + vname_segid_wm, & ! input: varibale hruid + dname_segid_wm, & ! input: dimension of varibale hru + dname_ylat, & ! input: dimension of lat + dname_xlon, & ! input: dimension of lon + wm_data_in%nSpace, & ! nSpace of the input in runoff or wm strcuture + wm_data_in%nTime, & ! nTime of the input in runoff or wm strcuture + wm_data_in%sim, & ! 1D simulation + wm_data_in%sim2D, & ! 2D simulation + wm_data_in%seg_id, & ! ID of seg or hru in data + time_units, calendar, & ! output: number of time steps, time units, calendar + ierr, cmessage) ! output: error control if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif ! allocate the hru_ix based on number of hru_id presented in the allocate(wm_data_in%seg_ix(size(wm_data_in%seg_id)), stat=ierr) if(ierr/=0)then; message=trim(message)//'problem allocating runoff_data_in%hru_ix'; return; endif - ! get indices of the HRU ids in the runoff file in the routing layer + ! get indices of the seg ids in the input file in the routing layer call get_qix(wm_data_in%seg_id, & ! input: vector of ids in mapping file - basinID, & ! input: vector of ids in the routing layer + basinID, & ! input: vector of ids in the routing layer wm_data_in%seg_ix, & ! output: indices of hru ids in routing layer - ierr, cmessage) ! output: error control + ierr, cmessage) ! output: error control if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif endif diff --git a/route/build/src/standalone/read_runoff.f90 b/route/build/src/standalone/read_runoff.f90 index bca62932..4cf3bc17 100644 --- a/route/build/src/standalone/read_runoff.f90 +++ b/route/build/src/standalone/read_runoff.f90 @@ -51,13 +51,13 @@ subroutine read_runoff_metadata(& character(*), intent(in) :: dim_ylat_name ! name of dimension along lat character(*), intent(in) :: dim_xlon_name ! name of dimension along lon ! output variables - integer(i4b), intent(out) :: nSpace(1:2) ! nSpace of the input in runoff or wm strcuture - integer(i4b), intent(out) :: nTime ! nTime of the input in runoff or wm strcuture - real(dp), allocatable, intent(out) :: sim(:) ! 1D simulation - real(dp), allocatable, intent(out) :: sim2D(:,:) ! 2D simulation - integer(i4b),allocatable, intent(out) :: ID_array(:) ! ID of seg or hru in data - character(*), intent(out) :: timeUnits ! time units - character(*), intent(out) :: calendar ! calendar + integer(i4b), intent(out) :: nSpace(1:2) ! nSpace of the input in runoff or wm strcuture + integer(i4b), intent(out) :: nTime ! nTime of the input in runoff or wm strcuture + real(dp), allocatable, intent(out) :: sim(:) ! 1D simulation + real(dp), allocatable, intent(out) :: sim2D(:,:) ! 2D simulation + integer(i4b), allocatable, intent(out) :: ID_array(:) ! ID of seg or hru in data + character(*), intent(out) :: timeUnits ! time units + character(*), intent(out) :: calendar ! calendar ! error control integer(i4b), intent(out) :: ierr ! error code character(*), intent(out) :: message ! error message From 761b44dbfaca75e4808035d794ff51bd0f61cdcd Mon Sep 17 00:00:00 2001 From: ShervanGharari Date: Wed, 12 Aug 2020 17:11:22 -0400 Subject: [PATCH 08/29] changes in read runoff to make it similar to the origin --- .../build/src/standalone/get_basin_runoff.f90 | 19 +++++++++++--- route/build/src/standalone/read_runoff.f90 | 26 +++++++++++-------- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/route/build/src/standalone/get_basin_runoff.f90 b/route/build/src/standalone/get_basin_runoff.f90 index dff9d2c2..0f62d714 100644 --- a/route/build/src/standalone/get_basin_runoff.f90 +++ b/route/build/src/standalone/get_basin_runoff.f90 @@ -38,7 +38,6 @@ SUBROUTINE get_hru_runoff(ierr, message) ! output: error control USE globalData, ONLY:nRch ! number of routing seg (reaches and lakes) USE globalData, ONLY:runoff_data ! data structure to hru runoff data USE globalData, ONLY:wm_data ! data strcuture for water management - USE globalData, ONLY:wm_data ! data structure to hru runoff data USE globalData, ONLY:remap_data ! data structure to remap data ! subroutines USE read_runoff, ONLY:read_runoff_data ! read runoff value into runoff_data data strucuture @@ -58,13 +57,19 @@ SUBROUTINE get_hru_runoff(ierr, message) ! output: error control call infile_name(ierr, cmessage) ! read the infile name for given iTime if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif + !print statements + print*, iTime_local, iTime_local_wm + print*, fname_qsim, fname_wm + print*, runoff_data%nSpace + print*, wm_data%nSpace + ! get the simulated runoff for the current time step - runoff_data%sim(:) or %sim2D(:,:) call read_runoff_data(trim(input_dir)//trim(fname_qsim), & ! input: filename trim(vname_qsim), & ! input: varname iTime_local, & ! input: time index runoff_data%nSpace, & ! inout: runoff data structure - runoff_data%sim, & ! inout: runoff data structure - runoff_data%sim2D, & ! inout: runoff data structure + runoff_data%sim, & ! inout: runoff data structure + runoff_data%sim2D, & ! inout: runoff data structure ierr, cmessage) ! output: error control if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif @@ -209,6 +214,14 @@ SUBROUTINE get_hru_runoff(ierr, message) ! output: error control if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif end if + ! printing statement + print*, wm_data%flux_wm + print*, wm_data%seg_id + print*, wm_data%seg_id + print*, iTime_local + print*, iTime_local_wm + stop + END SUBROUTINE get_hru_runoff diff --git a/route/build/src/standalone/read_runoff.f90 b/route/build/src/standalone/read_runoff.f90 index 4cf3bc17..cbb9f695 100644 --- a/route/build/src/standalone/read_runoff.f90 +++ b/route/build/src/standalone/read_runoff.f90 @@ -273,7 +273,7 @@ end subroutine read_2D_runoff_metadata ! ********************************************************************* subroutine read_runoff_data(fname, & ! input: filename var_name, & ! input: varibale name - iTime, & ! input: time index + time_index, & ! input: time index nSpace, & ! input: dimension of data to be read sim, & ! output: read data 1D sim sim2D, & ! output: read data 2D sim @@ -282,7 +282,7 @@ subroutine read_runoff_data(fname, & ! input: filename ! input variables character(*), intent(in) :: fname ! filename character(*), intent(in) :: var_name ! variable name - integer(i4b), intent(in) :: iTime ! index of time element + integer(i4b), intent(in) :: time_index ! index of time element integer(i4b), intent(in) :: nSpace(1:2) ! dimension of data for one time step ! output variables real(dp), allocatable, intent(out) :: sim(:) ! runoff for one time step for all spatial dimension @@ -296,10 +296,10 @@ subroutine read_runoff_data(fname, & ! input: filename ierr=0; message='read_runoff_data/' if (nSpace(2) == integerMissing) then - call read_1D_runoff(fname, var_name, iTime, nSpace(1), sim, ierr, cmessage) + call read_1D_runoff(fname, var_name, time_index, nSpace(1), sim, ierr, cmessage) if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif else - call read_2D_runoff(fname, var_name, iTime, nSpace, sim2D, ierr, cmessage) + call read_2D_runoff(fname, var_name, time_index, nSpace, sim2D, ierr, cmessage) if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif endif @@ -310,7 +310,7 @@ end subroutine read_runoff_data ! ********************************************************************* subroutine read_1D_runoff(fname, & ! input: filename var_name, & ! input: variable name - iTime, & ! input: time index + time_index, & ! input: time index nSpace, & ! input: size of HRUs sim, & ! output: runoff data structure ierr, message) ! output: error control @@ -318,10 +318,10 @@ subroutine read_1D_runoff(fname, & ! input: filename ! input variables character(*), intent(in) :: fname ! filename character(*), intent(in) :: var_name ! variable name - integer(i4b), intent(in) :: iTime ! index of time element + integer(i4b), intent(in) :: time_index ! index of time element integer(i4b), intent(in) :: nSpace ! size of spatial dimensions ! output variables - real(dp), allocatable, intent(out) :: sim(:) + real(dp), allocatable, intent(out) :: sim(:) integer(i4b), intent(out) :: ierr ! error code character(*), intent(out) :: message ! error message ! local variables @@ -333,7 +333,7 @@ subroutine read_1D_runoff(fname, & ! input: filename ierr=0; message='read_1D_runoff/' ! get the simulated runoff data - call get_nc(trim(fname), trim(var_name), dummy, (/1,iTime/), (/nSpace,1/), ierr, cmessage) + call get_nc(trim(fname), trim(var_name), dummy, (/1,time_index/), (/nSpace,1/), ierr, cmessage) if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif ! get the _fill_values for runoff variable @@ -353,7 +353,7 @@ end subroutine read_1D_runoff ! ********************************************************************* subroutine read_2D_runoff(fname, & ! input: filename var_name, & ! input: variable name - iTime, & ! input: time index + time_index, & ! input: time index nSpace, & ! input: size of HRUs sim2D, & ! output: runoff data structure ierr, message) ! output: error control @@ -361,7 +361,7 @@ subroutine read_2D_runoff(fname, & ! input: filename ! input variables character(*), intent(in) :: fname ! filename character(*), intent(in) :: var_name ! variable name - integer(i4b), intent(in) :: iTime ! index of time element + integer(i4b), intent(in) :: time_index ! index of time element integer(i4b), intent(in) :: nSpace(1:2) ! size of spatial dimensions ! output variables real(dp), allocatable, intent(out) :: sim2D(:,:) ! runoff for one time step for all spatial dimension @@ -376,7 +376,11 @@ subroutine read_2D_runoff(fname, & ! input: filename ierr=0; message='read_2D_runoff/' ! get the simulated runoff data - call get_nc(trim(fname), trim(var_name), dummy, (/1,1,iTime/), (/nSpace(2), nSpace(1), 1/), ierr, cmessage) + print*, fname + print*, var_name + print*, time_index + print*, nSpace + call get_nc(trim(fname), trim(var_name), dummy, (/1,1,time_index/), (/nSpace(2), nSpace(1), 1/), ierr, cmessage) if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif ! get the _fill_values for runoff variable From bf2e96a4a189e6a1e7a0b15aca08271807ddb962 Mon Sep 17 00:00:00 2001 From: ShervanGharari Date: Wed, 12 Aug 2020 17:15:02 -0400 Subject: [PATCH 09/29] changes in read runoff to make it similar to the origin --- route/build/src/standalone/read_runoff.f90 | 62 +++++++++++++--------- 1 file changed, 37 insertions(+), 25 deletions(-) diff --git a/route/build/src/standalone/read_runoff.f90 b/route/build/src/standalone/read_runoff.f90 index cbb9f695..44b88aac 100644 --- a/route/build/src/standalone/read_runoff.f90 +++ b/route/build/src/standalone/read_runoff.f90 @@ -6,6 +6,7 @@ module read_runoff USE io_netcdf, only:open_nc USE io_netcdf, only:get_nc USE io_netcdf, only:get_var_attr +USE io_netcdf, only:check_attr USE io_netcdf, only:get_nc_dim_len @@ -325,7 +326,9 @@ subroutine read_1D_runoff(fname, & ! input: filename integer(i4b), intent(out) :: ierr ! error code character(*), intent(out) :: message ! error message ! local variables - real(dp) :: fill_value ! fill_value + integer(i4b) :: iStart(2) + integer(i4b) :: iCount(2) + logical(lgt) :: existFillVal real(dp) :: dummy(nSpace,1) ! data read character(len=strLen) :: cmessage ! error message from subroutine @@ -333,15 +336,20 @@ subroutine read_1D_runoff(fname, & ! input: filename ierr=0; message='read_1D_runoff/' ! get the simulated runoff data - call get_nc(trim(fname), trim(var_name), dummy, (/1,time_index/), (/nSpace,1/), ierr, cmessage) + iStart = [1,time_index] + iCount = [nSpace,1] + call get_nc(fname, var_name, dummy, iStart, iCount, ierr, cmessage) if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif - ! get the _fill_values for runoff variable - call get_var_attr(trim(fname), trim(var_name), '_FillValue', fill_value, ierr, cmessage) - if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif + ! get the _fill_values for runoff variable if exist + existFillVal = check_attr(fname, var_name, '_FillValue') + if (existFillval) then + call get_var_attr(fname, var_name, '_FillValue', input_fillvalue, ierr, cmessage) + if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif + end if ! replace _fill_value with -999 for dummy - where ( abs(dummy - fill_value) < verySmall ) dummy = realMissing + where ( abs(dummy - input_fillvalue) < verySmall ) dummy = realMissing ! reshape sim(1:nSpace) = dummy(1:nSpace,1) @@ -359,39 +367,43 @@ subroutine read_2D_runoff(fname, & ! input: filename ierr, message) ! output: error control implicit none ! input variables - character(*), intent(in) :: fname ! filename - character(*), intent(in) :: var_name ! variable name - integer(i4b), intent(in) :: time_index ! index of time element - integer(i4b), intent(in) :: nSpace(1:2) ! size of spatial dimensions + character(*), intent(in) :: fname ! filename + character(*), intent(in) :: var_name ! variable name + integer(i4b), intent(in) :: time_index ! index of time element + integer(i4b), intent(in) :: nSpace(1:2) ! size of spatial dimensions ! output variables - real(dp), allocatable, intent(out) :: sim2D(:,:) ! runoff for one time step for all spatial dimension - integer(i4b), intent(out) :: ierr ! error code - character(*), intent(out) :: message ! error message + real(dp), allocatable, intent(out) :: sim2D(:,:) ! runoff for one time step for all spatial dimension + integer(i4b), intent(out) :: ierr ! error code + character(*), intent(out) :: message ! error message ! local variables - real(dp) :: fill_value ! fill_value - real(dp) :: dummy(nSpace(2),nSpace(1),1) ! data read - character(len=strLen) :: cmessage ! error message from subroutine + logical(lgt) :: existFillVal + integer(i4b) :: iStart(3) + integer(i4b) :: iCount(3) + real(dp) :: dummy(nSpace(2),nSpace(1),1) ! data read + character(len=strLen) :: cmessage ! error message from subroutine + ! initialize error control ierr=0; message='read_2D_runoff/' ! get the simulated runoff data - print*, fname - print*, var_name - print*, time_index - print*, nSpace - call get_nc(trim(fname), trim(var_name), dummy, (/1,1,time_index/), (/nSpace(2), nSpace(1), 1/), ierr, cmessage) + iStart = [1,1,time_index] + iCount = [nSpace(2),nSpace(1),1] + call get_nc(fname, var_name, dummy, iStart, iCount, ierr, cmessage) if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif ! get the _fill_values for runoff variable - call get_var_attr(trim(fname), trim(var_name), '_FillValue', fill_value, ierr, cmessage) - if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif + existFillVal = check_attr(fname, var_name, '_FillValue') + if (existFillval) then + call get_var_attr(fname, var_name, '_FillValue', input_fillvalue, ierr, cmessage) + if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif + end if ! replace _fill_value with -999 for dummy - where ( abs(dummy - fill_value) < verySmall ) dummy = realMissing + where ( abs(dummy - input_fillvalue) < verySmall ) dummy = realMissing ! reshape - sim2D(1:nSpace(2),1:nSpace(1)) = dummy(1:nSpace(2),1:nSpace(1),1) + sim2d(1:nSpace(2),1:nSpace(1)) = dummy(1:nSpace(2),1:nSpace(1),1) end subroutine read_2D_runoff From f578fc1f680bc9b4e42385e9954923034bdd7af7 Mon Sep 17 00:00:00 2001 From: ShervanGharari Date: Wed, 12 Aug 2020 20:16:06 -0400 Subject: [PATCH 10/29] the model setup is fixed so that the seg_id length is similar to the seg length in the river network topology --- .../build/src/standalone/get_basin_runoff.f90 | 12 ++-- route/build/src/standalone/model_setup.f90 | 5 +- route/build/src/standalone/read_runoff.f90 | 55 ++++++++++--------- 3 files changed, 39 insertions(+), 33 deletions(-) diff --git a/route/build/src/standalone/get_basin_runoff.f90 b/route/build/src/standalone/get_basin_runoff.f90 index 0f62d714..f629e5e4 100644 --- a/route/build/src/standalone/get_basin_runoff.f90 +++ b/route/build/src/standalone/get_basin_runoff.f90 @@ -215,12 +215,12 @@ SUBROUTINE get_hru_runoff(ierr, message) ! output: error control end if ! printing statement - print*, wm_data%flux_wm - print*, wm_data%seg_id - print*, wm_data%seg_id - print*, iTime_local - print*, iTime_local_wm - stop + !print*, wm_data%flux_wm + !print*, wm_data%seg_id + !print*, wm_data%seg_id + !print*, iTime_local + !print*, iTime_local_wm + !stop END SUBROUTINE get_hru_runoff diff --git a/route/build/src/standalone/model_setup.f90 b/route/build/src/standalone/model_setup.f90 index a9879fa6..5ccd185e 100644 --- a/route/build/src/standalone/model_setup.f90 +++ b/route/build/src/standalone/model_setup.f90 @@ -639,6 +639,7 @@ SUBROUTINE init_runoff(remap_flag, & ! input: logical whether or not runno USE public_var, ONLY: is_flux_wm ! logical whether or not abstraction or injection should be read USE public_var, ONLY: is_vol_wm ! logical whether or not target volume should be read USE globalData, ONLY: basinID ! basin ID + USE globalData, ONLY: reachID ! reach ID USE dataTypes, ONLY: remap ! remapping data type USE dataTypes, ONLY: runoff ! runoff data type USE dataTypes, ONLY: wm ! wm data type @@ -777,8 +778,10 @@ SUBROUTINE init_runoff(remap_flag, & ! input: logical whether or not runno if(ierr/=0)then; message=trim(message)//'problem allocating runoff_data_in%hru_ix'; return; endif ! get indices of the seg ids in the input file in the routing layer + print*, size(wm_data_in%seg_id) + print*, size(reachID) call get_qix(wm_data_in%seg_id, & ! input: vector of ids in mapping file - basinID, & ! input: vector of ids in the routing layer + reachID, & ! input: vector of ids in the routing layer wm_data_in%seg_ix, & ! output: indices of hru ids in routing layer ierr, cmessage) ! output: error control if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif diff --git a/route/build/src/standalone/read_runoff.f90 b/route/build/src/standalone/read_runoff.f90 index 44b88aac..59dadadf 100644 --- a/route/build/src/standalone/read_runoff.f90 +++ b/route/build/src/standalone/read_runoff.f90 @@ -276,22 +276,23 @@ subroutine read_runoff_data(fname, & ! input: filename var_name, & ! input: varibale name time_index, & ! input: time index nSpace, & ! input: dimension of data to be read - sim, & ! output: read data 1D sim - sim2D, & ! output: read data 2D sim + sim, & ! input/output: read data 1D sim + sim2D, & ! input/output: read data 2D sim ierr, message) ! output: error control implicit none ! input variables - character(*), intent(in) :: fname ! filename - character(*), intent(in) :: var_name ! variable name - integer(i4b), intent(in) :: time_index ! index of time element - integer(i4b), intent(in) :: nSpace(1:2) ! dimension of data for one time step + character(*), intent(in) :: fname ! filename + character(*), intent(in) :: var_name ! variable name + integer(i4b), intent(in) :: time_index ! index of time element + integer(i4b), intent(in) :: nSpace(1:2) ! dimension of data for one time step + ! input/output variables + real(dp), allocatable, intent(inout) :: sim(:) ! runoff for one time step for all spatial dimension + real(dp), allocatable, intent(inout) :: sim2D(:,:) ! runoff for one time step for all spatial dimension ! output variables - real(dp), allocatable, intent(out) :: sim(:) ! runoff for one time step for all spatial dimension - real(dp), allocatable, intent(out) :: sim2D(:,:) ! runoff for one time step for all spatial dimension - integer(i4b), intent(out) :: ierr ! error code - character(*), intent(out) :: message ! error message + integer(i4b), intent(out) :: ierr ! error code + character(*), intent(out) :: message ! error message ! local variables - character(len=strLen) :: cmessage ! error message from subroutine + character(len=strLen) :: cmessage ! error message from subroutine ! initialize error control ierr=0; message='read_runoff_data/' @@ -313,24 +314,25 @@ subroutine read_1D_runoff(fname, & ! input: filename var_name, & ! input: variable name time_index, & ! input: time index nSpace, & ! input: size of HRUs - sim, & ! output: runoff data structure + sim, & ! input/output: runoff data structure ierr, message) ! output: error control implicit none ! input variables - character(*), intent(in) :: fname ! filename - character(*), intent(in) :: var_name ! variable name - integer(i4b), intent(in) :: time_index ! index of time element - integer(i4b), intent(in) :: nSpace ! size of spatial dimensions + character(*), intent(in) :: fname ! filename + character(*), intent(in) :: var_name ! variable name + integer(i4b), intent(in) :: time_index ! index of time element + integer(i4b), intent(in) :: nSpace ! size of spatial dimensions + ! input/output variables + real(dp), allocatable, intent(inout) :: sim(:) ! runoff for one time step for all spatial dimension ! output variables - real(dp), allocatable, intent(out) :: sim(:) - integer(i4b), intent(out) :: ierr ! error code - character(*), intent(out) :: message ! error message + integer(i4b), intent(out) :: ierr ! error code + character(*), intent(out) :: message ! error message ! local variables - integer(i4b) :: iStart(2) - integer(i4b) :: iCount(2) - logical(lgt) :: existFillVal - real(dp) :: dummy(nSpace,1) ! data read - character(len=strLen) :: cmessage ! error message from subroutine + integer(i4b) :: iStart(2) + integer(i4b) :: iCount(2) + logical(lgt) :: existFillVal + real(dp) :: dummy(nSpace,1) ! data read + character(len=strLen) :: cmessage ! error message from subroutine ! initialize error control ierr=0; message='read_1D_runoff/' @@ -363,7 +365,7 @@ subroutine read_2D_runoff(fname, & ! input: filename var_name, & ! input: variable name time_index, & ! input: time index nSpace, & ! input: size of HRUs - sim2D, & ! output: runoff data structure + sim2D, & ! input/output: runoff data structure ierr, message) ! output: error control implicit none ! input variables @@ -371,8 +373,9 @@ subroutine read_2D_runoff(fname, & ! input: filename character(*), intent(in) :: var_name ! variable name integer(i4b), intent(in) :: time_index ! index of time element integer(i4b), intent(in) :: nSpace(1:2) ! size of spatial dimensions + ! input/output variables + real(dp), allocatable, intent(inout) :: sim2D(:,:) ! runoff for one time step for all spatial dimension ! output variables - real(dp), allocatable, intent(out) :: sim2D(:,:) ! runoff for one time step for all spatial dimension integer(i4b), intent(out) :: ierr ! error code character(*), intent(out) :: message ! error message ! local variables From c6c4aa9742e917509a2ddb3d963330ecbe5ebcf1 Mon Sep 17 00:00:00 2001 From: ShervanGharari Date: Thu, 13 Aug 2020 00:19:41 -0400 Subject: [PATCH 11/29] print statments and fixing of time correction for second file --- route/build/src/standalone/get_basin_runoff.f90 | 16 +++++++++------- route/build/src/standalone/model_setup.f90 | 13 +++++++++++-- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/route/build/src/standalone/get_basin_runoff.f90 b/route/build/src/standalone/get_basin_runoff.f90 index f629e5e4..be28dcc9 100644 --- a/route/build/src/standalone/get_basin_runoff.f90 +++ b/route/build/src/standalone/get_basin_runoff.f90 @@ -281,13 +281,15 @@ SUBROUTINE infile_name(ierr, message) ! output ierr=20; message=trim(message)//'iTime local is out of bound for the netcdf file inputs based on given simulation time'; print*, ierr ; print*, message ; return ; endif - !print*, counter - !print*, ierr - !print*, message - !print*, infileinfo_data_wm(1)%iTimebound(1) - !print*, infileinfo_data_wm(1)%iTimebound(2) - !print*, infileinfo_data(1)%iTimebound(1) - !print*, infileinfo_data(1)%iTimebound(2) + print*, counter + print*, ierr + print*, message + print*, infileinfo_data_wm(1)%iTimebound(1) + print*, infileinfo_data_wm(1)%iTimebound(2) + print*, infileinfo_data(1)%iTimebound(1) + print*, infileinfo_data(1)%iTimebound(2) + print*, iTime_local + print*, iTime_local_wm END SUBROUTINE infile_name diff --git a/route/build/src/standalone/model_setup.f90 b/route/build/src/standalone/model_setup.f90 index 5ccd185e..e260987d 100644 --- a/route/build/src/standalone/model_setup.f90 +++ b/route/build/src/standalone/model_setup.f90 @@ -298,6 +298,11 @@ SUBROUTINE inFile_pop(dir_name, & ! input: name of the directory of the inputfileinfo(iFile)%iTimebound(2) = inputfileinfo(iFile-1)%iTimebound(2) + nTime ! the last index from the perivous nc file + 1 endif + print*, iFile + print*, inputfileinfo(iFile)%iTimebound(1) + print*, inputfileinfo(iFile)%iTimebound(2) + print*, inputfileinfo(iFile)%infilename + enddo ! close ascii file @@ -357,8 +362,12 @@ SUBROUTINE inFile_corr_time(inputfileinfo, & ! input: the structure of simu day_start_diff = inputfileinfo_wm(iFile)%timeVar(1) /inputfileinfo_wm(iFile)%convTime2Days+inputfileinfo_wm(iFile)%ncrefjulday - refJulday_local day_end_diff = inputfileinfo_wm(iFile)%timeVar(nt)/inputfileinfo_wm(iFile)%convTime2Days+inputfileinfo_wm(iFile)%ncrefjulday - refJulday_local - inputfileinfo_wm(iFile)%iTimebound(1) = day_start_diff*secprday/dt + 1 ! to convert the day difference into time step difference - inputfileinfo_wm(iFile)%iTimebound(2) = day_end_diff *secprday/dt ! to convert the day difference into time step difference + inputfileinfo_wm(iFile)%iTimebound(1) = day_start_diff * secprday/dt + 1 ! to convert the day difference into time step difference + inputfileinfo_wm(iFile)%iTimebound(2) = day_end_diff * secprday/dt + 1 ! to convert the day difference into time step difference + + print*, iFile + print*, inputfileinfo_wm(iFile)%iTimebound(1) + print*, inputfileinfo_wm(iFile)%iTimebound(2) end do From bbc6db70847b6dc90f8d666e18159d90b16dcd0f Mon Sep 17 00:00:00 2001 From: ShervanGharari Date: Mon, 17 Aug 2020 14:12:44 -0400 Subject: [PATCH 12/29] minor changes in commnets and also reading calendar and time step in model_setup.f90 --- route/build/src/public_var.f90 | 6 ++--- route/build/src/standalone/model_setup.f90 | 30 +++++++++++++++------- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/route/build/src/public_var.f90 b/route/build/src/public_var.f90 index b13df4ca..67e681a2 100644 --- a/route/build/src/public_var.f90 +++ b/route/build/src/public_var.f90 @@ -92,9 +92,9 @@ module public_var integer(i4b) ,public :: routOpt = integerMissing ! routing scheme options 0-> both, 1->IRF, 2->KWT, otherwise error integer(i4b) ,public :: doesBasinRoute = 1 ! basin routing options 0-> no, 1->IRF, otherwise error integer(i4b) ,public :: doesAccumRunoff = 1 ! option to delayed runoff accumulation over all the upstream reaches - logical(lgt),public :: is_lake_sim = .false. ! logical whether or not lakes are activated in simulation - logical(lgt),public :: is_flux_wm = .false. ! logical whether or not water management componenets, abstraction, injections and target volums are provided and will be used in the simulation - logical(lgt),public :: is_vol_wm = .false. ! logical whether or not water management componenets, abstraction, injections and target volums are provided and will be used in the simulation + logical(lgt),public :: is_lake_sim = .false. ! logical if lakes are activated in simulation + logical(lgt),public :: is_flux_wm = .false. ! logical if flow is added or removed from a reach + logical(lgt),public :: is_vol_wm = .false. ! logical if target volume is considered for a lake ! RIVER NETWORK TOPOLOGY character(len=strLen),public :: fname_ntopOld = '' ! old filename containing stream network topology information logical(lgt) ,public :: ntopAugmentMode = .false. ! option for river network augmentation mode. terminate the program after writing augmented ntopo. diff --git a/route/build/src/standalone/model_setup.f90 b/route/build/src/standalone/model_setup.f90 index e260987d..2e2853ff 100644 --- a/route/build/src/standalone/model_setup.f90 +++ b/route/build/src/standalone/model_setup.f90 @@ -80,7 +80,7 @@ SUBROUTINE init_data(pid, & ! input: proc id ierr=0; message='init_data/' ! runoff input files initialization - call init_inFile_pop(ierr, message) + call init_inFile_pop(ierr, cmessage) if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif ! time initialization @@ -194,6 +194,10 @@ SUBROUTINE inFile_pop(dir_name, & ! input: name of the directory of the USE io_netcdf, ONLY: get_var_attr ! get the attributes interface USE io_netcdf, ONLY: get_nc_dim_len ! get the nc dimension length + ! Shared data + USE public_var, ONLY: time_units ! get the time units from control file and replace if not provided in nc files + USE public_var, ONLY: calendar ! get the calendar from control file and replace if not provided in nc files + ! input character(len=strLen), intent(in) :: dir_name ! the name of the directory that the txt file located character(len=strLen), intent(in) :: file_name ! the name of the file that include the nc file names @@ -249,15 +253,23 @@ SUBROUTINE inFile_pop(dir_name, & ! input: name of the directory of the ! set forcing file name inputfileinfo(iFile)%infilename = trim(filenameData) - ! get the time units - call get_var_attr(trim(dir_name)//trim(inputfileinfo(iFile)%infilename), & - trim(time_var_name), 'units', inputfileinfo(iFile)%unit, ierr, cmessage) - if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif + ! get the time units, assuming the water managment nc files has the same calendar as the first + if (trim(time_units) == charMissing) then + call get_var_attr(trim(dir_name)//trim(inputfileinfo(iFile)%infilename), & + trim(time_var_name), 'units', inputfileinfo(iFile)%unit, ierr, cmessage) + if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif + else + inputfileinfo(iFile)%unit = trim(time_units) + end if - ! get the calendar - call get_var_attr(trim(dir_name)//trim(inputfileinfo(iFile)%infilename), & - trim(time_var_name), 'calendar', inputfileinfo(iFile)%calendar, ierr, cmessage) - if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif + ! get the calendar, assuming the water managment nc files has the same calendar as the first + if (trim(calendar) == charMissing) then + call get_var_attr(trim(dir_name)//trim(inputfileinfo(iFile)%infilename), & + trim(time_var_name), 'calendar', inputfileinfo(iFile)%calendar, ierr, cmessage) + if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif + else + inputfileinfo(iFile)%calendar = trim(calendar) + end if ! get the dimension of the time to populate nTime and pass it to the get_nc file call get_nc_dim_len(trim(dir_name)//trim(inputfileinfo(iFile)%infilename), & From dace0e0f083432b268adade3eb267d815f067cc2 Mon Sep 17 00:00:00 2001 From: ShervanGharari Date: Wed, 19 Aug 2020 00:06:49 -0400 Subject: [PATCH 13/29] cleaing of get basin runoff --- route/build/src/globalData.f90 | 2 - .../build/src/standalone/get_basin_runoff.f90 | 42 ++++--------------- route/build/src/standalone/model_setup.f90 | 21 +++------- 3 files changed, 13 insertions(+), 52 deletions(-) diff --git a/route/build/src/globalData.f90 b/route/build/src/globalData.f90 index 16ae458e..e0a1fff3 100644 --- a/route/build/src/globalData.f90 +++ b/route/build/src/globalData.f90 @@ -74,8 +74,6 @@ module globalData ! ---------- Date/Time data ------------------------------------------------------------------------- integer(i4b) , public :: iTime ! time index at simulation time step - integer(i4b) , public :: iTime_local ! time index at simulation time step for a given input file - integer(i4b) , public :: iTime_local_wm ! time index at simulation time step for a given wm input file real(dp) , public :: startJulday ! julian day: start of routing simulation real(dp) , public :: endJulday ! julian day: end of routing simulation real(dp) , public :: refJulday ! julian day: reference diff --git a/route/build/src/standalone/get_basin_runoff.f90 b/route/build/src/standalone/get_basin_runoff.f90 index be28dcc9..65a7bb5e 100644 --- a/route/build/src/standalone/get_basin_runoff.f90 +++ b/route/build/src/standalone/get_basin_runoff.f90 @@ -4,6 +4,9 @@ MODULE get_runoff implicit none +integer(i4b) :: iTime_local ! time index at simulation time step for a given runoff file +integer(i4b) :: iTime_local_wm ! time index at simulation time step for a given water management file + private public::get_hru_runoff @@ -32,8 +35,6 @@ SUBROUTINE get_hru_runoff(ierr, message) ! output: error control USE public_var, ONLY:is_vol_wm ! logical water management components target volume should be read USE globalData, ONLY:basinID ! basin ID USE globalData, ONLY:reachID ! reach ID - USE globalData, ONLY:iTime_local ! iTime index for the given netcdf file - USE globalData, ONLY:iTime_local_wm ! iTime index for the given netcdf file USE globalData, ONLY:nHRU ! number of routing sub-basin USE globalData, ONLY:nRch ! number of routing seg (reaches and lakes) USE globalData, ONLY:runoff_data ! data structure to hru runoff data @@ -57,12 +58,6 @@ SUBROUTINE get_hru_runoff(ierr, message) ! output: error control call infile_name(ierr, cmessage) ! read the infile name for given iTime if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif - !print statements - print*, iTime_local, iTime_local_wm - print*, fname_qsim, fname_wm - print*, runoff_data%nSpace - print*, wm_data%nSpace - ! get the simulated runoff for the current time step - runoff_data%sim(:) or %sim2D(:,:) call read_runoff_data(trim(input_dir)//trim(fname_qsim), & ! input: filename trim(vname_qsim), & ! input: varname @@ -214,14 +209,6 @@ SUBROUTINE get_hru_runoff(ierr, message) ! output: error control if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif end if - ! printing statement - !print*, wm_data%flux_wm - !print*, wm_data%seg_id - !print*, wm_data%seg_id - !print*, iTime_local - !print*, iTime_local_wm - !stop - END SUBROUTINE get_hru_runoff @@ -238,8 +225,6 @@ SUBROUTINE infile_name(ierr, message) ! output USE globalData, ONLY: iTime ! time index at simulation time step USE globalData, ONLY: infileinfo_data ! the information of the input files for runoff, evapo and precip USE globalData, ONLY: infileinfo_data_wm ! the information of the input files - USE globalData, ONLY: iTime_local ! iTime index for the given netcdf file - USE globalData, ONLY: iTime_local_wm ! iTime index for the given netcdf file implicit none @@ -248,18 +233,17 @@ SUBROUTINE infile_name(ierr, message) ! output character(*), intent(out) :: message ! error message ! local variable integer(i4b) :: ix - integer(i4b) :: counter ! to check if both iTime_local are read properly + logical(lgt) :: wm_not_read_flag ! to turn false if there is a iTime_local_wn to be read !character(len=strLen) :: cmessage ! error message ! initialize error control - ierr=0; message='infile_name/'; counter = 0 ; + ierr=0; message='infile_name/'; wm_not_read_flag = .true. ! fast forward time to time index at simStart and save iTime and modJulday ixloop: do ix = 1, size(infileinfo_data) !loop over number of file if ((iTime >= infileinfo_data(ix)%iTimebound(1)).and.(iTime <= infileinfo_data(ix)%iTimebound(2))) then iTime_local = iTime - infileinfo_data(ix)%iTimebound(1) + 1 fname_qsim = trim(infileinfo_data(ix)%infilename) - counter = counter + 1 exit ixloop endif enddo ixloop @@ -270,27 +254,17 @@ SUBROUTINE infile_name(ierr, message) ! output if ((iTime >= infileinfo_data_wm(ix)%iTimebound(1)).and.(iTime <= infileinfo_data_wm(ix)%iTimebound(2))) then iTime_local_wm = iTime - infileinfo_data_wm(ix)%iTimebound(1) + 1 fname_wm = trim(infileinfo_data_wm(ix)%infilename) - counter = counter + 1 + wm_not_read_flag = .false. ! file is read so the not read flag is turned false exit iyloop endif enddo iyloop endif ! check if the two files are identified in case is flux and vol flags are set to true - if ((counter /= 2).and.((is_flux_wm).or.(is_vol_wm))) then - ierr=20; message=trim(message)//'iTime local is out of bound for the netcdf file inputs based on given simulation time'; print*, ierr ; print*, message ; return ; + if ((wm_not_read_flag).and.((is_flux_wm).or.(is_vol_wm))) then + ierr=20; message=trim(message)//'iTime local is out of bound for the water management netcdf file inputs based on given simulation date and time in control file'; return ; endif - print*, counter - print*, ierr - print*, message - print*, infileinfo_data_wm(1)%iTimebound(1) - print*, infileinfo_data_wm(1)%iTimebound(2) - print*, infileinfo_data(1)%iTimebound(1) - print*, infileinfo_data(1)%iTimebound(2) - print*, iTime_local - print*, iTime_local_wm - END SUBROUTINE infile_name END MODULE get_runoff diff --git a/route/build/src/standalone/model_setup.f90 b/route/build/src/standalone/model_setup.f90 index 2e2853ff..d63f5835 100644 --- a/route/build/src/standalone/model_setup.f90 +++ b/route/build/src/standalone/model_setup.f90 @@ -163,7 +163,7 @@ SUBROUTINE init_inFile_pop (ierr, message) ! output ! passing the first nc file as global file name to read fname_wm = trim(infileinfo_data_wm(1)%infilename) - call inFile_corr_time(infileinfo_data, & ! input: the structure of simulated runoff, evapo and + call inFile_sync_time(infileinfo_data, & ! input: the structure of simulated runoff, evapo and infileinfo_data_wm, & ! inout: input file information ierr, cmessage) ! output: error control @@ -310,11 +310,6 @@ SUBROUTINE inFile_pop(dir_name, & ! input: name of the directory of the inputfileinfo(iFile)%iTimebound(2) = inputfileinfo(iFile-1)%iTimebound(2) + nTime ! the last index from the perivous nc file + 1 endif - print*, iFile - print*, inputfileinfo(iFile)%iTimebound(1) - print*, inputfileinfo(iFile)%iTimebound(2) - print*, inputfileinfo(iFile)%infilename - enddo ! close ascii file @@ -324,10 +319,10 @@ END SUBROUTINE inFile_pop ! ********************************************************************* - ! private subroutine: get the two infiledata and convert the iTimebound of - ! the input_info_wm to match the input_info + ! private subroutine: to synchronize the iTimebound of + ! the inputfileinfo_wm to match the inputfileinfo ! ********************************************************************* - SUBROUTINE inFile_corr_time(inputfileinfo, & ! input: the structure of simulated runoff, evapo and + SUBROUTINE inFile_sync_time(inputfileinfo, & ! input: the structure of simulated runoff, evapo and inputfileinfo_wm, & ! inout: input file information ierr, message) ! output: error control @@ -377,10 +372,6 @@ SUBROUTINE inFile_corr_time(inputfileinfo, & ! input: the structure of simu inputfileinfo_wm(iFile)%iTimebound(1) = day_start_diff * secprday/dt + 1 ! to convert the day difference into time step difference inputfileinfo_wm(iFile)%iTimebound(2) = day_end_diff * secprday/dt + 1 ! to convert the day difference into time step difference - print*, iFile - print*, inputfileinfo_wm(iFile)%iTimebound(1) - print*, inputfileinfo_wm(iFile)%iTimebound(2) - end do ! checks if the staring and ending iTime of the inputfileinfo_wm overlap with the inputfileinfo of simulated runoff, evapo and precip @@ -398,7 +389,7 @@ SUBROUTINE inFile_corr_time(inputfileinfo, & ! input: the structure of simu endif - END SUBROUTINE inFile_corr_time + END SUBROUTINE inFile_sync_time ! ********************************************************************* ! private subroutine: initialize time data @@ -799,8 +790,6 @@ SUBROUTINE init_runoff(remap_flag, & ! input: logical whether or not runno if(ierr/=0)then; message=trim(message)//'problem allocating runoff_data_in%hru_ix'; return; endif ! get indices of the seg ids in the input file in the routing layer - print*, size(wm_data_in%seg_id) - print*, size(reachID) call get_qix(wm_data_in%seg_id, & ! input: vector of ids in mapping file reachID, & ! input: vector of ids in the routing layer wm_data_in%seg_ix, & ! output: indices of hru ids in routing layer From c8e85421f466fc6cdb271a196ca2e820a1babca3 Mon Sep 17 00:00:00 2001 From: ShervanGharari Date: Tue, 25 Aug 2020 03:01:10 -0400 Subject: [PATCH 14/29] the checks for start and end of the second nc file is incorporated in the model setup --- route/build/src/standalone/model_setup.f90 | 127 ++++++++++++++++----- 1 file changed, 97 insertions(+), 30 deletions(-) diff --git a/route/build/src/standalone/model_setup.f90 b/route/build/src/standalone/model_setup.f90 index d63f5835..db0ffc29 100644 --- a/route/build/src/standalone/model_setup.f90 +++ b/route/build/src/standalone/model_setup.f90 @@ -402,50 +402,63 @@ SUBROUTINE init_time(ierr, message) ! output USE process_time_module, ONLY: conv_cal2julian ! compute data and time from julian day USE time_utils_module, ONLY: ndays_month ! compute number of days in a month ! derived datatype - USE dataTypes, ONLY: time ! time data type + USE dataTypes, ONLY: time ! time data type ! public data - USE public_var, ONLY: time_units ! time units (seconds, hours, or days) - USE public_var, ONLY: simStart ! date string defining the start of the simulation - USE public_var, ONLY: simEnd ! date string defining the end of the simulation - USE public_var, ONLY: calendar ! calendar name + USE public_var, ONLY: time_units ! time units (seconds, hours, or days) + USE public_var, ONLY: simStart ! date string defining the start of the simulation + USE public_var, ONLY: simEnd ! date string defining the end of the simulation + USE public_var, ONLY: calendar ! calendar name USE public_var, ONLY: dt USE public_var, ONLY: secprday - USE public_var, ONLY: restart_write ! restart write option - USE public_var, ONLY: restart_date ! restart date - USE public_var, ONLY: restart_month ! periodic restart month - USE public_var, ONLY: restart_day ! periodic restart day - USE public_var, ONLY: restart_hour ! periodic restart hr + USE public_var, ONLY: restart_write ! restart write option + USE public_var, ONLY: restart_date ! restart date + USE public_var, ONLY: restart_month ! periodic restart month + USE public_var, ONLY: restart_day ! periodic restart day + USE public_var, ONLY: restart_hour ! periodic restart hr + USE public_var, ONLY: verySmall ! very small value ! saved time variables - USE globalData, ONLY: timeVar ! time variables (unit given by runoff data) - USE globalData, ONLY: iTime ! time index at simulation time step - USE globalData, ONLY: refJulday ! julian day: reference - USE globalData, ONLY: roJulday ! julian day: runoff input time - USE globalData, ONLY: startJulday ! julian day: start of routing simulation - USE globalData, ONLY: endJulday ! julian day: end of routing simulation - USE globalData, ONLY: modJulday ! julian day: at model time step - USE globalData, ONLY: modTime ! model time data (yyyy:mm:dd:hh:mm:ss) - USE globalData, ONLY: restCal ! restart time data (yyyy:mm:dd:hh:mm:sec) - USE globalData, ONLY: dropCal ! restart dropoff calendar date/time - USE globalData, ONLY: infileinfo_data ! the information of the input files + USE globalData, ONLY: timeVar ! time variables (unit given by runoff data) + USE globalData, ONLY: iTime ! time index at simulation time step + USE globalData, ONLY: refJulday ! julian day: reference + USE globalData, ONLY: roJulday ! julian day: runoff input time + USE globalData, ONLY: startJulday ! julian day: start of routing simulation + USE globalData, ONLY: endJulday ! julian day: end of routing simulation + USE globalData, ONLY: modJulday ! julian day: at model time step + USE globalData, ONLY: modTime ! model time data (yyyy:mm:dd:hh:mm:ss) + USE globalData, ONLY: restCal ! restart time data (yyyy:mm:dd:hh:mm:sec) + USE globalData, ONLY: dropCal ! restart dropoff calendar date/time + USE globalData, ONLY: infileinfo_data ! the information of the input files + USE globalData, ONLY: infileinfo_data_wm ! the information of the input files + USE public_var, ONLY: is_flux_wm ! logical whether or not abstraction and injection should be read from the file + USE public_var, ONLY: is_vol_wm ! logical whether or not target volume for lakes should be read implicit none ! output: error control - integer(i4b), intent(out) :: ierr ! error code - character(*), intent(out) :: message ! error message + integer(i4b), intent(out) :: ierr ! error code + character(*), intent(out) :: message ! error message ! local variable integer(i4b) :: ix integer(i4b) :: counter integer(i4b) :: nTime + integer(i4b) :: nTime_wm integer(i4b) :: nt - integer(i4b) :: nFile ! number of nc files - integer(i4b) :: iFile ! for loop over the nc files + integer(i4b) :: nFile ! number of nc files + integer(i4b) :: nFile_wm ! number of nc files + integer(i4b) :: iFile ! for loop over the nc files type(time) :: rofCal type(time) :: simCal - integer(i4b) :: nDays ! number of days in a month + integer(i4b) :: nDays ! number of days in a month + real(dp), allocatable :: roJulday_diff(:) ! the difference of two concequative elements in roJulyday real(dp) :: restartJulday - real(dp) :: tempJulday - character(len=strLen) :: cmessage ! error message of downwind routine + real(dp), allocatable :: timeVar_wm(:) ! + real(dp) :: refJulday_wm ! + real(dp) :: startJulday_wm ! time varibale from + real(dp) :: endJulday_wm ! time varibale from + real(dp), allocatable :: roJulday_wm(:) ! Julian day of concatenated netCDF for water management + real(dp), allocatable :: timeVar_diff(:) ! difference between the concequative timeVar elements + real(dp) :: tempJulday ! + character(len=strLen) :: cmessage ! error message of downwind routine character(len=50) :: fmt1='(a,I4,a,I2.2,a,I2.2,x,I2.2,a,I2.2,a,F5.2)' ! initialize error control @@ -490,11 +503,11 @@ SUBROUTINE init_time(ierr, message) ! output ierr=20; message=trim(message)//trim(cmessage); return endif - ! check sim_start is before the last time step in runoff data + ! check sim_start is after the last time step in runoff data if(startJulday>roJulday(nTime)) then call conv_julian2cal(roJulday(nTime), calendar, rofCal, ierr, cmessage) call conv_julian2cal(startJulday, calendar, simCal, ierr, cmessage) - write(iulog,'(2a)') new_line('a'),'ERROR: is after the first time step in input runoff' + write(iulog,'(2a)') new_line('a'),'ERROR: is after the last time step in input runoff' write(iulog,fmt1) ' runoff_end : ', rofCal%iy,'-',rofCal%im,'-',rofCal%id, rofCal%ih,':', rofCal%imin,':',rofCal%dsec write(iulog,fmt1) ' : ', simCal%iy,'-',simCal%im,'-',simCal%id, simCal%ih,':', simCal%imin,':',simCal%dsec ierr=20; message=trim(message)//'check against runoff input time'; return @@ -522,6 +535,22 @@ SUBROUTINE init_time(ierr, message) ! output endJulday = roJulday(nTime) endif + ! check if the julian day of contacenated files do not have overlap or gap if nTime is larger than 1 + if (nTime>1) then + ! allocate the difference array + allocate(roJulday_diff(nTime-1), stat=ierr) + if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif + ! calculate the difference of consequative time in julian day + roJulday_diff = roJulday (1:nTime-1) - roJulday (2:nTime) + ! check if the difference are identical otherwise error and terminate + do counter = 1, nTime-2 + if ((abs(roJulday_diff(counter)-roJulday_diff(counter+1)))>verySmall) then + write(iulog,'(2a)') new_line('a'),'ERROR: contacenated netCDF files have time overlaps or gap' + ierr=20; message=trim(message)//'make sure the input netCDF files do not have time overlap or gap'; return + endif + enddo + endif + ! fast forward time to time index at simStart and save iTime and modJulday do ix = 1, nTime modJulday = roJulday(ix) @@ -533,6 +562,44 @@ SUBROUTINE init_time(ierr, message) ! output ! initialize previous model time modTime(0) = time(integerMissing, integerMissing, integerMissing, integerMissing, integerMissing, realMissing) + ! if one of the two flags are set it true + if ((is_flux_wm).or.(is_vol_wm)) then + + ! get the number of the total time length of all the water management nc files + nFile_wm = size(infileinfo_data_wm) + nTime_wm = 0 + do iFile=1,nFile_wm + nTime_wm = nTime_wm + infileinfo_data_wm(iFile)%nTime + enddo + + ! Define time varialbes: roJulday_wm + allocate(roJulday_wm(nTime_wm), stat=ierr) + if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif + + ! roJulday_wm: Julian day of concatenated netCDF for water management + counter = 1; + do iFile=1,nFile_wm + nt = infileinfo_data_wm(iFile)%nTime + roJulday_wm(counter:counter+nt-1) = & + infileinfo_data_wm(iFile)%timeVar(1:nt)/infileinfo_data_wm(iFile)%convTime2Days+infileinfo_data_wm(iFile)%ncrefjulday + counter = counter + infileinfo_data_wm(iFile)%nTime + enddo + + ! check sim_start is after the last time step in water management data + if(startJulday>roJulday_wm(nTime_wm)) then + write(iulog,'(2a)') new_line('a'),'ERROR: is after the last time step in input runoff' + ierr=20; message=trim(message)//'check against water management input time'; return + endif + + ! check sim_end is before the first time step in water management data + if(endJulday is before the last time step in input runoff' + ierr=20; message=trim(message)//'check against water management input time'; return + endif + + endif + + ! Set restart calendar date/time and dropoff calendar date/time and ! -- For periodic restart options --------------------------------------------------------------------- ! Ensure that user-input restart month, day are valid. From 3e25ec7781061b2be9184dd0fcaa8e9529cc14be Mon Sep 17 00:00:00 2001 From: ShervanGharari Date: Tue, 25 Aug 2020 03:22:22 -0400 Subject: [PATCH 15/29] chekcing if nc files do not have gap or overlaps --- route/build/src/standalone/model_setup.f90 | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/route/build/src/standalone/model_setup.f90 b/route/build/src/standalone/model_setup.f90 index db0ffc29..1158c687 100644 --- a/route/build/src/standalone/model_setup.f90 +++ b/route/build/src/standalone/model_setup.f90 @@ -450,6 +450,7 @@ SUBROUTINE init_time(ierr, message) ! output type(time) :: simCal integer(i4b) :: nDays ! number of days in a month real(dp), allocatable :: roJulday_diff(:) ! the difference of two concequative elements in roJulyday + real(dp), allocatable :: roJulday_diff_wm(:)! the difference of two concequative elements in roJulyday_wm real(dp) :: restartJulday real(dp), allocatable :: timeVar_wm(:) ! real(dp) :: refJulday_wm ! @@ -597,6 +598,22 @@ SUBROUTINE init_time(ierr, message) ! output ierr=20; message=trim(message)//'check against water management input time'; return endif + ! check if the julian day of contacenated files do not have overlap or gap if nTime_wm is larger than 1 + if (nTime_wm>1) then + ! allocate the difference array + allocate(roJulday_diff_wm(nTime_wm-1), stat=ierr) + if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif + ! calculate the difference of consequative time in julian day + roJulday_diff_wm = roJulday_wm (1:nTime-1) - roJulday_wm (2:nTime) + ! check if the difference are identical otherwise error and terminate + do counter = 1, nTime_wm-2 + if ((abs(roJulday_diff_wm(counter)-roJulday_diff_wm(counter+1)))>verySmall) then + write(iulog,'(2a)') new_line('a'),'ERROR: water managmentcontacenated netCDF files have time overlaps or gap' + ierr=20; message=trim(message)//'make sure the water management input netCDF files do not have time overlap or gap'; return + endif + enddo + endif + endif From 8e571b727c5eba2c49c2ab60b55ad1d5169d81ee Mon Sep 17 00:00:00 2001 From: ShervanGharari Date: Tue, 25 Aug 2020 03:24:07 -0400 Subject: [PATCH 16/29] few changes --- route/build/src/standalone/model_setup.f90 | 31 +++++++++++----------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/route/build/src/standalone/model_setup.f90 b/route/build/src/standalone/model_setup.f90 index 1158c687..1439e88d 100644 --- a/route/build/src/standalone/model_setup.f90 +++ b/route/build/src/standalone/model_setup.f90 @@ -435,31 +435,30 @@ SUBROUTINE init_time(ierr, message) ! output implicit none ! output: error control - integer(i4b), intent(out) :: ierr ! error code - character(*), intent(out) :: message ! error message + integer(i4b), intent(out) :: ierr ! error code + character(*), intent(out) :: message ! error message ! local variable integer(i4b) :: ix integer(i4b) :: counter integer(i4b) :: nTime integer(i4b) :: nTime_wm integer(i4b) :: nt - integer(i4b) :: nFile ! number of nc files - integer(i4b) :: nFile_wm ! number of nc files - integer(i4b) :: iFile ! for loop over the nc files + integer(i4b) :: nFile ! number of nc files + integer(i4b) :: nFile_wm ! number of nc files + integer(i4b) :: iFile ! for loop over the nc files type(time) :: rofCal type(time) :: simCal - integer(i4b) :: nDays ! number of days in a month - real(dp), allocatable :: roJulday_diff(:) ! the difference of two concequative elements in roJulyday - real(dp), allocatable :: roJulday_diff_wm(:)! the difference of two concequative elements in roJulyday_wm + integer(i4b) :: nDays ! number of days in a month + real(dp), allocatable :: roJulday_diff(:) ! the difference of two concequative elements in roJulyday + real(dp), allocatable :: roJulday_diff_wm(:) ! the difference of two concequative elements in roJulyday_wm real(dp) :: restartJulday - real(dp), allocatable :: timeVar_wm(:) ! - real(dp) :: refJulday_wm ! - real(dp) :: startJulday_wm ! time varibale from - real(dp) :: endJulday_wm ! time varibale from - real(dp), allocatable :: roJulday_wm(:) ! Julian day of concatenated netCDF for water management - real(dp), allocatable :: timeVar_diff(:) ! difference between the concequative timeVar elements - real(dp) :: tempJulday ! - character(len=strLen) :: cmessage ! error message of downwind routine + real(dp) :: refJulday_wm ! + real(dp) :: startJulday_wm ! time varibale from + real(dp) :: endJulday_wm ! time varibale from + real(dp), allocatable :: roJulday_wm(:) ! Julian day of concatenated netCDF for water management + real(dp), allocatable :: timeVar_diff(:) ! difference between the concequative timeVar elements + real(dp) :: tempJulday ! + character(len=strLen) :: cmessage ! error message of downwind routine character(len=50) :: fmt1='(a,I4,a,I2.2,a,I2.2,x,I2.2,a,I2.2,a,F5.2)' ! initialize error control From db80cdcf38304a5381ac7558bdb44cf189268f86 Mon Sep 17 00:00:00 2001 From: ShervanGharari Date: Tue, 25 Aug 2020 03:32:29 -0400 Subject: [PATCH 17/29] small changes --- route/build/src/standalone/model_setup.f90 | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/route/build/src/standalone/model_setup.f90 b/route/build/src/standalone/model_setup.f90 index 1439e88d..24e6f420 100644 --- a/route/build/src/standalone/model_setup.f90 +++ b/route/build/src/standalone/model_setup.f90 @@ -450,13 +450,10 @@ SUBROUTINE init_time(ierr, message) ! output type(time) :: simCal integer(i4b) :: nDays ! number of days in a month real(dp), allocatable :: roJulday_diff(:) ! the difference of two concequative elements in roJulyday - real(dp), allocatable :: roJulday_diff_wm(:) ! the difference of two concequative elements in roJulyday_wm real(dp) :: restartJulday real(dp) :: refJulday_wm ! - real(dp) :: startJulday_wm ! time varibale from - real(dp) :: endJulday_wm ! time varibale from real(dp), allocatable :: roJulday_wm(:) ! Julian day of concatenated netCDF for water management - real(dp), allocatable :: timeVar_diff(:) ! difference between the concequative timeVar elements + real(dp), allocatable :: roJulday_diff_wm(:) ! the difference of two concequative elements in roJulyday_wm real(dp) :: tempJulday ! character(len=strLen) :: cmessage ! error message of downwind routine character(len=50) :: fmt1='(a,I4,a,I2.2,a,I2.2,x,I2.2,a,I2.2,a,F5.2)' From 1bfc0cabf4d6d69944fc20350476e5bdba644c7c Mon Sep 17 00:00:00 2001 From: ShervanGharari Date: Tue, 25 Aug 2020 19:35:09 -0400 Subject: [PATCH 18/29] scatter_wm is implemented in mpi_process.f90 --- route/build/src/mpi_process.f90 | 124 +++++++++++++++++++++++++++++--- 1 file changed, 115 insertions(+), 9 deletions(-) diff --git a/route/build/src/mpi_process.f90 b/route/build/src/mpi_process.f90 index d543458d..a7816c98 100644 --- a/route/build/src/mpi_process.f90 +++ b/route/build/src/mpi_process.f90 @@ -949,17 +949,17 @@ SUBROUTINE scatter_runoff(nNodes, comm, & ! mpi variables: number nodes, communi ! input variables - integer(i4b), intent(in) :: nNodes ! number of processes (MPI) - integer(i4b), intent(in) :: comm ! communicator + integer(i4b), intent(in) :: nNodes ! number of processes (MPI) + integer(i4b), intent(in) :: comm ! communicator ! output variables - integer(i4b), intent(out) :: ierr ! error code - character(len=strLen), intent(out) :: message ! error message + integer(i4b), intent(out) :: ierr ! error code + character(len=strLen), intent(out) :: message ! error message ! local variables - integer(i4b) :: iHru,jHru ! loop indices - real(dp) :: basinRunoff_local(nHRU) ! temporal basin runoff (m/s) for whole domain - real(dp) :: basinEvapo_local(nHRU) ! temporal basin runoff (m/s) for whole domain - real(dp) :: basinPrecip_local(nHRU) ! temporal basin runoff (m/s) for whole domain - character(len=strLen) :: cmessage ! error message from a subroutine + integer(i4b) :: iHru,jHru ! loop indices + real(dp) :: basinRunoff_local(nHRU) ! temporal basin runoff (m/s) for whole domain + real(dp) :: basinEvapo_local(nHRU) ! temporal basin evaporation (m/s) for whole domain + real(dp) :: basinPrecip_local(nHRU) ! temporal basin precipitation (m/s) for whole domain + character(len=strLen) :: cmessage ! error message from a subroutine ierr=0; message='scatter_runoff/' @@ -1058,6 +1058,112 @@ SUBROUTINE scatter_runoff(nNodes, comm, & ! mpi variables: number nodes, communi END SUBROUTINE scatter_runoff + + ! ********************************************************************* + ! private subroutine: scatter global domain water management data to local domain + ! ********************************************************************* + SUBROUTINE scatter_wm(nNodes, comm, & ! mpi variables: number nodes, communicator + ierr, message) ! error controls + + USE globalData, ONLY: nRch ! number of all reach + USE globalData, ONLY: nRch_mainstem ! number of mainstem reach + USE globalData, ONLY: wm_data ! water management data structure + USE globalData, ONLY: rch_per_proc ! number of reach assigned to each proc (i.e., node) + USE globalData, ONLY: flux_wm_main ! nRch flux holder for mainstem + USE globalData, ONLY: flux_wm_trib ! nRch flux holder for tributary + USE globalData, ONLY: vol_wm_main ! nRch target vol holder for mainstem + USE globalData, ONLY: vol_wm_trib ! nRch target vol holder for tributary + USE public_var, ONLY: is_flux_wm ! logical whether or not fluxes should be passed + USE public_var, ONLY: is_vol_wm ! logical whether or not target volume should be passed + + ! input variables + integer(i4b), intent(in) :: nNodes ! number of processes (MPI) + integer(i4b), intent(in) :: comm ! communicator + ! output variables + integer(i4b), intent(out) :: ierr ! error code + character(len=strLen), intent(out) :: message ! error message + ! local variables + integer(i4b) :: iHru,jHru ! loop indices + real(dp) :: Rch_flux_local(nRch) ! temporal reach flux (m3/s) for whole domain + real(dp) :: Rch_vol_local(nRch) ! temporal reach (lake) volume (m3) for whole domain + character(len=strLen) :: cmessage ! error message from a subroutine + + ierr=0; message='scatter_runoff/' + + if (nNodes==1) then + + if (is_flux_wm) then + + ! if only single proc is used, all fluxes are stored in mainstem runoff array + if (.not. allocated(flux_wm_main)) then + allocate(flux_wm_main(nRch), stat=ierr) + if(ierr/=0)then; message=trim(message)//'problem allocating array for [flux_wm_main]'; return; endif + end if + flux_wm_main(:) = wm_data%flux_wm(:) + + endif + + if (is_vol_wm) then + + ! if only single proc is used, all target volumes are stored in mainstem runoff array + if (.not. allocated(vol_wm_main)) then + allocate(vol_wm_main(nRch), stat=ierr) + if(ierr/=0)then; message=trim(message)//'problem allocating array for [vol_wm_main]'; return; endif + end if + vol_wm_main(:) = wm_data%vol_wm(:) + + endif + + else + + ! sort the reach flux, target vol in terms of nodes/domains + if (masterproc) then ! this is a root process + + if (is_flux_wm) then + if (.not. allocated(flux_wm_main)) then + allocate(flux_wm_main(nRch_mainstem), stat=ierr) + if(ierr/=0)then; message=trim(message)//'problem allocating array for [flux_wm_main]'; return; endif + endif + ! flux or target vol at reach in mainstem and tributaries + Rch_flux_local(1:nRch) = wm_data%flux_wm(1:nRch) + flux_wm_main(1:nRch_mainstem) = Rch_flux_local(1:nRch_mainstem) + endif + + if (is_vol_wm) then + if (.not. allocated(vol_wm_main)) then + allocate(vol_wm_main(nRch_mainstem), stat=ierr) + if(ierr/=0)then; message=trim(message)//'problem allocating array for [vol_wm_main]'; return; endif + endif + ! target vol at reach in mainstem and tributaries + Rch_vol_local(1:nRch) = wm_data%vol_wm(1:nRch) + vol_wm_main(1:nRch_mainstem) = Rch_vol_local(1:nRch_mainstem) + end if + + end if + + call shr_mpi_barrier(comm, message) + + ! Distribute the read flux to each process + if (is_flux_wm) then + call shr_mpi_scatterV(Rch_flux_local(nRch_mainstem+1:nRch), & + rch_per_proc(0:nNodes-1), & + flux_wm_trib, & + ierr, cmessage) + if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif + endif + + if (is_vol_wm) then + call shr_mpi_scatterV(Rch_vol_local(nRch_mainstem+1:nRch), & + rch_per_proc(0:nNodes-1), & + vol_wm_trib, & + ierr, cmessage) + if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif + endif + + end if + + END SUBROUTINE scatter_wm + ! ********************************************************************* ! subroutine: single flux communication ! ********************************************************************* From d9734f695a1e47f02f166a9257d63baf4ae96791 Mon Sep 17 00:00:00 2001 From: ShervanGharari Date: Wed, 26 Aug 2020 13:58:02 -0400 Subject: [PATCH 19/29] the checks for scatter runoff, evaporation and precipitation are added to the mpi_process.f90 --- route/build/src/mpi_process.f90 | 54 ++++++++++++++++++++++++++++++--- 1 file changed, 50 insertions(+), 4 deletions(-) diff --git a/route/build/src/mpi_process.f90 b/route/build/src/mpi_process.f90 index a7816c98..b4f0922b 100644 --- a/route/build/src/mpi_process.f90 +++ b/route/build/src/mpi_process.f90 @@ -716,6 +716,7 @@ subroutine mpi_route(pid, & ! input: proc id USE globalData, ONLY: tribOutlet_per_proc ! number of tributary outlets per proc (array size = nNodes) USE globalData, ONLY: global_ix_main ! reach index at tributary reach outlets to mainstem (size = sum of tributary outlets in all the procs) USE globalData, ONLY: local_ix_comm ! local reach index at tributary reach outlets to mainstem for each proc (size = sum of tributary outlets in proc) + USE public_var, ONLY: is_lake_sim ! logical whether or not lake should be simulated ! routing driver USE main_route_module, ONLY: main_route ! routing driver @@ -753,33 +754,78 @@ subroutine mpi_route(pid, & ! input: proc id end if ! -------------------------------- - ! distribute (scatter) global runoff array to local runoff arrays + ! distribute (scatter) global runoff, evaporation + ! and precipitation array to local runoff arrays ! - basinRunoff_main (only at master proc) ! - basinRunoff_trib (all procs) ! -------------------------------- if (doesScatterRunoff) then + call t_startf ('route/scatter-runoff') call scatter_runoff(nNodes, comm, ierr, cmessage) if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif call t_stopf ('route/scatter-runoff') + else + if (nNodes==1) then + if (.not.allocated(basinRunoff_main)) then ierr=10; message=trim(message)//'master proc: mainstem runoff array is not allocated'; return - endif + end if + if (is_lake_sim) then + if (.not.allocated(basinEvapo_main)) then + ierr=10; message=trim(message)//'master proc: mainstem evaporation array is not allocated'; return + end if + if (.not.allocated(basinPrecip_main)) then + ierr=10; message=trim(message)//'master proc: mainstem precipitation array is not allocated'; return + end if + end if + else + if (masterproc) then + write(iulog,*) 'NOTE: HRU Runoff is already decomposed into mainstems and tributaries. No need for scatter_runoff' + if (nHRU_mainstem > 0 .and. .not.allocated(basinRunoff_main)) then ierr=10; message=trim(message)//'mainstem runoff array is not allocated/populated'; return - endif + end if + if (is_lake_sim) then + if (nHRU_mainstem > 0 .and. .not.allocated(basinEvapo_main)) then + ierr=10; message=trim(message)//'mainstem evaporation array is not allocated/populated'; return + end if + if (nHRU_mainstem > 0 .and. .not.allocated(basinPrecip_main)) then + ierr=10; message=trim(message)//'mainstem precipitation array is not allocated/populated'; return + end if + end if + if (.not.allocated(basinRunoff_trib)) then ierr=10; message=trim(message)//'master proc: tributary runoff array is not allocated'; return - endif + end if + if (is_lake_sim) then + if (.not.allocated(basinEvapo_trib)) then + ierr=10; message=trim(message)//'master proc: tributary evaporation array is not allocated'; return + end if + if (.not.allocated(basinPrecip_trib)) then + ierr=10; message=trim(message)//'master proc: tributary precipitation array is not allocated'; return + end if + end if + else + if(.not.allocated(basinRunoff_trib)) then ierr=10; message=trim(message)//'tributary runoff array is not allocated/populated'; return end if + if (is_lake_sim) then + if (.not.allocated(basinEvapo_trib)) then + ierr=10; message=trim(message)//'tributary evaporation array is not allocated/populated'; return + end if + if (.not.allocated(basinPrecip_trib)) then + ierr=10; message=trim(message)//'tributary precipitation array is not allocated/populated'; return + end if + end if + end if end if end if From 3fb572e9821f5045e4d4d746c22f1114e52e13e3 Mon Sep 17 00:00:00 2001 From: ShervanGharari Date: Wed, 26 Aug 2020 14:32:48 -0400 Subject: [PATCH 20/29] scatter_wm and its check is called in the mpi_process/f90 --- route/build/src/mpi_process.f90 | 106 +++++++++++++++++++++++++++++--- 1 file changed, 97 insertions(+), 9 deletions(-) diff --git a/route/build/src/mpi_process.f90 b/route/build/src/mpi_process.f90 index b4f0922b..4efc1d55 100644 --- a/route/build/src/mpi_process.f90 +++ b/route/build/src/mpi_process.f90 @@ -712,11 +712,17 @@ subroutine mpi_route(pid, & ! input: proc id USE globalData, ONLY: river_basin_trib ! tributary OMP domain data structure USE globalData, ONLY: river_basin_main ! mainstem OMP domain data structure USE globalData, ONLY: nRch_mainstem ! number of mainstem reaches + USE globalData, ONLY: flux_wm_main ! nRch flux holder for mainstem + USE globalData, ONLY: flux_wm_trib ! nRch flux holder for tributary + USE globalData, ONLY: vol_wm_main ! nRch target vol holder for mainstem + USE globalData, ONLY: vol_wm_trib ! nRch target vol holder for tributary USE globalData, ONLY: rch_per_proc ! number of reaches assigned to each proc USE globalData, ONLY: tribOutlet_per_proc ! number of tributary outlets per proc (array size = nNodes) USE globalData, ONLY: global_ix_main ! reach index at tributary reach outlets to mainstem (size = sum of tributary outlets in all the procs) USE globalData, ONLY: local_ix_comm ! local reach index at tributary reach outlets to mainstem for each proc (size = sum of tributary outlets in proc) USE public_var, ONLY: is_lake_sim ! logical whether or not lake should be simulated + USE public_var, ONLY: is_flux_wm ! logical whether or not fluxes should be passed + USE public_var, ONLY: is_vol_wm ! logical whether or not target volume should be passed ! routing driver USE main_route_module, ONLY: main_route ! routing driver @@ -758,6 +764,10 @@ subroutine mpi_route(pid, & ! input: proc id ! and precipitation array to local runoff arrays ! - basinRunoff_main (only at master proc) ! - basinRunoff_trib (all procs) + ! - basinEvapo_main (only at master proc) + ! - basinEvapo_trib (all procs) + ! - basinPrecip_main (only at master proc) + ! - basinPrecip_trib (all procs) ! -------------------------------- if (doesScatterRunoff) then @@ -791,25 +801,23 @@ subroutine mpi_route(pid, & ! input: proc id if (nHRU_mainstem > 0 .and. .not.allocated(basinRunoff_main)) then ierr=10; message=trim(message)//'mainstem runoff array is not allocated/populated'; return end if - if (is_lake_sim) then - if (nHRU_mainstem > 0 .and. .not.allocated(basinEvapo_main)) then - ierr=10; message=trim(message)//'mainstem evaporation array is not allocated/populated'; return - end if - if (nHRU_mainstem > 0 .and. .not.allocated(basinPrecip_main)) then - ierr=10; message=trim(message)//'mainstem precipitation array is not allocated/populated'; return - end if - end if - if (.not.allocated(basinRunoff_trib)) then ierr=10; message=trim(message)//'master proc: tributary runoff array is not allocated'; return end if + if (is_lake_sim) then + if (nHRU_mainstem > 0 .and. .not.allocated(basinEvapo_main)) then + ierr=10; message=trim(message)//'mainstem evaporation array is not allocated/populated'; return + end if if (.not.allocated(basinEvapo_trib)) then ierr=10; message=trim(message)//'master proc: tributary evaporation array is not allocated'; return end if if (.not.allocated(basinPrecip_trib)) then ierr=10; message=trim(message)//'master proc: tributary precipitation array is not allocated'; return end if + if (nHRU_mainstem > 0 .and. .not.allocated(basinPrecip_main)) then + ierr=10; message=trim(message)//'mainstem precipitation array is not allocated/populated'; return + end if end if else @@ -830,6 +838,86 @@ subroutine mpi_route(pid, & ! input: proc id end if end if + + ! -------------------------------- + ! distribute (scatter) water managemnt flux and + ! volume in the + ! - flux_wm_main (only at master proc) + ! - flux_wm_trib (all procs) + ! - vol_wm_main (only at master proc) + ! - vol_wm_trib (all procs) + ! -------------------------------- + + if (is_flux_wm.or.is_vol_wm) then + + if (doesScatterRunoff) then + + call t_startf ('route/scatter-wm') + call scatter_wm(nNodes, comm, ierr, cmessage) + if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif + call t_stopf ('route/scatter-wm') + + else + + if (nNodes==1) then + + if (is_flux_wm) then + if (.not.allocated(flux_wm_main)) then + ierr=10; message=trim(message)//'master proc: mainstem water management flux array is not allocated'; return + end if + end if + if (is_vol_wm) then + if (.not.allocated(vol_wm_main)) then + ierr=10; message=trim(message)//'master proc: mainstem target volume array (for lakes) is not allocated'; return + end if + end if + + else + + if (masterproc) then + + write(iulog,*) 'NOTE: reach flux and target volume are already decomposed into mainstems and tributaries. No need for scatter_wm' + + if (is_flux_wm) then + if (nRch_mainstem > 0 .and. .not.allocated(flux_wm_main)) then + ierr=10; message=trim(message)//'mainstem water management flux array is not allocated/populated'; return + end if + if (.not.allocated(flux_wm_trib)) then + ierr=10; message=trim(message)//'master proc: tributary water management flux array is not allocated'; return + end if + end if + + if (is_vol_wm) then + if (nRch_mainstem > 0 .and. .not.allocated(vol_wm_main)) then + ierr=10; message=trim(message)//'mainstem target volume array (for lakes) is not allocated/populated'; return + end if + if (.not.allocated(vol_wm_trib)) then + ierr=10; message=trim(message)//'master proc: tributary target volume array (for lakes) is not allocated'; return + end if + end if + + + else + + if (is_flux_wm) then + if(.not.allocated(flux_wm_trib)) then + ierr=10; message=trim(message)//'tributary water management fluxes array is not allocated/populated'; return + end if + end if + + if (is_vol_wm) then + if(.not.allocated(vol_wm_trib)) then + ierr=10; message=trim(message)//'tributary target volume array (for lakes) is not allocated/populated'; return + end if + end if + + end if + end if + end if + + end if + + ! -------------------------------- ! Perform tributary routing (for all procs) ! -------------------------------- From 085e2d84c75c66cb9736cf3ca9d0ff27d2e88d9b Mon Sep 17 00:00:00 2001 From: ShervanGharari Date: Wed, 26 Aug 2020 15:06:56 -0400 Subject: [PATCH 21/29] the scattered flux and target volumes are passed to main_route.f90 and main_route subroutine --- route/build/src/main_route.f90 | 4 ++++ route/build/src/mpi_process.f90 | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/route/build/src/main_route.f90 b/route/build/src/main_route.f90 index 54614c94..9cb829d6 100644 --- a/route/build/src/main_route.f90 +++ b/route/build/src/main_route.f90 @@ -40,6 +40,8 @@ SUBROUTINE main_route(& basinRunoff_in, & ! basin (i.e.,HRU) runoff (m/s) basinEvapo_in, & ! basin (i.e.,HRU) evaporation (m/s) basinPrecip_in, & ! basin (i.e.,HRU) precipitation (m/s) + reachflux_in, & ! reach (i.e.,reach) flux (m3/s) + reachvol_in, & ! reach (i.e.,reach) target volume for lakes (m3) ixRchProcessed, & ! indices of reach to be routed river_basin, & ! OMP basin decomposition NETOPO_in, & ! reach topology data structure @@ -75,6 +77,8 @@ SUBROUTINE main_route(& real(dp), allocatable, intent(in) :: basinRunoff_in(:) ! basin (i.e.,HRU) runoff (m/s) real(dp), allocatable, intent(in) :: basinEvapo_in(:) ! basin (i.e.,HRU) evaporation (m/s) real(dp), allocatable, intent(in) :: basinPrecip_in(:) ! basin (i.e.,HRU) precipitation (m/s) + real(dp), allocatable, intent(in) :: reachflux_in(:) ! reach (i.e.,reach) flux (m3/s) + real(dp), allocatable, intent(in) :: reachvol_in(:) ! reach (i.e.,reach) target volume for lakes (m3) integer(i4b), allocatable, intent(in) :: ixRchProcessed(:) ! indices of reach to be routed type(subbasin_omp), allocatable, intent(in) :: river_basin(:) ! OMP basin decomposition type(RCHTOPO), allocatable, intent(in) :: NETOPO_in(:) ! River Network topology diff --git a/route/build/src/mpi_process.f90 b/route/build/src/mpi_process.f90 index 4efc1d55..d6e5ea10 100644 --- a/route/build/src/mpi_process.f90 +++ b/route/build/src/mpi_process.f90 @@ -938,6 +938,8 @@ subroutine mpi_route(pid, & ! input: proc id basinRunoff_trib, & ! input: basin (i.e.,HRU) runoff (m/s) basinEvapo_trib, & ! input: basin (i.e. HRU) Evapo (m/s) basinPrecip_trib, & ! input: basin (i.e. HRU) Precip (m/s) + flux_wm_trib, & ! reach (i.e.,reach) flux (m3/s) + vol_wm_trib, & ! reach (i.e.,reach) target volume for lakes (m3) ixRchProcessed, & ! input: indices of reach to be routed river_basin_trib, & ! input: OMP basin decomposition NETOPO_trib, & ! input: reach topology data structure @@ -1016,6 +1018,8 @@ subroutine mpi_route(pid, & ! input: proc id basinRunoff_main, & ! input: basin (i.e.,HRU) runoff (m/s) basinEvapo_main, & ! input: basin (i.e. HRU) Evapo (m/s) basinPrecip_main, & ! input: basin (i.e. HRU) Precip (m/s) + flux_wm_main, & ! reach (i.e.,reach) flux (m3/s) + vol_wm_main, & ! reach (i.e.,reach) target volume for lakes (m3) ixRchProcessed, & ! input: indices of reach to be routed river_basin_main, & ! input: OMP basin decomposition NETOPO_main, & ! input: reach topology data structure From b7784958f73d7a526d2e58f1de3866f9840bbbe5 Mon Sep 17 00:00:00 2001 From: ShervanGharari Date: Wed, 26 Aug 2020 15:31:02 -0400 Subject: [PATCH 22/29] passing and allocating the flux and target volume to the RCHFLX_OUT in main_route --- route/build/src/dataTypes.f90 | 2 ++ route/build/src/main_route.f90 | 14 ++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/route/build/src/dataTypes.f90 b/route/build/src/dataTypes.f90 index df690695..c96630db 100644 --- a/route/build/src/dataTypes.f90 +++ b/route/build/src/dataTypes.f90 @@ -277,6 +277,8 @@ MODULE dataTypes real(dp) :: REACH_Q_IRF ! time-step average streamflow (m3/s) from IRF routing real(dp) :: UPSTREAM_QI ! sum of upstream streamflow (m3/s) real(dp) :: REACH_VOL(0:1) ! volume of water at previous and current time step [m3] + real(dp) :: REACH_WM_FLUX ! water management fluxes to and from each reach + real(dp) :: REACH_WM_VOL ! target volume from the second water management file (m3) real(dp) :: TAKE ! average take logical(lgt) :: isRoute ! .true. if the reach is routed END TYPE strflx diff --git a/route/build/src/main_route.f90 b/route/build/src/main_route.f90 index 9cb829d6..0c92d058 100644 --- a/route/build/src/main_route.f90 +++ b/route/build/src/main_route.f90 @@ -69,6 +69,8 @@ SUBROUTINE main_route(& USE public_var, ONLY: impulseResponseFunc USE globalData, ONLY: TSEC ! beginning/ending of simulation time step [sec] USE public_var, ONLY: is_lake_sim ! logical whether or not lake should be simulated + USE public_var, ONLY: is_flux_wm ! logical whether or not fluxes should be passed + USE public_var, ONLY: is_vol_wm ! logical whether or not target volume should be passed implicit none @@ -111,6 +113,18 @@ SUBROUTINE main_route(& allocate(reachRunoff_local(nSeg), stat=ierr) if(ierr/=0)then; message=trim(message)//'problem allocating arrays for [reachRunoff_local]'; return; endif + ! passing of the water management fluxes and lake target vol if presence + if (is_flux_wm) then + do iSeg = 1,nSeg + RCHFLX_out(iens,ixRchProcessed(iSeg))%REACH_WM_FLUX = reachflux_in(iSeg) ! added or subtracted stremflow for each reach + end do + end if + if (is_vol_wm) then + do iSeg = 1,nSeg + RCHFLX_out(iens,ixRchProcessed(iSeg))%REACH_WM_VOL = reachvol_in(iSeg) ! target volume for the lakes + end do + end if + ! 1. subroutine: map basin runoff to river network HRUs ! map the basin runoff to the stream network... call basin2reach(basinRunoff_in, & ! input: basin runoff (m/s) From c53633615bd5b220755134efe5f942fff01627f8 Mon Sep 17 00:00:00 2001 From: ShervanGharari Date: Mon, 31 Aug 2020 22:36:45 -0400 Subject: [PATCH 23/29] small change of nTime to nTime_wm in model setup also print statements int irf route and get basin runoff --- route/build/src/irf_route.f90 | 3 +++ route/build/src/main_route.f90 | 2 +- route/build/src/mpi_process.f90 | 15 ++++++++------- route/build/src/standalone/get_basin_runoff.f90 | 8 ++++++-- route/build/src/standalone/model_setup.f90 | 7 ++++--- 5 files changed, 22 insertions(+), 13 deletions(-) diff --git a/route/build/src/irf_route.f90 b/route/build/src/irf_route.f90 index ed285626..7a1aa3c2 100644 --- a/route/build/src/irf_route.f90 +++ b/route/build/src/irf_route.f90 @@ -190,6 +190,9 @@ subroutine segment_irf(& RCHFLX_out(iens,segIndex)%BASIN_QR(1),RCHFLX_out(iens,segIndex)%REACH_Q_IRF endif + ! print statement to compare the computed REACH_Q_IRF and water management abstraction/injection + print*, RCHFLX_out(iens,segIndex)%REACH_Q_IRF, RCHFLX_out(iens,segIndex)%REACH_WM_FLUX + end subroutine segment_irf diff --git a/route/build/src/main_route.f90 b/route/build/src/main_route.f90 index 0c92d058..0ae10c76 100644 --- a/route/build/src/main_route.f90 +++ b/route/build/src/main_route.f90 @@ -119,7 +119,7 @@ SUBROUTINE main_route(& RCHFLX_out(iens,ixRchProcessed(iSeg))%REACH_WM_FLUX = reachflux_in(iSeg) ! added or subtracted stremflow for each reach end do end if - if (is_vol_wm) then + if (is_vol_wm.and.is_lake_sim) then do iSeg = 1,nSeg RCHFLX_out(iens,ixRchProcessed(iSeg))%REACH_WM_VOL = reachvol_in(iSeg) ! target volume for the lakes end do diff --git a/route/build/src/mpi_process.f90 b/route/build/src/mpi_process.f90 index d6e5ea10..05eba70d 100644 --- a/route/build/src/mpi_process.f90 +++ b/route/build/src/mpi_process.f90 @@ -848,7 +848,7 @@ subroutine mpi_route(pid, & ! input: proc id ! - vol_wm_trib (all procs) ! -------------------------------- - if (is_flux_wm.or.is_vol_wm) then + if (is_flux_wm.or.(is_vol_wm.and.is_lake_sim)) then if (doesScatterRunoff) then @@ -866,7 +866,7 @@ subroutine mpi_route(pid, & ! input: proc id ierr=10; message=trim(message)//'master proc: mainstem water management flux array is not allocated'; return end if end if - if (is_vol_wm) then + if (is_vol_wm.and.is_lake_sim) then if (.not.allocated(vol_wm_main)) then ierr=10; message=trim(message)//'master proc: mainstem target volume array (for lakes) is not allocated'; return end if @@ -887,7 +887,7 @@ subroutine mpi_route(pid, & ! input: proc id end if end if - if (is_vol_wm) then + if (is_vol_wm.and.is_lake_sim) then if (nRch_mainstem > 0 .and. .not.allocated(vol_wm_main)) then ierr=10; message=trim(message)//'mainstem target volume array (for lakes) is not allocated/populated'; return end if @@ -905,7 +905,7 @@ subroutine mpi_route(pid, & ! input: proc id end if end if - if (is_vol_wm) then + if (is_vol_wm.and.is_lake_sim) then if(.not.allocated(vol_wm_trib)) then ierr=10; message=trim(message)//'tributary target volume array (for lakes) is not allocated/populated'; return end if @@ -1211,6 +1211,7 @@ SUBROUTINE scatter_wm(nNodes, comm, & ! mpi variables: number nodes, communic USE globalData, ONLY: flux_wm_trib ! nRch flux holder for tributary USE globalData, ONLY: vol_wm_main ! nRch target vol holder for mainstem USE globalData, ONLY: vol_wm_trib ! nRch target vol holder for tributary + USE public_var, ONLY: is_lake_sim ! logical whether or not fluxes should be passed USE public_var, ONLY: is_flux_wm ! logical whether or not fluxes should be passed USE public_var, ONLY: is_vol_wm ! logical whether or not target volume should be passed @@ -1241,7 +1242,7 @@ SUBROUTINE scatter_wm(nNodes, comm, & ! mpi variables: number nodes, communic endif - if (is_vol_wm) then + if (is_vol_wm.and.is_lake_sim) then ! if only single proc is used, all target volumes are stored in mainstem runoff array if (.not. allocated(vol_wm_main)) then @@ -1267,7 +1268,7 @@ SUBROUTINE scatter_wm(nNodes, comm, & ! mpi variables: number nodes, communic flux_wm_main(1:nRch_mainstem) = Rch_flux_local(1:nRch_mainstem) endif - if (is_vol_wm) then + if (is_vol_wm.and.is_lake_sim) then if (.not. allocated(vol_wm_main)) then allocate(vol_wm_main(nRch_mainstem), stat=ierr) if(ierr/=0)then; message=trim(message)//'problem allocating array for [vol_wm_main]'; return; endif @@ -1290,7 +1291,7 @@ SUBROUTINE scatter_wm(nNodes, comm, & ! mpi variables: number nodes, communic if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif endif - if (is_vol_wm) then + if (is_vol_wm.and.is_lake_sim) then call shr_mpi_scatterV(Rch_vol_local(nRch_mainstem+1:nRch), & rch_per_proc(0:nNodes-1), & vol_wm_trib, & diff --git a/route/build/src/standalone/get_basin_runoff.f90 b/route/build/src/standalone/get_basin_runoff.f90 index 65a7bb5e..f9f18d5c 100644 --- a/route/build/src/standalone/get_basin_runoff.f90 +++ b/route/build/src/standalone/get_basin_runoff.f90 @@ -209,6 +209,9 @@ SUBROUTINE get_hru_runoff(ierr, message) ! output: error control if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif end if + ! print statemenets + print*, wm_data%flux_wm + END SUBROUTINE get_hru_runoff @@ -220,6 +223,7 @@ SUBROUTINE infile_name(ierr, message) ! output ! Shared data USE public_var, ONLY: fname_qsim ! simulated runoff netCDF name USE public_var, ONLY: fname_wm ! water management netCDF name + USE public_var, ONLY: is_lake_sim ! logical whether or not abstraction or injection should be read USE public_var, ONLY: is_flux_wm ! logical whether or not abstraction or injection should be read USE public_var, ONLY: is_vol_wm ! logical whether or not target volume should be read USE globalData, ONLY: iTime ! time index at simulation time step @@ -249,7 +253,7 @@ SUBROUTINE infile_name(ierr, message) ! output enddo ixloop ! fast forward time to time index at simStart and save iTime and modJulday for water management nc file - if ((is_flux_wm).or.(is_vol_wm)) then + if ((is_flux_wm).or.(is_vol_wm.and.is_lake_sim)) then iyloop: do ix = 1, size(infileinfo_data_wm) !loop over number of file if ((iTime >= infileinfo_data_wm(ix)%iTimebound(1)).and.(iTime <= infileinfo_data_wm(ix)%iTimebound(2))) then iTime_local_wm = iTime - infileinfo_data_wm(ix)%iTimebound(1) + 1 @@ -261,7 +265,7 @@ SUBROUTINE infile_name(ierr, message) ! output endif ! check if the two files are identified in case is flux and vol flags are set to true - if ((wm_not_read_flag).and.((is_flux_wm).or.(is_vol_wm))) then + if ((wm_not_read_flag).and.((is_flux_wm).or.(is_vol_wm.and.is_lake_sim))) then ierr=20; message=trim(message)//'iTime local is out of bound for the water management netcdf file inputs based on given simulation date and time in control file'; return ; endif diff --git a/route/build/src/standalone/model_setup.f90 b/route/build/src/standalone/model_setup.f90 index 24e6f420..9bae0aa5 100644 --- a/route/build/src/standalone/model_setup.f90 +++ b/route/build/src/standalone/model_setup.f90 @@ -151,7 +151,7 @@ SUBROUTINE init_inFile_pop (ierr, message) ! output ! passing the first nc file as global file name to read fname_qsim = trim(infileinfo_data(1)%infilename) - if ((is_flux_wm).or.(is_vol_wm)) then ! if either of abstraction injection or target volume is activated + if ((is_flux_wm).or.(is_vol_wm.and.is_lake_sim)) then ! if either of abstraction injection or target volume is activated call inFile_pop(input_dir, & ! input: name of the directory of the txt file fname_wm, & ! input: name of the txt file hold the nc file names vname_time_wm, & ! input: name of variable time in the nc files @@ -429,6 +429,7 @@ SUBROUTINE init_time(ierr, message) ! output USE globalData, ONLY: dropCal ! restart dropoff calendar date/time USE globalData, ONLY: infileinfo_data ! the information of the input files USE globalData, ONLY: infileinfo_data_wm ! the information of the input files + USE public_var, ONLY: is_lake_sim ! logical whether or not lake simulations are activated USE public_var, ONLY: is_flux_wm ! logical whether or not abstraction and injection should be read from the file USE public_var, ONLY: is_vol_wm ! logical whether or not target volume for lakes should be read @@ -560,7 +561,7 @@ SUBROUTINE init_time(ierr, message) ! output modTime(0) = time(integerMissing, integerMissing, integerMissing, integerMissing, integerMissing, realMissing) ! if one of the two flags are set it true - if ((is_flux_wm).or.(is_vol_wm)) then + if ((is_flux_wm).or.(is_vol_wm.and.is_lake_sim)) then ! get the number of the total time length of all the water management nc files nFile_wm = size(infileinfo_data_wm) @@ -600,7 +601,7 @@ SUBROUTINE init_time(ierr, message) ! output allocate(roJulday_diff_wm(nTime_wm-1), stat=ierr) if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif ! calculate the difference of consequative time in julian day - roJulday_diff_wm = roJulday_wm (1:nTime-1) - roJulday_wm (2:nTime) + roJulday_diff_wm = roJulday_wm (1:nTime_wm-1) - roJulday_wm (2:nTime_wm) ! check if the difference are identical otherwise error and terminate do counter = 1, nTime_wm-2 if ((abs(roJulday_diff_wm(counter)-roJulday_diff_wm(counter+1)))>verySmall) then From 15bd6d3eefffbae82544eb730164861cc022cfb0 Mon Sep 17 00:00:00 2001 From: ShervanGharari Date: Mon, 31 Aug 2020 23:28:40 -0400 Subject: [PATCH 24/29] minor changed, commenting the print statments in irt_rote --- route/build/src/irf_route.f90 | 2 +- route/build/src/standalone/get_basin_runoff.f90 | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/route/build/src/irf_route.f90 b/route/build/src/irf_route.f90 index 7a1aa3c2..c8d28d69 100644 --- a/route/build/src/irf_route.f90 +++ b/route/build/src/irf_route.f90 @@ -191,7 +191,7 @@ subroutine segment_irf(& endif ! print statement to compare the computed REACH_Q_IRF and water management abstraction/injection - print*, RCHFLX_out(iens,segIndex)%REACH_Q_IRF, RCHFLX_out(iens,segIndex)%REACH_WM_FLUX + ! print*, RCHFLX_out(iens,segIndex)%REACH_Q_IRF, RCHFLX_out(iens,segIndex)%REACH_WM_FLUX end subroutine segment_irf diff --git a/route/build/src/standalone/get_basin_runoff.f90 b/route/build/src/standalone/get_basin_runoff.f90 index f9f18d5c..99ef18a2 100644 --- a/route/build/src/standalone/get_basin_runoff.f90 +++ b/route/build/src/standalone/get_basin_runoff.f90 @@ -209,9 +209,6 @@ SUBROUTINE get_hru_runoff(ierr, message) ! output: error control if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif end if - ! print statemenets - print*, wm_data%flux_wm - END SUBROUTINE get_hru_runoff From dd07ebd298af8e618be04232494c3ba55fa4d95e Mon Sep 17 00:00:00 2001 From: ShervanGharari Date: Tue, 1 Sep 2020 15:06:37 -0400 Subject: [PATCH 25/29] print statements are added --- route/build/src/irf_route.f90 | 2 +- route/build/src/standalone/get_basin_runoff.f90 | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/route/build/src/irf_route.f90 b/route/build/src/irf_route.f90 index c8d28d69..052dd3bf 100644 --- a/route/build/src/irf_route.f90 +++ b/route/build/src/irf_route.f90 @@ -191,7 +191,7 @@ subroutine segment_irf(& endif ! print statement to compare the computed REACH_Q_IRF and water management abstraction/injection - ! print*, RCHFLX_out(iens,segIndex)%REACH_Q_IRF, RCHFLX_out(iens,segIndex)%REACH_WM_FLUX + print*, NETOPO_in(segIndex)%REACHID, RCHFLX_out(iens,segIndex)%REACH_Q_IRF, RCHFLX_out(iens,segIndex)%REACH_WM_FLUX end subroutine segment_irf diff --git a/route/build/src/standalone/get_basin_runoff.f90 b/route/build/src/standalone/get_basin_runoff.f90 index 99ef18a2..0f8d0fef 100644 --- a/route/build/src/standalone/get_basin_runoff.f90 +++ b/route/build/src/standalone/get_basin_runoff.f90 @@ -209,6 +209,8 @@ SUBROUTINE get_hru_runoff(ierr, message) ! output: error control if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif end if + print*, wm_data%flux_wm + END SUBROUTINE get_hru_runoff From 21f1f11064010d3bee956916cfd01b5a844844a9 Mon Sep 17 00:00:00 2001 From: ShervanGharari Date: Tue, 20 Oct 2020 19:06:32 -0400 Subject: [PATCH 26/29] the abstraction or injection to the river segment is added to irf; at this moment the is not abstraction or injection or target volume to the lake as there is no lake module --- route/build/src/irf_route.f90 | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/route/build/src/irf_route.f90 b/route/build/src/irf_route.f90 index 052dd3bf..71fd9ce6 100644 --- a/route/build/src/irf_route.f90 +++ b/route/build/src/irf_route.f90 @@ -3,14 +3,14 @@ MODULE irf_route_module !numeric type USE nrtype ! data type -USE dataTypes, ONLY: STRFLX ! fluxes in each reach -USE dataTypes, ONLY: RCHTOPO ! Network topology +USE dataTypes, ONLY: STRFLX ! fluxes in each reach +USE dataTypes, ONLY: RCHTOPO ! Network topology ! global parameters -USE public_var, ONLY: iulog ! i/o logical unit number -USE public_var, ONLY: realMissing ! missing value for real number -USE public_var, ONLY: integerMissing ! missing value for integer number +USE public_var, ONLY: iulog ! i/o logical unit number +USE public_var, ONLY: realMissing ! missing value for real number +USE public_var, ONLY: integerMissing ! missing value for integer number ! subroutines: general -USE perf_mod, ONLY: t_startf,t_stopf ! timing start/stop +USE perf_mod, ONLY: t_startf,t_stopf ! timing start/stop ! privary implicit none @@ -128,6 +128,8 @@ subroutine segment_irf(& ! output ierr, message) ! output: error control + ! shared data + USE public_var, ONLY:is_flux_wm ! logical water management components fluxes should be read implicit none ! Input INTEGER(I4B), intent(IN) :: iEns ! runoff ensemble to be routed @@ -141,6 +143,7 @@ subroutine segment_irf(& character(*), intent(out) :: message ! error message ! Local variables to type(STRFLX), allocatable :: uprflux(:) ! upstream Reach fluxes + real(dp) :: abstract_actual! actual abstraction INTEGER(I4B) :: nUps ! number of upstream segment INTEGER(I4B) :: iUps ! upstream reach index INTEGER(I4B) :: iRch_ups ! index of upstream reach in NETOPO @@ -191,7 +194,22 @@ subroutine segment_irf(& endif ! print statement to compare the computed REACH_Q_IRF and water management abstraction/injection - print*, NETOPO_in(segIndex)%REACHID, RCHFLX_out(iens,segIndex)%REACH_Q_IRF, RCHFLX_out(iens,segIndex)%REACH_WM_FLUX + ! print*, NETOPO_in(segIndex)%REACHID, RCHFLX_out(iens,segIndex)%REACH_Q_IRF, RCHFLX_out(iens,segIndex)%REACH_WM_FLUX + + ! take out the water from the reach if the wm flag is true and the value are not missing + ! here we should make sure the real missing is not injection (or negative abstration) + if((RCHFLX_out(iens,segIndex)%REACH_WM_FLUX /= realMissing).and.(is_flux_wm)) then + abstract_actual = RCHFLX_out(iens,segIndex)%REACH_Q_IRF ! get the reach streamflow as actual abstration + ! reach streamflow is updated based on abstration (positive) or injection (negative) + RCHFLX_out(iens,segIndex)%REACH_Q_IRF = RCHFLX_out(iens,segIndex)%REACH_Q_IRF - RCHFLX_out(iens,segIndex)%REACH_WM_FLUX + if (RCHFLX_out(iens,segIndex)%REACH_Q_IRF>0) then ! abstration was negative or smaller than reach streamflow + abstract_actual = RCHFLX_out(iens,segIndex)%REACH_WM_FLUX ! actual abstration will be equal to abstration value + else + RCHFLX_out(iens,segIndex)%REACH_Q_IRF = 0._dp ! all the water is taken and actual abstration is reach streamflow + endif + endif + + print*, NETOPO_in(segIndex)%REACHID, RCHFLX_out(iens,segIndex)%REACH_Q_IRF, RCHFLX_out(iens,segIndex)%REACH_WM_FLUX, abstract_actual end subroutine segment_irf From f0261d8626dd81fcd6bc4e2e49db00d61c1bcdd4 Mon Sep 17 00:00:00 2001 From: ShervanGharari Date: Tue, 20 Oct 2020 20:05:27 -0400 Subject: [PATCH 27/29] water balance is caluclated for each reach, so the inital streamflow, the streamflow after abstration and actual abstration are compared to give a sum of zero --- route/build/src/irf_route.f90 | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/route/build/src/irf_route.f90 b/route/build/src/irf_route.f90 index 71fd9ce6..34b5e72c 100644 --- a/route/build/src/irf_route.f90 +++ b/route/build/src/irf_route.f90 @@ -143,7 +143,9 @@ subroutine segment_irf(& character(*), intent(out) :: message ! error message ! Local variables to type(STRFLX), allocatable :: uprflux(:) ! upstream Reach fluxes - real(dp) :: abstract_actual! actual abstraction + real(dp) :: abstract_actual! actual abstraction TO BE DELETED + real(dp) :: WB_check ! water balance TO BE DELETED + real(dp) :: init_STRQ ! init TO BE DELETED INTEGER(I4B) :: nUps ! number of upstream segment INTEGER(I4B) :: iUps ! upstream reach index INTEGER(I4B) :: iRch_ups ! index of upstream reach in NETOPO @@ -200,6 +202,7 @@ subroutine segment_irf(& ! here we should make sure the real missing is not injection (or negative abstration) if((RCHFLX_out(iens,segIndex)%REACH_WM_FLUX /= realMissing).and.(is_flux_wm)) then abstract_actual = RCHFLX_out(iens,segIndex)%REACH_Q_IRF ! get the reach streamflow as actual abstration + init_STRQ = RCHFLX_out(iens,segIndex)%REACH_Q_IRF ! TO BE DELETED ! reach streamflow is updated based on abstration (positive) or injection (negative) RCHFLX_out(iens,segIndex)%REACH_Q_IRF = RCHFLX_out(iens,segIndex)%REACH_Q_IRF - RCHFLX_out(iens,segIndex)%REACH_WM_FLUX if (RCHFLX_out(iens,segIndex)%REACH_Q_IRF>0) then ! abstration was negative or smaller than reach streamflow @@ -209,7 +212,9 @@ subroutine segment_irf(& endif endif - print*, NETOPO_in(segIndex)%REACHID, RCHFLX_out(iens,segIndex)%REACH_Q_IRF, RCHFLX_out(iens,segIndex)%REACH_WM_FLUX, abstract_actual + WB_check = RCHFLX_out(iens,segIndex)%REACH_Q_IRF + abstract_actual - init_STRQ + + print*, NETOPO_in(segIndex)%REACHID, RCHFLX_out(iens,segIndex)%REACH_Q_IRF, RCHFLX_out(iens,segIndex)%REACH_WM_FLUX, abstract_actual, WB_check end subroutine segment_irf From 3fb60396685f2c06c1269eade1af2f3bb739734e Mon Sep 17 00:00:00 2001 From: ShervanGharari Date: Thu, 22 Oct 2020 23:56:49 -0400 Subject: [PATCH 28/29] the commnets where fixed --- route/build/src/irf_route.f90 | 20 +++++++++----------- route/build/src/read_control.f90 | 2 +- route/build/src/standalone/model_setup.f90 | 2 +- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/route/build/src/irf_route.f90 b/route/build/src/irf_route.f90 index 34b5e72c..0ef355a3 100644 --- a/route/build/src/irf_route.f90 +++ b/route/build/src/irf_route.f90 @@ -201,21 +201,19 @@ subroutine segment_irf(& ! take out the water from the reach if the wm flag is true and the value are not missing ! here we should make sure the real missing is not injection (or negative abstration) if((RCHFLX_out(iens,segIndex)%REACH_WM_FLUX /= realMissing).and.(is_flux_wm)) then - abstract_actual = RCHFLX_out(iens,segIndex)%REACH_Q_IRF ! get the reach streamflow as actual abstration - init_STRQ = RCHFLX_out(iens,segIndex)%REACH_Q_IRF ! TO BE DELETED - ! reach streamflow is updated based on abstration (positive) or injection (negative) - RCHFLX_out(iens,segIndex)%REACH_Q_IRF = RCHFLX_out(iens,segIndex)%REACH_Q_IRF - RCHFLX_out(iens,segIndex)%REACH_WM_FLUX - if (RCHFLX_out(iens,segIndex)%REACH_Q_IRF>0) then ! abstration was negative or smaller than reach streamflow - abstract_actual = RCHFLX_out(iens,segIndex)%REACH_WM_FLUX ! actual abstration will be equal to abstration value - else - RCHFLX_out(iens,segIndex)%REACH_Q_IRF = 0._dp ! all the water is taken and actual abstration is reach streamflow - endif + abstract_actual = RCHFLX_out(iens,segIndex)%REACH_Q_IRF ! get the reach streamflow as actual abstration + init_STRQ = RCHFLX_out(iens,segIndex)%REACH_Q_IRF ! TO BE DELETED + ! reach streamflow is updated based on abstration (positive) or injection (negative) + RCHFLX_out(iens,segIndex)%REACH_Q_IRF = RCHFLX_out(iens,segIndex)%REACH_Q_IRF - RCHFLX_out(iens,segIndex)%REACH_WM_FLUX + if (RCHFLX_out(iens,segIndex)%REACH_Q_IRF>0) then ! abstration was negative or smaller than reach streamflow + abstract_actual = RCHFLX_out(iens,segIndex)%REACH_WM_FLUX ! actual abstration will be equal to abstration value + else + RCHFLX_out(iens,segIndex)%REACH_Q_IRF = 0._dp ! all the water is taken and actual abstration is reach streamflow + endif endif WB_check = RCHFLX_out(iens,segIndex)%REACH_Q_IRF + abstract_actual - init_STRQ - print*, NETOPO_in(segIndex)%REACHID, RCHFLX_out(iens,segIndex)%REACH_Q_IRF, RCHFLX_out(iens,segIndex)%REACH_WM_FLUX, abstract_actual, WB_check - end subroutine segment_irf diff --git a/route/build/src/read_control.f90 b/route/build/src/read_control.f90 index 20880731..aa6719f9 100644 --- a/route/build/src/read_control.f90 +++ b/route/build/src/read_control.f90 @@ -124,7 +124,7 @@ SUBROUTINE read_control(ctl_fname, err, message) case(''); dname_nhru = trim(cData) ! dimension name of the HRUs case(''); dname_sseg = trim(cData) ! dimension name of the stream segments ! RUNOFF, EVAPORATION AND PRECIPITATION FILE - case(''); fname_qsim = trim(cData) ! name of text file containing ordered nc file names + case(''); fname_qsim = trim(cData) ! name of text file listing netcdf names. netCDF include runoff, evaporation and precipitation varialbes case(''); vname_qsim = trim(cData) ! name of runoff variable case(''); vname_evapo = trim(cData) ! name of actual evapoartion variable case(''); vname_precip = trim(cData) ! name of precipitation variable diff --git a/route/build/src/standalone/model_setup.f90 b/route/build/src/standalone/model_setup.f90 index 9bae0aa5..64b6111e 100644 --- a/route/build/src/standalone/model_setup.f90 +++ b/route/build/src/standalone/model_setup.f90 @@ -355,7 +355,7 @@ SUBROUTINE inFile_sync_time(inputfileinfo, & ! input: the structure of simu ! initialize error control - ierr=0; message='inFile_corr_time/' + ierr=0; message='inFile_sync_time/' ! set the reference julday based on the first nc file of simulation refJulday_local = inputfileinfo(1)%ncrefjulday From a06954b21bb10da75376f3c1cf7b84613f01c1ae Mon Sep 17 00:00:00 2001 From: ShervanGharari Date: Thu, 22 Oct 2020 23:58:47 -0400 Subject: [PATCH 29/29] print statement is removed --- route/build/src/standalone/get_basin_runoff.f90 | 2 -- 1 file changed, 2 deletions(-) diff --git a/route/build/src/standalone/get_basin_runoff.f90 b/route/build/src/standalone/get_basin_runoff.f90 index 0f8d0fef..99ef18a2 100644 --- a/route/build/src/standalone/get_basin_runoff.f90 +++ b/route/build/src/standalone/get_basin_runoff.f90 @@ -209,8 +209,6 @@ SUBROUTINE get_hru_runoff(ierr, message) ! output: error control if(ierr/=0)then; message=trim(message)//trim(cmessage); return; endif end if - print*, wm_data%flux_wm - END SUBROUTINE get_hru_runoff