MODFLOW 6  version 6.8.0.dev0
USGS Modular Hydrologic Model
gwf-sfr.f90
Go to the documentation of this file.
1 !> @brief This module contains the SFR package methods
2 !!
3 !! This module contains the overridden methods for the streamflow routing (SFR)
4 !! package. Most of the methods in the base Boundary Package are overridden.
5 !!
6 !<
7 module sfrmodule
8  !
9  use kindmodule, only: dp, i4b, lgp
11  maxadpit, &
12  dzero, dprec, dem30, dem6, dem5, dem4, dem2, &
14  dp9, dp99, dp999, &
16  dhundred, dep20, &
19  lenbudtxt, &
20  dhnoflo, dhdry, dnodata, &
22  mnormal
27  use bndmodule, only: bndtype
29  use tablemodule, only: tabletype, table_cr
30  use observemodule, only: observetype
32  use basedismodule, only: disbasetype
41  use dag_module, only: dag
43  !
44  implicit none
45  !
46  character(len=LENFTYPE) :: ftype = 'SFR' !< package ftype string
47  character(len=LENPACKAGENAME) :: text = ' SFR' !< package budget string
48  !
49  private
50  public :: sfr_create
51  public :: sfrtype
52  !
53  type, extends(bndtype) :: sfrtype
54  ! -- scalars
55  ! -- for budgets
56  ! -- characters
57  character(len=16), dimension(:), pointer, contiguous :: csfrbudget => null() !< advanced package budget names
58  character(len=16), dimension(:), pointer, contiguous :: cauxcbc => null() !< aux names
59  character(len=LENBOUNDNAME), dimension(:), pointer, &
60  contiguous :: sfrname => null() !< internal SFR reach name
61  ! -- integers
62  integer(I4B), pointer :: istorage => null() !< flag for using kinematic wave approximation
63  integer(I4B), pointer :: iprhed => null() !< flag for printing stages to listing file
64  integer(I4B), pointer :: istageout => null() !< flag and unit number for binary stage output
65  integer(I4B), pointer :: ibudgetout => null() !< flag and unit number for binary sfr budget output
66  integer(I4B), pointer :: ibudcsv => null() !< unit number for csv budget output file
67  integer(I4B), pointer :: ipakcsv => null() !< flag and unit number for package convergence information
68  integer(I4B), pointer :: idiversions => null() !< flag indicating if there are any diversions
69  integer(I4B), pointer :: nconn => null() !< number of reach connections
70  integer(I4B), pointer :: maxsfrpicard => null() !< maximum number of Picard iteration calls to SFR solve
71  integer(I4B), pointer :: maxsfrit => null() !< maximum number of iterations in SFR solve
72  integer(I4B), pointer :: bditems => null() !< number of SFR budget items
73  integer(I4B), pointer :: cbcauxitems => null() !< number of aux items in cell-by-cell budget file
74  integer(I4B), pointer :: icheck => null() !< flag indicating if input should be checked (default is yes)
75  integer(I4B), pointer :: iconvchk => null() !< flag indicating of final convergence run is executed
76  integer(I4B), pointer :: gwfiss => null() !< groundwater model steady-state flag
77  integer(I4B), pointer :: ianynone => null() !< number of reaches with 'none' connection
78  ! -- double precision
79  real(dp), pointer :: unitconv => null() !< unit conversion factor (SI to model units)
80  real(dp), pointer :: lengthconv => null() !< length conversion factor (SI to model units)
81  real(dp), pointer :: timeconv => null() !< time conversion factor (SI to model units)
82  real(dp), pointer :: dmaxchg => null() !< maximum depth change allowed
83  real(dp), pointer :: deps => null() !< perturbation value
84  real(dp), pointer :: storage_weight => null() !< time weighting factor for kinematic wave approximation
85  ! -- integer vectors
86  integer(I4B), dimension(:), pointer, contiguous :: isfrorder => null() !< sfr reach order determined from DAG of upstream reaches
87  integer(I4B), dimension(:), pointer, contiguous :: ia => null() !< CRS row pointer for SFR reaches
88  integer(I4B), dimension(:), pointer, contiguous :: ja => null() !< CRS column pointers for SFR reach connections
89  ! -- double precision output vectors
90  real(dp), dimension(:), pointer, contiguous :: qoutflow => null() !< reach downstream flow
91  real(dp), dimension(:), pointer, contiguous :: qextoutflow => null() !< reach discharge to external boundary
92  real(dp), dimension(:), pointer, contiguous :: qauxcbc => null() !< aux value
93  real(dp), dimension(:), pointer, contiguous :: dbuff => null() !< temporary vector
94  !
95  ! -- sfr budget object
96  type(budgetobjecttype), pointer :: budobj => null() !< SFR budget object
97  !
98  ! -- sfr table objects
99  type(tabletype), pointer :: stagetab => null() !< reach stage table written to the listing file
100  type(tabletype), pointer :: couranttab => null() !< Courant number table written to the listing file
101  type(tabletype), pointer :: pakcsvtab => null() !< SFR package convergence table
102  !
103  ! -- sfr reach data
104  integer(I4B), dimension(:), pointer, contiguous :: iboundpak => null() !< ibound array for SFR reaches that defines active, inactive, and constant reaches
105  integer(I4B), dimension(:), pointer, contiguous :: igwfnode => null() !< groundwater node connected to SFR reaches
106  integer(I4B), dimension(:), pointer, contiguous :: igwftopnode => null() !< highest active groundwater node under SFR reaches
107  real(dp), dimension(:), pointer, contiguous :: length => null() !< reach length
108  real(dp), dimension(:), pointer, contiguous :: width => null() !< reach width
109  real(dp), dimension(:), pointer, contiguous :: strtop => null() !< reach bed top elevation
110  real(dp), dimension(:), pointer, contiguous :: bthick => null() !< reach bed thickness
111  real(dp), dimension(:), pointer, contiguous :: hk => null() !< vertical hydraulic conductivity of reach bed sediments
112  real(dp), dimension(:), pointer, contiguous :: slope => null() !< reach slope
113  integer(I4B), dimension(:), pointer, contiguous :: nconnreach => null() !< number of connections for each reach
114  real(dp), dimension(:), pointer, contiguous :: ustrf => null() !< upstream flow fraction for upstream connections
115  real(dp), dimension(:), pointer, contiguous :: ftotnd => null() !< total fraction of connected reaches that are not diversions
116  integer(I4B), dimension(:), pointer, contiguous :: ndiv => null() !< number of diversions for each reach
117  real(dp), dimension(:), pointer, contiguous :: usflow => null() !< upstream reach flow
118  real(dp), dimension(:), pointer, contiguous :: dsflow => null() !< downstream reach flow
119  real(dp), dimension(:), pointer, contiguous :: dsflowold => null() !< downstream reach flow for previous time step
120  real(dp), dimension(:), pointer, contiguous :: usinflow => null() !< upstream reach flow for previous time step
121  real(dp), dimension(:), pointer, contiguous :: usinflowold => null() !< upstream reach flow for previous time step
122  real(dp), pointer :: ats_courant => null() !< target Courant number for ATS time step submission
123  integer(I4B), dimension(:), pointer, contiguous :: itvd_upstream => null() !< upstream reach index for TVD limiter (0 = headwater or confluence)
124  real(dp), dimension(:), pointer, contiguous :: crmin => null() !< simulation-wide minimum Courant number per reach
125  real(dp), dimension(:), pointer, contiguous :: crmax => null() !< simulation-wide maximum Courant number per reach
126  real(dp), dimension(:), pointer, contiguous :: crsum => null() !< simulation-wide sum of Courant numbers per reach
127  integer(I4B), dimension(:), pointer, contiguous :: crcnt => null() !< simulation-wide count of non-zero Courant evaluations per reach
128  real(dp), dimension(:), pointer, contiguous :: depth => null() !< reach depth
129  real(dp), dimension(:), pointer, contiguous :: stage => null() !< reach stage
130  real(dp), dimension(:), pointer, contiguous :: stageold => null() !< reach stage for last timestep
131  real(dp), dimension(:), pointer, contiguous :: gwflow => null() !< flow from groundwater to reach
132  real(dp), dimension(:), pointer, contiguous :: simevap => null() !< simulated reach evaporation
133  real(dp), dimension(:), pointer, contiguous :: simrunoff => null() !< simulated reach runoff
134  real(dp), dimension(:), pointer, contiguous :: stage0 => null() !< previous reach stage iterate
135  real(dp), dimension(:), pointer, contiguous :: usflow0 => null() !< previous upstream reach flow iterate
136  real(dp), dimension(:), pointer, contiguous :: storage => null() !< previous upstream reach flow iterate
137  ! -- cross-section data
138  integer(I4B), pointer :: ncrossptstot => null() !< total number of cross-section points
139  integer(I4B), dimension(:), pointer, contiguous :: ncrosspts => null() !< number of cross-section points for each reach
140  integer(I4B), dimension(:), pointer, contiguous :: iacross => null() !< pointers to cross-section data for each reach
141  real(dp), dimension(:), pointer, contiguous :: station => null() !< cross-section station (x-position) data
142  real(dp), dimension(:), pointer, contiguous :: xsheight => null() !< cross-section height data
143  real(dp), dimension(:), pointer, contiguous :: xsrough => null() !< cross-section roughness data
144  ! -- connection data
145  integer(I4B), dimension(:), pointer, contiguous :: idir => null() !< reach connection direction
146  integer(I4B), dimension(:), pointer, contiguous :: idiv => null() !< reach connection diversion number
147  real(dp), dimension(:), pointer, contiguous :: qconn => null() !< reach connection flow
148  ! -- boundary data
149  real(dp), dimension(:), pointer, contiguous :: rough => null() !< reach Manning's roughness coefficient (SI units)
150  real(dp), dimension(:), pointer, contiguous :: rain => null() !< reach rainfall
151  real(dp), dimension(:), pointer, contiguous :: evap => null() !< reach potential evaporation
152  real(dp), dimension(:), pointer, contiguous :: inflow => null() !< reach upstream inflow
153  real(dp), dimension(:), pointer, contiguous :: runoff => null() !< reach maximum runoff
154  real(dp), dimension(:), pointer, contiguous :: sstage => null() !< reach specified stage
155  ! -- reach aux variables
156  real(dp), dimension(:, :), pointer, contiguous :: rauxvar => null() !< reach aux variable
157  ! -- diversion data
158  integer(I4B), dimension(:), pointer, contiguous :: iadiv => null() !< row pointer for reach diversions
159  integer(I4B), dimension(:), pointer, contiguous :: divreach => null() !< diversion reach
160  character(len=10), dimension(:), pointer, contiguous :: divcprior => null() !< diversion rule
161  real(dp), dimension(:), pointer, contiguous :: divflow => null() !< specified diversion flow value
162  real(dp), dimension(:), pointer, contiguous :: divq => null() !< simulated diversion flow
163  !
164  ! -- density variables
165  integer(I4B), pointer :: idense !< flag indicating if density corrections are active
166  real(dp), dimension(:, :), pointer, contiguous :: denseterms => null() !< density terms
167  !
168  ! -- viscosity variables
169  real(dp), dimension(:, :), pointer, contiguous :: viscratios => null() !< viscosity ratios (1: sfr vsc ratio; 2: gwf vsc ratio)
170  !
171  ! -- type bound procedures
172  contains
173  procedure :: sfr_allocate_scalars
174  procedure :: sfr_allocate_arrays
175  procedure :: bnd_options => sfr_options
176  procedure :: read_dimensions => sfr_read_dimensions
177  ! procedure :: set_pointers => sfr_set_pointers
178  procedure :: bnd_ar => sfr_ar
179  procedure :: bnd_rp => sfr_rp
180  procedure :: bnd_ad => sfr_ad
181  procedure :: bnd_cf => sfr_cf
182  procedure :: bnd_fc => sfr_fc
183  procedure :: bnd_fn => sfr_fn
184  procedure :: bnd_cc => sfr_cc
185  procedure :: bnd_cq => sfr_cq
186  procedure :: bnd_ot_package_flows => sfr_ot_package_flows
187  procedure :: bnd_ot_dv => sfr_ot_dv
188  procedure :: bnd_ot_bdsummary => sfr_ot_bdsummary
189  procedure :: bnd_dt => sfr_dt
190  procedure :: bnd_fp => sfr_fp
191  procedure :: bnd_da => sfr_da
192  procedure :: define_listlabel
193  ! -- methods for observations
194  procedure, public :: bnd_obs_supported => sfr_obs_supported
195  procedure, public :: bnd_df_obs => sfr_df_obs
196  procedure, public :: bnd_rp_obs => sfr_rp_obs
197  procedure, public :: bnd_bd_obs => sfr_bd_obs
198  ! -- private procedures
199  procedure, private :: sfr_set_stressperiod
200  procedure, private :: sfr_solve
201  procedure, private :: sfr_calc_constant
202  procedure, private :: sfr_calc_transient
203  procedure, private :: sfr_calc_tvd
204  procedure, private :: sfr_calc_celerity
205  procedure, private :: sfr_calc_steady
206  procedure, private :: sfr_precompute_tvd
207  procedure, private :: sfr_update_flows
208  procedure, private :: sfr_adjust_ro_ev
209  procedure, private :: sfr_calc_qgwf
210  procedure, private :: sfr_gwf_conn
211  procedure, private :: sfr_calc_cond
212  procedure, private :: sfr_calc_qman
213  procedure, private :: sfr_calc_qd
214  procedure, private :: sfr_calc_qsource
215  procedure, private :: sfr_calc_div
216  ! -- geometry
217  procedure, private :: calc_area_wet
218  procedure, private :: calc_perimeter_wet
219  procedure, private :: calc_surface_area
220  procedure, private :: calc_surface_area_wet
221  procedure, private :: calc_top_width_wet
222  ! -- reading
223  procedure, private :: sfr_read_packagedata
224  procedure, private :: sfr_read_crossection
225  procedure, private :: sfr_read_connectiondata
226  procedure, private :: sfr_read_diversions
227  procedure, private :: sfr_read_initial_stages
228  ! -- calculations
229  procedure, private :: sfr_calc_reach_depth
230  procedure, private :: sfr_calc_xs_depth
231  ! -- error checking
232  procedure, private :: sfr_check_conversion
233  procedure, private :: sfr_check_storage_weight
234  procedure, private :: sfr_check_reaches
235  procedure, private :: sfr_check_connections
236  procedure, private :: sfr_check_diversions
237  procedure, private :: sfr_check_initialstages
238  procedure, private :: sfr_check_ustrf
239  ! -- budget
240  procedure, private :: sfr_setup_budobj
241  procedure, private :: sfr_fill_budobj
242  ! -- table
243  procedure, private :: sfr_setup_tableobj
244  ! -- density
245  procedure :: sfr_activate_density
246  procedure, private :: sfr_calculate_density_exchange
247  ! -- viscosity
249  end type sfrtype
250 
251  interface
252  module subroutine sfr_calc_steady(this, n, d1, hgwf, &
253  qu, qi, qfrommvr, qr, qe, qro, &
254  qgwf, qd)
255  class(sfrtype) :: this !< SfrType object
256  integer(I4B), intent(in) :: n !< reach number
257  real(dp), intent(inout) :: d1 !< current reach depth estimate
258  real(dp), intent(in) :: hgwf !< head in gw cell
259  real(dp), intent(in) :: qu !< reach upstream flow
260  real(dp), intent(in) :: qi !< reach specified inflow
261  real(dp), intent(in) :: qfrommvr !< reach flow from mover
262  real(dp), intent(in) :: qr !< reach rainfall
263  real(dp), intent(in) :: qe !< reach evaporation
264  real(dp), intent(in) :: qro !< reach runoff flow
265  real(dp), intent(inout) :: qgwf !< reach-aquifer exchange
266  real(dp), intent(inout) :: qd !< reach outflow
267  end subroutine
268  end interface
269 
270  interface
271  module subroutine sfr_calc_transient(this, n, d1, hgwf, &
272  qu, qi, qfrommvr, qr, qe, qro, &
273  qgwf, qd)
274  class(sfrtype) :: this !< SfrType object
275  integer(I4B), intent(in) :: n !< reach number
276  real(dp), intent(inout) :: d1 !< current reach depth estimate
277  real(dp), intent(in) :: hgwf !< head in gw cell
278  real(dp), intent(in) :: qu !< reach upstream flow
279  real(dp), intent(in) :: qi !< reach specified inflow
280  real(dp), intent(in) :: qfrommvr !< reach flow from mover
281  real(dp), intent(in) :: qr !< reach rainfall
282  real(dp), intent(in) :: qe !< reach evaporation
283  real(dp), intent(in) :: qro !< reach runoff flow
284  real(dp), intent(inout) :: qgwf !< reach-aquifer exchange
285  real(dp), intent(inout) :: qd !< reach outflow
286  end subroutine
287  end interface
288 
289  interface
290  module subroutine sfr_calc_tvd(this, n, d1, hgwf, &
291  qu, qi, qfrommvr, qr, qe, qro, &
292  qgwf, qd)
293  class(sfrtype) :: this !< SfrType object
294  integer(I4B), intent(in) :: n !< reach number
295  real(dp), intent(inout) :: d1 !< current reach depth estimate
296  real(dp), intent(in) :: hgwf !< head in gw cell
297  real(dp), intent(in) :: qu !< reach upstream flow
298  real(dp), intent(in) :: qi !< reach specified inflow
299  real(dp), intent(in) :: qfrommvr !< reach flow from mover
300  real(dp), intent(in) :: qr !< reach rainfall
301  real(dp), intent(in) :: qe !< reach evaporation
302  real(dp), intent(in) :: qro !< reach runoff flow
303  real(dp), intent(inout) :: qgwf !< reach-aquifer exchange
304  real(dp), intent(inout) :: qd !< reach outflow
305  end subroutine
306  end interface
307 
308  interface
309  module subroutine sfr_calc_constant(this, n, d1, hgwf, qgwf, qd)
310  class(sfrtype) :: this !< SfrType object
311  integer(I4B), intent(in) :: n !< reach number
312  real(dp), intent(inout) :: d1 !< current reach depth estimate
313  real(dp), intent(in) :: hgwf !< head in gw cell
314  real(dp), intent(inout) :: qgwf !< reach-aquifer exchange
315  real(dp), intent(inout) :: qd !< reach outflow
316  end subroutine
317  end interface
318 
319 contains
320 
321  !> @ brief Create a new package object
322  !!
323  !! Create a new SFR Package object
324  !<
325  subroutine sfr_create(packobj, id, ibcnum, inunit, iout, namemodel, pakname)
326  ! -- modules
328  ! -- dummy
329  class(bndtype), pointer :: packobj !< pointer to default package type
330  integer(I4B), intent(in) :: id !< package id
331  integer(I4B), intent(in) :: ibcnum !< boundary condition number
332  integer(I4B), intent(in) :: inunit !< unit number of SFR package input file
333  integer(I4B), intent(in) :: iout !< unit number of model listing file
334  character(len=*), intent(in) :: namemodel !< model name
335  character(len=*), intent(in) :: pakname !< package name
336  ! -- local
337  type(sfrtype), pointer :: sfrobj
338  !
339  ! -- allocate the object and assign values to object variables
340  allocate (sfrobj)
341  packobj => sfrobj
342  !
343  ! -- create name and memory path
344  call packobj%set_names(ibcnum, namemodel, pakname, ftype)
345  packobj%text = text
346  !
347  ! -- allocate scalars
348  call sfrobj%sfr_allocate_scalars()
349  !
350  ! -- initialize package
351  call packobj%pack_initialize()
352 
353  packobj%inunit = inunit
354  packobj%iout = iout
355  packobj%id = id
356  packobj%ibcnum = ibcnum
357  packobj%ncolbnd = 4
358  packobj%iscloc = 0 ! not supported
359  packobj%isadvpak = 1
360  packobj%ictMemPath = create_mem_path(namemodel, 'NPF')
361  end subroutine sfr_create
362 
363  !> @ brief Allocate scalars
364  !!
365  !! Allocate and initialize scalars for the SFR package. The base model
366  !! allocate scalars method is also called.
367  !<
368  subroutine sfr_allocate_scalars(this)
369  ! -- modules
372  ! -- dummy
373  class(sfrtype), intent(inout) :: this !< SfrType object
374  !
375  ! -- call standard BndType allocate scalars
376  call this%BndType%allocate_scalars()
377  !
378  ! -- allocate the object and assign values to object variables
379  call mem_allocate(this%ats_courant, 'ATS_COURANT', this%memoryPath)
380  call mem_allocate(this%istorage, 'ISTORAGE', this%memoryPath)
381  call mem_allocate(this%iprhed, 'IPRHED', this%memoryPath)
382  call mem_allocate(this%istageout, 'ISTAGEOUT', this%memoryPath)
383  call mem_allocate(this%ibudgetout, 'IBUDGETOUT', this%memoryPath)
384  call mem_allocate(this%ibudcsv, 'IBUDCSV', this%memoryPath)
385  call mem_allocate(this%ipakcsv, 'IPAKCSV', this%memoryPath)
386  call mem_allocate(this%idiversions, 'IDIVERSIONS', this%memoryPath)
387  call mem_allocate(this%maxsfrpicard, 'MAXSFRPICARD', this%memoryPath)
388  call mem_allocate(this%maxsfrit, 'MAXSFRIT', this%memoryPath)
389  call mem_allocate(this%bditems, 'BDITEMS', this%memoryPath)
390  call mem_allocate(this%cbcauxitems, 'CBCAUXITEMS', this%memoryPath)
391  call mem_allocate(this%unitconv, 'UNITCONV', this%memoryPath)
392  call mem_allocate(this%lengthconv, 'LENGTHCONV', this%memoryPath)
393  call mem_allocate(this%timeconv, 'TIMECONV', this%memoryPath)
394  call mem_allocate(this%dmaxchg, 'DMAXCHG', this%memoryPath)
395  call mem_allocate(this%deps, 'DEPS', this%memoryPath)
396  call mem_allocate(this%storage_weight, 'STORAGE_WEIGHT', this%memoryPath)
397  call mem_allocate(this%nconn, 'NCONN', this%memoryPath)
398  call mem_allocate(this%icheck, 'ICHECK', this%memoryPath)
399  call mem_allocate(this%iconvchk, 'ICONVCHK', this%memoryPath)
400  call mem_allocate(this%idense, 'IDENSE', this%memoryPath)
401  call mem_allocate(this%ianynone, 'IANYNONE', this%memoryPath)
402  call mem_allocate(this%ncrossptstot, 'NCROSSPTSTOT', this%memoryPath)
403  !
404  ! -- set pointer to gwf iss
405  call mem_setptr(this%gwfiss, 'ISS', create_mem_path(this%name_model))
406  !
407  ! -- Set values
408  this%istorage = 0
409  this%iprhed = 0
410  this%istageout = 0
411  this%ibudgetout = 0
412  this%ibudcsv = 0
413  this%ipakcsv = 0
414  this%idiversions = 0
415  this%maxsfrpicard = 100
416  this%maxsfrit = maxadpit
417  this%bditems = 8
418  this%cbcauxitems = 1
419  this%unitconv = done
420  this%lengthconv = dnodata
421  this%timeconv = dnodata
422  this%dmaxchg = dem5
423  this%deps = dp999 * this%dmaxchg
424  this%storage_weight = dnodata
425  this%nconn = 0
426  this%ats_courant = dnodata
427  this%icheck = 1
428  this%iconvchk = 1
429  this%idense = 0
430  this%ivsc = 0
431  this%ianynone = 0
432  this%ncrossptstot = 0
433  end subroutine sfr_allocate_scalars
434 
435  !> @ brief Allocate arrays
436  !!
437  !! Allocate and initialize array for the SFR package.
438  !<
439  subroutine sfr_allocate_arrays(this)
440  ! -- modules
442  ! -- dummy
443  class(sfrtype), intent(inout) :: this !< SfrType object
444  ! -- local
445  integer(I4B) :: i
446  integer(I4B) :: j
447  !
448  ! -- allocate character array for budget text
449  allocate (this%csfrbudget(this%bditems))
450  call mem_allocate(this%sfrname, lenboundname, this%maxbound, &
451  'SFRNAME', this%memoryPath)
452  !
453  ! -- variables originally in SfrDataType
454  call mem_allocate(this%iboundpak, this%maxbound, 'IBOUNDPAK', &
455  this%memoryPath)
456  call mem_allocate(this%igwfnode, this%maxbound, 'IGWFNODE', this%memoryPath)
457  call mem_allocate(this%igwftopnode, this%maxbound, 'IGWFTOPNODE', &
458  this%memoryPath)
459  call mem_allocate(this%length, this%maxbound, 'LENGTH', this%memoryPath)
460  call mem_allocate(this%width, this%maxbound, 'WIDTH', this%memoryPath)
461  call mem_allocate(this%strtop, this%maxbound, 'STRTOP', this%memoryPath)
462  call mem_allocate(this%bthick, this%maxbound, 'BTHICK', this%memoryPath)
463  call mem_allocate(this%hk, this%maxbound, 'HK', this%memoryPath)
464  call mem_allocate(this%slope, this%maxbound, 'SLOPE', this%memoryPath)
465  call mem_allocate(this%nconnreach, this%maxbound, 'NCONNREACH', &
466  this%memoryPath)
467  call mem_allocate(this%ustrf, this%maxbound, 'USTRF', this%memoryPath)
468  call mem_allocate(this%ftotnd, this%maxbound, 'FTOTND', this%memoryPath)
469  call mem_allocate(this%ndiv, this%maxbound, 'NDIV', this%memoryPath)
470  call mem_allocate(this%usflow, this%maxbound, 'USFLOW', this%memoryPath)
471  call mem_allocate(this%dsflow, this%maxbound, 'DSFLOW', this%memoryPath)
472  call mem_allocate(this%depth, this%maxbound, 'DEPTH', this%memoryPath)
473  call mem_allocate(this%stage, this%maxbound, 'STAGE', this%memoryPath)
474  call mem_allocate(this%gwflow, this%maxbound, 'GWFLOW', this%memoryPath)
475  call mem_allocate(this%simevap, this%maxbound, 'SIMEVAP', this%memoryPath)
476  call mem_allocate(this%simrunoff, this%maxbound, 'SIMRUNOFF', &
477  this%memoryPath)
478  call mem_allocate(this%stage0, this%maxbound, 'STAGE0', this%memoryPath)
479  call mem_allocate(this%usflow0, this%maxbound, 'USFLOW0', this%memoryPath)
480  !
481  ! -- stage, usflow, inflow, and dsflow for previous timestep
482  if (this%istorage == 1) then
483  call mem_allocate(this%stageold, this%maxbound, 'STAGEOLD', &
484  this%memoryPath)
485  call mem_allocate(this%usinflow, this%maxbound, 'USINFLOW', &
486  this%memoryPath)
487  call mem_allocate(this%usinflowold, this%maxbound, 'USINFLOWOLD', &
488  this%memoryPath)
489  call mem_allocate(this%dsflowold, this%maxbound, 'DSFLOWOLD', &
490  this%memoryPath)
491  call mem_allocate(this%storage, this%maxbound, 'STORAGE', &
492  this%memoryPath)
493  call mem_allocate(this%crmin, this%maxbound, 'CRMIN', this%memoryPath)
494  call mem_allocate(this%crmax, this%maxbound, 'CRMAX', this%memoryPath)
495  call mem_allocate(this%crsum, this%maxbound, 'CRSUM', this%memoryPath)
496  call mem_allocate(this%crcnt, this%maxbound, 'CRCNT', this%memoryPath)
497  if (this%ats_courant /= dnodata) then
498  call mem_allocate(this%itvd_upstream, this%maxbound, &
499  'ITVD_UPSTREAM', this%memoryPath)
500  else
501  call mem_allocate(this%itvd_upstream, 0, 'ITVD_UPSTREAM', this%memoryPath)
502  end if
503  end if
504  !
505  ! -- reach order and connection data
506  call mem_allocate(this%isfrorder, this%maxbound, 'ISFRORDER', &
507  this%memoryPath)
508  call mem_allocate(this%ia, this%maxbound + 1, 'IA', this%memoryPath)
509  call mem_allocate(this%ja, 0, 'JA', this%memoryPath)
510  call mem_allocate(this%idir, 0, 'IDIR', this%memoryPath)
511  call mem_allocate(this%idiv, 0, 'IDIV', this%memoryPath)
512  call mem_allocate(this%qconn, 0, 'QCONN', this%memoryPath)
513  !
514  ! -- boundary data
515  call mem_allocate(this%rough, this%maxbound, 'ROUGH', this%memoryPath)
516  call mem_allocate(this%rain, this%maxbound, 'RAIN', this%memoryPath)
517  call mem_allocate(this%evap, this%maxbound, 'EVAP', this%memoryPath)
518  call mem_allocate(this%inflow, this%maxbound, 'INFLOW', this%memoryPath)
519  call mem_allocate(this%runoff, this%maxbound, 'RUNOFF', this%memoryPath)
520  call mem_allocate(this%sstage, this%maxbound, 'SSTAGE', this%memoryPath)
521  !
522  ! -- aux variables
523  call mem_allocate(this%rauxvar, this%naux, this%maxbound, &
524  'RAUXVAR', this%memoryPath)
525  !
526  ! -- diversion variables
527  call mem_allocate(this%iadiv, this%maxbound + 1, 'IADIV', this%memoryPath)
528  call mem_allocate(this%divreach, 0, 'DIVREACH', this%memoryPath)
529  call mem_allocate(this%divflow, 0, 'DIVFLOW', this%memoryPath)
530  call mem_allocate(this%divq, 0, 'DIVQ', this%memoryPath)
531  !
532  ! -- cross-section data
533  call mem_allocate(this%ncrosspts, this%maxbound, 'NCROSSPTS', &
534  this%memoryPath)
535  call mem_allocate(this%iacross, this%maxbound + 1, 'IACROSS', &
536  this%memoryPath)
537  call mem_allocate(this%station, this%ncrossptstot, 'STATION', &
538  this%memoryPath)
539  call mem_allocate(this%xsheight, this%ncrossptstot, 'XSHEIGHT', &
540  this%memoryPath)
541  call mem_allocate(this%xsrough, this%ncrossptstot, 'XSROUGH', &
542  this%memoryPath)
543  !
544  ! -- initialize variables
545  this%iacross(1) = 0
546  do i = 1, this%maxbound
547  this%iboundpak(i) = 1
548  this%igwfnode(i) = 0
549  this%igwftopnode(i) = 0
550  this%length(i) = dzero
551  this%width(i) = dzero
552  this%strtop(i) = dzero
553  this%bthick(i) = dzero
554  this%hk(i) = dzero
555  this%slope(i) = dzero
556  this%nconnreach(i) = 0
557  this%ustrf(i) = dzero
558  this%ftotnd(i) = dzero
559  this%ndiv(i) = 0
560  this%usflow(i) = dzero
561  this%dsflow(i) = dzero
562  this%depth(i) = dzero
563  this%stage(i) = dzero
564  this%gwflow(i) = dzero
565  this%simevap(i) = dzero
566  this%simrunoff(i) = dzero
567  this%stage0(i) = dzero
568  this%usflow0(i) = dzero
569  !
570  ! -- stage
571  if (this%istorage == 1) then
572  this%stageold(i) = dzero
573  this%usinflow(i) = dzero
574  this%usinflowold(i) = dzero
575  this%dsflowold(i) = dzero
576  this%storage(i) = dzero
577  this%crmin(i) = dep20
578  this%crmax(i) = -dep20
579  this%crsum(i) = dzero
580  this%crcnt(i) = 0
581  if (this%ats_courant /= dnodata) then
582  this%itvd_upstream(i) = 0
583  end if
584  end if
585  !
586  ! -- boundary data
587  this%rough(i) = dzero
588  this%rain(i) = dzero
589  this%evap(i) = dzero
590  this%inflow(i) = dzero
591  this%runoff(i) = dzero
592  this%sstage(i) = dzero
593  !
594  ! -- aux variables
595  do j = 1, this%naux
596  this%rauxvar(j, i) = dzero
597  end do
598  !
599  ! -- cross-section data
600  this%ncrosspts(i) = 0
601  this%iacross(i + 1) = 0
602  end do
603  !
604  ! -- initialize additional cross-section data
605  do i = 1, this%ncrossptstot
606  this%station(i) = dzero
607  this%xsheight(i) = dzero
608  this%xsrough(i) = dzero
609  end do
610  !
611  !-- fill csfrbudget
612  this%csfrbudget(1) = ' RAINFALL'
613  this%csfrbudget(2) = ' EVAPORATION'
614  this%csfrbudget(3) = ' RUNOFF'
615  this%csfrbudget(4) = ' EXT-INFLOW'
616  this%csfrbudget(5) = ' GWF'
617  this%csfrbudget(6) = ' EXT-OUTFLOW'
618  this%csfrbudget(7) = ' FROM-MVR'
619  this%csfrbudget(8) = ' TO-MVR'
620  !
621  ! -- allocate and initialize budget output data
622  call mem_allocate(this%qoutflow, this%maxbound, 'QOUTFLOW', this%memoryPath)
623  call mem_allocate(this%qextoutflow, this%maxbound, 'QEXTOUTFLOW', &
624  this%memoryPath)
625  do i = 1, this%maxbound
626  this%qoutflow(i) = dzero
627  this%qextoutflow(i) = dzero
628  end do
629  !
630  ! -- allocate and initialize dbuff
631  if (this%istageout > 0) then
632  call mem_allocate(this%dbuff, this%maxbound, 'DBUFF', this%memoryPath)
633  do i = 1, this%maxbound
634  this%dbuff(i) = dzero
635  end do
636  else
637  call mem_allocate(this%dbuff, 0, 'DBUFF', this%memoryPath)
638  end if
639  !
640  ! -- allocate character array for budget text
641  allocate (this%cauxcbc(this%cbcauxitems))
642  !
643  ! -- allocate and initialize qauxcbc
644  call mem_allocate(this%qauxcbc, this%cbcauxitems, 'QAUXCBC', &
645  this%memoryPath)
646  do i = 1, this%cbcauxitems
647  this%qauxcbc(i) = dzero
648  end do
649  !
650  ! -- fill cauxcbc
651  this%cauxcbc(1) = 'FLOW-AREA '
652  !
653  ! -- allocate denseterms to size 0
654  call mem_allocate(this%denseterms, 3, 0, 'DENSETERMS', this%memoryPath)
655  !
656  ! -- allocate viscratios to size 0
657  call mem_allocate(this%viscratios, 2, 0, 'VISCRATIOS', this%memoryPath)
658  end subroutine sfr_allocate_arrays
659 
660  !> @ brief Read dimensions for package
661  !!
662  !! Read dimensions for the SFR package.
663  !<
664  subroutine sfr_read_dimensions(this)
665  ! -- dummy
666  class(sfrtype), intent(inout) :: this !< SfrType object
667  ! -- local
668  character(len=LINELENGTH) :: keyword
669  integer(I4B) :: ierr
670  logical(LGP) :: isfound
671  logical(LGP) :: endOfBlock
672  !
673  ! -- initialize dimensions to 0
674  this%maxbound = 0
675  !
676  ! -- get dimensions block
677  call this%parser%GetBlock('DIMENSIONS', isfound, ierr, &
678  supportopenclose=.true.)
679  !
680  ! -- parse dimensions block if detected
681  if (isfound) then
682  write (this%iout, '(/1x,a)') &
683  'PROCESSING '//trim(adjustl(this%text))//' DIMENSIONS'
684  do
685  call this%parser%GetNextLine(endofblock)
686  if (endofblock) exit
687  call this%parser%GetStringCaps(keyword)
688  select case (keyword)
689  case ('NREACHES')
690  this%maxbound = this%parser%GetInteger()
691  write (this%iout, '(4x,a,i0)') 'NREACHES = ', this%maxbound
692  case default
693  write (errmsg, '(2a)') &
694  'Unknown '//trim(this%text)//' dimension: ', trim(keyword)
695  call store_error(errmsg)
696  end select
697  end do
698  write (this%iout, '(1x,a)') &
699  'END OF '//trim(adjustl(this%text))//' DIMENSIONS'
700  else
701  call store_error('Required dimensions block not found.')
702  end if
703  !
704  ! -- verify dimensions were set
705  if (this%maxbound < 1) then
706  write (errmsg, '(a)') &
707  'NREACHES was not specified or was specified incorrectly.'
708  call store_error(errmsg)
709  end if
710  !
711  ! -- write summary of error messages for block
712  if (count_errors() > 0) then
713  call this%parser%StoreErrorUnit()
714  end if
715  !
716  ! -- Call define_listlabel to construct the list label that is written
717  ! when PRINT_INPUT option is used.
718  call this%define_listlabel()
719  !
720  ! -- Define default cross-section data size
721  this%ncrossptstot = this%maxbound
722  !
723  ! -- Allocate arrays in package superclass
724  call this%sfr_allocate_arrays()
725  !
726  ! -- read package data
727  call this%sfr_read_packagedata()
728  !
729  ! -- read cross-section data
730  call this%sfr_read_crossection()
731  !
732  ! -- read connection data
733  call this%sfr_read_connectiondata()
734  !
735  ! -- read diversion data
736  call this%sfr_read_diversions()
737  !
738  ! -- read initial stage data
739  call this%sfr_read_initial_stages()
740  !
741  ! -- setup the budget object
742  call this%sfr_setup_budobj()
743  !
744  ! -- setup the stage table object
745  call this%sfr_setup_tableobj()
746  end subroutine sfr_read_dimensions
747 
748  !> @ brief Read additional options for package
749  !!
750  !! Read additional options for SFR package.
751  !<
752  subroutine sfr_options(this, option, found)
753  ! -- modules
754  use openspecmodule, only: access, form
756  ! -- dummy
757  class(sfrtype), intent(inout) :: this !< SfrType object
758  character(len=*), intent(inout) :: option !< option keyword string
759  logical(LGP), intent(inout) :: found !< boolean indicating if option found
760  ! -- local
761  real(DP) :: r
762  character(len=MAXCHARLEN) :: fname
763  character(len=MAXCHARLEN) :: keyword
764  ! -- formats
765  character(len=*), parameter :: fmttimeconv = &
766  &"(4x, 'TIME CONVERSION VALUE (',g0,') SPECIFIED.')"
767  character(len=*), parameter :: fmtlengthconv = &
768  &"(4x, 'LENGTH CONVERSION VALUE (',g0,') SPECIFIED.')"
769  character(len=*), parameter :: fmtpicard = &
770  &"(4x, 'MAXIMUM SFR PICARD ITERATION VALUE (',i0,') SPECIFIED.')"
771  character(len=*), parameter :: fmtiter = &
772  &"(4x, 'MAXIMUM SFR ITERATION VALUE (',i0,') SPECIFIED.')"
773  character(len=*), parameter :: fmtdmaxchg = &
774  &"(4x, 'MAXIMUM DEPTH CHANGE VALUE (',g0,') SPECIFIED.')"
775  character(len=*), parameter :: fmtsfrbin = &
776  "(4x, 'SFR ', 1x, a, 1x, ' WILL BE SAVED TO FILE: ', a, /4x, &
777  &'OPENED ON UNIT: ', I0)"
778  character(len=*), parameter :: fmtstoweight = &
779  &"(4x, 'KINEMATIC STORAGE WEIGHT (',g0,') SPECIFIED.')"
780  !
781  ! -- Check for SFR options
782  found = .true.
783  select case (option)
784  case ('STORAGE')
785  this%istorage = 1
786  write (this%iout, '(4x,a)') trim(adjustl(this%text))// &
787  ' REACH STORAGE IS ACTIVE.'
788  case ('PRINT_STAGE')
789  this%iprhed = 1
790  write (this%iout, '(4x,a)') trim(adjustl(this%text))// &
791  ' STAGES WILL BE PRINTED TO LISTING FILE.'
792  case ('STAGE')
793  call this%parser%GetStringCaps(keyword)
794  if (keyword == 'FILEOUT') then
795  call this%parser%GetString(fname)
796  this%istageout = getunit()
797  call openfile(this%istageout, this%iout, fname, 'DATA(BINARY)', &
798  form, access, 'REPLACE', mnormal)
799  write (this%iout, fmtsfrbin) &
800  'STAGE', trim(adjustl(fname)), this%istageout
801  else
802  call store_error('Optional stage keyword must &
803  &be followed by fileout.')
804  end if
805  case ('BUDGET')
806  call this%parser%GetStringCaps(keyword)
807  if (keyword == 'FILEOUT') then
808  call this%parser%GetString(fname)
809  call assign_iounit(this%ibudgetout, this%inunit, "BUDGET fileout")
810  call openfile(this%ibudgetout, this%iout, fname, 'DATA(BINARY)', &
811  form, access, 'REPLACE', mnormal)
812  write (this%iout, fmtsfrbin) &
813  'BUDGET', trim(adjustl(fname)), this%ibudgetout
814  else
815  call store_error('Optional budget keyword must be '// &
816  'followed by fileout.')
817  end if
818  case ('BUDGETCSV')
819  call this%parser%GetStringCaps(keyword)
820  if (keyword == 'FILEOUT') then
821  call this%parser%GetString(fname)
822  call assign_iounit(this%ibudcsv, this%inunit, "BUDGETCSV fileout")
823  call openfile(this%ibudcsv, this%iout, fname, 'CSV', &
824  filstat_opt='REPLACE')
825  write (this%iout, fmtsfrbin) &
826  'BUDGET CSV', trim(adjustl(fname)), this%ibudcsv
827  else
828  call store_error('OPTIONAL BUDGETCSV KEYWORD MUST BE FOLLOWED BY &
829  &FILEOUT')
830  end if
831  case ('PACKAGE_CONVERGENCE')
832  call this%parser%GetStringCaps(keyword)
833  if (keyword == 'FILEOUT') then
834  call this%parser%GetString(fname)
835  this%ipakcsv = getunit()
836  call openfile(this%ipakcsv, this%iout, fname, 'CSV', &
837  filstat_opt='REPLACE', mode_opt=mnormal)
838  write (this%iout, fmtsfrbin) &
839  'PACKAGE_CONVERGENCE', trim(adjustl(fname)), this%ipakcsv
840  else
841  call store_error('Optional package_convergence keyword must be '// &
842  'followed by fileout.')
843  end if
844  case ('UNIT_CONVERSION')
845  this%unitconv = this%parser%GetDouble()
846  !
847  ! -- create warning message
848  write (warnmsg, '(a)') &
849  'SETTING UNIT_CONVERSION DIRECTLY'
850  !
851  ! -- create deprecation warning
852  call deprecation_warning('OPTIONS', 'UNIT_CONVERSION', '6.4.2', &
853  warnmsg, this%parser%GetUnit())
854  case ('LENGTH_CONVERSION')
855  this%lengthconv = this%parser%GetDouble()
856  write (this%iout, fmtlengthconv) this%lengthconv
857  case ('TIME_CONVERSION')
858  this%timeconv = this%parser%GetDouble()
859  write (this%iout, fmttimeconv) this%timeconv
860  case ('MAXIMUM_PICARD_ITERATIONS')
861  this%maxsfrpicard = this%parser%GetInteger()
862  write (this%iout, fmtpicard) this%maxsfrpicard
863  case ('MAXIMUM_ITERATIONS')
864  this%maxsfrit = this%parser%GetInteger()
865  write (this%iout, fmtiter) this%maxsfrit
866  case ('MAXIMUM_DEPTH_CHANGE')
867  r = this%parser%GetDouble()
868  this%dmaxchg = r
869  this%deps = dp999 * r
870  write (this%iout, fmtdmaxchg) this%dmaxchg
871  case ('MOVER')
872  this%imover = 1
873  write (this%iout, '(4x,A)') 'MOVER OPTION ENABLED'
874  !
875  ! -- right now these are options that are only available in the
876  ! development version and are not included in the documentation.
877  ! These options are only available when IDEVELOPMODE in
878  ! constants module is set to 1
879  case ('ATS_COURANT')
880  this%ats_courant = this%parser%GetDouble()
881  if (this%ats_courant <= dzero) then
882  write (errmsg, '(a,g0,a)') &
883  "ATS_COURANT SPECIFIED TO BE '", this%ats_courant, &
884  "' BUT MUST BE GREATER THAN ZERO"
885  call store_error(errmsg)
886  else
887  write (this%iout, '(4x,a,1pg15.6)') &
888  'TARGET COURANT NUMBER FOR ADAPTIVE TIME STEPS: ', &
889  this%ats_courant
890  end if
891  case ('DEV_NO_CHECK')
892  call this%parser%DevOpt()
893  this%icheck = 0
894  write (this%iout, '(4x,A)') 'SFR CHECKS OF REACH GEOMETRY '// &
895  'RELATIVE TO MODEL GRID AND '// &
896  'REASONABLE PARAMETERS WILL NOT '// &
897  'BE PERFORMED.'
898  case ('DEV_NO_FINAL_CHECK')
899  call this%parser%DevOpt()
900  this%iconvchk = 0
901  write (this%iout, '(4x,a)') &
902  'A FINAL CONVERGENCE CHECK OF THE CHANGE IN STREAM FLOW ROUTING &
903  &STAGES AND FLOWS WILL NOT BE MADE'
904  case ('DEV_STORAGE_WEIGHT')
905  call this%parser%DevOpt()
906  r = this%parser%GetDouble()
907  if (r < dhalf .or. r > done) then
908  write (errmsg, '(a,g0,a)') &
909  "STORAGE_WEIGHT SPECIFIED TO BE '", r, &
910  "' BUT CANNOT BE LESS THAN 0.5 OR GREATER THAN 1.0"
911  call store_error(errmsg)
912  else
913  this%storage_weight = r
914  write (this%iout, fmtstoweight) this%storage_weight
915  end if
916  !
917  ! -- no valid options found
918  case default
919  !
920  ! -- No options found
921  found = .false.
922  end select
923  end subroutine sfr_options
924 
925  !> @ brief Allocate and read method for package
926  !!
927  !! Method to read and prepare period data for the SFR package.
928  !<
929  subroutine sfr_ar(this)
930  ! -- modules
931  use tdismodule, only: inats
932  ! -- dummy
933  class(sfrtype), intent(inout) :: this !< SfrType object
934  ! -- local
935  integer(I4B) :: n
936  integer(I4B) :: ierr
937  !
938  ! -- allocate and read observations
939  call this%obs%obs_ar()
940  !
941  ! -- call standard BndType allocate scalars
942  call this%BndType%allocate_arrays()
943  !
944  ! -- set boundname for each connection
945  if (this%inamedbound /= 0) then
946  do n = 1, this%maxbound
947  this%boundname(n) = this%sfrname(n)
948  end do
949  end if
950  !
951  ! -- copy boundname into boundname_cst
952  call this%copy_boundname()
953  !
954  ! -- copy igwfnode into nodelist
955  do n = 1, this%maxbound
956  this%nodelist(n) = this%igwfnode(n)
957  end do
958  !
959  ! -- check the sfr unit conversion data
960  call this%sfr_check_conversion()
961  !
962  ! -- check the storage_weight
963  call this%sfr_check_storage_weight()
964  !
965  ! -- check that ATS_COURANT is only used with STORAGE
966  if (this%ats_courant /= dnodata .and. this%istorage /= 1) then
967  write (errmsg, '(a)') &
968  'ATS_COURANT OPTION REQUIRES STORAGE OPTION TO BE ACTIVE'
969  call store_error(errmsg)
970  end if
971  !
972  ! -- warn when ATS_COURANT is specified but ATS is not active in TDIS
973  if (this%ats_courant /= dnodata .and. inats == 0) then
974  write (warnmsg, '(a)') &
975  'ATS_COURANT IS SPECIFIED IN THE SFR OPTIONS BLOCK BUT THE '// &
976  'ATS PACKAGE IS NOT ACTIVE IN TDIS, SO THE TIME STEP IS NOT '// &
977  'ADAPTED TO THE COURANT NUMBER. IF THE COURANT NUMBER EXCEEDS 1 '// &
978  'THE EXPLICIT KINEMATIC-WAVE ROUTING MAY OSCILLATE WHILE STILL '// &
979  'CLOSING THE BUDGET. ACTIVATE THE ATS PACKAGE OR USE A SMALLER '// &
980  'TIME STEP.'
981  call store_warning(warnmsg)
982  end if
983  !
984  ! -- pre-compute TVD upstream connectivity when ATS_COURANT is active
985  if (this%ats_courant /= dnodata .and. this%istorage == 1) then
986  call this%sfr_precompute_tvd()
987  end if
988  !
989  ! -- check the sfr reach data
990  call this%sfr_check_reaches()
991 
992  ! -- check the connection data
993  call this%sfr_check_connections()
994 
995  ! -- check the diversion data
996  if (this%idiversions /= 0) then
997  call this%sfr_check_diversions()
998  end if
999 
1000  ! -- check the diversion data
1001  if (this%istorage == 1) then
1002  call this%sfr_check_initialstages()
1003  end if
1004  !
1005  ! -- terminate if errors were detected in any of the static sfr data
1006  ierr = count_errors()
1007  if (ierr > 0) then
1008  call this%parser%StoreErrorUnit()
1009  end if
1010  !
1011  ! -- setup pakmvrobj
1012  if (this%imover /= 0) then
1013  allocate (this%pakmvrobj)
1014  call this%pakmvrobj%ar(this%maxbound, this%maxbound, this%memoryPath)
1015  end if
1016  end subroutine sfr_ar
1017 
1018  !> @ brief Read packagedata for the package
1019  !!
1020  !! Method to read packagedata for each reach for the SFR package.
1021  !<
1022  subroutine sfr_read_packagedata(this)
1023  ! -- modules
1025  ! -- dummy
1026  class(sfrtype), intent(inout) :: this !< SfrType object
1027  ! -- local
1028  character(len=LINELENGTH) :: text
1029  character(len=LINELENGTH) :: cellid
1030  character(len=10) :: cnum
1031  character(len=LENBOUNDNAME) :: bndName
1032  character(len=LENBOUNDNAME) :: bndNameTemp
1033  character(len=LENBOUNDNAME) :: hkname
1034  character(len=LENBOUNDNAME) :: manningname
1035  character(len=LENBOUNDNAME) :: ustrfname
1036  character(len=50), dimension(:), allocatable :: caux
1037  integer(I4B) :: n, ierr, ival
1038  logical(LGP) :: isfound
1039  logical(LGP) :: endOfBlock
1040  integer(I4B) :: i
1041  integer(I4B) :: ii
1042  integer(I4B) :: jj
1043  integer(I4B) :: iaux
1044  integer(I4B) :: nconzero
1045  integer(I4B) :: ipos
1046  integer, allocatable, dimension(:) :: nboundchk
1047  real(DP), pointer :: bndElem => null()
1048  !
1049  ! -- allocate space for checking sfr reach data
1050  allocate (nboundchk(this%maxbound))
1051  do i = 1, this%maxbound
1052  nboundchk(i) = 0
1053  end do
1054  nconzero = 0
1055  !
1056  ! -- allocate local storage for aux variables
1057  if (this%naux > 0) then
1058  allocate (caux(this%naux))
1059  end if
1060  !
1061  ! -- read reach data
1062  call this%parser%GetBlock('PACKAGEDATA', isfound, ierr, &
1063  supportopenclose=.true.)
1064  !
1065  ! -- parse reaches block if detected
1066  if (isfound) then
1067  write (this%iout, '(/1x,a)') 'PROCESSING '//trim(adjustl(this%text))// &
1068  ' PACKAGEDATA'
1069  do
1070  call this%parser%GetNextLine(endofblock)
1071  if (endofblock) exit
1072  ! -- read reach number
1073  n = this%parser%GetInteger()
1074 
1075  if (n < 1 .or. n > this%maxbound) then
1076  write (errmsg, '(a,1x,a,1x,i0)') &
1077  'Reach number (rno) must be greater than 0 and less', &
1078  'than or equal to', this%maxbound
1079  call store_error(errmsg)
1080  cycle
1081  end if
1082 
1083  ! -- increment nboundchk
1084  nboundchk(n) = nboundchk(n) + 1
1085  !
1086  ! -- get model node number
1087  call this%parser%GetCellid(this%dis%ndim, cellid, flag_string=.true.)
1088  this%igwfnode(n) = this%dis%noder_from_cellid(cellid, this%inunit, &
1089  this%iout, &
1090  flag_string=.true., &
1091  allow_zero=.true.)
1092  this%igwftopnode(n) = this%igwfnode(n)
1093  !
1094  ! -- read the cellid string and determine if 'none' is specified
1095  if (this%igwfnode(n) < 1) then
1096  this%ianynone = this%ianynone + 1
1097  call upcase(cellid)
1098  if (cellid == 'NONE') then
1099  call this%parser%GetStringCaps(cellid)
1100  !
1101  ! -- create warning message
1102  write (cnum, '(i0)') n
1103  warnmsg = 'CELLID for unconnected reach '//trim(cnum)// &
1104  ' specified to be NONE. Unconnected reaches '// &
1105  'should be specified with a zero for each grid '// &
1106  'dimension. For example, for a DIS grid a CELLID '// &
1107  'of 0 0 0 should be specified for unconnected reaches'
1108  !
1109  ! -- create deprecation warning
1110  call deprecation_warning('PACKAGEDATA', 'CELLID=NONE', '6.4.3', &
1111  warnmsg, this%parser%GetUnit())
1112  else
1113 
1114  end if
1115  end if
1116  ! -- get reach length
1117  this%length(n) = this%parser%GetDouble()
1118  ! -- get reach width
1119  this%width(n) = this%parser%GetDouble()
1120  ! -- get reach slope
1121  this%slope(n) = this%parser%GetDouble()
1122  ! -- get reach streambed top elevation
1123  this%strtop(n) = this%parser%GetDouble()
1124  ! -- get reach bed thickness
1125  this%bthick(n) = this%parser%GetDouble()
1126  ! -- get reach bed hk
1127  call this%parser%GetStringCaps(hkname)
1128  ! -- get reach roughness
1129  call this%parser%GetStringCaps(manningname)
1130  ! -- get number of connections for reach
1131  ival = this%parser%GetInteger()
1132  this%nconnreach(n) = ival
1133  this%nconn = this%nconn + ival
1134  if (ival < 0) then
1135  write (errmsg, '(a,1x,i0,1x,a,i0,a)') &
1136  'NCON for reach', n, &
1137  'must be greater than or equal to 0 (', ival, ').'
1138  call store_error(errmsg)
1139  else if (ival == 0) then
1140  nconzero = nconzero + 1
1141  end if
1142  ! -- get upstream fraction for reach
1143  call this%parser%GetString(ustrfname)
1144  ! -- get number of diversions for reach
1145  ival = this%parser%GetInteger()
1146  this%ndiv(n) = ival
1147  if (ival > 0) then
1148  this%idiversions = 1
1149  else if (ival < 0) then
1150  ival = 0
1151  end if
1152 
1153  ! -- get aux data
1154  do iaux = 1, this%naux
1155  call this%parser%GetString(caux(iaux))
1156  end do
1157 
1158  ! -- set default bndName
1159  write (cnum, '(i10.10)') n
1160  bndname = 'Reach'//cnum
1161 
1162  ! -- get reach name
1163  if (this%inamedbound /= 0) then
1164  call this%parser%GetStringCaps(bndnametemp)
1165  if (bndnametemp /= '') then
1166  bndname = bndnametemp
1167  end if
1168  !this%boundname(n) = bndName
1169  end if
1170  this%sfrname(n) = bndname
1171  !
1172  ! -- set reach hydraulic conductivity
1173  text = hkname
1174  jj = 1 !for 'BEDK'
1175  bndelem => this%hk(n)
1176  call read_value_or_time_series_adv(text, n, jj, bndelem, &
1177  this%packName, 'BND', &
1178  this%tsManager, this%iprpak, &
1179  'BEDK')
1180  !
1181  ! -- set Mannings
1182  text = manningname
1183  jj = 1 !for 'MANNING'
1184  bndelem => this%rough(n)
1185  call read_value_or_time_series_adv(text, n, jj, bndelem, &
1186  this%packName, 'BND', &
1187  this%tsManager, this%iprpak, &
1188  'MANNING')
1189  !
1190  ! -- set upstream fraction
1191  text = ustrfname
1192  jj = 1 ! For 'USTRF'
1193  bndelem => this%ustrf(n)
1194  call read_value_or_time_series_adv(text, n, jj, bndelem, &
1195  this%packName, 'BND', &
1196  this%tsManager, this%iprpak, 'USTRF')
1197  !
1198  ! -- get aux data
1199  do jj = 1, this%naux
1200  text = caux(jj)
1201  ii = n
1202  bndelem => this%rauxvar(jj, ii)
1203  call read_value_or_time_series_adv(text, ii, jj, bndelem, &
1204  this%packName, 'AUX', &
1205  this%tsManager, this%iprpak, &
1206  this%auxname(jj))
1207  end do
1208  !
1209  ! -- initialize sstage to the top of the reach
1210  ! this value would be used by simple routing reaches
1211  ! on kper = 1 and kstp = 1 if a stage is not specified
1212  ! on the status line for the reach
1213  this%sstage(n) = this%strtop(n)
1214 
1215  end do
1216  write (this%iout, '(1x,a)') &
1217  'END OF '//trim(adjustl(this%text))//' PACKAGEDATA'
1218  else
1219  call store_error('REQUIRED PACKAGEDATA BLOCK NOT FOUND.')
1220  end if
1221  !
1222  ! -- Check to make sure that every reach is specified and that no reach
1223  ! is specified more than once.
1224  do i = 1, this%maxbound
1225  if (nboundchk(i) == 0) then
1226  write (errmsg, '(a,i0,1x,a)') &
1227  'Information for reach ', i, 'not specified in packagedata block.'
1228  call store_error(errmsg)
1229  else if (nboundchk(i) > 1) then
1230  write (errmsg, '(a,1x,i0,1x,a,1x,i0)') &
1231  'Reach information specified', nboundchk(i), 'times for reach', i
1232  call store_error(errmsg)
1233  end if
1234  end do
1235  deallocate (nboundchk)
1236  !
1237  ! -- Submit warning message if any reach has zero connections
1238  if (nconzero > 0) then
1239  write (warnmsg, '(a,1x,a,1x,a,1x,i0,1x, a)') &
1240  'SFR Package', trim(this%packName), &
1241  'has', nconzero, 'reach(es) with zero connections.'
1242  call store_warning(warnmsg)
1243  end if
1244  !
1245  ! -- terminate if errors encountered in reach block
1246  if (count_errors() > 0) then
1247  call this%parser%StoreErrorUnit()
1248  end if
1249  !
1250  ! -- initialize the cross-section data
1251  ipos = 1
1252  this%iacross(1) = ipos
1253  do i = 1, this%maxbound
1254  this%ncrosspts(i) = 1
1255  this%station(ipos) = this%width(i)
1256  this%xsheight(ipos) = dzero
1257  this%xsrough(ipos) = done
1258  ipos = ipos + 1
1259  this%iacross(i + 1) = ipos
1260  end do
1261  !
1262  ! -- deallocate local storage for aux variables
1263  if (this%naux > 0) then
1264  deallocate (caux)
1265  end if
1266  end subroutine sfr_read_packagedata
1267 
1268  !> @ brief Read crosssection block for the package
1269  !!
1270  !! Method to read crosssection data for the SFR package.
1271  !<
1272  subroutine sfr_read_crossection(this)
1273  ! -- modules
1276  ! -- dummy
1277  class(sfrtype), intent(inout) :: this !< SfrType object
1278  ! -- local
1279  character(len=LINELENGTH) :: keyword
1280  character(len=LINELENGTH) :: line
1281  logical(LGP) :: isfound
1282  logical(LGP) :: endOfBlock
1283  integer(I4B) :: n
1284  integer(I4B) :: ierr
1285  integer(I4B) :: ncrossptstot
1286  integer, allocatable, dimension(:) :: nboundchk
1287  type(sfrcrosssection), pointer :: cross_data => null()
1288  !
1289  ! -- read cross-section data
1290  call this%parser%GetBlock('CROSSSECTIONS', isfound, ierr, &
1291  supportopenclose=.true., &
1292  blockrequired=.false.)
1293  !
1294  ! -- parse reach connectivity block if detected
1295  if (isfound) then
1296  write (this%iout, '(/1x,a)') &
1297  'PROCESSING '//trim(adjustl(this%text))//' CROSSSECTIONS'
1298  !
1299  ! -- allocate and initialize local variables for reach cross-sections
1300  allocate (nboundchk(this%maxbound))
1301  do n = 1, this%maxbound
1302  nboundchk(n) = 0
1303  end do
1304  !
1305  ! -- create and initialize cross-section data
1306  call cross_section_cr(cross_data, this%iout, this%iprpak, this%maxbound)
1307  call cross_data%initialize(this%ncrossptstot, this%ncrosspts, &
1308  this%iacross, &
1309  this%station, this%xsheight, &
1310  this%xsrough)
1311  !
1312  ! -- read all of the entries in the block
1313  readtable: do
1314  call this%parser%GetNextLine(endofblock)
1315  if (endofblock) exit
1316  !
1317  ! -- get reach number
1318  n = this%parser%GetInteger()
1319  !
1320  ! -- check for reach number error
1321  if (n < 1 .or. n > this%maxbound) then
1322  write (errmsg, '(a,1x,a,1x,i0)') &
1323  'SFR reach in crosssections block is less than one or greater', &
1324  'than NREACHES:', n
1325  call store_error(errmsg)
1326  cycle readtable
1327  end if
1328  !
1329  ! -- increment nboundchk
1330  nboundchk(n) = nboundchk(n) + 1
1331  !
1332  ! -- read FILE keyword
1333  call this%parser%GetStringCaps(keyword)
1334  select case (keyword)
1335  case ('TAB6')
1336  call this%parser%GetStringCaps(keyword)
1337  if (trim(adjustl(keyword)) /= 'FILEIN') then
1338  errmsg = 'TAB6 keyword must be followed by "FILEIN" '// &
1339  'then by filename.'
1340  call store_error(errmsg)
1341  cycle readtable
1342  end if
1343  call this%parser%GetString(line)
1344  call cross_data%read_table(n, this%width(n), &
1345  trim(adjustl(line)))
1346  case default
1347  write (errmsg, '(a,1x,i4,1x,a)') &
1348  'CROSS-SECTION TABLE ENTRY for REACH ', n, &
1349  'MUST INCLUDE TAB6 KEYWORD'
1350  call store_error(errmsg)
1351  cycle readtable
1352  end select
1353  end do readtable
1354 
1355  write (this%iout, '(1x,a)') &
1356  'END OF '//trim(adjustl(this%text))//' CROSSSECTIONS'
1357 
1358  !
1359  ! -- check for duplicate sfr crosssections
1360  do n = 1, this%maxbound
1361  if (nboundchk(n) > 1) then
1362  write (errmsg, '(a,1x,i0,1x,a,1x,i0,1x,a)') &
1363  'Cross-section data for reach', n, &
1364  'specified', nboundchk(n), 'times.'
1365  call store_error(errmsg)
1366  end if
1367  end do
1368  !
1369  ! -- terminate if errors encountered in cross-sections block
1370  if (count_errors() > 0) then
1371  call this%parser%StoreErrorUnit()
1372  end if
1373  !
1374  ! -- determine the current size of cross-section data
1375  ncrossptstot = cross_data%get_ncrossptstot()
1376  !
1377  ! -- reallocate sfr package cross-section data
1378  if (ncrossptstot /= this%ncrossptstot) then
1379  this%ncrossptstot = ncrossptstot
1380  call mem_reallocate(this%station, this%ncrossptstot, 'STATION', &
1381  this%memoryPath)
1382  call mem_reallocate(this%xsheight, this%ncrossptstot, 'XSHEIGHT', &
1383  this%memoryPath)
1384  call mem_reallocate(this%xsrough, this%ncrossptstot, 'XSROUGH', &
1385  this%memoryPath)
1386  end if
1387  !
1388  ! -- write cross-section data to the model listing file
1389  call cross_data%output(this%width, this%rough)
1390  !
1391  ! -- pack cross-section data
1392  call cross_data%pack(this%ncrossptstot, this%ncrosspts, &
1393  this%iacross, &
1394  this%station, &
1395  this%xsheight, &
1396  this%xsrough)
1397  !
1398  ! -- deallocate temporary local storage for reach cross-sections
1399  deallocate (nboundchk)
1400  call cross_data%destroy()
1401  deallocate (cross_data)
1402  nullify (cross_data)
1403  end if
1404  end subroutine sfr_read_crossection
1405 
1406  !> @ brief Read connectiondata for the package
1407  !!
1408  !! Method to read connectiondata for each reach for the SFR package.
1409  !<
1410  subroutine sfr_read_connectiondata(this)
1411  ! -- modules
1413  use sparsemodule, only: sparsematrix
1414  ! -- dummy
1415  class(sfrtype), intent(inout) :: this !< SfrType object
1416  ! -- local
1417  character(len=LINELENGTH) :: line
1418  logical(LGP) :: isfound
1419  logical(LGP) :: endOfBlock
1420  integer(I4B) :: n
1421  integer(I4B) :: i
1422  integer(I4B) :: j
1423  integer(I4B) :: jj
1424  integer(I4B) :: jcol
1425  integer(I4B) :: jcol2
1426  integer(I4B) :: nja
1427  integer(I4B) :: ival
1428  integer(I4B) :: idir
1429  integer(I4B) :: ierr
1430  integer(I4B) :: nconnmax
1431  integer(I4B) :: nup
1432  integer(I4B) :: ipos
1433  integer(I4B) :: istat
1434  integer(I4B), dimension(:), pointer, contiguous :: rowmaxnnz => null()
1435  integer, allocatable, dimension(:) :: nboundchk
1436  integer, allocatable, dimension(:, :) :: iconndata
1437  type(sparsematrix), pointer :: sparse => null()
1438  integer(I4B), dimension(:), allocatable :: iup
1439  integer(I4B), dimension(:), allocatable :: order
1440  type(dag) :: sfr_dag
1441  !
1442  ! -- allocate and initialize local variables for reach connections
1443  allocate (nboundchk(this%maxbound))
1444  do n = 1, this%maxbound
1445  nboundchk(n) = 0
1446  end do
1447  !
1448  ! -- calculate the number of non-zero entries (size of ja maxtrix)
1449  nja = 0
1450  nconnmax = 0
1451  allocate (rowmaxnnz(this%maxbound))
1452  do n = 1, this%maxbound
1453  ival = this%nconnreach(n)
1454  if (ival < 0) ival = 0
1455  rowmaxnnz(n) = ival + 1
1456  nja = nja + ival + 1
1457  if (ival > nconnmax) then
1458  nconnmax = ival
1459  end if
1460  end do
1461  !
1462  ! -- reallocate connection data for package
1463  call mem_reallocate(this%ja, nja, 'JA', this%memoryPath)
1464  call mem_reallocate(this%idir, nja, 'IDIR', this%memoryPath)
1465  call mem_reallocate(this%idiv, nja, 'IDIV', this%memoryPath)
1466  call mem_reallocate(this%qconn, nja, 'QCONN', this%memoryPath)
1467  !
1468  ! -- initialize connection data
1469  do n = 1, nja
1470  this%idir(n) = 0
1471  this%idiv(n) = 0
1472  this%qconn(n) = dzero
1473  end do
1474  !
1475  ! -- allocate space for iconndata
1476  allocate (iconndata(nconnmax, this%maxbound))
1477  !
1478  ! -- initialize iconndata
1479  do n = 1, this%maxbound
1480  do j = 1, nconnmax
1481  iconndata(j, n) = 0
1482  end do
1483  end do
1484  !
1485  ! -- allocate space for connectivity
1486  allocate (sparse)
1487  !
1488  ! -- set up sparse
1489  call sparse%init(this%maxbound, this%maxbound, rowmaxnnz)
1490  !
1491  ! -- read connection data
1492  call this%parser%GetBlock('CONNECTIONDATA', isfound, ierr, &
1493  supportopenclose=.true.)
1494  !
1495  ! -- parse reach connectivity block if detected
1496  if (isfound) then
1497  write (this%iout, '(/1x,a)') &
1498  'PROCESSING '//trim(adjustl(this%text))//' CONNECTIONDATA'
1499  do
1500  call this%parser%GetNextLine(endofblock)
1501  if (endofblock) exit
1502  !
1503  ! -- get reach number
1504  n = this%parser%GetInteger()
1505  !
1506  ! -- check for error
1507  if (n < 1 .or. n > this%maxbound) then
1508  write (errmsg, '(a,1x,a,1x,i0)') &
1509  'SFR reach in connectiondata block is less than one or greater', &
1510  'than NREACHES:', n
1511  call store_error(errmsg)
1512  cycle
1513  end if
1514  !
1515  ! -- increment nboundchk
1516  nboundchk(n) = nboundchk(n) + 1
1517  !
1518  ! -- add diagonal connection for reach
1519  call sparse%addconnection(n, n, 1)
1520  !
1521  ! -- fill off diagonals
1522  do i = 1, this%nconnreach(n)
1523  !
1524  ! -- get connected reach
1525  ival = this%parser%GetInteger()
1526  !
1527  ! -- save connection data to temporary iconndata
1528  iconndata(i, n) = ival
1529  !
1530  ! -- determine idir
1531  if (ival < 0) then
1532  idir = -1
1533  ival = abs(ival)
1534  elseif (ival == 0) then
1535  call store_error('Missing or zero connection reach in line:')
1536  call store_error(line)
1537  else
1538  idir = 1
1539  end if
1540  if (ival > this%maxbound) then
1541  call store_error('Reach number exceeds NREACHES in line:')
1542  call store_error(line)
1543  end if
1544  !
1545  ! -- add connection to sparse
1546  call sparse%addconnection(n, ival, 1)
1547  end do
1548  end do
1549 
1550  write (this%iout, '(1x,a)') &
1551  'END OF '//trim(adjustl(this%text))//' CONNECTIONDATA'
1552 
1553  do n = 1, this%maxbound
1554  !
1555  ! -- check for missing or duplicate sfr connections
1556  if (nboundchk(n) == 0) then
1557  write (errmsg, '(a,1x,i0)') &
1558  'No connection data specified for reach', n
1559  call store_error(errmsg)
1560  else if (nboundchk(n) > 1) then
1561  write (errmsg, '(a,1x,i0,1x,a,1x,i0,1x,a)') &
1562  'Connection data for reach', n, &
1563  'specified', nboundchk(n), 'times.'
1564  call store_error(errmsg)
1565  end if
1566  end do
1567  else
1568  call store_error('Required connectiondata block not found.')
1569  end if
1570  !
1571  ! -- terminate if errors encountered in connectiondata block
1572  if (count_errors() > 0) then
1573  call this%parser%StoreErrorUnit()
1574  end if
1575  !
1576  ! -- create ia and ja from sparse
1577  call sparse%filliaja(this%ia, this%ja, ierr, sort=.true.)
1578  !
1579  ! -- test for error condition
1580  if (ierr /= 0) then
1581  write (errmsg, '(a,3(1x,a))') &
1582  'Could not fill', trim(this%packName), &
1583  'package IA and JA connection data.', &
1584  'Check connectivity data in connectiondata block.'
1585  call store_error(errmsg)
1586  end if
1587  !
1588  ! -- fill flat connection storage
1589  do n = 1, this%maxbound
1590  do j = this%ia(n) + 1, this%ia(n + 1) - 1
1591  jcol = this%ja(j)
1592  do jj = 1, this%nconnreach(n)
1593  jcol2 = iconndata(jj, n)
1594  if (abs(jcol2) == jcol) then
1595  idir = 1
1596  if (jcol2 < 0) then
1597  idir = -1
1598  end if
1599  this%idir(j) = idir
1600  exit
1601  end if
1602  end do
1603  end do
1604  end do
1605  !
1606  ! -- deallocate temporary local storage for reach connections
1607  deallocate (rowmaxnnz)
1608  deallocate (nboundchk)
1609  deallocate (iconndata)
1610  !
1611  ! -- destroy sparse
1612  call sparse%destroy()
1613  deallocate (sparse)
1614  !
1615  ! -- calculate reach order using DAG
1616  !
1617  ! -- initialize the DAG
1618  call sfr_dag%set_vertices(this%maxbound)
1619  !
1620  ! -- fill DAG
1621  fill_dag: do n = 1, this%maxbound
1622  !
1623  ! -- determine the number of upstream reaches
1624  nup = 0
1625  do j = this%ia(n) + 1, this%ia(n + 1) - 1
1626  if (this%idir(j) > 0) then
1627  nup = nup + 1
1628  end if
1629  end do
1630  !
1631  ! -- cycle if nu upstream reacches
1632  if (nup == 0) cycle fill_dag
1633  !
1634  ! -- allocate local storage
1635  allocate (iup(nup))
1636  !
1637  ! -- fill local storage
1638  ipos = 1
1639  do j = this%ia(n) + 1, this%ia(n + 1) - 1
1640  if (this%idir(j) > 0) then
1641  iup(ipos) = this%ja(j)
1642  ipos = ipos + 1
1643  end if
1644  end do
1645  !
1646  ! -- add upstream connections to DAG
1647  call sfr_dag%set_edges(n, iup)
1648  !
1649  ! -- clean up local storage
1650  deallocate (iup)
1651  end do fill_dag
1652  !
1653  ! -- perform toposort on DAG
1654  call sfr_dag%toposort(order, istat)
1655  !
1656  ! -- write warning if circular dependency
1657  if (istat == -1) then
1658  write (warnmsg, '(a)') &
1659  trim(adjustl(this%text))//' PACKAGE ('// &
1660  trim(adjustl(this%packName))//') cannot calculate a '// &
1661  'Directed Asyclic Graph for reach connectivity because '// &
1662  'of circular dependency. Using the reach number for '// &
1663  'solution ordering.'
1664  call store_warning(warnmsg)
1665  end if
1666  !
1667  ! -- fill isfrorder
1668  do n = 1, this%maxbound
1669  if (istat == 0) then
1670  this%isfrorder(n) = order(n)
1671  else
1672  this%isfrorder(n) = n
1673  end if
1674  end do
1675  !
1676  ! -- clean up DAG and remaining local storage
1677  call sfr_dag%destroy()
1678  if (istat == 0) then
1679  deallocate (order)
1680  end if
1681  end subroutine sfr_read_connectiondata
1682 
1683  !> @ brief Read diversions for the package
1684  !!
1685  !! Method to read diversions for the SFR package.
1686  !<
1687  subroutine sfr_read_diversions(this)
1688  ! -- modules
1690  ! -- dummy
1691  class(sfrtype), intent(inout) :: this !< SfrType object
1692  ! -- local
1693  character(len=10) :: cnum
1694  character(len=10) :: cval
1695  integer(I4B) :: j
1696  integer(I4B) :: n
1697  integer(I4B) :: ierr
1698  integer(I4B) :: ival
1699  integer(I4B) :: i0
1700  integer(I4B) :: ipos
1701  integer(I4B) :: jpos
1702  integer(I4B) :: ndiv
1703  integer(I4B) :: ndiversions
1704  integer(I4B) :: idivreach
1705  logical(LGP) :: isfound
1706  logical(LGP) :: endOfBlock
1707  integer(I4B) :: idiv
1708  integer, allocatable, dimension(:) :: iachk
1709  integer, allocatable, dimension(:) :: nboundchk
1710  !
1711  ! -- determine the total number of diversions and fill iadiv
1712  ndiversions = 0
1713  i0 = 1
1714  this%iadiv(1) = i0
1715  do n = 1, this%maxbound
1716  ndiversions = ndiversions + this%ndiv(n)
1717  i0 = i0 + this%ndiv(n)
1718  this%iadiv(n + 1) = i0
1719  end do
1720  !
1721  ! -- reallocate memory for diversions
1722  if (ndiversions > 0) then
1723  call mem_reallocate(this%divreach, ndiversions, 'DIVREACH', &
1724  this%memoryPath)
1725  allocate (this%divcprior(ndiversions))
1726  call mem_reallocate(this%divflow, ndiversions, 'DIVFLOW', this%memoryPath)
1727  call mem_reallocate(this%divq, ndiversions, 'DIVQ', this%memoryPath)
1728  end if
1729  !
1730  ! -- initialize diversion flow
1731  do n = 1, ndiversions
1732  this%divflow(n) = dzero
1733  this%divq(n) = dzero
1734  end do
1735  !
1736  ! -- read diversions
1737  call this%parser%GetBlock('DIVERSIONS', isfound, ierr, &
1738  supportopenclose=.true., &
1739  blockrequired=.false.)
1740  !
1741  ! -- parse reach connectivity block if detected
1742  if (isfound) then
1743  if (this%idiversions /= 0) then
1744  write (this%iout, '(/1x,a)') 'PROCESSING '//trim(adjustl(this%text))// &
1745  ' DIVERSIONS'
1746  !
1747  ! -- allocate and initialize local variables for diversions
1748  ndiv = 0
1749  do n = 1, this%maxbound
1750  ndiv = ndiv + this%ndiv(n)
1751  end do
1752  allocate (iachk(this%maxbound + 1))
1753  allocate (nboundchk(ndiv))
1754  iachk(1) = 1
1755  do n = 1, this%maxbound
1756  iachk(n + 1) = iachk(n) + this%ndiv(n)
1757  end do
1758  do n = 1, ndiv
1759  nboundchk(n) = 0
1760  end do
1761  !
1762  ! -- read diversion data
1763  do
1764  call this%parser%GetNextLine(endofblock)
1765  if (endofblock) exit
1766  !
1767  ! -- get reach number
1768  n = this%parser%GetInteger()
1769  if (n < 1 .or. n > this%maxbound) then
1770  write (cnum, '(i0)') n
1771  errmsg = 'Reach number should be between 1 and '// &
1772  trim(cnum)//'.'
1773  call store_error(errmsg)
1774  cycle
1775  end if
1776  !
1777  ! -- make sure reach has at least one diversion
1778  if (this%ndiv(n) < 1) then
1779  write (cnum, '(i0)') n
1780  errmsg = 'Diversions cannot be specified '// &
1781  'for reach '//trim(cnum)
1782  call store_error(errmsg)
1783  cycle
1784  end if
1785  !
1786  ! -- read diversion number
1787  ival = this%parser%GetInteger()
1788  if (ival < 1 .or. ival > this%ndiv(n)) then
1789  write (cnum, '(i0)') n
1790  errmsg = 'Reach '//trim(cnum)
1791  write (cnum, '(i0)') this%ndiv(n)
1792  errmsg = trim(errmsg)//' diversion number should be between '// &
1793  '1 and '//trim(cnum)//'.'
1794  call store_error(errmsg)
1795  cycle
1796  end if
1797 
1798  ! -- increment nboundchk
1799  ipos = iachk(n) + ival - 1
1800  nboundchk(ipos) = nboundchk(ipos) + 1
1801 
1802  idiv = ival
1803  !
1804  ! -- get target reach for diversion
1805  ival = this%parser%GetInteger()
1806  if (ival < 1 .or. ival > this%maxbound) then
1807  write (cnum, '(i0)') ival
1808  errmsg = 'Diversion target reach number should be '// &
1809  'between 1 and '//trim(cnum)//'.'
1810  call store_error(errmsg)
1811  cycle
1812  end if
1813  idivreach = ival
1814  jpos = this%iadiv(n) + idiv - 1
1815  this%divreach(jpos) = idivreach
1816  !
1817  ! -- get cprior
1818  call this%parser%GetStringCaps(cval)
1819  ival = -1
1820  select case (cval)
1821  case ('UPTO')
1822  ival = 0
1823  case ('THRESHOLD')
1824  ival = -1
1825  case ('FRACTION')
1826  ival = -2
1827  case ('EXCESS')
1828  ival = -3
1829  case default
1830  errmsg = 'Invalid cprior type '//trim(cval)//'.'
1831  call store_error(errmsg)
1832  end select
1833  !
1834  ! -- set cprior for diversion
1835  this%divcprior(jpos) = cval
1836  end do
1837 
1838  write (this%iout, '(1x,a)') 'END OF '//trim(adjustl(this%text))// &
1839  ' DIVERSIONS'
1840 
1841  do n = 1, this%maxbound
1842  do j = 1, this%ndiv(n)
1843  ipos = iachk(n) + j - 1
1844  !
1845  ! -- check for missing or duplicate reach diversions
1846  if (nboundchk(ipos) == 0) then
1847  write (errmsg, '(a,1x,i0,1x,a,1x,i0)') &
1848  'No data specified for reach', n, 'diversion', j
1849  call store_error(errmsg)
1850  else if (nboundchk(ipos) > 1) then
1851  write (errmsg, '(a,1x,i0,1x,a,1x,i0,1x,a,1x,i0,1x,a)') &
1852  'Data for reach', n, 'diversion', j, &
1853  'specified', nboundchk(ipos), 'times'
1854  call store_error(errmsg)
1855  end if
1856  end do
1857  end do
1858  !
1859  ! -- deallocate local variables
1860  deallocate (iachk)
1861  deallocate (nboundchk)
1862  else
1863  !
1864  ! -- error condition
1865  write (errmsg, '(a,1x,a)') &
1866  'A diversions block should not be', &
1867  'specified if diversions are not specified.'
1868  call store_error(errmsg)
1869  end if
1870  else
1871  if (this%idiversions /= 0) then
1872  call store_error('REQUIRED DIVERSIONS BLOCK NOT FOUND.')
1873  end if
1874  end if
1875  !
1876  ! -- write summary of diversion error messages
1877  if (count_errors() > 0) then
1878  call this%parser%StoreErrorUnit()
1879  end if
1880  end subroutine sfr_read_diversions
1881 
1882  !> @ brief Read initialstages data for the package
1883  !!
1884  !! Method to read initialstages data for each reach for the SFR package.
1885  !<
1886  subroutine sfr_read_initial_stages(this)
1887  ! -- modules
1889  ! -- dummy
1890  class(sfrtype), intent(inout) :: this !< SfrType object
1891  ! -- local
1892  integer(I4B) :: n
1893  integer(I4B) :: ierr
1894  logical(LGP) :: isfound
1895  logical(LGP) :: endOfBlock
1896  integer(I4B) :: i
1897  real(DP) :: rval
1898  integer, allocatable, dimension(:) :: nboundchk
1899  !
1900  ! -- read data
1901  call this%parser%GetBlock('INITIALSTAGES', isfound, ierr, &
1902  supportopenclose=.true., &
1903  blockrequired=.false.)
1904  !
1905  ! -- parse block if detected
1906  if (isfound) then
1907  write (this%iout, '(/1x,a)') &
1908  'PROCESSING '//trim(adjustl(this%text))//' INITIALSTAGES'
1909 
1910  allocate (nboundchk(this%maxbound))
1911  do n = 1, this%maxbound
1912  nboundchk(n) = 0
1913  end do
1914 
1915  do
1916  call this%parser%GetNextLine(endofblock)
1917  if (endofblock) exit
1918 
1919  ! -- read reach number
1920  n = this%parser%GetInteger()
1921 
1922  if (n < 1 .or. n > this%maxbound) then
1923  write (errmsg, '(a,i0,a,1x,i0,a)') &
1924  'Reach number (', n, ') must be greater than 0 and less &
1925  &than or equal to', this%maxbound, '.'
1926  call store_error(errmsg)
1927  cycle
1928  end if
1929 
1930  ! -- increment nboundchk
1931  nboundchk(n) = nboundchk(n) + 1
1932 
1933  rval = this%parser%GetDouble()
1934  this%stage(n) = rval
1935  this%depth(n) = rval - this%strtop(n)
1936 
1937  if (rval < this%strtop(n)) then
1938  write (errmsg, '(a,g0,a,1x,i0,1x,a,g0,a)') &
1939  'Initial stage (', rval, ') for reach', n, &
1940  'is less than the reach top (', this%strtop(n), ').'
1941  call store_error(errmsg)
1942  end if
1943  end do
1944 
1945  write (this%iout, '(1x,a)') &
1946  'END OF '//trim(adjustl(this%text))//' INITIALSTAGES'
1947 
1948  !
1949  ! -- Check to make sure that every reach is specified and that no reach
1950  ! is specified more than once.
1951  do i = 1, this%maxbound
1952  if (nboundchk(i) == 0) then
1953  write (errmsg, '(a,i0,1x,a)') &
1954  'Information for reach ', i, 'not specified in initialstages block.'
1955  call store_error(errmsg)
1956  else if (nboundchk(i) > 1) then
1957  write (errmsg, '(a,1x,i0,1x,a,1x,i0)') &
1958  'Initial stage information specified', &
1959  nboundchk(i), 'times for reach', i
1960  call store_error(errmsg)
1961  end if
1962  end do
1963  deallocate (nboundchk)
1964  else
1965  ! -- set default initial stage based on a zero depth
1966  if (this%istorage == 1) then
1967  do n = 1, this%maxbound
1968  rval = this%strtop(n)
1969  this%stage(n) = rval
1970  end do
1971  end if
1972  end if
1973  !
1974  ! -- terminate if errors encountered in reach block
1975  if (count_errors() > 0) then
1976  call this%parser%StoreErrorUnit()
1977  end if
1978  end subroutine sfr_read_initial_stages
1979 
1980  !> @ brief Read and prepare period data for package
1981  !!
1982  !! Method to read and prepare period data for the SFR package.
1983  !<
1984  subroutine sfr_rp(this)
1985  ! -- modules
1986  use tdismodule, only: kper, nper
1989  ! -- dummy
1990  class(sfrtype), intent(inout) :: this !< SfrType object
1991  ! -- local
1992  character(len=LINELENGTH) :: title
1993  character(len=LINELENGTH) :: line
1994  character(len=LINELENGTH) :: crossfile
1995  integer(I4B) :: ierr
1996  integer(I4B) :: n
1997  integer(I4B) :: ichkustrm
1998  integer(I4B) :: ichkcross
1999  integer(I4B) :: ncrossptstot
2000  logical(LGP) :: isfound
2001  logical(LGP) :: endOfBlock
2002  type(sfrcrosssection), pointer :: cross_data => null()
2003  ! -- formats
2004  character(len=*), parameter :: fmtblkerr = &
2005  &"('Looking for BEGIN PERIOD iper. Found ', a, ' instead.')"
2006  character(len=*), parameter :: fmtlsp = &
2007  &"(1X,/1X,'REUSING ',A,'S FROM LAST STRESS PERIOD')"
2008  character(len=*), parameter :: fmtnbd = &
2009  "(1X,/1X,'The number of active ',A,'S (',I6, &
2010  &') is greater than maximum (',I6,')')"
2011  !
2012  ! -- initialize flags
2013  ichkustrm = 0
2014  ichkcross = 0
2015  if (kper == 1) then
2016  ichkustrm = 1
2017  end if
2018  !
2019  ! -- set nbound to maxbound
2020  this%nbound = this%maxbound
2021  !
2022  ! -- Set ionper to the stress period number for which a new block of data
2023  ! will be read.
2024  if (this%ionper < kper) then
2025  !
2026  ! -- get period block
2027  call this%parser%GetBlock('PERIOD', isfound, ierr, &
2028  supportopenclose=.true., &
2029  blockrequired=.false.)
2030  if (isfound) then
2031  !
2032  ! -- read ionper and check for increasing period numbers
2033  call this%read_check_ionper()
2034  else
2035  !
2036  ! -- PERIOD block not found
2037  if (ierr < 0) then
2038  ! -- End of file found; data applies for remainder of simulation.
2039  this%ionper = nper + 1
2040  else
2041  ! -- Found invalid block
2042  call this%parser%GetCurrentLine(line)
2043  write (errmsg, fmtblkerr) adjustl(trim(line))
2044  call store_error(errmsg)
2045  call this%parser%StoreErrorUnit()
2046  end if
2047  end if
2048  end if
2049  !
2050  ! -- Read data if ionper == kper
2051  if (this%ionper == kper) then
2052  !
2053  ! -- create and initialize cross-section data
2054  call cross_section_cr(cross_data, this%iout, this%iprpak, this%maxbound)
2055  call cross_data%initialize(this%ncrossptstot, this%ncrosspts, &
2056  this%iacross, &
2057  this%station, this%xsheight, &
2058  this%xsrough)
2059  !
2060  ! -- setup table for period data
2061  if (this%iprpak /= 0) then
2062  !
2063  ! -- reset the input table object
2064  title = trim(adjustl(this%text))//' PACKAGE ('// &
2065  trim(adjustl(this%packName))//') DATA FOR PERIOD'
2066  write (title, '(a,1x,i6)') trim(adjustl(title)), kper
2067  call table_cr(this%inputtab, this%packName, title)
2068  call this%inputtab%table_df(1, 4, this%iout, finalize=.false.)
2069  text = 'NUMBER'
2070  call this%inputtab%initialize_column(text, 10, alignment=tabcenter)
2071  text = 'KEYWORD'
2072  call this%inputtab%initialize_column(text, 20, alignment=tableft)
2073  do n = 1, 2
2074  write (text, '(a,1x,i6)') 'VALUE', n
2075  call this%inputtab%initialize_column(text, 15, alignment=tabcenter)
2076  end do
2077  end if
2078  !
2079  ! -- read data
2080  do
2081  call this%parser%GetNextLine(endofblock)
2082  if (endofblock) exit
2083  n = this%parser%GetInteger()
2084  if (n < 1 .or. n > this%maxbound) then
2085  write (errmsg, '(a,1x,a,1x,i0,a)') &
2086  'Reach number (RNO) must be greater than 0 and', &
2087  'less than or equal to', this%maxbound, '.'
2088  call store_error(errmsg)
2089  cycle
2090  end if
2091  !
2092  ! -- read data from the rest of the line
2093  call this%sfr_set_stressperiod(n, ichkustrm, crossfile)
2094  !
2095  ! -- write line to table
2096  if (this%iprpak /= 0) then
2097  call this%parser%GetCurrentLine(line)
2098  call this%inputtab%line_to_columns(line)
2099  end if
2100  !
2101  ! -- process cross-section file
2102  if (trim(adjustl(crossfile)) /= 'NONE') then
2103  call cross_data%read_table(n, this%width(n), &
2104  trim(adjustl(crossfile)))
2105  end if
2106  end do
2107  !
2108  ! -- write raw period data
2109  if (this%iprpak /= 0) then
2110  call this%inputtab%finalize_table()
2111  end if
2112  !
2113  ! -- finalize cross-sections
2114 
2115  !
2116  ! -- determine the current size of cross-section data
2117  ncrossptstot = cross_data%get_ncrossptstot()
2118  !
2119  ! -- reallocate sfr package cross-section data
2120  if (ncrossptstot /= this%ncrossptstot) then
2121  this%ncrossptstot = ncrossptstot
2122  call mem_reallocate(this%station, this%ncrossptstot, 'STATION', &
2123  this%memoryPath)
2124  call mem_reallocate(this%xsheight, this%ncrossptstot, 'XSHEIGHT', &
2125  this%memoryPath)
2126  call mem_reallocate(this%xsrough, this%ncrossptstot, 'XSROUGH', &
2127  this%memoryPath)
2128  end if
2129  !
2130  ! -- write cross-section data to the model listing file
2131  call cross_data%output(this%width, this%rough, kstp=1, kper=kper)
2132  !
2133  ! -- pack cross-section data
2134  call cross_data%pack(this%ncrossptstot, this%ncrosspts, &
2135  this%iacross, &
2136  this%station, &
2137  this%xsheight, &
2138  this%xsrough)
2139  !
2140  ! -- deallocate temporary local storage for reach cross-sections
2141  call cross_data%destroy()
2142  deallocate (cross_data)
2143  nullify (cross_data)
2144  !
2145  ! -- Reuse data from last stress period
2146  else
2147  write (this%iout, fmtlsp) trim(this%filtyp)
2148  end if
2149  !
2150  ! -- check upstream fraction values
2151  if (ichkustrm /= 0) then
2152  call this%sfr_check_ustrf()
2153  end if
2154  !
2155  ! -- write summary of package block error messages
2156  if (count_errors() > 0) then
2157  call this%parser%StoreErrorUnit()
2158  end if
2159  end subroutine sfr_rp
2160 
2161  !> @ brief Advance the package
2162  !!
2163  !! Advance data in the SFR package. The method sets advances
2164  !! time series, time array series, and observation data.
2165  !<
2166  subroutine sfr_ad(this)
2167  ! -- modules
2169  ! -- dummy
2170  class(sfrtype) :: this !< SfrType object
2171  ! -- local
2172  integer(I4B) :: n
2173  integer(I4B) :: iaux
2174 
2175  ! -- update previous values
2176  if (this%istorage == 1) then
2177  do n = 1, this%maxbound
2178  this%stageold(n) = this%stage(n)
2179  this%usinflowold(n) = this%usinflow(n)
2180  this%dsflowold(n) = this%dsflow(n)
2181  end do
2182  end if
2183  !
2184  ! -- Most advanced package AD routines have to restore state if
2185  ! the solution failed and the time step is being retried with a smaller
2186  ! step size. This is not needed here because there is no old stage
2187  ! or storage effects in the stream.
2188  !
2189  ! -- Advance the time series manager
2190  call this%TsManager%ad()
2191  !
2192  ! -- check upstream fractions if time series are being used to
2193  ! define this variable
2194  if (var_timeseries(this%tsManager, this%packName, 'USTRF')) then
2195  call this%sfr_check_ustrf()
2196  end if
2197  !
2198  ! -- update auxiliary variables by copying from the derived-type time
2199  ! series variable into the bndpackage auxvar variable so that this
2200  ! information is properly written to the GWF budget file
2201  if (this%naux > 0) then
2202  do n = 1, this%maxbound
2203  do iaux = 1, this%naux
2204  if (this%noupdateauxvar(iaux) /= 0) cycle
2205  this%auxvar(iaux, n) = this%rauxvar(iaux, n)
2206  end do
2207  end do
2208  end if
2209  !
2210  ! -- reset upstream flow to zero and set specified stage
2211  do n = 1, this%maxbound
2212  this%usflow(n) = dzero
2213  if (this%iboundpak(n) < 0) then
2214  this%stage(n) = this%sstage(n)
2215  end if
2216  end do
2217  !
2218  ! -- pakmvrobj ad
2219  if (this%imover == 1) then
2220  call this%pakmvrobj%ad()
2221  end if
2222  !
2223  ! -- For each observation, push simulated value and corresponding
2224  ! simulation time from "current" to "preceding" and reset
2225  ! "current" value.
2226  call this%obs%obs_ad()
2227  end subroutine sfr_ad
2228 
2229  !> @ brief Formulate the package hcof and rhs terms.
2230  !!
2231  !! Formulate the hcof and rhs terms for the WEL package that will be
2232  !! added to the coefficient matrix and right-hand side vector.
2233  !<
2234  subroutine sfr_cf(this)
2235  ! -- dummy
2236  class(sfrtype) :: this !< SfrType object
2237  ! -- local
2238  integer(I4B) :: n
2239  integer(I4B) :: igwfnode
2240  !
2241  ! -- return if no sfr reaches
2242  if (this%nbound == 0) return
2243  !
2244  ! -- find highest active cell
2245  do n = 1, this%nbound
2246  igwfnode = this%igwftopnode(n)
2247  if (igwfnode > 0) then
2248  if (this%ibound(igwfnode) == 0) then
2249  call this%dis%highest_active(igwfnode, this%ibound)
2250  end if
2251  end if
2252  this%igwfnode(n) = igwfnode
2253  this%nodelist(n) = igwfnode
2254  end do
2255  end subroutine sfr_cf
2256 
2257  !> @ brief Copy hcof and rhs terms into solution.
2258  !!
2259  !! Add the hcof and rhs terms for the SFR package to the
2260  !! coefficient matrix and right-hand side vector.
2261  !<
2262  subroutine sfr_fc(this, rhs, ia, idxglo, matrix_sln)
2263  ! -- dummy
2264  class(sfrtype) :: this !< SfrType object
2265  real(DP), dimension(:), intent(inout) :: rhs !< right-hand side vector for model
2266  integer(I4B), dimension(:), intent(in) :: ia !< solution CRS row pointers
2267  integer(I4B), dimension(:), intent(in) :: idxglo !< mapping vector for model (local) to solution (global)
2268  class(matrixbasetype), pointer :: matrix_sln !< solution coefficient matrix
2269  ! -- local
2270  integer(I4B) :: i
2271  integer(I4B) :: j
2272  integer(I4B) :: n
2273  integer(I4B) :: ipos
2274  integer(I4B) :: node
2275  real(DP) :: s0
2276  real(DP) :: ds
2277  real(DP) :: dsmax
2278  real(DP) :: hgwf
2279  real(DP) :: v
2280  real(DP) :: hhcof
2281  real(DP) :: rrhs
2282  !
2283  ! -- picard iterations for sfr to achieve good solution regardless
2284  ! of reach order
2285  sfrpicard: do i = 1, this%maxsfrpicard
2286  !
2287  ! -- initialize maximum stage change for iteration to zero
2288  dsmax = dzero
2289  !
2290  ! -- pakmvrobj fc - reset qformvr to zero
2291  if (this%imover == 1) then
2292  call this%pakmvrobj%fc()
2293  end if
2294  !
2295  ! -- solve for each sfr reach
2296  reachsolve: do j = 1, this%nbound
2297  n = this%isfrorder(j)
2298  node = this%igwfnode(n)
2299  if (node > 0) then
2300  hgwf = this%xnew(node)
2301  else
2302  hgwf = dep20
2303  end if
2304  !
2305  ! -- save previous stage and upstream flow
2306  if (i == 1) then
2307  this%stage0(n) = this%stage(n)
2308  this%usflow0(n) = this%usflow(n)
2309  end if
2310  !
2311  ! -- set initial stage to calculate stage change
2312  s0 = this%stage(n)
2313  !
2314  ! -- solve for flow in swr
2315  if (this%iboundpak(n) /= 0) then
2316  call this%sfr_solve(n, hgwf, hhcof, rrhs)
2317  else
2318  this%depth(n) = dzero
2319  this%stage(n) = this%strtop(n)
2320  v = dzero
2321  call this%sfr_update_flows(n, v, v)
2322  hhcof = dzero
2323  rrhs = dzero
2324  end if
2325  !
2326  ! -- set package hcof and rhs
2327  this%hcof(n) = hhcof
2328  this%rhs(n) = rrhs
2329  !
2330  ! -- calculate stage change
2331  ds = s0 - this%stage(n)
2332  !
2333  ! -- evaluate if stage change exceeds dsmax
2334  if (abs(ds) > abs(dsmax)) then
2335  dsmax = ds
2336  end if
2337 
2338  end do reachsolve
2339  !
2340  ! -- evaluate if the sfr picard iterations should be terminated
2341  if (abs(dsmax) <= this%dmaxchg) then
2342  exit sfrpicard
2343  end if
2344 
2345  end do sfrpicard
2346  !
2347  ! -- Copy package rhs and hcof into solution rhs and amat
2348  do n = 1, this%nbound
2349  node = this%nodelist(n)
2350  if (node < 1) cycle
2351  rhs(node) = rhs(node) + this%rhs(n)
2352  ipos = ia(node)
2353  call matrix_sln%add_value_pos(idxglo(ipos), this%hcof(n))
2354  end do
2355  end subroutine sfr_fc
2356 
2357  !> @ brief Add Newton-Raphson terms for package into solution.
2358  !!
2359  !! Calculate and add the Newton-Raphson terms for the SFR package to the
2360  !! coefficient matrix and right-hand side vector.
2361  !<
2362  subroutine sfr_fn(this, rhs, ia, idxglo, matrix_sln)
2363  ! -- dummy
2364  class(sfrtype) :: this !< SfrType object
2365  real(DP), dimension(:), intent(inout) :: rhs !< right-hand side vector for model
2366  integer(I4B), dimension(:), intent(in) :: ia !< solution CRS row pointers
2367  integer(I4B), dimension(:), intent(in) :: idxglo !< mapping vector for model (local) to solution (global)
2368  class(matrixbasetype), pointer :: matrix_sln !< solution coefficient matrix
2369  ! -- local
2370  integer(I4B) :: i
2371  integer(I4B) :: j
2372  integer(I4B) :: n
2373  integer(I4B) :: ipos
2374  real(DP) :: rterm
2375  real(DP) :: drterm
2376  real(DP) :: rhs1
2377  real(DP) :: hcof1
2378  real(DP) :: q1
2379  real(DP) :: q2
2380  real(DP) :: hgwf
2381  !
2382  ! -- Copy package rhs and hcof into solution rhs and amat
2383  do j = 1, this%nbound
2384  i = this%isfrorder(j)
2385  ! -- skip inactive reaches
2386  if (this%iboundpak(i) < 1) cycle
2387  ! -- skip if reach is not connected to gwf
2388  n = this%nodelist(i)
2389  if (n < 1) cycle
2390  ipos = ia(n)
2391  rterm = this%hcof(i) * this%xnew(n)
2392  ! -- calculate perturbed head
2393  hgwf = this%xnew(n) + dem4
2394  call this%sfr_solve(i, hgwf, hcof1, rhs1, update=.false.)
2395  q1 = rhs1 - hcof1 * hgwf
2396  ! -- calculate unperturbed head
2397  q2 = this%rhs(i) - this%hcof(i) * this%xnew(n)
2398  ! -- calculate derivative
2399  drterm = (q2 - q1) / dem4
2400  ! -- add terms to convert conductance formulation into
2401  ! newton-raphson formulation
2402  call matrix_sln%add_value_pos(idxglo(ipos), drterm - this%hcof(i))
2403  rhs(n) = rhs(n) - rterm + drterm * this%xnew(n)
2404  end do
2405  end subroutine sfr_fn
2406 
2407  !> @ brief Convergence check for package.
2408  !!
2409  !! Perform additional convergence checks on the flow between the SFR package
2410  !! and the model it is attached to.
2411  !<
2412  subroutine sfr_cc(this, innertot, kiter, iend, icnvgmod, cpak, ipak, dpak)
2413  ! -- modules
2414  use tdismodule, only: totim, kstp, kper, delt
2415  ! -- dummy
2416  class(sfrtype), intent(inout) :: this !< SfrType object
2417  integer(I4B), intent(in) :: innertot !< total number of inner iterations
2418  integer(I4B), intent(in) :: kiter !< Picard iteration number
2419  integer(I4B), intent(in) :: iend !< flag indicating if this is the last Picard iteration
2420  integer(I4B), intent(in) :: icnvgmod !< flag inficating if the model has met specific convergence criteria
2421  character(len=LENPAKLOC), intent(inout) :: cpak !< string for user node
2422  integer(I4B), intent(inout) :: ipak !< location of the maximum dependent variable change
2423  real(DP), intent(inout) :: dpak !< maximum dependent variable change
2424  ! -- local
2425  character(len=LENPAKLOC) :: cloc
2426  character(len=LINELENGTH) :: tag
2427  integer(I4B) :: icheck
2428  integer(I4B) :: ipakfail
2429  integer(I4B) :: locdhmax
2430  integer(I4B) :: locrmax
2431  integer(I4B) :: locdqfrommvrmax
2432  integer(I4B) :: ntabrows
2433  integer(I4B) :: ntabcols
2434  integer(I4B) :: n
2435  real(DP) :: q
2436  real(DP) :: q0
2437  real(DP) :: qtolfact
2438  real(DP) :: dh
2439  real(DP) :: r
2440  real(DP) :: dhmax
2441  real(DP) :: rmax
2442  real(DP) :: dqfrommvr
2443  real(DP) :: dqfrommvrmax
2444  !
2445  ! -- initialize local variables
2446  icheck = this%iconvchk
2447  ipakfail = 0
2448  locdhmax = 0
2449  locrmax = 0
2450  r = dzero
2451  dhmax = dzero
2452  rmax = dzero
2453  locdqfrommvrmax = 0
2454  dqfrommvrmax = dzero
2455  !
2456  ! -- if not saving package convergence data on check convergence if
2457  ! the model is considered converged
2458  if (this%ipakcsv == 0) then
2459  if (icnvgmod == 0) then
2460  icheck = 0
2461  end if
2462  !
2463  ! -- saving package convergence data
2464  else
2465  !
2466  ! -- header for package csv
2467  if (.not. associated(this%pakcsvtab)) then
2468  !
2469  ! -- determine the number of columns and rows
2470  ntabrows = 1
2471  ntabcols = 9
2472  if (this%imover == 1) then
2473  ntabcols = ntabcols + 2
2474  end if
2475  !
2476  ! -- setup table
2477  call table_cr(this%pakcsvtab, this%packName, '')
2478  call this%pakcsvtab%table_df(ntabrows, ntabcols, this%ipakcsv, &
2479  lineseparator=.false., separator=',', &
2480  finalize=.false.)
2481  !
2482  ! -- add columns to package csv
2483  tag = 'total_inner_iterations'
2484  call this%pakcsvtab%initialize_column(tag, 10, alignment=tableft)
2485  tag = 'totim'
2486  call this%pakcsvtab%initialize_column(tag, 10, alignment=tableft)
2487  tag = 'kper'
2488  call this%pakcsvtab%initialize_column(tag, 10, alignment=tableft)
2489  tag = 'kstp'
2490  call this%pakcsvtab%initialize_column(tag, 10, alignment=tableft)
2491  tag = 'nouter'
2492  call this%pakcsvtab%initialize_column(tag, 10, alignment=tableft)
2493  tag = 'dvmax'
2494  call this%pakcsvtab%initialize_column(tag, 15, alignment=tableft)
2495  tag = 'dvmax_loc'
2496  call this%pakcsvtab%initialize_column(tag, 15, alignment=tableft)
2497  tag = 'dinflowmax'
2498  call this%pakcsvtab%initialize_column(tag, 15, alignment=tableft)
2499  tag = 'dinflowmax_loc'
2500  call this%pakcsvtab%initialize_column(tag, 15, alignment=tableft)
2501  if (this%imover == 1) then
2502  tag = 'dqfrommvrmax'
2503  call this%pakcsvtab%initialize_column(tag, 15, alignment=tableft)
2504  tag = 'dqfrommvrmax_loc'
2505  call this%pakcsvtab%initialize_column(tag, 16, alignment=tableft)
2506  end if
2507  end if
2508  end if
2509  !
2510  ! -- perform package convergence check
2511  if (icheck /= 0) then
2512  final_check: do n = 1, this%maxbound
2513  if (this%iboundpak(n) == 0) cycle
2514  !
2515  ! -- set the Q to length factor
2516  qtolfact = delt / this%calc_surface_area(n)
2517  !
2518  ! -- calculate stage change
2519  dh = this%stage0(n) - this%stage(n)
2520  !
2521  ! -- evaluate flow difference if the time step is transient
2522  if (this%gwfiss == 0) then
2523  r = this%usflow0(n) - this%usflow(n)
2524  !
2525  ! -- normalize flow difference and convert to a depth
2526  r = r * qtolfact
2527  end if
2528  !
2529  ! -- q from mvr
2530  dqfrommvr = dzero
2531  if (this%imover == 1) then
2532  q = this%pakmvrobj%get_qfrommvr(n)
2533  q0 = this%pakmvrobj%get_qfrommvr0(n)
2534  dqfrommvr = qtolfact * (q0 - q)
2535  end if
2536  !
2537  ! -- evaluate magnitude of differences
2538  if (n == 1) then
2539  locdhmax = n
2540  dhmax = dh
2541  locrmax = n
2542  rmax = r
2543  dqfrommvrmax = dqfrommvr
2544  locdqfrommvrmax = n
2545  else
2546  if (abs(dh) > abs(dhmax)) then
2547  locdhmax = n
2548  dhmax = dh
2549  end if
2550  if (abs(r) > abs(rmax)) then
2551  locrmax = n
2552  rmax = r
2553  end if
2554  if (abs(dqfrommvr) > abs(dqfrommvrmax)) then
2555  dqfrommvrmax = dqfrommvr
2556  locdqfrommvrmax = n
2557  end if
2558  end if
2559  end do final_check
2560  !
2561  ! -- set dpak and cpak
2562  if (abs(dhmax) > abs(dpak)) then
2563  ipak = locdhmax
2564  dpak = dhmax
2565  write (cloc, "(a,'-',a)") trim(this%packName), 'stage'
2566  cpak = trim(cloc)
2567  end if
2568  if (abs(rmax) > abs(dpak)) then
2569  ipak = locrmax
2570  dpak = rmax
2571  write (cloc, "(a,'-',a)") trim(this%packName), 'inflow'
2572  cpak = trim(cloc)
2573  end if
2574  if (this%imover == 1) then
2575  if (abs(dqfrommvrmax) > abs(dpak)) then
2576  ipak = locdqfrommvrmax
2577  dpak = dqfrommvrmax
2578  write (cloc, "(a,'-',a)") trim(this%packName), 'qfrommvr'
2579  cpak = trim(cloc)
2580  end if
2581  end if
2582  !
2583  ! -- write convergence data to package csv
2584  if (this%ipakcsv /= 0) then
2585  !
2586  ! -- write the data
2587  call this%pakcsvtab%add_term(innertot)
2588  call this%pakcsvtab%add_term(totim)
2589  call this%pakcsvtab%add_term(kper)
2590  call this%pakcsvtab%add_term(kstp)
2591  call this%pakcsvtab%add_term(kiter)
2592  call this%pakcsvtab%add_term(dhmax)
2593  call this%pakcsvtab%add_term(locdhmax)
2594  call this%pakcsvtab%add_term(rmax)
2595  call this%pakcsvtab%add_term(locrmax)
2596  if (this%imover == 1) then
2597  call this%pakcsvtab%add_term(dqfrommvrmax)
2598  call this%pakcsvtab%add_term(locdqfrommvrmax)
2599  end if
2600  !
2601  ! -- finalize the package csv
2602  if (iend == 1) then
2603  call this%pakcsvtab%finalize_table()
2604  end if
2605  end if
2606  end if
2607  !
2608  end subroutine sfr_cc
2609 
2610  !> @ brief Calculate package flows.
2611  !!
2612  !! Calculate the flow between connected SFR package control volumes.
2613  !<
2614  subroutine sfr_cq(this, x, flowja, iadv)
2615  ! -- modules
2616  use budgetmodule, only: budgettype
2617  ! -- dummy
2618  class(sfrtype), intent(inout) :: this !< SfrType object
2619  real(DP), dimension(:), intent(in) :: x !< current dependent-variable value
2620  real(DP), dimension(:), contiguous, intent(inout) :: flowja !< flow between two connected control volumes
2621  integer(I4B), optional, intent(in) :: iadv !< flag that indicates if this is an advance package
2622  ! -- local
2623  integer(I4B) :: i
2624  real(DP) :: qext
2625  ! -- for budget
2626  integer(I4B) :: n
2627  integer(I4B) :: n2
2628  real(DP) :: qoutflow
2629  real(DP) :: qfrommvr
2630  real(DP) :: qtomvr
2631  !
2632  ! -- call base functionality in bnd_cq. This will calculate sfr-gwf flows
2633  ! and put them into this%simvals
2634  call this%BndType%bnd_cq(x, flowja, iadv=1)
2635  !
2636  ! -- Calculate qextoutflow and qoutflow for subsequent budgets
2637  do n = 1, this%maxbound
2638  !
2639  ! -- mover
2640  qfrommvr = dzero
2641  qtomvr = dzero
2642  if (this%imover == 1) then
2643  qfrommvr = this%pakmvrobj%get_qfrommvr(n)
2644  qtomvr = this%pakmvrobj%get_qtomvr(n)
2645  if (qtomvr > dzero) then
2646  qtomvr = -qtomvr
2647  end if
2648  end if
2649  !
2650  ! -- external downstream stream flow
2651  qext = this%dsflow(n)
2652  qoutflow = dzero
2653  if (qext > dzero) then
2654  qext = -qext
2655  end if
2656  do i = this%ia(n) + 1, this%ia(n + 1) - 1
2657  if (this%idir(i) > 0) cycle
2658  n2 = this%ja(i)
2659  if (this%iboundpak(n2) == 0) cycle
2660  qext = dzero
2661  exit
2662  end do
2663  !
2664  ! -- adjust external downstream stream flow using qtomvr
2665  if (qext < dzero) then
2666  if (qtomvr < dzero) then
2667  qext = qext - qtomvr
2668  end if
2669  else
2670  qoutflow = this%dsflow(n)
2671  if (qoutflow > dzero) then
2672  qoutflow = -qoutflow
2673  end if
2674  end if
2675  !
2676  ! -- set qextoutflow and qoutflow for cell by cell budget
2677  ! output and observations
2678  this%qextoutflow(n) = qext
2679  this%qoutflow(n) = qoutflow
2680  !
2681  end do
2682  !
2683  ! -- fill the budget object
2684  call this%sfr_fill_budobj()
2685  end subroutine sfr_cq
2686 
2687  !> @ brief Output package flow terms.
2688  !!
2689  !! Output SFR package flow terms.
2690  !<
2691  subroutine sfr_ot_package_flows(this, icbcfl, ibudfl)
2692  ! -- modules
2693  use tdismodule, only: kstp, kper, delt, pertim, totim
2694  ! -- dummy
2695  class(sfrtype) :: this !< SfrType object
2696  integer(I4B), intent(in) :: icbcfl !< flag and unit number for cell-by-cell output
2697  integer(I4B), intent(in) :: ibudfl !< flag indication if cell-by-cell data should be saved
2698  ! -- local
2699  integer(I4B) :: ibinun
2700  character(len=20), dimension(:), allocatable :: cellidstr
2701  integer(I4B) :: n
2702  integer(I4B) :: node
2703  !
2704  ! -- write the flows from the budobj
2705  ibinun = 0
2706  if (this%ibudgetout /= 0) then
2707  ibinun = this%ibudgetout
2708  end if
2709  if (icbcfl == 0) ibinun = 0
2710  if (ibinun > 0) then
2711  call this%budobj%save_flows(this%dis, ibinun, kstp, kper, delt, &
2712  pertim, totim, this%iout)
2713  end if
2714  !
2715  ! -- Print sfr flows table
2716  if (ibudfl /= 0 .and. this%iprflow /= 0) then
2717  !
2718  ! -- If there are any 'none' gwf connections then need to calculate
2719  ! a vector of cellids and pass that in to the budget flow table because
2720  ! the table assumes that there are maxbound gwf entries, which is not
2721  ! the case if any 'none's are specified.
2722  if (this%ianynone > 0) then
2723  allocate (cellidstr(this%maxbound))
2724  do n = 1, this%maxbound
2725  node = this%igwfnode(n)
2726  if (node > 0) then
2727  call this%dis%noder_to_string(node, cellidstr(n))
2728  else
2729  cellidstr(n) = 'NONE'
2730  end if
2731  end do
2732  call this%budobj%write_flowtable(this%dis, kstp, kper, cellidstr)
2733  deallocate (cellidstr)
2734  else
2735  call this%budobj%write_flowtable(this%dis, kstp, kper)
2736  end if
2737  end if
2738  end subroutine sfr_ot_package_flows
2739 
2740  !> @ brief Output package dependent-variable terms.
2741  !!
2742  !! Output SFR boundary package dependent-variable terms.
2743  !<
2744  subroutine sfr_ot_dv(this, idvsave, idvprint)
2745  ! -- modules
2746  use tdismodule, only: kstp, kper, pertim, totim
2747  use inputoutputmodule, only: ulasav
2748  ! -- dummy
2749  class(sfrtype) :: this !< SfrType object
2750  integer(I4B), intent(in) :: idvsave !< flag and unit number for dependent-variable output
2751  integer(I4B), intent(in) :: idvprint !< flag indicating if dependent-variable should be written to the model listing file
2752  ! -- local
2753  character(len=20) :: cellid
2754  integer(I4B) :: ibinun
2755  integer(I4B) :: n
2756  integer(I4B) :: node
2757  real(DP) :: d
2758  real(DP) :: v
2759  real(DP) :: hgwf
2760  real(DP) :: sbot
2761  real(DP) :: depth
2762  real(DP) :: stage
2763  real(DP) :: w
2764  real(DP) :: cond
2765  real(DP) :: grad
2766  !
2767  ! -- set unit number for binary dependent variable output
2768  ibinun = 0
2769  if (this%istageout /= 0) then
2770  ibinun = this%istageout
2771  end if
2772  if (idvsave == 0) ibinun = 0
2773  !
2774  ! -- write sfr binary output
2775  if (ibinun > 0) then
2776  do n = 1, this%maxbound
2777  d = this%depth(n)
2778  v = this%stage(n)
2779  if (this%iboundpak(n) == 0) then
2780  v = dhnoflo
2781  else if (d == dzero) then
2782  v = dhdry
2783  end if
2784  this%dbuff(n) = v
2785  end do
2786  call ulasav(this%dbuff, ' STAGE', kstp, kper, pertim, totim, &
2787  this%maxbound, 1, 1, ibinun)
2788  end if
2789  !
2790  ! -- print sfr stage and depth table
2791  if (idvprint /= 0 .and. this%iprhed /= 0) then
2792  !
2793  ! -- set table kstp and kper
2794  call this%stagetab%set_kstpkper(kstp, kper)
2795  !
2796  ! -- fill stage data
2797  do n = 1, this%maxbound
2798  node = this%igwfnode(n)
2799  if (node > 0) then
2800  call this%dis%noder_to_string(node, cellid)
2801  hgwf = this%xnew(node)
2802  else
2803  cellid = 'NONE'
2804  end if
2805  if (this%inamedbound == 1) then
2806  call this%stagetab%add_term(this%boundname(n))
2807  end if
2808  call this%stagetab%add_term(n)
2809  call this%stagetab%add_term(cellid)
2810  if (this%iboundpak(n) /= 0) then
2811  depth = this%depth(n)
2812  stage = this%stage(n)
2813  w = this%calc_top_width_wet(n, depth)
2814  call this%sfr_calc_cond(n, depth, cond, stage, hgwf)
2815  else
2816  depth = dhnoflo
2817  stage = dhnoflo
2818  w = dhnoflo
2819  cond = dhnoflo
2820  end if
2821  if (depth == dzero) then
2822  call this%stagetab%add_term(dhdry)
2823  else
2824  call this%stagetab%add_term(stage)
2825  end if
2826  call this%stagetab%add_term(depth)
2827  call this%stagetab%add_term(w)
2828  if (node > 0) then
2829  if (this%iboundpak(n) /= 0) then
2830  sbot = this%strtop(n) - this%bthick(n)
2831  if (hgwf < sbot) then
2832  grad = stage - sbot
2833  else
2834  grad = stage - hgwf
2835  end if
2836  grad = grad / this%bthick(n)
2837  else
2838  grad = dhnoflo
2839  end if
2840  call this%stagetab%add_term(hgwf)
2841  call this%stagetab%add_term(cond)
2842  call this%stagetab%add_term(grad)
2843  else
2844  call this%stagetab%add_term('--')
2845  call this%stagetab%add_term('--')
2846  call this%stagetab%add_term('--')
2847  end if
2848  end do
2849  end if
2850  end subroutine sfr_ot_dv
2851 
2852  !> @ brief Output advanced package budget summary.
2853  !!
2854  !! Output SFR package budget summary.
2855  !<
2856  subroutine sfr_ot_bdsummary(this, kstp, kper, iout, ibudfl)
2857  ! -- module
2858  use tdismodule, only: totim, delt
2859  ! -- dummy
2860  class(sfrtype) :: this !< SfrType object
2861  integer(I4B), intent(in) :: kstp !< time step number
2862  integer(I4B), intent(in) :: kper !< period number
2863  integer(I4B), intent(in) :: iout !< flag and unit number for the model listing file
2864  integer(I4B), intent(in) :: ibudfl !< flag indicating budget should be written
2865  !
2866  call this%budobj%write_budtable(kstp, kper, iout, ibudfl, totim, delt)
2867  end subroutine sfr_ot_bdsummary
2868 
2869  !> @brief Write the Courant-number summary table to the listing file
2870  !<
2871  subroutine sfr_fp(this)
2872  ! -- dummy
2873  class(sfrtype) :: this !< SfrType object
2874  ! -- local
2875  integer(I4B) :: n
2876  real(DP) :: crmean
2877  !
2878  if (this%istorage == 1) then
2879  do n = 1, this%maxbound
2880  if (this%inamedbound == 1) then
2881  call this%couranttab%add_term(this%boundname(n))
2882  end if
2883  call this%couranttab%add_term(n)
2884  if (this%crmin(n) == dep20) then
2885  call this%couranttab%add_term('--')
2886  else
2887  call this%couranttab%add_term(this%crmin(n))
2888  end if
2889  if (this%crmax(n) < dzero) then
2890  call this%couranttab%add_term('--')
2891  else
2892  call this%couranttab%add_term(this%crmax(n))
2893  end if
2894  if (this%crcnt(n) > 0) then
2895  crmean = this%crsum(n) / real(this%crcnt(n), dp)
2896  call this%couranttab%add_term(crmean)
2897  else
2898  call this%couranttab%add_term('--')
2899  end if
2900  end do
2901  end if
2902  end subroutine sfr_fp
2903 
2904  !> @brief Submit the ATS time step for the most Courant-constraining reach
2905  !<
2906  subroutine sfr_dt(this)
2907  ! -- modules
2908  use tdismodule, only: kstp, kper, ats
2909  ! -- dummy
2910  class(sfrtype) :: this !< SfrType object
2911  ! -- local
2912  integer(I4B) :: n
2913  integer(I4B) :: nrmin
2914  real(DP) :: celerity
2915  real(DP) :: dt_n
2916  real(DP) :: dtmin
2917  character(len=LINELENGTH) :: msg
2918  !
2919  if (this%ats_courant == dnodata) return
2920  if (this%istorage /= 1) return
2921  !
2922  dtmin = dnodata
2923  nrmin = 0
2924  !
2925  do n = 1, this%maxbound
2926  call this%sfr_calc_celerity(n, this%dsflow(n), celerity)
2927  if (celerity > dzero) then
2928  dt_n = this%ats_courant * this%length(n) / celerity
2929  if (dt_n < dtmin) then
2930  dtmin = dt_n
2931  nrmin = n
2932  end if
2933  end if
2934  end do
2935  !
2936  if (nrmin > 0) then
2937  write (msg, '(a,i0)') trim(this%packName)//'-REACH-', nrmin
2938  call ats%ats_submit_delt(kstp, kper, dtmin, trim(msg))
2939  end if
2940  end subroutine sfr_dt
2941 
2942  !> @brief Kinematic-wave celerity from a flow perturbation (0 if dry)
2943  !<
2944  subroutine sfr_calc_celerity(this, n, q, celerity)
2945  ! -- dummy
2946  class(sfrtype) :: this !< SfrType object
2947  integer(I4B), intent(in) :: n !< reach number
2948  real(DP), intent(in) :: q !< reach flow
2949  real(DP), intent(out) :: celerity !< kinematic-wave celerity
2950  ! -- local
2951  real(DP) :: d
2952  real(DP) :: a
2953  real(DP) :: a2
2954  !
2955  celerity = dzero
2956  call this%sfr_calc_reach_depth(n, q, d)
2957  if (d > dzero) then
2958  a = this%calc_area_wet(n, d)
2959  call this%sfr_calc_reach_depth(n, q + this%deps, d)
2960  a2 = this%calc_area_wet(n, d)
2961  if (a2 > a) then
2962  celerity = this%deps / (a2 - a)
2963  end if
2964  end if
2965  end subroutine sfr_calc_celerity
2966 
2967  !> @ brief Deallocate package memory
2968  !!
2969  !! Deallocate SFR package scalars and arrays.
2970  !<
2971  subroutine sfr_da(this)
2972  ! -- modules
2974  ! -- dummy
2975  class(sfrtype) :: this !< SfrType object
2976  !
2977  ! -- deallocate arrays
2978  call mem_deallocate(this%qoutflow)
2979  call mem_deallocate(this%qextoutflow)
2980  deallocate (this%csfrbudget)
2981  call mem_deallocate(this%sfrname, 'SFRNAME', this%memoryPath)
2982  call mem_deallocate(this%dbuff)
2983  deallocate (this%cauxcbc)
2984  call mem_deallocate(this%qauxcbc)
2985  call mem_deallocate(this%iboundpak)
2986  call mem_deallocate(this%igwfnode)
2987  call mem_deallocate(this%igwftopnode)
2988  call mem_deallocate(this%length)
2989  call mem_deallocate(this%width)
2990  call mem_deallocate(this%strtop)
2991  call mem_deallocate(this%bthick)
2992  call mem_deallocate(this%hk)
2993  call mem_deallocate(this%slope)
2994  call mem_deallocate(this%nconnreach)
2995  call mem_deallocate(this%ustrf)
2996  call mem_deallocate(this%ftotnd)
2997  call mem_deallocate(this%usflow)
2998  call mem_deallocate(this%dsflow)
2999  call mem_deallocate(this%depth)
3000  call mem_deallocate(this%stage)
3001  call mem_deallocate(this%gwflow)
3002  call mem_deallocate(this%simevap)
3003  call mem_deallocate(this%simrunoff)
3004  call mem_deallocate(this%stage0)
3005  call mem_deallocate(this%usflow0)
3006  call mem_deallocate(this%denseterms)
3007  call mem_deallocate(this%viscratios)
3008  !
3009  ! -- stage, usflow, and dsflow for previous timestep
3010  if (this%istorage == 1) then
3011  call mem_deallocate(this%stageold)
3012  call mem_deallocate(this%dsflowold)
3013  call mem_deallocate(this%storage)
3014  call mem_deallocate(this%usinflow)
3015  call mem_deallocate(this%usinflowold)
3016  call mem_deallocate(this%crmin)
3017  call mem_deallocate(this%crmax)
3018  call mem_deallocate(this%crsum)
3019  call mem_deallocate(this%crcnt)
3020  call mem_deallocate(this%itvd_upstream)
3021  end if
3022  !
3023  ! -- deallocate reach order and connection data
3024  call mem_deallocate(this%isfrorder)
3025  call mem_deallocate(this%ia)
3026  call mem_deallocate(this%ja)
3027  call mem_deallocate(this%idir)
3028  call mem_deallocate(this%idiv)
3029  call mem_deallocate(this%qconn)
3030  !
3031  ! -- deallocate boundary data
3032  call mem_deallocate(this%rough)
3033  call mem_deallocate(this%rain)
3034  call mem_deallocate(this%evap)
3035  call mem_deallocate(this%inflow)
3036  call mem_deallocate(this%runoff)
3037  call mem_deallocate(this%sstage)
3038  !
3039  ! -- deallocate aux variables
3040  call mem_deallocate(this%rauxvar)
3041  !
3042  ! -- deallocate diversion variables
3043  call mem_deallocate(this%iadiv)
3044  call mem_deallocate(this%divreach)
3045  if (associated(this%divcprior)) then
3046  deallocate (this%divcprior)
3047  end if
3048  call mem_deallocate(this%divflow)
3049  call mem_deallocate(this%divq)
3050  call mem_deallocate(this%ndiv)
3051  !
3052  ! -- deallocate cross-section data
3053  call mem_deallocate(this%ncrosspts)
3054  call mem_deallocate(this%iacross)
3055  call mem_deallocate(this%station)
3056  call mem_deallocate(this%xsheight)
3057  call mem_deallocate(this%xsrough)
3058  !
3059  ! -- deallocate budobj
3060  call this%budobj%budgetobject_da()
3061  deallocate (this%budobj)
3062  nullify (this%budobj)
3063  !
3064  ! -- deallocate stage table
3065  if (this%iprhed > 0) then
3066  call this%stagetab%table_da()
3067  deallocate (this%stagetab)
3068  nullify (this%stagetab)
3069  end if
3070  !
3071  ! -- deallocate Courant number table
3072  if (associated(this%couranttab)) then
3073  call this%couranttab%table_da()
3074  deallocate (this%couranttab)
3075  nullify (this%couranttab)
3076  end if
3077  !
3078  ! -- deallocate package csv table
3079  if (this%ipakcsv > 0) then
3080  if (associated(this%pakcsvtab)) then
3081  call this%pakcsvtab%table_da()
3082  deallocate (this%pakcsvtab)
3083  nullify (this%pakcsvtab)
3084  end if
3085  end if
3086  !
3087  ! -- deallocate scalars
3088  call mem_deallocate(this%ats_courant)
3089  call mem_deallocate(this%istorage)
3090  call mem_deallocate(this%storage_weight)
3091  call mem_deallocate(this%iprhed)
3092  call mem_deallocate(this%istageout)
3093  call mem_deallocate(this%ibudgetout)
3094  call mem_deallocate(this%ibudcsv)
3095  call mem_deallocate(this%ipakcsv)
3096  call mem_deallocate(this%idiversions)
3097  call mem_deallocate(this%maxsfrpicard)
3098  call mem_deallocate(this%maxsfrit)
3099  call mem_deallocate(this%bditems)
3100  call mem_deallocate(this%cbcauxitems)
3101  call mem_deallocate(this%unitconv)
3102  call mem_deallocate(this%lengthconv)
3103  call mem_deallocate(this%timeconv)
3104  call mem_deallocate(this%dmaxchg)
3105  call mem_deallocate(this%deps)
3106  call mem_deallocate(this%nconn)
3107  call mem_deallocate(this%icheck)
3108  call mem_deallocate(this%iconvchk)
3109  call mem_deallocate(this%idense)
3110  call mem_deallocate(this%ianynone)
3111  call mem_deallocate(this%ncrossptstot)
3112  nullify (this%gwfiss)
3113  !
3114  ! -- call base BndType deallocate
3115  call this%BndType%bnd_da()
3116  end subroutine sfr_da
3117 
3118  !> @brief Pre-compute the single upstream reach index for the TVD limiter
3119  !!
3120  !! Index 0 for reaches with zero or multiple upstream connections.
3121  !<
3122  subroutine sfr_precompute_tvd(this)
3123  ! -- dummy
3124  class(sfrtype), intent(inout) :: this !< SfrType object
3125  ! -- local
3126  integer(I4B) :: n
3127  integer(I4B) :: j
3128  integer(I4B) :: iup_count
3129  integer(I4B) :: m
3130  !
3131  do n = 1, this%maxbound
3132  iup_count = 0
3133  m = 0
3134  do j = this%ia(n) + 1, this%ia(n + 1) - 1
3135  if (this%idir(j) > 0) then
3136  iup_count = iup_count + 1
3137  m = this%ja(j)
3138  end if
3139  end do
3140  if (iup_count == 1) then
3141  this%itvd_upstream(n) = m
3142  else
3143  this%itvd_upstream(n) = 0
3144  end if
3145  end do
3146  end subroutine sfr_precompute_tvd
3147 
3148  !> @ brief Define the list label for the package
3149  !!
3150  !! Method defined the list label for the SFR package. The list label is
3151  !! the heading that is written to iout when PRINT_INPUT option is used.
3152  !<
3153  subroutine define_listlabel(this)
3154  ! -- dummy
3155  class(sfrtype), intent(inout) :: this !< SfrType object
3156  !
3157  ! -- create the header list label
3158  this%listlabel = trim(this%filtyp)//' NO.'
3159  if (this%dis%ndim == 3) then
3160  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'LAYER'
3161  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'ROW'
3162  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'COL'
3163  elseif (this%dis%ndim == 2) then
3164  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'LAYER'
3165  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'CELL2D'
3166  else
3167  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'NODE'
3168  end if
3169  write (this%listlabel, '(a, a16)') trim(this%listlabel), 'STRESS RATE'
3170  if (this%inamedbound == 1) then
3171  write (this%listlabel, '(a, a16)') trim(this%listlabel), 'BOUNDARY NAME'
3172  end if
3173  end subroutine define_listlabel
3174 
3175  !
3176  ! -- Procedures related to observations (type-bound)
3177 
3178  !> @brief Determine if observations are supported.
3179  !!
3180  !! Function to determine if observations are supported by the SFR package.
3181  !! Observations are supported by the SFR package.
3182  !!
3183  !! @return sfr_obs_supported boolean indicating if observations are supported
3184  !<
3185  logical function sfr_obs_supported(this)
3186  ! -- dummy
3187  class(sfrtype) :: this !< SfrType object
3188  !
3189  ! -- set boolean
3190  sfr_obs_supported = .true.
3191  end function sfr_obs_supported
3192 
3193  !> @brief Define the observation types available in the package
3194  !!
3195  !! Method to define the observation types available in the SFR package.
3196  !<
3197  subroutine sfr_df_obs(this)
3198  ! -- dummy
3199  class(sfrtype) :: this !< SfrType object
3200  ! -- local
3201  integer(I4B) :: indx
3202  !
3203  ! -- Store obs type and assign procedure pointer
3204  ! for stage observation type.
3205  call this%obs%StoreObsType('stage', .false., indx)
3206  this%obs%obsData(indx)%ProcessIdPtr => sfr_process_obsid
3207  !
3208  ! -- Store obs type and assign procedure pointer
3209  ! for inflow observation type.
3210  call this%obs%StoreObsType('inflow', .true., indx)
3211  this%obs%obsData(indx)%ProcessIdPtr => sfr_process_obsid
3212  !
3213  ! -- Store obs type and assign procedure pointer
3214  ! for inflow observation type.
3215  call this%obs%StoreObsType('ext-inflow', .true., indx)
3216  this%obs%obsData(indx)%ProcessIdPtr => sfr_process_obsid
3217  !
3218  ! -- Store obs type and assign procedure pointer
3219  ! for rainfall observation type.
3220  call this%obs%StoreObsType('rainfall', .true., indx)
3221  this%obs%obsData(indx)%ProcessIdPtr => sfr_process_obsid
3222  !
3223  ! -- Store obs type and assign procedure pointer
3224  ! for runoff observation type.
3225  call this%obs%StoreObsType('runoff', .true., indx)
3226  this%obs%obsData(indx)%ProcessIdPtr => sfr_process_obsid
3227  !
3228  ! -- Store obs type and assign procedure pointer
3229  ! for evaporation observation type.
3230  call this%obs%StoreObsType('evaporation', .true., indx)
3231  this%obs%obsData(indx)%ProcessIdPtr => sfr_process_obsid
3232  !
3233  ! -- Store obs type and assign procedure pointer
3234  ! for outflow observation type.
3235  call this%obs%StoreObsType('outflow', .true., indx)
3236  this%obs%obsData(indx)%ProcessIdPtr => sfr_process_obsid
3237  !
3238  ! -- Store obs type and assign procedure pointer
3239  ! for ext-outflow observation type.
3240  call this%obs%StoreObsType('ext-outflow', .true., indx)
3241  this%obs%obsData(indx)%ProcessIdPtr => sfr_process_obsid
3242  !
3243  ! -- Store obs type and assign procedure pointer
3244  ! for to-mvr observation type.
3245  call this%obs%StoreObsType('to-mvr', .true., indx)
3246  this%obs%obsData(indx)%ProcessIdPtr => sfr_process_obsid
3247  !
3248  ! -- Store obs type and assign procedure pointer
3249  ! for sfr-frommvr observation type.
3250  call this%obs%StoreObsType('from-mvr', .true., indx)
3251  this%obs%obsData(indx)%ProcessIdPtr => sfr_process_obsid
3252  !
3253  ! -- Store obs type and assign procedure pointer
3254  ! for sfr observation type.
3255  call this%obs%StoreObsType('sfr', .true., indx)
3256  this%obs%obsData(indx)%ProcessIdPtr => sfr_process_obsid
3257  !
3258  ! -- Store obs type and assign procedure pointer
3259  ! for upstream flow observation type.
3260  call this%obs%StoreObsType('upstream-flow', .true., indx)
3261  this%obs%obsData(indx)%ProcessIdPtr => sfr_process_obsid
3262  !
3263  ! -- Store obs type and assign procedure pointer
3264  ! for downstream flow observation type.
3265  call this%obs%StoreObsType('downstream-flow', .true., indx)
3266  this%obs%obsData(indx)%ProcessIdPtr => sfr_process_obsid
3267  !
3268  ! -- Store obs type and assign procedure pointer
3269  ! for depth observation type.
3270  call this%obs%StoreObsType('depth', .false., indx)
3271  this%obs%obsData(indx)%ProcessIdPtr => sfr_process_obsid
3272  !
3273  ! -- Store obs type and assign procedure pointer
3274  ! for wetted-perimeter observation type.
3275  call this%obs%StoreObsType('wet-perimeter', .false., indx)
3276  this%obs%obsData(indx)%ProcessIdPtr => sfr_process_obsid
3277  !
3278  ! -- Store obs type and assign procedure pointer
3279  ! for wetted-area observation type.
3280  call this%obs%StoreObsType('wet-area', .false., indx)
3281  this%obs%obsData(indx)%ProcessIdPtr => sfr_process_obsid
3282  !
3283  ! -- Store obs type and assign procedure pointer
3284  ! for wetted-width observation type.
3285  call this%obs%StoreObsType('wet-width', .false., indx)
3286  this%obs%obsData(indx)%ProcessIdPtr => sfr_process_obsid
3287  end subroutine sfr_df_obs
3288 
3289  !> @brief Save observations for the package
3290  !!
3291  !! Method to save simulated values for the SFR package.
3292  !<
3293  subroutine sfr_bd_obs(this)
3294  ! -- dummy
3295  class(sfrtype) :: this !< SfrType object
3296  ! -- local
3297  integer(I4B) :: i
3298  integer(I4B) :: j
3299  integer(I4B) :: n
3300  real(DP) :: v
3301  character(len=100) :: msg
3302  type(observetype), pointer :: obsrv => null()
3303  !
3304  ! Write simulated values for all sfr observations
3305  if (this%obs%npakobs > 0) then
3306  call this%obs%obs_bd_clear()
3307  do i = 1, this%obs%npakobs
3308  obsrv => this%obs%pakobs(i)%obsrv
3309  do j = 1, obsrv%indxbnds_count
3310  n = obsrv%indxbnds(j)
3311  v = dzero
3312  select case (obsrv%ObsTypeId)
3313  case ('STAGE')
3314  v = this%stage(n)
3315  case ('TO-MVR')
3316  v = dnodata
3317  if (this%imover == 1) then
3318  v = this%pakmvrobj%get_qtomvr(n)
3319  if (v > dzero) then
3320  v = -v
3321  end if
3322  end if
3323  case ('FROM-MVR')
3324  v = dnodata
3325  if (this%imover == 1) then
3326  v = this%pakmvrobj%get_qfrommvr(n)
3327  end if
3328  case ('EXT-INFLOW')
3329  v = this%inflow(n)
3330  case ('INFLOW')
3331  v = this%usflow(n)
3332  case ('OUTFLOW')
3333  v = this%qoutflow(n)
3334  case ('EXT-OUTFLOW')
3335  v = this%qextoutflow(n)
3336  case ('RAINFALL')
3337  if (this%iboundpak(n) /= 0) then
3338  v = this%rain(n)
3339  else
3340  v = dzero
3341  end if
3342  case ('RUNOFF')
3343  v = this%simrunoff(n)
3344  case ('EVAPORATION')
3345  v = this%simevap(n)
3346  case ('SFR')
3347  v = this%gwflow(n)
3348  case ('UPSTREAM-FLOW')
3349  v = this%usflow(n)
3350  if (this%imover == 1) then
3351  v = v + this%pakmvrobj%get_qfrommvr(n)
3352  end if
3353  case ('DOWNSTREAM-FLOW')
3354  v = this%dsflow(n)
3355  if (v > dzero) then
3356  v = -v
3357  end if
3358  case ('DEPTH')
3359  v = this%depth(n)
3360  case ('WET-PERIMETER')
3361  v = this%calc_perimeter_wet(n, this%depth(n))
3362  case ('WET-AREA')
3363  v = this%calc_area_wet(n, this%depth(n))
3364  case ('WET-WIDTH')
3365  v = this%calc_top_width_wet(n, this%depth(n))
3366  case default
3367  msg = 'Unrecognized observation type: '//trim(obsrv%ObsTypeId)
3368  call store_error(msg)
3369  end select
3370  call this%obs%SaveOneSimval(obsrv, v)
3371  end do
3372  end do
3373  !
3374  ! -- write summary of package error messages
3375  if (count_errors() > 0) then
3376  call this%parser%StoreErrorUnit()
3377  end if
3378  end if
3379  end subroutine sfr_bd_obs
3380 
3381  !> @brief Read and prepare observations for a package
3382  !!
3383  !! Method to read and prepare observations for a SFR package.
3384  !<
3385  subroutine sfr_rp_obs(this)
3386  ! -- modules
3387  use tdismodule, only: kper
3388  ! -- dummy
3389  class(sfrtype), intent(inout) :: this !< SfrType object
3390  ! -- local
3391  integer(I4B) :: i
3392  integer(I4B) :: j
3393  integer(I4B) :: nn1
3394  character(len=LENBOUNDNAME) :: bname
3395  logical(LGP) :: jfound
3396  class(observetype), pointer :: obsrv => null()
3397  ! -- formats
3398 10 format('Boundary "', a, '" for observation "', a, &
3399  '" is invalid in package "', a, '"')
3400 30 format('Boundary name not provided for observation "', a, &
3401  '" in package "', a, '"')
3402  !
3403  ! -- process each package observation
3404  ! only done the first stress period since boundaries are fixed
3405  ! for the simulation
3406  if (kper == 1) then
3407  do i = 1, this%obs%npakobs
3408  obsrv => this%obs%pakobs(i)%obsrv
3409  !
3410  ! -- get node number 1
3411  nn1 = obsrv%NodeNumber
3412  if (nn1 == namedboundflag) then
3413  bname = obsrv%FeatureName
3414  if (bname /= '') then
3415  ! -- Observation location(s) is(are) based on a boundary name.
3416  ! Iterate through all boundaries to identify and store
3417  ! corresponding index(indices) in bound array.
3418  jfound = .false.
3419  do j = 1, this%maxbound
3420  if (this%boundname(j) == bname) then
3421  jfound = .true.
3422  call obsrv%AddObsIndex(j)
3423  end if
3424  end do
3425  if (.not. jfound) then
3426  write (errmsg, 10) &
3427  trim(bname), trim(obsrv%name), trim(this%packName)
3428  call store_error(errmsg)
3429  end if
3430  else
3431  write (errmsg, 30) trim(obsrv%name), trim(this%packName)
3432  call store_error(errmsg)
3433  end if
3434  else if (nn1 < 1 .or. nn1 > this%maxbound) then
3435  write (errmsg, '(a,1x,a,1x,i0,1x,a,1x,i0,a)') &
3436  trim(adjustl(obsrv%ObsTypeId)), &
3437  'reach must be greater than 0 and less than or equal to', &
3438  this%maxbound, '(specified value is ', nn1, ')'
3439  call store_error(errmsg)
3440  else
3441  if (obsrv%indxbnds_count == 0) then
3442  call obsrv%AddObsIndex(nn1)
3443  else
3444  errmsg = 'Programming error in sfr_rp_obs'
3445  call store_error(errmsg)
3446  end if
3447  end if
3448  !
3449  ! -- catch non-cumulative observation assigned to observation defined
3450  ! by a boundname that is assigned to more than one element
3451  if (obsrv%ObsTypeId == 'STAGE' .or. &
3452  obsrv%ObsTypeId == 'DEPTH' .or. &
3453  obsrv%ObsTypeId == 'WET-PERIMETER' .or. &
3454  obsrv%ObsTypeId == 'WET-AREA' .or. &
3455  obsrv%ObsTypeId == 'WET-WIDTH') then
3456  nn1 = obsrv%NodeNumber
3457  if (nn1 == namedboundflag) then
3458  if (obsrv%indxbnds_count > 1) then
3459  write (errmsg, '(a,3(1x,a))') &
3460  trim(adjustl(obsrv%ObsTypeId)), &
3461  'for observation', trim(adjustl(obsrv%Name)), &
3462  ' must be assigned to a reach with a unique boundname.'
3463  call store_error(errmsg)
3464  end if
3465  end if
3466  end if
3467  !
3468  ! -- check that node number 1 is valid; call store_error if not
3469  do j = 1, obsrv%indxbnds_count
3470  nn1 = obsrv%indxbnds(j)
3471  if (nn1 < 1 .or. nn1 > this%maxbound) then
3472  write (errmsg, '(a,1x,a,1x,i0,1x,a,1x,i0,a)') &
3473  trim(adjustl(obsrv%ObsTypeId)), &
3474  'reach must be greater than 0 and less than or equal to', &
3475  this%maxbound, '(specified value is ', nn1, ')'
3476  call store_error(errmsg)
3477  end if
3478  end do
3479  end do
3480  !
3481  ! -- evaluate if there are any observation errors
3482  if (count_errors() > 0) then
3483  call this%parser%StoreErrorUnit()
3484  end if
3485  end if
3486  end subroutine sfr_rp_obs
3487 
3488  !
3489  ! -- Procedures related to observations (NOT type-bound)
3490 
3491  !> @brief Process observation IDs for a package
3492  !!
3493  !! Method to process observation ID strings for a SFR package.
3494  !<
3495  subroutine sfr_process_obsid(obsrv, dis, inunitobs, iout)
3496  ! -- dummy
3497  type(observetype), intent(inout) :: obsrv !< Observation object
3498  class(disbasetype), intent(in) :: dis !< Discretization object
3499  integer(I4B), intent(in) :: inunitobs !< file unit number for the package observation file
3500  integer(I4B), intent(in) :: iout !< model listing file unit number
3501  ! -- local
3502  integer(I4B) :: nn1
3503  integer(I4B) :: icol
3504  integer(I4B) :: istart
3505  integer(I4B) :: istop
3506  character(len=LINELENGTH) :: string
3507  character(len=LENBOUNDNAME) :: bndname
3508  !
3509  ! -- initialize local variables
3510  string = obsrv%IDstring
3511  !
3512  ! -- Extract reach number from string and store it.
3513  ! If 1st item is not an integer(I4B), it should be a
3514  ! boundary name--deal with it.
3515  icol = 1
3516  !
3517  ! -- get reach number or boundary name
3518  call extract_idnum_or_bndname(string, icol, istart, istop, nn1, bndname)
3519  if (nn1 == namedboundflag) then
3520  obsrv%FeatureName = bndname
3521  end if
3522  !
3523  ! -- store reach number (NodeNumber)
3524  obsrv%NodeNumber = nn1
3525  end subroutine sfr_process_obsid
3526 
3527  !
3528  ! -- private sfr methods
3529  !
3530 
3531  !> @brief Set period data
3532  !!
3533  !! Method to read and set period data for a SFR package reach.
3534  !<
3535  subroutine sfr_set_stressperiod(this, n, ichkustrm, crossfile)
3536  ! -- modules
3538  ! -- dummy
3539  class(sfrtype), intent(inout) :: this !< SfrType object
3540  integer(I4B), intent(in) :: n !< reach number
3541  integer(I4B), intent(inout) :: ichkustrm !< flag indicating if upstream fraction data specified
3542  character(len=LINELENGTH), intent(inout) :: crossfile !< cross-section file name
3543  ! -- local
3544  character(len=10) :: cnum
3545  character(len=LINELENGTH) :: text
3546  character(len=LINELENGTH) :: caux
3547  character(len=LINELENGTH) :: keyword
3548  integer(I4B) :: ival
3549  integer(I4B) :: ii
3550  integer(I4B) :: jj
3551  integer(I4B) :: idiv
3552  integer(I4B) :: ixserror
3553  character(len=10) :: cp
3554  real(DP) :: divq
3555  real(DP), pointer :: bndElem => null()
3556  !
3557  ! -- initialize variables
3558  crossfile = 'NONE'
3559  !
3560  ! -- read line
3561  call this%parser%GetStringCaps(keyword)
3562  select case (keyword)
3563  case ('STATUS')
3564  ichkustrm = 1
3565  call this%parser%GetStringCaps(text)
3566  if (text == 'INACTIVE') then
3567  this%iboundpak(n) = 0
3568  else if (text == 'ACTIVE') then
3569  this%iboundpak(n) = 1
3570  else if (text == 'SIMPLE') then
3571  this%iboundpak(n) = -1
3572  else
3573  write (errmsg, '(2a)') &
3574  'Unknown '//trim(this%text)//' sfr status keyword: ', trim(text)
3575  call store_error(errmsg)
3576  end if
3577  case ('BEDK')
3578  call this%parser%GetString(text)
3579  jj = 1 ! For 'BEDK'
3580  bndelem => this%hk(n)
3581  call read_value_or_time_series_adv(text, n, jj, bndelem, &
3582  this%packName, 'BND', &
3583  this%tsManager, this%iprpak, &
3584  'BEDK')
3585  case ('MANNING')
3586  call this%parser%GetString(text)
3587  jj = 1 ! For 'MANNING'
3588  bndelem => this%rough(n)
3589  call read_value_or_time_series_adv(text, n, jj, bndelem, &
3590  this%packName, 'BND', &
3591  this%tsManager, this%iprpak, &
3592  'MANNING')
3593  case ('STAGE')
3594  call this%parser%GetString(text)
3595  jj = 1 ! For 'STAGE'
3596  bndelem => this%sstage(n)
3597  call read_value_or_time_series_adv(text, n, jj, bndelem, &
3598  this%packName, 'BND', &
3599  this%tsManager, this%iprpak, 'STAGE')
3600  case ('RAINFALL')
3601  call this%parser%GetString(text)
3602  jj = 1 ! For 'RAIN'
3603  bndelem => this%rain(n)
3604  call read_value_or_time_series_adv(text, n, jj, bndelem, &
3605  this%packName, 'BND', &
3606  this%tsManager, this%iprpak, 'RAIN')
3607  case ('EVAPORATION')
3608  call this%parser%GetString(text)
3609  jj = 1 ! For 'EVAP'
3610  bndelem => this%evap(n)
3611  call read_value_or_time_series_adv(text, n, jj, bndelem, &
3612  this%packName, 'BND', &
3613  this%tsManager, this%iprpak, &
3614  'EVAP')
3615  case ('RUNOFF')
3616  call this%parser%GetString(text)
3617  jj = 1 ! For 'RUNOFF'
3618  bndelem => this%runoff(n)
3619  call read_value_or_time_series_adv(text, n, jj, bndelem, &
3620  this%packName, 'BND', &
3621  this%tsManager, this%iprpak, &
3622  'RUNOFF')
3623  case ('INFLOW')
3624  call this%parser%GetString(text)
3625  jj = 1 ! For 'INFLOW'
3626  bndelem => this%inflow(n)
3627  call read_value_or_time_series_adv(text, n, jj, bndelem, &
3628  this%packName, 'BND', &
3629  this%tsManager, this%iprpak, &
3630  'INFLOW')
3631  case ('DIVERSION')
3632  !
3633  ! -- make sure reach has at least one diversion
3634  if (this%ndiv(n) < 1) then
3635  write (cnum, '(i0)') n
3636  errmsg = 'diversions cannot be specified for reach '//trim(cnum)
3637  call store_error(errmsg)
3638  end if
3639  !
3640  ! -- read diversion number
3641  ival = this%parser%GetInteger()
3642  if (ival < 1 .or. ival > this%ndiv(n)) then
3643  write (cnum, '(i0)') n
3644  errmsg = 'Reach '//trim(cnum)
3645  write (cnum, '(i0)') this%ndiv(n)
3646  errmsg = trim(errmsg)//' diversion number should be between 1 '// &
3647  'and '//trim(cnum)//'.'
3648  call store_error(errmsg)
3649  end if
3650  idiv = ival
3651  !
3652  ! -- read value
3653  call this%parser%GetString(text)
3654  ii = this%iadiv(n) + idiv - 1
3655  jj = 1 ! For 'DIVERSION'
3656  bndelem => this%divflow(ii)
3657  call read_value_or_time_series_adv(text, ii, jj, bndelem, &
3658  this%packName, 'BND', &
3659  this%tsManager, this%iprpak, &
3660  'DIVFLOW')
3661  !
3662  ! -- if diversion cprior is 'fraction', ensure that 0.0 <= fraction <= 1.0
3663  cp = this%divcprior(ii)
3664  divq = this%divflow(ii)
3665  if (cp == 'FRACTION' .and. (divq < dzero .or. divq > done)) then
3666  write (errmsg, '(a,1x,i0,a)') &
3667  'cprior is type FRACTION for diversion no.', ii, &
3668  ', but divflow not within the range 0.0 to 1.0'
3669  call store_error(errmsg)
3670  end if
3671  case ('UPSTREAM_FRACTION')
3672  ichkustrm = 1
3673  call this%parser%GetString(text)
3674  jj = 1 ! For 'USTRF'
3675  bndelem => this%ustrf(n)
3676  call read_value_or_time_series_adv(text, n, jj, bndelem, &
3677  this%packName, 'BND', &
3678  this%tsManager, this%iprpak, 'USTRF')
3679 
3680  case ('CROSS_SECTION')
3681  ixserror = 0
3682  !
3683  ! -- read FILE keyword
3684  call this%parser%GetStringCaps(keyword)
3685  select case (keyword)
3686  case ('TAB6')
3687  call this%parser%GetStringCaps(keyword)
3688  if (trim(adjustl(keyword)) /= 'FILEIN') then
3689  errmsg = 'TAB6 keyword must be followed by "FILEIN" '// &
3690  'then by filename.'
3691  call store_error(errmsg)
3692  ixserror = 1
3693  end if
3694  if (ixserror == 0) then
3695  call this%parser%GetString(crossfile)
3696  end if
3697  case default
3698  write (errmsg, '(a,1x,i4,1x,a)') &
3699  'CROSS-SECTION TABLE ENTRY for REACH ', n, &
3700  'MUST INCLUDE TAB6 KEYWORD'
3701  call store_error(errmsg)
3702  end select
3703 
3704  case ('AUXILIARY')
3705  call this%parser%GetStringCaps(caux)
3706  do jj = 1, this%naux
3707  if (trim(adjustl(caux)) /= trim(adjustl(this%auxname(jj)))) cycle
3708  call this%parser%GetString(text)
3709  ii = n
3710  bndelem => this%rauxvar(jj, ii)
3711  call read_value_or_time_series_adv(text, ii, jj, bndelem, &
3712  this%packName, 'AUX', &
3713  this%tsManager, this%iprpak, &
3714  this%auxname(jj))
3715  exit
3716  end do
3717 
3718  case default
3719  write (errmsg, '(a,a)') &
3720  'Unknown '//trim(this%text)//' sfr data keyword: ', &
3721  trim(keyword)//'.'
3722  call store_error(errmsg)
3723  end select
3724  end subroutine sfr_set_stressperiod
3725 
3726  !> @brief Solve reach continuity equation
3727  !!
3728  !! Method to solve the continuity equation for a SFR package reach.
3729  !<
3730  subroutine sfr_solve(this, n, h, hcof, rhs, update)
3731  ! -- dummy
3732  class(sfrtype) :: this !< SfrType object
3733  integer(I4B), intent(in) :: n !< reach number
3734  real(DP), intent(in) :: h !< groundwater head in cell connected to reach
3735  real(DP), intent(inout) :: hcof !< coefficient term added to the diagonal
3736  real(DP), intent(inout) :: rhs !< right-hand side term
3737  logical(LGP), intent(in), optional :: update !< boolean indicating if the reach depth and stage variables should be updated to current iterate
3738  ! -- local
3739  logical(LGP) :: lupdate
3740  integer(I4B) :: i
3741  integer(I4B) :: ii
3742  integer(I4B) :: n2
3743  real(DP) :: hgwf
3744  real(DP) :: sa
3745  real(DP) :: sa_wet
3746  real(DP) :: qu
3747  real(DP) :: qi
3748  real(DP) :: qr
3749  real(DP) :: qe
3750  real(DP) :: qro
3751  real(DP) :: qsrc
3752  real(DP) :: qfrommvr
3753  real(DP) :: qgwf
3754  real(DP) :: tp
3755  real(DP) :: bt
3756  real(DP) :: hsfr
3757  real(DP) :: qd
3758  real(DP) :: d1
3759  real(DP) :: sumleak
3760  real(DP) :: sumrch
3761  real(DP) :: gwfhcof
3762  real(DP) :: gwfrhs
3763  !
3764  ! -- Process optional dummy variables
3765  if (present(update)) then
3766  lupdate = update
3767  else
3768  lupdate = .true.
3769  end if
3770 
3771  ! -- initialize variables
3772  hcof = dzero
3773  rhs = dzero
3774  !
3775  if (this%iboundpak(n) == 0) then
3776  this%depth(n) = dzero
3777  this%stage(n) = dhnoflo
3778  this%usflow(n) = dzero
3779  this%simevap(n) = dzero
3780  this%simrunoff(n) = dzero
3781  this%dsflow(n) = dzero
3782  this%gwflow(n) = dzero
3783  else
3784  hgwf = h
3785  d1 = dzero
3786  qsrc = dzero
3787  qgwf = dzero
3788  qd = this%dsflow(n)
3789 
3790  ! -- calculate initial depth assuming a wide cross-section and
3791  ! ignore groundwater leakage
3792  ! -- calculate upstream flow
3793  qu = dzero
3794  do i = this%ia(n) + 1, this%ia(n + 1) - 1
3795  if (this%idir(i) < 0) cycle
3796  n2 = this%ja(i)
3797  do ii = this%ia(n2) + 1, this%ia(n2 + 1) - 1
3798  if (this%idir(ii) > 0) cycle
3799  if (this%ja(ii) /= n) cycle
3800  qu = qu + this%qconn(ii)
3801  end do
3802  end do
3803  this%usflow(n) = qu
3804 
3805  ! -- calculate remaining terms
3806  sa = this%calc_surface_area(n)
3807  sa_wet = this%calc_surface_area_wet(n, this%depth(n))
3808  qi = this%inflow(n)
3809  qr = this%rain(n) * sa
3810  qe = this%evap(n) * sa_wet
3811  qro = this%runoff(n)
3812 
3813  ! -- Water mover term; assume that it goes in at the upstream end of the reach
3814  qfrommvr = dzero
3815  if (this%imover == 1) then
3816  qfrommvr = this%pakmvrobj%get_qfrommvr(n)
3817  end if
3818 
3819  ! -- calculate downstream flow ignoring groundwater leakage
3820  qsrc = qu + qi + qr - qe + qro + qfrommvr
3821 
3822  ! -- adjust runoff or evaporation if sum of sources is negative
3823  call this%sfr_adjust_ro_ev(qsrc, qu, qi, qr, qro, qe, qfrommvr)
3824 
3825  ! -- set simulated evaporation and runoff
3826  this%simevap(n) = qe
3827  this%simrunoff(n) = qro
3828 
3829  ! -- calculate reach flow using appropriate method
3830  if (this%iboundpak(n) < 0) then
3831  call this%sfr_calc_constant(n, d1, hgwf, qgwf, qd)
3832  else
3833  if (this%gwfiss == 0 .and. this%istorage == 1) then
3834  if (this%ats_courant /= dnodata) then
3835  call this%sfr_calc_tvd(n, d1, hgwf, qu, qi, &
3836  qfrommvr, qr, qe, qro, &
3837  qgwf, qd)
3838  else
3839  call this%sfr_calc_transient(n, d1, hgwf, qu, qi, &
3840  qfrommvr, qr, qe, qro, &
3841  qgwf, qd)
3842  end if
3843  else
3844  call this%sfr_calc_steady(n, d1, hgwf, qu, qi, &
3845  qfrommvr, qr, qe, qro, &
3846  qgwf, qd)
3847  end if
3848  end if
3849 
3850  ! -- update sfr stage
3851  tp = this%strtop(n)
3852  bt = tp - this%bthick(n)
3853  hsfr = tp + d1
3854 
3855  ! -- update stored values
3856  if (lupdate) then
3857  ! -- save depth and calculate stage
3858  this%depth(n) = d1
3859  this%stage(n) = hsfr
3860  ! -- update flows
3861  call this%sfr_update_flows(n, qd, qgwf)
3862  end if
3863 
3864  ! -- calculate sumleak and sumrch
3865  sumleak = dzero
3866  sumrch = dzero
3867  if (this%gwfiss == 0) then
3868  sumleak = qgwf
3869  else
3870  sumleak = qgwf
3871  end if
3872  if (hgwf < bt) then
3873  sumrch = qgwf
3874  end if
3875 
3876  ! -- make final qgwf calculation and obtain
3877  ! gwfhcof and gwfrhs values
3878  call this%sfr_calc_qgwf(n, d1, hgwf, qgwf, gwfhcof, gwfrhs)
3879 
3880  ! -- update hcof and rhs terms
3881  if (abs(sumleak) > dzero) then
3882  ! -- stream leakage is not head dependent
3883  if (hgwf < bt) then
3884  rhs = rhs - sumrch
3885  ! -- stream leakage is head dependent
3886  else if ((sumleak - qsrc) < -dem30) then
3887  if (this%gwfiss == 0) then
3888  rhs = rhs + gwfrhs - sumrch
3889  else
3890  rhs = rhs + gwfrhs
3891  end if
3892  hcof = gwfhcof
3893  ! -- place holder for UZF
3894  else
3895  if (this%gwfiss == 0) then
3896  rhs = rhs - sumleak - sumrch
3897  else
3898  rhs = rhs - sumleak
3899  end if
3900  end if
3901 
3902  ! -- add groundwater leakage
3903  else if (hgwf < bt) then
3904  rhs = rhs - sumrch
3905  end if
3906  end if
3907  end subroutine sfr_solve
3908 
3909  !> @brief Update flow terms
3910  !!
3911  !! Method to update downstream flow and groundwater leakage terms for
3912  !! a SFR package reach.
3913  !<
3914  subroutine sfr_update_flows(this, n, qd, qgwf)
3915  ! -- dummy
3916  class(sfrtype), intent(inout) :: this !< SfrType object
3917  integer(I4B), intent(in) :: n !< reach number
3918  real(DP), intent(inout) :: qd !< downstream reach flow
3919  real(DP), intent(in) :: qgwf !< groundwater leakage for reach
3920  ! -- local
3921  integer(I4B) :: i
3922  integer(I4B) :: n2
3923  integer(I4B) :: idiv
3924  integer(I4B) :: jpos
3925  real(DP) :: qdiv
3926  real(DP) :: f
3927  !
3928  ! -- update reach terms
3929  !
3930  ! -- save final downstream stream flow
3931  this%dsflow(n) = qd
3932  !
3933  ! -- save groundwater leakage
3934  this%gwflow(n) = qgwf
3935  !
3936  ! -- route downstream flow
3937  if (qd > dzero) then
3938  !
3939  ! -- route water to diversions
3940  do i = this%ia(n) + 1, this%ia(n + 1) - 1
3941  if (this%idir(i) > 0) cycle
3942  idiv = this%idiv(i)
3943  if (idiv == 0) cycle
3944  jpos = this%iadiv(n) + idiv - 1
3945  call this%sfr_calc_div(n, idiv, qd, qdiv)
3946  this%qconn(i) = qdiv
3947  this%divq(jpos) = qdiv
3948  end do
3949  !
3950  ! -- Mover terms: store outflow after diversion loss
3951  ! as qformvr and reduce outflow (qd)
3952  ! by how much was actually sent to the mover
3953  if (this%imover == 1) then
3954  call this%pakmvrobj%accumulate_qformvr(n, qd)
3955  qd = max(qd - this%pakmvrobj%get_qtomvr(n), dzero)
3956  end if
3957  !
3958  ! -- route remaining water to downstream reaches
3959  do i = this%ia(n) + 1, this%ia(n + 1) - 1
3960  if (this%idir(i) > 0) cycle
3961  if (this%idiv(i) > 0) cycle
3962  n2 = this%ja(i)
3963  if (this%iboundpak(n2) == 0) cycle
3964  f = this%ustrf(n2) / this%ftotnd(n)
3965  this%qconn(i) = qd * f
3966  end do
3967  else
3968  do i = this%ia(n) + 1, this%ia(n + 1) - 1
3969  if (this%idir(i) > 0) cycle
3970  this%qconn(i) = dzero
3971  idiv = this%idiv(i)
3972  if (idiv == 0) cycle
3973  jpos = this%iadiv(n) + idiv - 1
3974  this%divq(jpos) = dzero
3975  end do
3976  end if
3977  end subroutine sfr_update_flows
3978 
3979  !> @brief Adjust runoff and evaporation
3980  !!
3981  !! Method to adjust runoff and evaporation for a SFR package reach
3982  !! based on the total reach flow.
3983  !<
3984  subroutine sfr_adjust_ro_ev(this, qc, qu, qi, qr, qro, qe, qfrommvr)
3985  ! -- dummy
3986  class(sfrtype) :: this !< SfrType object
3987  real(DP), intent(inout) :: qc !< total reach volumetric flow
3988  real(DP), intent(in) :: qu !< upstream reach volumetric flow
3989  real(DP), intent(in) :: qi !< reach volumetric inflow
3990  real(DP), intent(in) :: qr !< reach volumetric rainfall
3991  real(DP), intent(inout) :: qro !< reach volumetric runoff
3992  real(DP), intent(inout) :: qe !< reach volumetric evaporation
3993  real(DP), intent(in) :: qfrommvr !< reach volumetric flow from mover
3994  ! -- local
3995  real(DP) :: qt
3996  !
3997  ! -- adjust runoff or evaporation if sum of sources is negative
3998  if (qc < dzero) then
3999  !
4000  ! -- calculate sources without evaporation
4001  qt = qu + qi + qr + qro + qfrommvr
4002  !
4003  ! -- runoff exceeds sources of water for reach
4004  if (qt < dzero) then
4005  if (qro < dzero) then
4006  qro = -(qu + qi + qr + qfrommvr)
4007  qe = dzero
4008  end if
4009  !
4010  ! -- evaporation exceeds sources of water for reach
4011  else
4012  if (qe > dzero) then
4013  qe = qu + qi + qr + qro + qfrommvr
4014  end if
4015  end if
4016  qc = qu + qi + qr - qe + qro + qfrommvr
4017  end if
4018  end subroutine sfr_adjust_ro_ev
4019 
4020  !> @brief Calculate downstream flow term
4021  !!
4022  !! Method to calculate downstream flow for a SFR package reach.
4023  !<
4024  subroutine sfr_calc_qd(this, n, depth, hgwf, qgwf, qd)
4025  ! -- dummy
4026  class(sfrtype) :: this !< SfrType object
4027  integer(I4B), intent(in) :: n !< reach number
4028  real(DP), intent(in) :: depth !< reach depth
4029  real(DP), intent(in) :: hgwf !< groundwater head in connected GWF cell
4030  real(DP), intent(inout) :: qgwf !< groundwater leakage for reach
4031  real(DP), intent(inout) :: qd !< residual
4032  ! -- local
4033  real(DP) :: qsrc
4034  !
4035  ! -- initialize residual
4036  qd = dzero
4037  !
4038  ! -- calculate total water sources excluding groundwater leakage
4039  call this%sfr_calc_qsource(n, depth, qsrc)
4040  !
4041  ! -- estimate groundwater leakage
4042  call this%sfr_calc_qgwf(n, depth, hgwf, qgwf)
4043  if (-qgwf > qsrc) qgwf = -qsrc
4044  !
4045  ! -- calculate down stream flow
4046  qd = qsrc + qgwf
4047  !
4048  ! -- limit downstream flow to a positive value
4049  if (qd < dem30) qd = dzero
4050  end subroutine sfr_calc_qd
4051 
4052  !> @brief Calculate sum of sources
4053  !!
4054  !! Method to calculate the sum of sources for reach, excluding
4055  !! reach leakage, for a SFR package reach.
4056  !<
4057  subroutine sfr_calc_qsource(this, n, depth, qsrc)
4058  ! -- dummy
4059  class(sfrtype) :: this !< SfrType object
4060  integer(I4B), intent(in) :: n !< reach number
4061  real(DP), intent(in) :: depth !< reach depth
4062  real(DP), intent(inout) :: qsrc !< sum of sources for reach
4063  ! -- local
4064  real(DP) :: qu
4065  real(DP) :: qi
4066  real(DP) :: qr
4067  real(DP) :: qe
4068  real(DP) :: qro
4069  real(DP) :: qfrommvr
4070  real(DP) :: a
4071  real(DP) :: ae
4072  !
4073  ! -- initialize residual
4074  qsrc = dzero
4075  !
4076  ! -- calculate flow terms
4077  qu = this%usflow(n)
4078  qi = this%inflow(n)
4079  qro = this%runoff(n)
4080  !
4081  ! -- calculate rainfall and evap
4082  a = this%calc_surface_area(n)
4083  ae = this%calc_surface_area_wet(n, depth)
4084  qr = this%rain(n) * a
4085  qe = this%evap(n) * ae
4086  !
4087  ! -- calculate mover term
4088  qfrommvr = dzero
4089  if (this%imover == 1) then
4090  qfrommvr = this%pakmvrobj%get_qfrommvr(n)
4091  end if
4092  !
4093  ! -- calculate down stream flow
4094  qsrc = qu + qi + qr - qe + qro + qfrommvr
4095  !
4096  ! -- adjust runoff or evaporation if sum of sources is negative
4097  call this%sfr_adjust_ro_ev(qsrc, qu, qi, qr, qro, qe, qfrommvr)
4098  end subroutine sfr_calc_qsource
4099 
4100  !> @brief Calculate streamflow
4101  !!
4102  !! Method to calculate the streamflow using Manning's equation for a
4103  !! SFR package reach.
4104  !<
4105  subroutine sfr_calc_qman(this, n, depth, qman)
4106  ! -- dummy
4107  class(sfrtype) :: this !< SfrType object
4108  integer(I4B), intent(in) :: n !< reach number
4109  real(DP), intent(in) :: depth !< reach depth
4110  real(DP), intent(inout) :: qman !< streamflow
4111  ! -- local
4112  integer(I4B) :: npts
4113  integer(I4B) :: i0
4114  integer(I4B) :: i1
4115  real(DP) :: sat
4116  real(DP) :: derv
4117  real(DP) :: s
4118  real(DP) :: r
4119  real(DP) :: aw
4120  real(DP) :: wp
4121  real(DP) :: rh
4122  !
4123  ! -- initialize variables
4124  qman = dzero
4125  !
4126  ! -- calculate Manning's discharge for non-zero depths
4127  if (depth > dzero) then
4128  npts = this%ncrosspts(n)
4129  !
4130  ! -- set constant terms for Manning's equation
4131  call schsmooth(depth, sat, derv)
4132  s = this%slope(n)
4133  !
4134  ! -- calculate the mannings coefficient that is a
4135  ! function of depth
4136  if (npts > 1) then
4137  !
4138  ! -- get the location of the cross-section data for the reach
4139  i0 = this%iacross(n)
4140  i1 = this%iacross(n + 1) - 1
4141  !
4142  ! -- get the Manning's sum of the Manning's discharge
4143  ! for each section
4144  qman = get_mannings_section(npts, &
4145  this%station(i0:i1), &
4146  this%xsheight(i0:i1), &
4147  this%xsrough(i0:i1), &
4148  this%rough(n), &
4149  this%unitconv, &
4150  s, &
4151  depth)
4152  else
4153  r = this%rough(n)
4154  aw = this%calc_area_wet(n, depth)
4155  wp = this%calc_perimeter_wet(n, depth)
4156  if (wp > dzero) then
4157  rh = aw / wp
4158  else
4159  rh = dzero
4160  end if
4161  qman = this%unitconv * aw * (rh**dtwothirds) * sqrt(s) / r
4162  end if
4163  !
4164  ! -- calculate stream flow
4165  qman = sat * qman
4166  end if
4167  end subroutine sfr_calc_qman
4168 
4169  !> @brief Calculate reach-aquifer exchange
4170  !!
4171  !! Method to calculate the reach-aquifer exchange for a SFR package reach.
4172  !! The reach-aquifer exchange is relative to the reach. Calculated flow
4173  !! is positive if flow is from the aquifer to the reach.
4174  !<
4175  subroutine sfr_calc_qgwf(this, n, depth, hgwf, qgwf, gwfhcof, gwfrhs)
4176  ! -- dummy
4177  class(sfrtype) :: this !< SfrType object
4178  integer(I4B), intent(in) :: n !< reach number
4179  real(DP), intent(in) :: depth !< reach depth
4180  real(DP), intent(in) :: hgwf !< head in GWF cell connected to reach
4181  real(DP), intent(inout) :: qgwf !< reach-aquifer exchange
4182  real(DP), intent(inout), optional :: gwfhcof !< diagonal coefficient term for reach
4183  real(DP), intent(inout), optional :: gwfrhs !< right-hand side term for reach
4184  ! -- local
4185  integer(I4B) :: node
4186  real(DP) :: tp
4187  real(DP) :: bt
4188  real(DP) :: hsfr
4189  real(DP) :: h_temp
4190  real(DP) :: cond
4191  real(DP) :: sat
4192  real(DP) :: derv
4193  real(DP) :: gwfhcof0
4194  real(DP) :: gwfrhs0
4195  !
4196  ! -- initialize qgwf
4197  qgwf = dzero
4198  !
4199  ! -- skip sfr-aquifer exchange in external cells
4200  node = this%igwfnode(n)
4201  if (node < 1) return
4202  !
4203  ! -- skip sfr-aquifer exchange in inactive cells
4204  if (this%ibound(node) == 0) return
4205  !
4206  ! -- calculate saturation
4207  call schsmooth(depth, sat, derv)
4208  !
4209  ! -- terms for calculating direction of gradient across streambed
4210  tp = this%strtop(n)
4211  bt = tp - this%bthick(n)
4212  hsfr = tp + depth
4213  h_temp = hgwf
4214  if (h_temp < bt) then
4215  h_temp = bt
4216  end if
4217  !
4218  ! -- calculate conductance
4219  call this%sfr_calc_cond(n, depth, cond, hsfr, h_temp)
4220  !
4221  ! -- calculate groundwater leakage
4222  qgwf = sat * cond * (h_temp - hsfr)
4223  gwfrhs0 = -sat * cond * hsfr
4224  gwfhcof0 = -sat * cond
4225  !
4226  ! Add density contributions, if active
4227  if (this%idense /= 0) then
4228  call this%sfr_calculate_density_exchange(n, hsfr, hgwf, cond, tp, &
4229  qgwf, gwfhcof0, gwfrhs0)
4230  end if
4231  !
4232  ! -- Set gwfhcof and gwfrhs if present
4233  if (present(gwfhcof)) gwfhcof = gwfhcof0
4234  if (present(gwfrhs)) gwfrhs = gwfrhs0
4235  end subroutine sfr_calc_qgwf
4236 
4237  !> @brief Determine if a reach is connected to a gwf cell
4238  !!
4239  !! Function to determine if a reach is connected to a gwf cell. If connected,
4240  !! the return value is 1. Otherwise, the return value is 0.
4241  !<
4242  function sfr_gwf_conn(this, n)
4243  ! -- return variable
4244  integer(I4B) :: sfr_gwf_conn !< flag indicating if reach is connected to a gwf cell
4245  ! -- dummy
4246  class(sfrtype) :: this !< SfrType object
4247  integer(I4B), intent(in) :: n !< reach number
4248  ! -- local
4249  integer(I4B) :: node
4250 
4251  sfr_gwf_conn = 0
4252  node = this%igwfnode(n)
4253  if (node > 0 .and. this%hk(n) > dzero) then
4254  sfr_gwf_conn = 1
4255  end if
4256  end function sfr_gwf_conn
4257 
4258  !> @brief Calculate reach-aquifer conductance
4259  !!
4260  !! Method to calculate the reach-aquifer conductance for a SFR package reach.
4261  !<
4262  subroutine sfr_calc_cond(this, n, depth, cond, hsfr, h_temp)
4263  ! -- dummy
4264  class(sfrtype) :: this !< SfrType object
4265  integer(I4B), intent(in) :: n !< reach number
4266  real(DP), intent(in) :: depth !< reach depth
4267  real(DP), intent(inout) :: cond !< reach-aquifer conductance
4268  real(DP), intent(in), optional :: hsfr !< stream stage
4269  real(DP), intent(in), optional :: h_temp !< head in gw cell
4270  ! -- local
4271  integer(I4B) :: node
4272  real(DP) :: wp
4273  real(DP) :: vscratio
4274  !
4275  ! -- initialize conductance
4276  cond = dzero
4277  !
4278  ! -- initial viscosity ratio to 1
4279  vscratio = done
4280  !
4281  ! -- calculate conductance if GWF cell is active
4282  ! rch-gwf flow will not occur if reach connected to an constant head cell
4283  node = this%igwfnode(n)
4284  if (node > 0) then
4285  if (this%ibound(node) > 0) then
4286  !
4287  ! -- direction of gradient across streambed determines which vsc ratio
4288  if (this%ivsc == 1) then
4289  if (hsfr > h_temp) then
4290  ! strm stg > gw head
4291  vscratio = this%viscratios(1, n)
4292  else
4293  vscratio = this%viscratios(2, n)
4294  end if
4295  end if
4296  wp = this%calc_perimeter_wet(n, depth)
4297  cond = this%hk(n) * vscratio * this%length(n) * wp / this%bthick(n)
4298  end if
4299  end if
4300  end subroutine sfr_calc_cond
4301 
4302  !> @brief Calculate diversion flow
4303  !!
4304  !! Method to calculate the diversion flow for a diversion connected
4305  !! to a SFR package reach. The downstream flow for a reach is passed
4306  !! in and adjusted by the diversion flow amount calculated in this
4307  !! method.
4308  !<
4309  subroutine sfr_calc_div(this, n, i, qd, qdiv)
4310  ! -- dummy
4311  class(sfrtype) :: this !< SfrType object
4312  integer(I4B), intent(in) :: n !< reach number
4313  integer(I4B), intent(in) :: i !< diversion number in reach
4314  real(DP), intent(inout) :: qd !< remaining downstream flow for reach
4315  real(DP), intent(inout) :: qdiv !< diversion flow for diversion i
4316  ! -- local
4317  character(len=10) :: cp
4318  integer(I4B) :: jpos
4319  integer(I4B) :: n2
4320  real(DP) :: v
4321  !
4322  ! -- set local variables
4323  jpos = this%iadiv(n) + i - 1
4324  n2 = this%divreach(jpos)
4325  cp = this%divcprior(jpos)
4326  v = this%divflow(jpos)
4327  !
4328  ! -- calculate diversion
4329  select case (cp)
4330  ! -- flood diversion
4331  case ('EXCESS')
4332  if (qd < v) then
4333  v = dzero
4334  else
4335  v = qd - v
4336  end if
4337  ! -- diversion percentage
4338  case ('FRACTION')
4339  v = qd * v
4340  ! -- STR priority algorithm
4341  case ('THRESHOLD')
4342  if (qd < v) then
4343  v = dzero
4344  end if
4345  ! -- specified diversion
4346  case ('UPTO')
4347  if (v > qd) then
4348  v = qd
4349  end if
4350  case default
4351  v = dzero
4352  end select
4353  !
4354  ! -- update upstream from for downstream reaches
4355  qd = qd - v
4356  qdiv = v
4357  end subroutine sfr_calc_div
4358 
4359  !> @brief Calculate the depth at the midpoint
4360  !!
4361  !! Method to calculate the depth at the midpoint of a reach.
4362  !<
4363  subroutine sfr_calc_reach_depth(this, n, q1, d1)
4364  ! -- dummy
4365  class(sfrtype) :: this !< SfrType object
4366  integer(I4B), intent(in) :: n !< reach number
4367  real(DP), intent(in) :: q1 !< streamflow
4368  real(DP), intent(inout) :: d1 !< stream depth at midpoint of reach
4369  ! -- local
4370  real(DP) :: w
4371  real(DP) :: s
4372  real(DP) :: r
4373  real(DP) :: qconst
4374  !
4375  ! -- initialize slope and roughness
4376  s = this%slope(n)
4377  r = this%rough(n)
4378  !
4379  ! -- calculate stream depth at the midpoint
4380  if (q1 > dzero) then
4381  if (this%ncrosspts(n) > 1) then
4382  call this%sfr_calc_xs_depth(n, q1, d1)
4383  else
4384  w = this%station(this%iacross(n))
4385  qconst = this%unitconv * w * sqrt(s) / r
4386  d1 = (q1 / qconst)**dp6
4387  end if
4388  else
4389  d1 = dzero
4390  end if
4391  end subroutine sfr_calc_reach_depth
4392 
4393  !> @brief Calculate the depth at the midpoint of a irregular cross-section
4394  !!
4395  !! Method to calculate the depth at the midpoint of a reach with a
4396  !! irregular cross-section using Newton-Raphson.
4397  !<
4398  subroutine sfr_calc_xs_depth(this, n, qrch, d)
4399  ! -- dummy
4400  class(sfrtype) :: this !< SfrType object
4401  integer(I4B), intent(in) :: n !< reach number
4402  real(DP), intent(in) :: qrch !< streamflow
4403  real(DP), intent(inout) :: d !< stream depth at midpoint of reach
4404  ! -- local
4405  integer(I4B) :: iter
4406  real(DP) :: perturbation
4407  real(DP) :: q0
4408  real(DP) :: q1
4409  real(DP) :: dq
4410  real(DP) :: derv
4411  real(DP) :: dd
4412  real(DP) :: residual
4413  !
4414  ! -- initialize variables
4415  perturbation = this%deps * dtwo
4416  d = dzero
4417  q0 = dzero
4418  residual = q0 - qrch
4419  !
4420  ! -- Newton-Raphson iteration
4421  nriter: do iter = 1, this%maxsfrit
4422  call this%sfr_calc_qman(n, d + perturbation, q1)
4423  dq = (q1 - q0)
4424  if (dq /= dzero) then
4425  derv = perturbation / (q1 - q0)
4426  else
4427  derv = dzero
4428  end if
4429  dd = derv * residual
4430  d = d - dd
4431  call this%sfr_calc_qman(n, d, q0)
4432  residual = q0 - qrch
4433  !
4434  ! -- check for convergence
4435  if (abs(dd) < this%dmaxchg) then
4436  exit nriter
4437  end if
4438  end do nriter
4439  end subroutine sfr_calc_xs_depth
4440 
4441  !> @brief Check unit conversion data
4442  !!
4443  !! Method to check unit conversion data for a SFR package. This method
4444  !! also calculates unitconv that is used in the Manning's equation.
4445  !<
4446  subroutine sfr_check_conversion(this)
4447  ! -- dummy
4448  class(sfrtype) :: this !< SfrType object
4449  ! -- local
4450  ! -- formats
4451  character(len=*), parameter :: fmtunitconv_error = &
4452  &"('SFR (',a,') UNIT_CONVERSION SPECIFIED VALUE (',g0,') AND', &
4453  &1x,'LENGTH_CONVERSION OR TIME_CONVERSION SPECIFIED.')"
4454  character(len=*), parameter :: fmtunitconv = &
4455  &"(1x,'SFR PACKAGE (',a,') CONVERSION DATA',&
4456  &/4x,'UNIT CONVERSION VALUE (',g0,').',/)"
4457  !
4458  ! -- check the reach data for simple errors
4459  if (this%lengthconv /= dnodata .or. this%timeconv /= dnodata) then
4460  if (this%unitconv /= done) then
4461  write (errmsg, fmtunitconv_error) &
4462  trim(adjustl(this%packName)), this%unitconv
4463  call store_error(errmsg)
4464  else
4465  if (this%lengthconv /= dnodata) then
4466  this%unitconv = this%unitconv * this%lengthconv**donethird
4467  end if
4468  if (this%timeconv /= dnodata) then
4469  this%unitconv = this%unitconv * this%timeconv
4470  end if
4471  write (this%iout, fmtunitconv) &
4472  trim(adjustl(this%packName)), this%unitconv
4473  end if
4474  end if
4475  end subroutine sfr_check_conversion
4476 
4477  !> @brief Check storage weight
4478  !!
4479  !! Method to check the kinematic storage weight for a SFR package.
4480  !! If the kinematic storage weight has not been set it is set to
4481  !! the default value.
4482  !<
4483  subroutine sfr_check_storage_weight(this)
4484  ! -- dummy
4485  class(sfrtype) :: this !< SfrType object
4486  ! -- formats
4487  character(len=*), parameter :: fmtweight = &
4488  &"(1x,'SFR PACKAGE (',a,') SETTING DEFAULT',&
4489  &/4x,'STORAGE_WEIGHT VALUE (',g0,').',/)"
4490  !
4491  ! -- set storage weight if it has not been defined yet
4492  if (this%istorage == 1) then
4493  if (this%storage_weight == dnodata) then
4494  this%storage_weight = done
4495  write (this%iout, fmtweight) &
4496  trim(adjustl(this%packName)), this%storage_weight
4497  end if
4498  end if
4499  end subroutine sfr_check_storage_weight
4500 
4501  !> @brief Check reach data
4502  !!
4503  !! Method to check specified data for a SFR package. This method
4504  !! also creates the tables used to print input data, if this
4505  !! option in enabled in the SFR package.
4506  !<
4507  subroutine sfr_check_reaches(this)
4508  ! -- dummy
4509  class(sfrtype) :: this !< SfrType object
4510  ! -- local
4511  character(len=5) :: crch
4512  character(len=10) :: cval
4513  character(len=30) :: nodestr
4514  character(len=LINELENGTH) :: title
4515  character(len=LINELENGTH) :: text
4516  integer(I4B) :: n
4517  integer(I4B) :: nn
4518  real(DP) :: btgwf
4519  real(DP) :: bt
4520  !
4521  ! -- setup inputtab tableobj
4522  if (this%iprpak /= 0) then
4523  title = trim(adjustl(this%text))//' PACKAGE ('// &
4524  trim(adjustl(this%packName))//') STATIC REACH DATA'
4525  call table_cr(this%inputtab, this%packName, title)
4526  call this%inputtab%table_df(this%maxbound, 10, this%iout)
4527  text = 'NUMBER'
4528  call this%inputtab%initialize_column(text, 10, alignment=tabcenter)
4529  text = 'CELLID'
4530  call this%inputtab%initialize_column(text, 20, alignment=tableft)
4531  text = 'LENGTH'
4532  call this%inputtab%initialize_column(text, 12, alignment=tabcenter)
4533  text = 'WIDTH'
4534  call this%inputtab%initialize_column(text, 12, alignment=tabcenter)
4535  text = 'SLOPE'
4536  call this%inputtab%initialize_column(text, 12, alignment=tabcenter)
4537  text = 'TOP'
4538  call this%inputtab%initialize_column(text, 12, alignment=tabcenter)
4539  text = 'THICKNESS'
4540  call this%inputtab%initialize_column(text, 12, alignment=tabcenter)
4541  text = 'HK'
4542  call this%inputtab%initialize_column(text, 12, alignment=tabcenter)
4543  text = 'ROUGHNESS'
4544  call this%inputtab%initialize_column(text, 12, alignment=tabcenter)
4545  text = 'UPSTREAM FRACTION'
4546  call this%inputtab%initialize_column(text, 12, alignment=tabcenter)
4547  end if
4548  !
4549  ! -- check the reach data for simple errors
4550  do n = 1, this%maxbound
4551  write (crch, '(i5)') n
4552  nn = this%igwfnode(n)
4553  if (nn > 0) then
4554  btgwf = this%dis%bot(nn)
4555  call this%dis%noder_to_string(nn, nodestr)
4556  else
4557  nodestr = 'none'
4558  end if
4559  ! -- check reach length
4560  if (this%length(n) <= dzero) then
4561  errmsg = 'Reach '//crch//' length must be greater than 0.0.'
4562  call store_error(errmsg)
4563  end if
4564  ! -- check reach width
4565  if (this%width(n) <= dzero) then
4566  errmsg = 'Reach '//crch//' width must be greater than 0.0.'
4567  call store_error(errmsg)
4568  end if
4569  ! -- check reach slope
4570  if (this%slope(n) <= dzero) then
4571  errmsg = 'Reach '//crch//' slope must be greater than 0.0.'
4572  call store_error(errmsg)
4573  end if
4574  ! -- check bed thickness and bed hk for reaches connected to GWF
4575  if (nn > 0) then
4576  bt = this%strtop(n) - this%bthick(n)
4577  if (bt <= btgwf .and. this%icheck /= 0) then
4578  write (cval, '(f10.4)') bt
4579  errmsg = 'Reach '//crch//' bed bottom (rtp-rbth ='// &
4580  cval//') must be greater than the bottom of cell ('// &
4581  nodestr
4582  write (cval, '(f10.4)') btgwf
4583  errmsg = trim(adjustl(errmsg))//'='//cval//').'
4584  call store_error(errmsg)
4585  end if
4586  if (this%hk(n) < dzero) then
4587  errmsg = 'Reach '//crch//' hk must be greater than or equal to 0.0.'
4588  call store_error(errmsg)
4589  end if
4590  end if
4591  ! -- check reach roughness
4592  if (this%rough(n) <= dzero) then
4593  errmsg = 'Reach '//crch//" Manning's roughness "// &
4594  'coefficient must be greater than 0.0.'
4595  call store_error(errmsg)
4596  end if
4597  ! -- check reach upstream fraction
4598  if (this%ustrf(n) < dzero) then
4599  errmsg = 'Reach '//crch//' upstream fraction must be greater '// &
4600  'than or equal to 0.0.'
4601  call store_error(errmsg)
4602  end if
4603  ! -- write summary of reach information
4604  if (this%iprpak /= 0) then
4605  call this%inputtab%add_term(n)
4606  call this%inputtab%add_term(nodestr)
4607  call this%inputtab%add_term(this%length(n))
4608  call this%inputtab%add_term(this%width(n))
4609  call this%inputtab%add_term(this%slope(n))
4610  call this%inputtab%add_term(this%strtop(n))
4611  call this%inputtab%add_term(this%bthick(n))
4612  call this%inputtab%add_term(this%hk(n))
4613  call this%inputtab%add_term(this%rough(n))
4614  call this%inputtab%add_term(this%ustrf(n))
4615  end if
4616  end do
4617  end subroutine sfr_check_reaches
4618 
4619  !> @brief Check connection data
4620  !!
4621  !! Method to check connection data for a SFR package. This method
4622  !! also creates the tables used to print input data, if this
4623  !! option in enabled in the SFR package.
4624  !<
4625  subroutine sfr_check_connections(this)
4626  ! -- dummy
4627  class(sfrtype) :: this !< SfrType object
4628  ! -- local
4629  logical(LGP) :: lreorder
4630  character(len=5) :: crch
4631  character(len=5) :: crch2
4632  character(len=LINELENGTH) :: text
4633  character(len=LINELENGTH) :: title
4634  integer(I4B) :: n
4635  integer(I4B) :: nn
4636  integer(I4B) :: nc
4637  integer(I4B) :: i
4638  integer(I4B) :: ii
4639  integer(I4B) :: j
4640  integer(I4B) :: ifound
4641  integer(I4B) :: ierr
4642  integer(I4B) :: maxconn
4643  integer(I4B) :: ntabcol
4644  !
4645  ! -- determine if the reaches have been reordered
4646  lreorder = .false.
4647  do j = 1, this%MAXBOUND
4648  n = this%isfrorder(j)
4649  if (n /= j) then
4650  lreorder = .true.
4651  exit
4652  end if
4653  end do
4654  !
4655  ! -- write message that the solution order h
4656  if (lreorder) then
4657  write (this%iout, '(/,1x,a)') &
4658  trim(adjustl(this%text))//' PACKAGE ('// &
4659  trim(adjustl(this%packName))//') REACH SOLUTION HAS BEEN '// &
4660  'REORDERED USING A DAG'
4661  !
4662  ! -- print table
4663  if (this%iprpak /= 0) then
4664  !
4665  ! -- reset the input table object
4666  ntabcol = 2
4667  title = trim(adjustl(this%text))//' PACKAGE ('// &
4668  trim(adjustl(this%packName))//') REACH SOLUTION ORDER'
4669  call table_cr(this%inputtab, this%packName, title)
4670  call this%inputtab%table_df(this%maxbound, ntabcol, this%iout)
4671  text = 'ORDER'
4672  call this%inputtab%initialize_column(text, 10, alignment=tabcenter)
4673  text = 'REACH'
4674  call this%inputtab%initialize_column(text, 10, alignment=tabcenter)
4675  !
4676  ! -- upstream connection data
4677  do j = 1, this%maxbound
4678  n = this%isfrorder(j)
4679  call this%inputtab%add_term(j)
4680  call this%inputtab%add_term(n)
4681  end do
4682  end if
4683  end if
4684  !
4685  ! -- create input table for reach connections data
4686  if (this%iprpak /= 0) then
4687  !
4688  ! -- calculate the maximum number of connections
4689  maxconn = 0
4690  do n = 1, this%maxbound
4691  maxconn = max(maxconn, this%nconnreach(n))
4692  end do
4693  ntabcol = 1 + maxconn
4694  !
4695  ! -- reset the input table object
4696  title = trim(adjustl(this%text))//' PACKAGE ('// &
4697  trim(adjustl(this%packName))//') STATIC REACH CONNECTION DATA'
4698  call table_cr(this%inputtab, this%packName, title)
4699  call this%inputtab%table_df(this%maxbound, ntabcol, this%iout)
4700  text = 'REACH'
4701  call this%inputtab%initialize_column(text, 10, alignment=tabcenter)
4702  do n = 1, maxconn
4703  write (text, '(a,1x,i6)') 'CONN', n
4704  call this%inputtab%initialize_column(text, 10, alignment=tabcenter)
4705  end do
4706  end if
4707  !
4708  ! -- check the reach connections for simple errors
4709  ! -- connection check
4710  do n = 1, this%MAXBOUND
4711  write (crch, '(i5)') n
4712  eachconn: do i = this%ia(n) + 1, this%ia(n + 1) - 1
4713  nn = this%ja(i)
4714  write (crch2, '(i5)') nn
4715  ifound = 0
4716  connreach: do ii = this%ia(nn) + 1, this%ia(nn + 1) - 1
4717  nc = this%ja(ii)
4718  if (nc == n) then
4719  ifound = 1
4720  exit connreach
4721  end if
4722  end do connreach
4723  if (ifound /= 1) then
4724  errmsg = 'Reach '//crch//' is connected to '// &
4725  'reach '//crch2//' but reach '//crch2// &
4726  ' is not connected to reach '//crch//'.'
4727  call store_error(errmsg)
4728  end if
4729  end do eachconn
4730  !
4731  ! -- write connection data to the table
4732  if (this%iprpak /= 0) then
4733  call this%inputtab%add_term(n)
4734  do i = this%ia(n) + 1, this%ia(n + 1) - 1
4735  call this%inputtab%add_term(this%ja(i))
4736  end do
4737  nn = maxconn - this%nconnreach(n)
4738  do i = 1, nn
4739  call this%inputtab%add_term(' ')
4740  end do
4741  end if
4742  end do
4743  !
4744  ! -- check for incorrect connections between upstream connections
4745  !
4746  ! -- check upstream connections for each reach
4747  ierr = 0
4748  do n = 1, this%maxbound
4749  write (crch, '(i5)') n
4750  eachconnv: do i = this%ia(n) + 1, this%ia(n + 1) - 1
4751  !
4752  ! -- skip downstream connections
4753  if (this%idir(i) < 0) cycle eachconnv
4754  nn = this%ja(i)
4755  write (crch2, '(i5)') nn
4756  connreachv: do ii = this%ia(nn) + 1, this%ia(nn + 1) - 1
4757  ! -- skip downstream connections
4758  if (this%idir(ii) < 0) cycle connreachv
4759  nc = this%ja(ii)
4760  !
4761  ! -- if nc == n then that means reach n is an upstream connection for
4762  ! reach nn and reach nn is an upstream connection for reach n
4763  if (nc == n) then
4764  ierr = ierr + 1
4765  errmsg = 'Reach '//crch//' is connected to '// &
4766  'reach '//crch2//' but streamflow from reach '// &
4767  crch//' to reach '//crch2//' is not permitted.'
4768  call store_error(errmsg)
4769  exit connreachv
4770  end if
4771  end do connreachv
4772  end do eachconnv
4773  end do
4774  !
4775  ! -- terminate if connectivity errors
4776  if (count_errors() > 0) then
4777  call this%parser%StoreErrorUnit()
4778  end if
4779  !
4780  ! -- check that downstream reaches for a reach are
4781  ! the upstream reaches for the reach
4782  do n = 1, this%maxbound
4783  write (crch, '(i5)') n
4784  eachconnds: do i = this%ia(n) + 1, this%ia(n + 1) - 1
4785  nn = this%ja(i)
4786  if (this%idir(i) > 0) cycle eachconnds
4787  write (crch2, '(i5)') nn
4788  ifound = 0
4789  connreachds: do ii = this%ia(nn) + 1, this%ia(nn + 1) - 1
4790  nc = this%ja(ii)
4791  if (nc == n) then
4792  if (this%idir(i) /= this%idir(ii)) then
4793  ifound = 1
4794  end if
4795  exit connreachds
4796  end if
4797  end do connreachds
4798  if (ifound /= 1) then
4799  errmsg = 'Reach '//crch//' downstream connected reach '// &
4800  'is reach '//crch2//' but reach '//crch//' is not'// &
4801  ' the upstream connected reach for reach '//crch2//'.'
4802  call store_error(errmsg)
4803  end if
4804  end do eachconnds
4805  end do
4806  !
4807  ! -- create input table for upstream and downstream connections
4808  if (this%iprpak /= 0) then
4809  !
4810  ! -- calculate the maximum number of upstream connections
4811  maxconn = 0
4812  do n = 1, this%maxbound
4813  ii = 0
4814  do i = this%ia(n) + 1, this%ia(n + 1) - 1
4815  if (this%idir(i) > 0) then
4816  ii = ii + 1
4817  end if
4818  end do
4819  maxconn = max(maxconn, ii)
4820  end do
4821  ntabcol = 1 + maxconn
4822  !
4823  ! -- reset the input table object
4824  title = trim(adjustl(this%text))//' PACKAGE ('// &
4825  trim(adjustl(this%packName))//') STATIC UPSTREAM REACH '// &
4826  'CONNECTION DATA'
4827  call table_cr(this%inputtab, this%packName, title)
4828  call this%inputtab%table_df(this%maxbound, ntabcol, this%iout)
4829  text = 'REACH'
4830  call this%inputtab%initialize_column(text, 10, alignment=tabcenter)
4831  do n = 1, maxconn
4832  write (text, '(a,1x,i6)') 'UPSTREAM CONN', n
4833  call this%inputtab%initialize_column(text, 10, alignment=tabcenter)
4834  end do
4835  !
4836  ! -- upstream connection data
4837  do n = 1, this%maxbound
4838  call this%inputtab%add_term(n)
4839  ii = 0
4840  do i = this%ia(n) + 1, this%ia(n + 1) - 1
4841  if (this%idir(i) > 0) then
4842  call this%inputtab%add_term(this%ja(i))
4843  ii = ii + 1
4844  end if
4845  end do
4846  nn = maxconn - ii
4847  do i = 1, nn
4848  call this%inputtab%add_term(' ')
4849  end do
4850  end do
4851  !
4852  ! -- calculate the maximum number of downstream connections
4853  maxconn = 0
4854  do n = 1, this%maxbound
4855  ii = 0
4856  do i = this%ia(n) + 1, this%ia(n + 1) - 1
4857  if (this%idir(i) < 0) then
4858  ii = ii + 1
4859  end if
4860  end do
4861  maxconn = max(maxconn, ii)
4862  end do
4863  ntabcol = 1 + maxconn
4864  !
4865  ! -- reset the input table object
4866  title = trim(adjustl(this%text))//' PACKAGE ('// &
4867  trim(adjustl(this%packName))//') STATIC DOWNSTREAM '// &
4868  'REACH CONNECTION DATA'
4869  call table_cr(this%inputtab, this%packName, title)
4870  call this%inputtab%table_df(this%maxbound, ntabcol, this%iout)
4871  text = 'REACH'
4872  call this%inputtab%initialize_column(text, 10, alignment=tabcenter)
4873  do n = 1, maxconn
4874  write (text, '(a,1x,i6)') 'DOWNSTREAM CONN', n
4875  call this%inputtab%initialize_column(text, 10, alignment=tabcenter)
4876  end do
4877  !
4878  ! -- downstream connection data
4879  do n = 1, this%maxbound
4880  call this%inputtab%add_term(n)
4881  ii = 0
4882  do i = this%ia(n) + 1, this%ia(n + 1) - 1
4883  if (this%idir(i) < 0) then
4884  call this%inputtab%add_term(this%ja(i))
4885  ii = ii + 1
4886  end if
4887  end do
4888  nn = maxconn - ii
4889  do i = 1, nn
4890  call this%inputtab%add_term(' ')
4891  end do
4892  end do
4893  end if
4894  end subroutine sfr_check_connections
4895 
4896  !> @brief Check diversions data
4897  !!
4898  !! Method to check diversion data for a SFR package. This method
4899  !! also creates the tables used to print input data, if this
4900  !! option in enabled in the SFR package.
4901  !<
4902  subroutine sfr_check_diversions(this)
4903  ! -- dummy
4904  class(sfrtype) :: this !< SfrType object
4905  ! -- local
4906  character(len=LINELENGTH) :: title
4907  character(len=LINELENGTH) :: text
4908  character(len=5) :: crch
4909  character(len=5) :: cdiv
4910  character(len=5) :: crch2
4911  character(len=10) :: cprior
4912  integer(I4B) :: maxdiv
4913  integer(I4B) :: n
4914  integer(I4B) :: nn
4915  integer(I4B) :: nc
4916  integer(I4B) :: ii
4917  integer(I4B) :: idiv
4918  integer(I4B) :: ifound
4919  integer(I4B) :: jpos
4920  ! -- format
4921 10 format('Diversion ', i0, ' of reach ', i0, &
4922  ' is invalid or has not been defined.')
4923  !
4924  ! -- write header
4925  if (this%iprpak /= 0) then
4926  !
4927  ! -- determine the maximum number of diversions
4928  maxdiv = 0
4929  do n = 1, this%maxbound
4930  maxdiv = maxdiv + this%ndiv(n)
4931  end do
4932  !
4933  ! -- reset the input table object
4934  title = trim(adjustl(this%text))//' PACKAGE ('// &
4935  trim(adjustl(this%packName))//') REACH DIVERSION DATA'
4936  call table_cr(this%inputtab, this%packName, title)
4937  call this%inputtab%table_df(maxdiv, 4, this%iout)
4938  text = 'REACH'
4939  call this%inputtab%initialize_column(text, 10, alignment=tabcenter)
4940  text = 'DIVERSION'
4941  call this%inputtab%initialize_column(text, 10, alignment=tabcenter)
4942  text = 'REACH 2'
4943  call this%inputtab%initialize_column(text, 10, alignment=tabcenter)
4944  text = 'CPRIOR'
4945  call this%inputtab%initialize_column(text, 10, alignment=tabcenter)
4946  end if
4947  !
4948  ! -- check that diversion data are correct
4949  do n = 1, this%maxbound
4950  if (this%ndiv(n) < 1) cycle
4951  write (crch, '(i5)') n
4952 
4953  do idiv = 1, this%ndiv(n)
4954  !
4955  ! -- determine diversion index
4956  jpos = this%iadiv(n) + idiv - 1
4957  !
4958  ! -- write idiv to cdiv
4959  write (cdiv, '(i5)') idiv
4960  !
4961  !
4962  nn = this%divreach(jpos)
4963  write (crch2, '(i5)') nn
4964  !
4965  ! -- make sure diversion reach is connected to current reach
4966  ifound = 0
4967  if (nn < 1 .or. nn > this%maxbound) then
4968  write (errmsg, 10) idiv, n
4969  call store_error(errmsg)
4970  cycle
4971  end if
4972  connreach: do ii = this%ia(nn) + 1, this%ia(nn + 1) - 1
4973  nc = this%ja(ii)
4974  if (nc == n) then
4975  if (this%idir(ii) > 0) then
4976  ifound = 1
4977  end if
4978  exit connreach
4979  end if
4980  end do connreach
4981  if (ifound /= 1) then
4982  errmsg = 'Reach '//crch//' is not a upstream reach for '// &
4983  'reach '//crch2//' as a result diversion '//cdiv// &
4984  ' from reach '//crch//' to reach '//crch2// &
4985  ' is not possible. Check reach connectivity.'
4986  call store_error(errmsg)
4987  end if
4988  ! -- iprior
4989  cprior = this%divcprior(jpos)
4990  !
4991  ! -- add terms to the table
4992  if (this%iprpak /= 0) then
4993  call this%inputtab%add_term(n)
4994  call this%inputtab%add_term(idiv)
4995  call this%inputtab%add_term(nn)
4996  call this%inputtab%add_term(cprior)
4997  end if
4998  end do
4999  end do
5000  end subroutine sfr_check_diversions
5001 
5002  !> @brief Check initial stage data
5003  !!
5004  !! Method to check initial data for a SFR package and calculates
5005  !! the initial upstream and downstream flows for the reach based
5006  !! on the initial staalso creates the tables used to print input
5007  !! data, if this option in enabled in the SFR package.
5008  !<
5009  subroutine sfr_check_initialstages(this)
5010  class(sfrtype) :: this !< SfrType object
5011 
5012  character(len=LINELENGTH) :: title
5013  character(len=LINELENGTH) :: text
5014  character(len=5) :: crch
5015  integer(I4B) :: n
5016  real(DP) :: qman
5017 
5018  ! skip check if storage is not activated
5019  if (this%istorage == 0) return
5020 
5021  ! write header
5022  if (this%iprpak /= 0) then
5023  !
5024  ! -- reset the input table object
5025  title = trim(adjustl(this%text))//' PACKAGE ('// &
5026  trim(adjustl(this%packName))//') REACH INITIAL STAGE DATA'
5027  call table_cr(this%inputtab, this%packName, title)
5028  call this%inputtab%table_df(this%maxbound, 4, this%iout)
5029  text = 'REACH'
5030  call this%inputtab%initialize_column(text, 10, alignment=tabcenter)
5031  text = 'INITIAL STAGE'
5032  call this%inputtab%initialize_column(text, 10, alignment=tabcenter)
5033  text = 'INITIAL DEPTH'
5034  call this%inputtab%initialize_column(text, 10, alignment=tabcenter)
5035  text = 'INITIAL FLOW'
5036  call this%inputtab%initialize_column(text, 10, alignment=tabcenter)
5037  end if
5038  !
5039  ! -- check that data are correct
5040  do n = 1, this%maxbound
5041  write (crch, '(i5)') n
5042 
5043  ! calculate the initial flows
5044  call this%sfr_calc_qman(n, this%depth(n), qman)
5045  this%usinflow(n) = qman
5046  this%dsflow(n) = qman
5047 
5048  ! add terms to the table
5049  if (this%iprpak /= 0) then
5050  call this%inputtab%add_term(n)
5051  call this%inputtab%add_term(this%stage(n))
5052  call this%inputtab%add_term(this%depth(n))
5053  call this%inputtab%add_term(qman)
5054  end if
5055  end do
5056  end subroutine sfr_check_initialstages
5057 
5058  !> @brief Check upstream fraction data
5059  !!
5060  !! Method to check upstream fraction data for a SFR package.
5061  !! This method also creates the tables used to print input data,
5062  !! if this option in enabled in the SFR package.
5063  !<
5064  subroutine sfr_check_ustrf(this)
5065  ! -- dummy
5066  class(sfrtype) :: this !< SfrType object
5067  ! -- local
5068  character(len=LINELENGTH) :: title
5069  character(len=LINELENGTH) :: text
5070  logical(LGP) :: lcycle
5071  logical(LGP) :: ladd
5072  character(len=5) :: crch
5073  character(len=5) :: crch2
5074  character(len=10) :: cval
5075  integer(I4B) :: maxcols
5076  integer(I4B) :: npairs
5077  integer(I4B) :: ipair
5078  integer(I4B) :: i
5079  integer(I4B) :: n
5080  integer(I4B) :: n2
5081  integer(I4B) :: idiv
5082  integer(I4B) :: i0
5083  integer(I4B) :: i1
5084  integer(I4B) :: jpos
5085  integer(I4B) :: ids
5086  real(DP) :: f
5087  real(DP) :: rval
5088  !
5089  ! -- write table header
5090  if (this%iprpak /= 0) then
5091  !
5092  ! -- determine the maximum number of columns
5093  npairs = 0
5094  do n = 1, this%maxbound
5095  ipair = 0
5096  ec: do i = this%ia(n) + 1, this%ia(n + 1) - 1
5097  !
5098  ! -- skip upstream connections
5099  if (this%idir(i) > 0) cycle ec
5100  n2 = this%ja(i)
5101  !
5102  ! -- skip inactive downstream reaches
5103  if (this%iboundpak(n2) == 0) cycle ec
5104  !
5105  ! -- increment ipair and see if it exceeds npairs
5106  ipair = ipair + 1
5107  npairs = max(npairs, ipair)
5108  end do ec
5109  end do
5110  maxcols = 1 + npairs * 2
5111  !
5112  ! -- reset the input table object
5113  title = trim(adjustl(this%text))//' PACKAGE ('// &
5114  trim(adjustl(this%packName))//') CONNECTED REACH UPSTREAM '// &
5115  'FRACTION DATA'
5116  call table_cr(this%inputtab, this%packName, title)
5117  call this%inputtab%table_df(this%maxbound, maxcols, this%iout)
5118  text = 'REACH'
5119  call this%inputtab%initialize_column(text, 10, alignment=tabcenter)
5120  do i = 1, npairs
5121  write (cval, '(i10)') i
5122  text = 'DOWNSTREAM REACH '//trim(adjustl(cval))
5123  call this%inputtab%initialize_column(text, 10, alignment=tabcenter)
5124  text = 'FRACTION '//trim(adjustl(cval))
5125  call this%inputtab%initialize_column(text, 12, alignment=tabcenter)
5126  end do
5127  end if
5128  !
5129  ! -- fill diversion number for each connection
5130  do n = 1, this%maxbound
5131  do idiv = 1, this%ndiv(n)
5132  i0 = this%iadiv(n)
5133  i1 = this%iadiv(n + 1) - 1
5134  do jpos = i0, i1
5135  do i = this%ia(n) + 1, this%ia(n + 1) - 1
5136  n2 = this%ja(i)
5137  if (this%divreach(jpos) == n2) then
5138  this%idiv(i) = jpos - i0 + 1
5139  exit
5140  end if
5141  end do
5142  end do
5143  end do
5144  end do
5145  !
5146  ! -- check that the upstream fraction for reach connected by
5147  ! a diversion is zero
5148  do n = 1, this%maxbound
5149  !
5150  ! -- determine the number of downstream reaches
5151  ids = 0
5152  do i = this%ia(n) + 1, this%ia(n + 1) - 1
5153  if (this%idir(i) < 0) then
5154  ids = ids + 1
5155  end if
5156  end do
5157  !
5158  ! -- evaluate the diversions
5159  do idiv = 1, this%ndiv(n)
5160  jpos = this%iadiv(n) + idiv - 1
5161  n2 = this%divreach(jpos)
5162  f = this%ustrf(n2)
5163  if (f /= dzero) then
5164  write (errmsg, '(a,2(1x,i0,1x,a),1x,a,g0,a,2(1x,a))') &
5165  'Reach', n, 'is connected to reach', n2, 'by a diversion', &
5166  'but the upstream fraction is not equal to zero (', f, '). Check', &
5167  trim(this%packName), 'package diversion and package data.'
5168  if (ids > 1) then
5169  call store_error(errmsg)
5170  else
5171  write (warnmsg, '(a,3(1x,a))') &
5172  trim(warnmsg), &
5173  'A warning instead of an error is issued because', &
5174  'the reach is only connected to the diversion reach in the ', &
5175  'downstream direction.'
5176  call store_warning(warnmsg)
5177  end if
5178  end if
5179  end do
5180  end do
5181  !
5182  ! -- calculate the total fraction of connected reaches that are
5183  ! not diversions and check that the sum of upstream fractions
5184  ! is equal to 1 for each reach
5185  do n = 1, this%maxbound
5186  ids = 0
5187  rval = dzero
5188  f = dzero
5189  write (crch, '(i5)') n
5190  if (this%iprpak /= 0) then
5191  call this%inputtab%add_term(n)
5192  end if
5193  ipair = 0
5194  eachconn: do i = this%ia(n) + 1, this%ia(n + 1) - 1
5195  lcycle = .false.
5196  !
5197  ! -- initialize downstream connection q
5198  this%qconn(i) = dzero
5199  !
5200  ! -- skip upstream connections
5201  if (this%idir(i) > 0) then
5202  lcycle = .true.
5203  end if
5204  n2 = this%ja(i)
5205  !
5206  ! -- skip inactive downstream reaches
5207  if (this%iboundpak(n2) == 0) then
5208  lcycle = .true.
5209  end if
5210  if (lcycle) then
5211  cycle eachconn
5212  end if
5213  ipair = ipair + 1
5214  write (crch2, '(i5)') n2
5215  ids = ids + 1
5216  ladd = .true.
5217  f = f + this%ustrf(n2)
5218  write (cval, '(f10.4)') this%ustrf(n2)
5219  !
5220  ! -- write upstream fractions
5221  if (this%iprpak /= 0) then
5222  call this%inputtab%add_term(n2)
5223  call this%inputtab%add_term(this%ustrf(n2))
5224  end if
5225  eachdiv: do idiv = 1, this%ndiv(n)
5226  jpos = this%iadiv(n) + idiv - 1
5227  if (this%divreach(jpos) == n2) then
5228  ladd = .false.
5229  exit eachdiv
5230  end if
5231  end do eachdiv
5232  if (ladd) then
5233  rval = rval + this%ustrf(n2)
5234  end if
5235  end do eachconn
5236  this%ftotnd(n) = rval
5237  !
5238  ! -- write remaining table columns
5239  if (this%iprpak /= 0) then
5240  ipair = ipair + 1
5241  do i = ipair, npairs
5242  call this%inputtab%add_term(' ')
5243  call this%inputtab%add_term(' ')
5244  end do
5245  end if
5246  !
5247  ! -- evaluate if an error condition has occurred
5248  ! the sum of fractions is not equal to 1
5249  if (ids /= 0) then
5250  if (abs(f - done) > dem6) then
5251  write (errmsg, '(a,1x,i0,1x,a,g0,a,3(1x,a))') &
5252  'Upstream fractions for reach ', n, 'is not equal to one (', f, &
5253  '). Check', trim(this%packName), 'package reach connectivity and', &
5254  'package data.'
5255  call store_error(errmsg)
5256  end if
5257  end if
5258  end do
5259  end subroutine sfr_check_ustrf
5260 
5261  !> @brief Setup budget object for package
5262  !!
5263  !! Method to set up the budget object that stores all the sfr flows
5264  !! The terms listed here must correspond in number and order to the ones
5265  !! listed in the sfr_fill_budobj method.
5266  !<
5267  subroutine sfr_setup_budobj(this)
5268  ! -- dummy
5269  class(sfrtype) :: this !< SfrType object
5270  ! -- local
5271  integer(I4B) :: nbudterm
5272  integer(I4B) :: i
5273  integer(I4B) :: n
5274  integer(I4B) :: n1
5275  integer(I4B) :: n2
5276  integer(I4B) :: maxlist
5277  integer(I4B) :: naux
5278  integer(I4B) :: idx
5279  real(DP) :: q
5280  character(len=LENBUDTXT) :: text
5281  character(len=LENBUDTXT), dimension(1) :: auxtxt
5282  !
5283  ! -- Determine the number of sfr budget terms. These are fixed for
5284  ! the simulation and cannot change. This includes FLOW-JA-FACE
5285  ! so they can be written to the binary budget files, but these internal
5286  ! flows are not included as part of the budget table.
5287  nbudterm = 8
5288  if (this%imover == 1) nbudterm = nbudterm + 2
5289  if (this%naux > 0) nbudterm = nbudterm + 1
5290  !
5291  ! -- set up budobj
5292  call budgetobject_cr(this%budobj, this%packName)
5293  call this%budobj%budgetobject_df(this%maxbound, nbudterm, 0, 0, &
5294  ibudcsv=this%ibudcsv)
5295  idx = 0
5296  !
5297  ! -- Go through and set up each budget term
5298  text = ' FLOW-JA-FACE'
5299  idx = idx + 1
5300  maxlist = this%nconn
5301  naux = 1
5302  auxtxt(1) = ' FLOW-AREA'
5303  call this%budobj%budterm(idx)%initialize(text, &
5304  this%name_model, &
5305  this%packName, &
5306  this%name_model, &
5307  this%packName, &
5308  maxlist, .false., .false., &
5309  naux, auxtxt)
5310  !
5311  ! -- store connectivity
5312  call this%budobj%budterm(idx)%reset(this%nconn)
5313  q = dzero
5314  do n = 1, this%maxbound
5315  n1 = n
5316  do i = this%ia(n) + 1, this%ia(n + 1) - 1
5317  n2 = this%ja(i)
5318  call this%budobj%budterm(idx)%update_term(n1, n2, q)
5319  end do
5320  end do
5321  !
5322  ! --
5323  text = ' GWF'
5324  idx = idx + 1
5325  maxlist = this%maxbound - this%ianynone
5326  naux = 1
5327  auxtxt(1) = ' FLOW-AREA'
5328  call this%budobj%budterm(idx)%initialize(text, &
5329  this%name_model, &
5330  this%packName, &
5331  this%name_model, &
5332  this%name_model, &
5333  maxlist, .false., .true., &
5334  naux, auxtxt)
5335  call this%budobj%budterm(idx)%reset(maxlist)
5336  q = dzero
5337  do n = 1, this%maxbound
5338  n2 = this%igwfnode(n)
5339  if (n2 > 0) then
5340  call this%budobj%budterm(idx)%update_term(n, n2, q)
5341  end if
5342  end do
5343  !
5344  ! --
5345  text = ' RAINFALL'
5346  idx = idx + 1
5347  maxlist = this%maxbound
5348  naux = 0
5349  call this%budobj%budterm(idx)%initialize(text, &
5350  this%name_model, &
5351  this%packName, &
5352  this%name_model, &
5353  this%packName, &
5354  maxlist, .false., .false., &
5355  naux)
5356  !
5357  ! --
5358  text = ' EVAPORATION'
5359  idx = idx + 1
5360  maxlist = this%maxbound
5361  naux = 0
5362  call this%budobj%budterm(idx)%initialize(text, &
5363  this%name_model, &
5364  this%packName, &
5365  this%name_model, &
5366  this%packName, &
5367  maxlist, .false., .false., &
5368  naux)
5369  !
5370  ! --
5371  text = ' RUNOFF'
5372  idx = idx + 1
5373  maxlist = this%maxbound
5374  naux = 0
5375  call this%budobj%budterm(idx)%initialize(text, &
5376  this%name_model, &
5377  this%packName, &
5378  this%name_model, &
5379  this%packName, &
5380  maxlist, .false., .false., &
5381  naux)
5382  !
5383  ! --
5384  text = ' EXT-INFLOW'
5385  idx = idx + 1
5386  maxlist = this%maxbound
5387  naux = 0
5388  call this%budobj%budterm(idx)%initialize(text, &
5389  this%name_model, &
5390  this%packName, &
5391  this%name_model, &
5392  this%packName, &
5393  maxlist, .false., .false., &
5394  naux)
5395  !
5396  ! --
5397  text = ' EXT-OUTFLOW'
5398  idx = idx + 1
5399  maxlist = this%maxbound
5400  naux = 0
5401  call this%budobj%budterm(idx)%initialize(text, &
5402  this%name_model, &
5403  this%packName, &
5404  this%name_model, &
5405  this%packName, &
5406  maxlist, .false., .false., &
5407  naux)
5408  !
5409  ! --
5410  text = ' STORAGE'
5411  idx = idx + 1
5412  maxlist = this%maxbound
5413  naux = 1
5414  auxtxt(1) = ' VOLUME'
5415  call this%budobj%budterm(idx)%initialize(text, &
5416  this%name_model, &
5417  this%packName, &
5418  this%name_model, &
5419  this%packName, &
5420  maxlist, .false., .false., &
5421  naux, auxtxt)
5422  !
5423  ! --
5424  if (this%imover == 1) then
5425  !
5426  ! --
5427  text = ' FROM-MVR'
5428  idx = idx + 1
5429  maxlist = this%maxbound
5430  naux = 0
5431  call this%budobj%budterm(idx)%initialize(text, &
5432  this%name_model, &
5433  this%packName, &
5434  this%name_model, &
5435  this%packName, &
5436  maxlist, .false., .false., &
5437  naux)
5438  !
5439  ! --
5440  text = ' TO-MVR'
5441  idx = idx + 1
5442  maxlist = this%maxbound
5443  naux = 0
5444  call this%budobj%budterm(idx)%initialize(text, &
5445  this%name_model, &
5446  this%packName, &
5447  this%name_model, &
5448  this%packName, &
5449  maxlist, .false., .false., &
5450  naux)
5451  end if
5452  !
5453  ! --
5454  naux = this%naux
5455  if (naux > 0) then
5456  !
5457  ! --
5458  text = ' AUXILIARY'
5459  idx = idx + 1
5460  maxlist = this%maxbound
5461  call this%budobj%budterm(idx)%initialize(text, &
5462  this%name_model, &
5463  this%packName, &
5464  this%name_model, &
5465  this%packName, &
5466  maxlist, .false., .false., &
5467  naux, this%auxname)
5468  end if
5469  !
5470  ! -- if sfr flow for each reach are written to the listing file
5471  if (this%iprflow /= 0) then
5472  call this%budobj%flowtable_df(this%iout, cellids='GWF')
5473  end if
5474  end subroutine sfr_setup_budobj
5475 
5476  !> @brief Copy flow terms into budget object for package
5477  !!
5478  !! Method to copy flows into the budget object that stores all the sfr flows
5479  !! The terms listed here must correspond in number and order to the ones
5480  !! added in the sfr_setup_budobj method.
5481  !<
5482  subroutine sfr_fill_budobj(this)
5483  ! -- dummy
5484  class(sfrtype) :: this !< SfrType object
5485  ! -- local
5486  integer(I4B) :: naux
5487  integer(I4B) :: i
5488  integer(I4B) :: n
5489  integer(I4B) :: n1
5490  integer(I4B) :: n2
5491  integer(I4B) :: ii
5492  integer(I4B) :: idx
5493  integer(I4B) :: idiv
5494  integer(I4B) :: jpos
5495  real(DP) :: q
5496  real(DP) :: qt
5497  real(DP) :: d
5498  real(DP) :: ca
5499  real(DP) :: a
5500  real(DP) :: wp
5501  real(DP) :: l
5502  !
5503  ! -- initialize counter
5504  idx = 0
5505  !
5506  ! -- FLOW JA FACE
5507  idx = idx + 1
5508  call this%budobj%budterm(idx)%reset(this%nconn)
5509  do n = 1, this%maxbound
5510  n1 = n
5511  q = dzero
5512  ca = dzero
5513  do i = this%ia(n) + 1, this%ia(n + 1) - 1
5514  n2 = this%ja(i)
5515  if (this%iboundpak(n) /= 0) then
5516  ! flow to downstream reaches
5517  if (this%idir(i) < 0) then
5518  qt = this%dsflow(n)
5519  q = -this%qconn(i)
5520  ! flow from upstream reaches
5521  else
5522  qt = this%usflow(n)
5523  do ii = this%ia(n2) + 1, this%ia(n2 + 1) - 1
5524  if (this%idir(ii) > 0) cycle
5525  if (this%ja(ii) /= n) cycle
5526  q = this%qconn(ii)
5527  exit
5528  end do
5529  end if
5530  ! calculate flow area
5531  call this%sfr_calc_reach_depth(n, qt, d)
5532  ca = this%calc_area_wet(n, d)
5533  else
5534  q = dzero
5535  ca = dzero
5536  end if
5537  this%qauxcbc(1) = ca
5538  call this%budobj%budterm(idx)%update_term(n1, n2, q, this%qauxcbc)
5539  end do
5540  end do
5541  !
5542  ! -- GWF (LEAKAGE)
5543  idx = idx + 1
5544  call this%budobj%budterm(idx)%reset(this%maxbound - this%ianynone)
5545  do n = 1, this%maxbound
5546  n2 = this%igwfnode(n)
5547  if (n2 > 0) then
5548  if (this%iboundpak(n) /= 0) then
5549  ! -- calc_perimeter_wet() does not enforce depth dependence
5550  if (this%depth(n) > dzero) then
5551  wp = this%calc_perimeter_wet(n, this%depth(n))
5552  else
5553  wp = dzero
5554  end if
5555  l = this%length(n)
5556  a = wp * l
5557  this%qauxcbc(1) = a
5558  q = -this%gwflow(n)
5559  else
5560  this%qauxcbc(1) = dzero
5561  q = dzero
5562  end if
5563  call this%budobj%budterm(idx)%update_term(n, n2, q, this%qauxcbc)
5564  end if
5565  end do
5566  !
5567  ! -- RAIN
5568  idx = idx + 1
5569  call this%budobj%budterm(idx)%reset(this%maxbound)
5570  do n = 1, this%maxbound
5571  if (this%iboundpak(n) /= 0) then
5572  a = this%calc_surface_area(n)
5573  q = this%rain(n) * a
5574  else
5575  q = dzero
5576  end if
5577  call this%budobj%budterm(idx)%update_term(n, n, q)
5578  end do
5579  !
5580  ! -- EVAPORATION
5581  idx = idx + 1
5582  call this%budobj%budterm(idx)%reset(this%maxbound)
5583  do n = 1, this%maxbound
5584  if (this%iboundpak(n) /= 0) then
5585  q = -this%simevap(n)
5586  else
5587  q = dzero
5588  end if
5589  call this%budobj%budterm(idx)%update_term(n, n, q)
5590  end do
5591  !
5592  ! -- RUNOFF
5593  idx = idx + 1
5594  call this%budobj%budterm(idx)%reset(this%maxbound)
5595  do n = 1, this%maxbound
5596  if (this%iboundpak(n) /= 0) then
5597  q = this%simrunoff(n)
5598  else
5599  q = dzero
5600  end if
5601  call this%budobj%budterm(idx)%update_term(n, n, q)
5602  end do
5603  !
5604  ! -- INFLOW
5605  idx = idx + 1
5606  call this%budobj%budterm(idx)%reset(this%maxbound)
5607  do n = 1, this%maxbound
5608  if (this%iboundpak(n) /= 0) then
5609  q = this%inflow(n)
5610  else
5611  q = dzero
5612  end if
5613  call this%budobj%budterm(idx)%update_term(n, n, q)
5614  end do
5615  !
5616  ! -- EXTERNAL OUTFLOW
5617  idx = idx + 1
5618  call this%budobj%budterm(idx)%reset(this%maxbound)
5619  do n = 1, this%maxbound
5620  q = dzero
5621  if (this%iboundpak(n) /= 0) then
5622  do i = this%ia(n) + 1, this%ia(n + 1) - 1
5623  if (this%idir(i) > 0) cycle
5624  idiv = this%idiv(i)
5625  if (idiv > 0) then
5626  jpos = this%iadiv(n) + idiv - 1
5627  q = q + this%divq(jpos)
5628  else
5629  q = q + this%qconn(i)
5630  end if
5631  end do
5632  q = q - this%dsflow(n)
5633  if (this%imover == 1) then
5634  q = q + this%pakmvrobj%get_qtomvr(n)
5635  end if
5636  else
5637  if (this%imover == 1) then
5638  q = this%pakmvrobj%get_qfrommvr(n)
5639  end if
5640  end if
5641  call this%budobj%budterm(idx)%update_term(n, n, q)
5642  end do
5643  !
5644  ! -- STORAGE
5645  idx = idx + 1
5646  call this%budobj%budterm(idx)%reset(this%maxbound)
5647  do n = 1, this%maxbound
5648  q = dzero
5649  if (this%iboundpak(n) /= 0) then
5650  d = this%depth(n)
5651  a = this%calc_surface_area_wet(n, d)
5652  this%qauxcbc(1) = a * d
5653  if (this%gwfiss == 0 .and. this%istorage == 1) then
5654  q = this%storage(n)
5655  end if
5656  else
5657  q = dzero
5658  this%qauxcbc(1) = dzero
5659  end if
5660  call this%budobj%budterm(idx)%update_term(n, n, q, this%qauxcbc)
5661  end do
5662  !
5663  ! -- MOVER
5664  if (this%imover == 1) then
5665  !
5666  ! -- FROM MOVER
5667  idx = idx + 1
5668  call this%budobj%budterm(idx)%reset(this%maxbound)
5669  do n = 1, this%maxbound
5670  q = dzero
5671  if (this%iboundpak(n) /= 0) then
5672  q = this%pakmvrobj%get_qfrommvr(n)
5673  end if
5674  call this%budobj%budterm(idx)%update_term(n, n, q)
5675  end do
5676  !
5677  ! -- TO MOVER
5678  idx = idx + 1
5679  call this%budobj%budterm(idx)%reset(this%maxbound)
5680  do n = 1, this%maxbound
5681  if (this%iboundpak(n) /= 0) then
5682  q = this%pakmvrobj%get_qtomvr(n)
5683  if (q > dzero) then
5684  q = -q
5685  end if
5686  else
5687  q = dzero
5688  end if
5689  call this%budobj%budterm(idx)%update_term(n, n, q)
5690  end do
5691  end if
5692  !
5693  ! -- AUXILIARY VARIABLES
5694  naux = this%naux
5695  if (naux > 0) then
5696  idx = idx + 1
5697  call this%budobj%budterm(idx)%reset(this%maxbound)
5698  do n = 1, this%maxbound
5699  q = dzero
5700  call this%budobj%budterm(idx)%update_term(n, n, q, this%auxvar(:, n))
5701  end do
5702  end if
5703  !
5704  ! --Terms are filled, now accumulate them for this time step
5705  call this%budobj%accumulate_terms()
5706  end subroutine sfr_fill_budobj
5707 
5708  !> @brief Setup stage table object for package
5709  !!
5710  !! Method to set up the table object that is used to write the sfr
5711  !! stage data. The terms listed here must correspond in number and
5712  !! order to the ones written to the stage table in the sfr_ot method.
5713  !<
5714  subroutine sfr_setup_tableobj(this)
5715  ! -- dummy
5716  class(sfrtype) :: this !< SfrType object
5717  ! -- local
5718  integer(I4B) :: nterms
5719  character(len=LINELENGTH) :: title
5720  character(len=LINELENGTH) :: text
5721  !
5722  ! -- setup stage table
5723  if (this%iprhed > 0) then
5724  !
5725  ! -- Determine the number of sfr budget terms. These are fixed for
5726  ! the simulation and cannot change. This includes FLOW-JA-FACE
5727  ! so they can be written to the binary budget files, but these internal
5728  ! flows are not included as part of the budget table.
5729  nterms = 8
5730  if (this%inamedbound == 1) then
5731  nterms = nterms + 1
5732  end if
5733  !
5734  ! -- set up table title
5735  title = trim(adjustl(this%text))//' PACKAGE ('// &
5736  trim(adjustl(this%packName))//') STAGES FOR EACH CONTROL VOLUME'
5737  !
5738  ! -- set up stage tableobj
5739  call table_cr(this%stagetab, this%packName, title)
5740  call this%stagetab%table_df(this%maxbound, nterms, this%iout, &
5741  transient=.true.)
5742  !
5743  ! -- Go through and set up table budget term
5744  if (this%inamedbound == 1) then
5745  text = 'NAME'
5746  call this%stagetab%initialize_column(text, lenboundname, &
5747  alignment=tableft)
5748  end if
5749  !
5750  ! -- reach number
5751  text = 'NUMBER'
5752  call this%stagetab%initialize_column(text, 10, alignment=tabcenter)
5753  !
5754  ! -- cellids
5755  text = 'CELLID'
5756  call this%stagetab%initialize_column(text, 20, alignment=tableft)
5757  !
5758  ! -- reach stage
5759  text = 'STAGE'
5760  call this%stagetab%initialize_column(text, 12, alignment=tabcenter)
5761  !
5762  ! -- reach depth
5763  text = 'DEPTH'
5764  call this%stagetab%initialize_column(text, 12, alignment=tabcenter)
5765  !
5766  ! -- reach width
5767  text = 'WIDTH'
5768  call this%stagetab%initialize_column(text, 12, alignment=tabcenter)
5769  !
5770  ! -- gwf head
5771  text = 'GWF HEAD'
5772  call this%stagetab%initialize_column(text, 12, alignment=tabcenter)
5773  !
5774  ! -- streambed conductance
5775  text = 'STREAMBED CONDUCTANCE'
5776  call this%stagetab%initialize_column(text, 12, alignment=tabcenter)
5777  !
5778  ! -- streambed gradient
5779  text = 'STREAMBED GRADIENT'
5780  call this%stagetab%initialize_column(text, 12, alignment=tabcenter)
5781  end if
5782  !
5783  ! -- setup Courant number table
5784  if (this%istorage == 1) then
5785  nterms = 4
5786  if (this%inamedbound == 1) then
5787  nterms = nterms + 1
5788  end if
5789  !
5790  ! -- set up table title
5791  title = trim(adjustl(this%text))//' PACKAGE ('// &
5792  trim(adjustl(this%packName))//') COURANT NUMBER FOR EACH REACH'
5793  !
5794  ! -- set up Courant tableobj
5795  call table_cr(this%couranttab, this%packName, title)
5796  call this%couranttab%table_df(this%maxbound, nterms, this%iout)
5797  !
5798  if (this%inamedbound == 1) then
5799  text = 'NAME'
5800  call this%couranttab%initialize_column(text, lenboundname, &
5801  alignment=tableft)
5802  end if
5803  !
5804  ! -- reach number
5805  text = 'NUMBER'
5806  call this%couranttab%initialize_column(text, 10, alignment=tabcenter)
5807  !
5808  ! -- minimum Courant number
5809  text = 'MINIMUM'
5810  call this%couranttab%initialize_column(text, 16, alignment=tabcenter)
5811  !
5812  ! -- maximum Courant number
5813  text = 'MAXIMUM'
5814  call this%couranttab%initialize_column(text, 16, alignment=tabcenter)
5815  !
5816  ! -- mean Courant number
5817  text = 'MEAN'
5818  call this%couranttab%initialize_column(text, 16, alignment=tabcenter)
5819  end if
5820  end subroutine sfr_setup_tableobj
5821 
5822  ! -- reach geometry functions
5823 
5824  !> @brief Calculate wetted area
5825  !!
5826  !! Function to calculate the wetted area for a SFR package reach.
5827  !<
5828  function calc_area_wet(this, n, depth)
5829  ! -- return variable
5830  real(dp) :: calc_area_wet !< wetted area
5831  ! -- dummy
5832  class(sfrtype) :: this !< SfrType object
5833  integer(I4B), intent(in) :: n !< reach number
5834  real(dp), intent(in) :: depth !< reach depth
5835  ! -- local
5836  integer(I4B) :: npts
5837  integer(I4B) :: i0
5838  integer(I4B) :: i1
5839  !
5840  ! -- Calculate wetted area
5841  npts = this%ncrosspts(n)
5842  i0 = this%iacross(n)
5843  i1 = this%iacross(n + 1) - 1
5844  if (npts > 1) then
5845  calc_area_wet = get_cross_section_area(npts, this%station(i0:i1), &
5846  this%xsheight(i0:i1), depth)
5847  else
5848  calc_area_wet = this%station(i0) * depth
5849  end if
5850  end function calc_area_wet
5851 
5852  !> @brief Calculate wetted perimeter
5853  !!
5854  !! Function to calculate the wetted perimeter for a SFR package reach.
5855  !<
5856  function calc_perimeter_wet(this, n, depth)
5857  ! -- return variable
5858  real(dp) :: calc_perimeter_wet !< wetted perimeter
5859  ! -- dummy
5860  class(sfrtype) :: this !< SfrType object
5861  integer(I4B), intent(in) :: n !< reach number
5862  real(dp), intent(in) :: depth !< reach depth
5863  ! -- local
5864  integer(I4B) :: npts
5865  integer(I4B) :: i0
5866  integer(I4B) :: i1
5867  !
5868  ! -- Calculate wetted perimeter
5869  npts = this%ncrosspts(n)
5870  i0 = this%iacross(n)
5871  i1 = this%iacross(n + 1) - 1
5872  if (npts > 1) then
5873  calc_perimeter_wet = get_wetted_perimeter(npts, this%station(i0:i1), &
5874  this%xsheight(i0:i1), depth)
5875  else
5876  calc_perimeter_wet = this%station(i0) ! no depth dependence in original implementation
5877  end if
5878  end function calc_perimeter_wet
5879 
5880  !> @brief Calculate maximum surface area
5881  !!
5882  !! Function to calculate the maximum surface area for a SFR package reach.
5883  !<
5884  function calc_surface_area(this, n)
5885  ! -- return variable
5886  real(dp) :: calc_surface_area !< surface area
5887  ! -- dummy
5888  class(sfrtype) :: this !< SfrType object
5889  integer(I4B), intent(in) :: n !< reach number
5890  ! -- local
5891  integer(I4B) :: npts
5892  integer(I4B) :: i0
5893  integer(I4B) :: i1
5894  real(dp) :: top_width
5895  !
5896  ! -- Calculate surface area
5897  npts = this%ncrosspts(n)
5898  i0 = this%iacross(n)
5899  i1 = this%iacross(n + 1) - 1
5900  if (npts > 1) then
5901  top_width = get_saturated_topwidth(npts, this%station(i0:i1))
5902  else
5903  top_width = this%station(i0)
5904  end if
5905  calc_surface_area = top_width * this%length(n)
5906  end function calc_surface_area
5907 
5908  !> @brief Calculate wetted surface area
5909  !!
5910  !! Function to calculate the wetted surface area for a SFR package reach.
5911  !<
5912  function calc_surface_area_wet(this, n, depth)
5913  ! -- return variable
5914  real(dp) :: calc_surface_area_wet !< wetted surface area
5915  ! -- dummy
5916  class(sfrtype) :: this !< SfrType object
5917  integer(I4B), intent(in) :: n !< reach number
5918  real(dp), intent(in) :: depth !< reach depth
5919  ! -- local
5920  real(dp) :: top_width
5921  !
5922  ! -- Calculate wetted surface area
5923  top_width = this%calc_top_width_wet(n, depth)
5924  calc_surface_area_wet = top_width * this%length(n)
5925  end function calc_surface_area_wet
5926 
5927  !> @brief Calculate wetted top width
5928  !!
5929  !! Function to calculate the wetted top width for a SFR package reach.
5930  !<
5931  function calc_top_width_wet(this, n, depth)
5932  ! -- return variable
5933  real(dp) :: calc_top_width_wet !< wetted top width
5934  ! -- dummy
5935  class(sfrtype) :: this !< SfrType object
5936  integer(I4B), intent(in) :: n !< reach number
5937  real(dp), intent(in) :: depth !< reach depth
5938  ! -- local
5939  integer(I4B) :: npts
5940  integer(I4B) :: i0
5941  integer(I4B) :: i1
5942  real(dp) :: sat
5943  !
5944  ! -- Calculate wetted top width
5945  npts = this%ncrosspts(n)
5946  i0 = this%iacross(n)
5947  i1 = this%iacross(n + 1) - 1
5948  sat = scubicsaturation(dem5, dzero, depth, dem5)
5949  if (npts > 1) then
5950  calc_top_width_wet = sat * get_wetted_topwidth(npts, &
5951  this%station(i0:i1), &
5952  this%xsheight(i0:i1), &
5953  depth)
5954  else
5955  calc_top_width_wet = sat * this%station(i0)
5956  end if
5957  end function calc_top_width_wet
5958 
5959  !> @brief Activate density terms
5960  !!
5961  !! Method to activate addition of density terms for a SFR package reach.
5962  !<
5963  subroutine sfr_activate_density(this)
5964  ! -- modules
5966  ! -- dummy
5967  class(sfrtype), intent(inout) :: this !< SfrType object
5968  ! -- local
5969  integer(I4B) :: i
5970  integer(I4B) :: j
5971  !
5972  ! -- Set idense and reallocate denseterms to be of size MAXBOUND
5973  this%idense = 1
5974  call mem_reallocate(this%denseterms, 3, this%MAXBOUND, 'DENSETERMS', &
5975  this%memoryPath)
5976  do i = 1, this%maxbound
5977  do j = 1, 3
5978  this%denseterms(j, i) = dzero
5979  end do
5980  end do
5981  write (this%iout, '(/1x,a)') 'DENSITY TERMS HAVE BEEN ACTIVATED FOR SFR &
5982  &PACKAGE: '//trim(adjustl(this%packName))
5983  end subroutine sfr_activate_density
5984 
5985  !> @brief Activate viscosity terms
5986  !!
5987  !! Method to activate addition of viscosity terms for exchange
5988  !! with groundwater along a SFR package reach.
5989  !<
5990  subroutine sfr_activate_viscosity(this)
5991  ! -- modules
5993  ! -- dummy
5994  class(sfrtype), intent(inout) :: this !< SfrType object
5995  ! -- local
5996  integer(I4B) :: i
5997  integer(I4B) :: j
5998  !
5999  ! -- Set ivsc and reallocate viscratios to be of size MAXBOUND
6000  this%ivsc = 1
6001  call mem_reallocate(this%viscratios, 2, this%MAXBOUND, 'VISCRATIOS', &
6002  this%memoryPath)
6003  do i = 1, this%maxbound
6004  do j = 1, 2
6005  this%viscratios(j, i) = done
6006  end do
6007  end do
6008  write (this%iout, '(/1x,a)') 'VISCOSITY HAS BEEN ACTIVATED FOR SFR &
6009  &PACKAGE: '//trim(adjustl(this%packName))
6010  end subroutine sfr_activate_viscosity
6011 
6012  !> @brief Calculate density terms
6013  !!
6014  !! Method to calculate groundwater-reach density exchange terms for a
6015  !! SFR package reach.
6016  !!
6017  !! Member variable used here
6018  !! denseterms : shape (3, MAXBOUND), filled by buoyancy package
6019  !! col 1 is relative density of sfr (densesfr / denseref)
6020  !! col 2 is relative density of gwf cell (densegwf / denseref)
6021  !! col 3 is elevation of gwf cell
6022  !<
6023  subroutine sfr_calculate_density_exchange(this, n, stage, head, cond, &
6024  tops, flow, gwfhcof, gwfrhs)
6025  ! -- dummy
6026  class(sfrtype), intent(inout) :: this !< SfrType object
6027  integer(I4B), intent(in) :: n !< reach number
6028  real(DP), intent(in) :: stage !< reach stage
6029  real(DP), intent(in) :: head !< head in connected GWF cell
6030  real(DP), intent(in) :: cond !< reach conductance
6031  real(DP), intent(in) :: tops !< top elevation of streambed
6032  real(DP), intent(inout) :: flow !< calculated flow, updated here with density terms
6033  real(DP), intent(inout) :: gwfhcof !< GWF diagonal coefficient, updated here with density terms
6034  real(DP), intent(inout) :: gwfrhs !< GWF right-hand-side value, updated here with density terms
6035  ! -- local
6036  real(DP) :: ss
6037  real(DP) :: hh
6038  real(DP) :: havg
6039  real(DP) :: rdensesfr
6040  real(DP) :: rdensegwf
6041  real(DP) :: rdenseavg
6042  real(DP) :: elevsfr
6043  real(DP) :: elevgwf
6044  real(DP) :: elevavg
6045  real(DP) :: d1
6046  real(DP) :: d2
6047  logical(LGP) :: stage_below_bot
6048  logical(LGP) :: head_below_bot
6049  !
6050  ! -- Set sfr density to sfr density or gwf density
6051  if (stage >= tops) then
6052  ss = stage
6053  stage_below_bot = .false.
6054  rdensesfr = this%denseterms(1, n) ! sfr rel density
6055  else
6056  ss = tops
6057  stage_below_bot = .true.
6058  rdensesfr = this%denseterms(2, n) ! gwf rel density
6059  end if
6060  !
6061  ! -- set hh to head or tops (top elev of streambed)
6062  if (head >= tops) then
6063  hh = head
6064  head_below_bot = .false.
6065  rdensegwf = this%denseterms(2, n) ! gwf rel density
6066  else
6067  hh = tops
6068  head_below_bot = .true.
6069  rdensegwf = this%denseterms(1, n) ! sfr rel density
6070  end if
6071  !
6072  ! -- todo: hack because denseterms not updated in a cf calculation
6073  if (rdensegwf == dzero) return
6074  !
6075  ! -- Update flow
6076  if (stage_below_bot .and. head_below_bot) then
6077  !
6078  ! -- flow is zero, so no terms are updated
6079  !
6080  else
6081  !
6082  ! -- calculate average relative density
6083  rdenseavg = dhalf * (rdensesfr + rdensegwf)
6084  !
6085  ! -- Add contribution of first density term:
6086  ! cond * (denseavg/denseref - 1) * (hgwf - hsfr)
6087  d1 = cond * (rdenseavg - done)
6088  gwfhcof = gwfhcof - d1
6089  gwfrhs = gwfrhs - d1 * ss
6090  d1 = d1 * (hh - ss)
6091  flow = flow + d1
6092  !
6093  ! -- Add second density term if stage and head not below bottom
6094  if (.not. stage_below_bot .and. .not. head_below_bot) then
6095  !
6096  ! -- Add contribution of second density term:
6097  ! cond * (havg - elevavg) * (densegwf - densesfr) / denseref
6098  elevgwf = this%denseterms(3, n)
6099  elevsfr = tops
6100  elevavg = dhalf * (elevsfr + elevgwf)
6101  havg = dhalf * (hh + ss)
6102  d2 = cond * (havg - elevavg) * (rdensegwf - rdensesfr)
6103  gwfrhs = gwfrhs + d2
6104  flow = flow + d2
6105  end if
6106  end if
6107  end subroutine sfr_calculate_density_exchange
6108 
6109 end module sfrmodule
This module contains the base boundary package.
This module contains the BudgetModule.
Definition: Budget.f90:20
subroutine, public budgetobject_cr(this, name)
Create a new budget object.
This module contains simulation constants.
Definition: Constants.f90:9
integer(i4b), parameter linelength
maximum length of a standard line
Definition: Constants.f90:45
real(dp), parameter dhdry
real dry cell constant
Definition: Constants.f90:94
@ tabcenter
centered table column
Definition: Constants.f90:172
@ tabright
right justified table column
Definition: Constants.f90:173
@ tableft
left justified table column
Definition: Constants.f90:171
@ mnormal
normal output mode
Definition: Constants.f90:206
real(dp), parameter dtwothirds
real constant 2/3
Definition: Constants.f90:70
integer(i4b), parameter lenpackagename
maximum length of the package name
Definition: Constants.f90:23
real(dp), parameter dp9
real constant 9/10
Definition: Constants.f90:72
real(dp), parameter deight
real constant 8
Definition: Constants.f90:83
real(dp), parameter dfivethirds
real constant 5/3
Definition: Constants.f90:78
real(dp), parameter dp999
real constant 999/1000
Definition: Constants.f90:74
integer(i4b), parameter namedboundflag
named bound flag
Definition: Constants.f90:49
real(dp), parameter donethird
real constant 1/3
Definition: Constants.f90:67
real(dp), parameter dnodata
real no data constant
Definition: Constants.f90:95
real(dp), parameter d1p1
real constant 1.1
Definition: Constants.f90:77
real(dp), parameter dhnoflo
real no flow constant
Definition: Constants.f90:93
real(dp), parameter dhundred
real constant 100
Definition: Constants.f90:86
integer(i4b), parameter lenpakloc
maximum length of a package location
Definition: Constants.f90:50
integer(i4b), parameter lentimeseriesname
maximum length of a time series name
Definition: Constants.f90:42
real(dp), parameter dep20
real constant 1e20
Definition: Constants.f90:91
real(dp), parameter dp6
real constant 3/5
Definition: Constants.f90:69
integer(i4b), parameter maxadpit
maximum advanced package Newton-Raphson iterations
Definition: Constants.f90:53
real(dp), parameter dhalf
real constant 1/2
Definition: Constants.f90:68
integer(i4b), parameter lenftype
maximum length of a package type (DIS, WEL, OC, etc.)
Definition: Constants.f90:39
real(dp), parameter dpi
real constant
Definition: Constants.f90:128
real(dp), parameter dp99
real constant 99/100
Definition: Constants.f90:73
integer(i4b), parameter lenboundname
maximum length of a bound name
Definition: Constants.f90:36
real(dp), parameter dem4
real constant 1e-4
Definition: Constants.f90:107
real(dp), parameter dem30
real constant 1e-30
Definition: Constants.f90:118
real(dp), parameter dem6
real constant 1e-6
Definition: Constants.f90:109
real(dp), parameter dzero
real constant zero
Definition: Constants.f90:65
real(dp), parameter dem5
real constant 1e-5
Definition: Constants.f90:108
real(dp), parameter dprec
real constant machine precision
Definition: Constants.f90:120
integer(i4b), parameter maxcharlen
maximum length of char string
Definition: Constants.f90:47
real(dp), parameter dp7
real constant 7/10
Definition: Constants.f90:71
real(dp), parameter dem2
real constant 1e-2
Definition: Constants.f90:105
real(dp), parameter dtwo
real constant 2
Definition: Constants.f90:79
integer(i4b), parameter lenbudtxt
maximum length of a budget component names
Definition: Constants.f90:37
real(dp), parameter done
real constant 1
Definition: Constants.f90:76
This module contains stateless sfr subroutines and functions.
real(dp) function, public get_wetted_topwidth(npts, stations, heights, d)
Calculate the wetted top width for a reach.
real(dp) function, public get_wetted_perimeter(npts, stations, heights, d)
Calculate the wetted perimeter for a reach.
real(dp) function, public get_cross_section_area(npts, stations, heights, d)
Calculate the cross-sectional area for a reach.
real(dp) function, public get_saturated_topwidth(npts, stations)
Calculate the saturated top width for a reach.
real(dp) function, public get_mannings_section(npts, stations, heights, roughfracs, roughness, conv_fact, slope, d)
Calculate the manning's discharge for a reach.
subroutine, public assign_iounit(iounit, errunit, description)
@ brief assign io unit number
subroutine, public extract_idnum_or_bndname(line, icol, istart, istop, idnum, bndname)
Starting at position icol, define string as line(istart:istop).
integer(i4b) function, public getunit()
Get a free unit number.
subroutine, public upcase(word)
Convert to upper case.
subroutine, public ulasav(buf, text, kstp, kper, pertim, totim, ncol, nrow, ilay, ichn)
Save 1 layer array on disk.
subroutine, public openfile(iu, iout, fname, ftype, fmtarg_opt, accarg_opt, filstat_opt, mode_opt)
Open a file.
Definition: InputOutput.f90:30
This module defines variable data types.
Definition: kind.f90:8
character(len=lenmempath) function create_mem_path(component, subcomponent, context)
returns the path to the memory object
This module contains the derived types ObserveType and ObsDataType.
Definition: Observe.f90:15
character(len=20) access
Definition: OpenSpec.f90:7
character(len=20) form
Definition: OpenSpec.f90:7
subroutine, public cross_section_cr(this, iout, iprpak, nreaches)
Create a cross-section object.
This module contains the SFR package methods.
Definition: gwf-sfr.f90:7
subroutine sfr_calc_celerity(this, n, q, celerity)
Kinematic-wave celerity from a flow perturbation (0 if dry)
Definition: gwf-sfr.f90:2945
real(dp) function calc_top_width_wet(this, n, depth)
Calculate wetted top width.
Definition: gwf-sfr.f90:5932
subroutine sfr_precompute_tvd(this)
Pre-compute the single upstream reach index for the TVD limiter.
Definition: gwf-sfr.f90:3123
subroutine sfr_setup_tableobj(this)
Setup stage table object for package.
Definition: gwf-sfr.f90:5715
subroutine sfr_cc(this, innertot, kiter, iend, icnvgmod, cpak, ipak, dpak)
@ brief Convergence check for package.
Definition: gwf-sfr.f90:2413
subroutine sfr_cq(this, x, flowja, iadv)
@ brief Calculate package flows.
Definition: gwf-sfr.f90:2615
subroutine sfr_ot_package_flows(this, icbcfl, ibudfl)
@ brief Output package flow terms.
Definition: gwf-sfr.f90:2692
subroutine sfr_activate_viscosity(this)
Activate viscosity terms.
Definition: gwf-sfr.f90:5991
subroutine sfr_da(this)
@ brief Deallocate package memory
Definition: gwf-sfr.f90:2972
subroutine sfr_read_diversions(this)
@ brief Read diversions for the package
Definition: gwf-sfr.f90:1688
subroutine sfr_calc_reach_depth(this, n, q1, d1)
Calculate the depth at the midpoint.
Definition: gwf-sfr.f90:4364
real(dp) function calc_surface_area(this, n)
Calculate maximum surface area.
Definition: gwf-sfr.f90:5885
subroutine sfr_check_ustrf(this)
Check upstream fraction data.
Definition: gwf-sfr.f90:5065
subroutine sfr_read_connectiondata(this)
@ brief Read connectiondata for the package
Definition: gwf-sfr.f90:1411
subroutine sfr_calc_xs_depth(this, n, qrch, d)
Calculate the depth at the midpoint of a irregular cross-section.
Definition: gwf-sfr.f90:4399
subroutine sfr_set_stressperiod(this, n, ichkustrm, crossfile)
Set period data.
Definition: gwf-sfr.f90:3536
subroutine sfr_check_diversions(this)
Check diversions data.
Definition: gwf-sfr.f90:4903
subroutine sfr_ot_dv(this, idvsave, idvprint)
@ brief Output package dependent-variable terms.
Definition: gwf-sfr.f90:2745
subroutine sfr_dt(this)
Submit the ATS time step for the most Courant-constraining reach.
Definition: gwf-sfr.f90:2907
subroutine sfr_fc(this, rhs, ia, idxglo, matrix_sln)
@ brief Copy hcof and rhs terms into solution.
Definition: gwf-sfr.f90:2263
subroutine, public sfr_create(packobj, id, ibcnum, inunit, iout, namemodel, pakname)
@ brief Create a new package object
Definition: gwf-sfr.f90:326
subroutine sfr_fn(this, rhs, ia, idxglo, matrix_sln)
@ brief Add Newton-Raphson terms for package into solution.
Definition: gwf-sfr.f90:2363
subroutine define_listlabel(this)
@ brief Define the list label for the package
Definition: gwf-sfr.f90:3154
subroutine sfr_df_obs(this)
Define the observation types available in the package.
Definition: gwf-sfr.f90:3198
subroutine sfr_options(this, option, found)
@ brief Read additional options for package
Definition: gwf-sfr.f90:753
subroutine sfr_calc_cond(this, n, depth, cond, hsfr, h_temp)
Calculate reach-aquifer conductance.
Definition: gwf-sfr.f90:4263
subroutine sfr_check_connections(this)
Check connection data.
Definition: gwf-sfr.f90:4626
subroutine sfr_allocate_arrays(this)
@ brief Allocate arrays
Definition: gwf-sfr.f90:440
subroutine sfr_bd_obs(this)
Save observations for the package.
Definition: gwf-sfr.f90:3294
subroutine sfr_setup_budobj(this)
Setup budget object for package.
Definition: gwf-sfr.f90:5268
subroutine sfr_check_initialstages(this)
Check initial stage data.
Definition: gwf-sfr.f90:5010
subroutine sfr_rp(this)
@ brief Read and prepare period data for package
Definition: gwf-sfr.f90:1985
subroutine sfr_ar(this)
@ brief Allocate and read method for package
Definition: gwf-sfr.f90:930
subroutine sfr_calc_qman(this, n, depth, qman)
Calculate streamflow.
Definition: gwf-sfr.f90:4106
subroutine sfr_fp(this)
Write the Courant-number summary table to the listing file.
Definition: gwf-sfr.f90:2872
subroutine sfr_check_reaches(this)
Check reach data.
Definition: gwf-sfr.f90:4508
real(dp) function calc_perimeter_wet(this, n, depth)
Calculate wetted perimeter.
Definition: gwf-sfr.f90:5857
subroutine sfr_read_packagedata(this)
@ brief Read packagedata for the package
Definition: gwf-sfr.f90:1023
subroutine sfr_read_initial_stages(this)
@ brief Read initialstages data for the package
Definition: gwf-sfr.f90:1887
subroutine sfr_update_flows(this, n, qd, qgwf)
Update flow terms.
Definition: gwf-sfr.f90:3915
subroutine sfr_calc_qd(this, n, depth, hgwf, qgwf, qd)
Calculate downstream flow term.
Definition: gwf-sfr.f90:4025
subroutine sfr_fill_budobj(this)
Copy flow terms into budget object for package.
Definition: gwf-sfr.f90:5483
subroutine sfr_cf(this)
@ brief Formulate the package hcof and rhs terms.
Definition: gwf-sfr.f90:2235
subroutine sfr_ot_bdsummary(this, kstp, kper, iout, ibudfl)
@ brief Output advanced package budget summary.
Definition: gwf-sfr.f90:2857
subroutine sfr_calc_div(this, n, i, qd, qdiv)
Calculate diversion flow.
Definition: gwf-sfr.f90:4310
subroutine sfr_calc_qgwf(this, n, depth, hgwf, qgwf, gwfhcof, gwfrhs)
Calculate reach-aquifer exchange.
Definition: gwf-sfr.f90:4176
character(len=lenftype) ftype
package ftype string
Definition: gwf-sfr.f90:46
subroutine sfr_calculate_density_exchange(this, n, stage, head, cond, tops, flow, gwfhcof, gwfrhs)
Calculate density terms.
Definition: gwf-sfr.f90:6025
character(len=lenpackagename) text
package budget string
Definition: gwf-sfr.f90:47
subroutine sfr_calc_qsource(this, n, depth, qsrc)
Calculate sum of sources.
Definition: gwf-sfr.f90:4058
subroutine sfr_allocate_scalars(this)
@ brief Allocate scalars
Definition: gwf-sfr.f90:369
logical function sfr_obs_supported(this)
Determine if observations are supported.
Definition: gwf-sfr.f90:3186
subroutine sfr_check_storage_weight(this)
Check storage weight.
Definition: gwf-sfr.f90:4484
subroutine sfr_solve(this, n, h, hcof, rhs, update)
Solve reach continuity equation.
Definition: gwf-sfr.f90:3731
subroutine sfr_read_dimensions(this)
@ brief Read dimensions for package
Definition: gwf-sfr.f90:665
real(dp) function calc_area_wet(this, n, depth)
Calculate wetted area.
Definition: gwf-sfr.f90:5829
subroutine sfr_read_crossection(this)
@ brief Read crosssection block for the package
Definition: gwf-sfr.f90:1273
subroutine sfr_rp_obs(this)
Read and prepare observations for a package.
Definition: gwf-sfr.f90:3386
subroutine sfr_activate_density(this)
Activate density terms.
Definition: gwf-sfr.f90:5964
subroutine sfr_adjust_ro_ev(this, qc, qu, qi, qr, qro, qe, qfrommvr)
Adjust runoff and evaporation.
Definition: gwf-sfr.f90:3985
subroutine sfr_check_conversion(this)
Check unit conversion data.
Definition: gwf-sfr.f90:4447
real(dp) function calc_surface_area_wet(this, n, depth)
Calculate wetted surface area.
Definition: gwf-sfr.f90:5913
integer(i4b) function sfr_gwf_conn(this, n)
Determine if a reach is connected to a gwf cell.
Definition: gwf-sfr.f90:4243
subroutine sfr_ad(this)
@ brief Advance the package
Definition: gwf-sfr.f90:2167
This module contains simulation methods.
Definition: Sim.f90:10
subroutine, public store_warning(msg, substring)
Store warning message.
Definition: Sim.f90:236
subroutine, public store_error(msg, terminate)
Store an error message.
Definition: Sim.f90:92
integer(i4b) function, public count_errors()
Return number of errors.
Definition: Sim.f90:59
subroutine, public deprecation_warning(cblock, cvar, cver, endmsg, iunit)
Store deprecation warning message.
Definition: Sim.f90:256
subroutine, public store_error_unit(iunit, terminate)
Store the file unit number.
Definition: Sim.f90:168
This module contains simulation variables.
Definition: SimVariables.f90:9
character(len=maxcharlen) errmsg
error message string
character(len=maxcharlen) warnmsg
warning message string
real(dp) function squadraticsaturation(top, bot, x, eps)
@ brief sQuadraticSaturation
real(dp) function scubicsaturation(top, bot, x, eps)
@ brief sCubicSaturation
real(dp) function squadraticsaturationderivative(top, bot, x, eps)
@ brief Derivative of the quadratic saturation function
real(dp) function sqsaturationderivative(top, bot, x, c1, c2)
@ brief sQSaturationDerivative
subroutine schsmooth(d, smooth, dwdh)
@ brief sChSmooth
real(dp) function sqsaturation(top, bot, x, c1, c2)
@ brief sQSaturation
subroutine, public table_cr(this, name, title)
Definition: Table.f90:87
real(dp), pointer, public pertim
time relative to start of stress period
Definition: tdis.f90:33
real(dp), pointer, public totim
time relative to start of simulation
Definition: tdis.f90:35
class(atstype), pointer, public ats
Definition: tdis.f90:48
integer(i4b), pointer, public inats
flag indicating ats active for simulation
Definition: tdis.f90:28
integer(i4b), pointer, public kstp
current time step number
Definition: tdis.f90:27
integer(i4b), pointer, public kper
current stress period number
Definition: tdis.f90:26
real(dp), pointer, public delt
length of the current time step
Definition: tdis.f90:32
integer(i4b), pointer, public nper
number of stress period
Definition: tdis.f90:24
subroutine, public read_value_or_time_series_adv(textInput, ii, jj, bndElem, pkgName, auxOrBnd, tsManager, iprpak, varName)
Call this subroutine from advanced packages to define timeseries link for a variable (varName).
logical function, public var_timeseries(tsManager, pkgName, varName, auxOrBnd)
Determine if a timeseries link with varName is defined.
@ brief BndType
Derived type for the Budget object.
Definition: Budget.f90:39