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