MODFLOW 6  version 6.8.0.dev0
USGS Modular Hydrologic Model
swf-zdg.f90
Go to the documentation of this file.
1 !> @brief This module contains the ZDG package methods
2 !!
3 !! This module can be used to represent outflow from streams using
4 !! a zero-depth-gradient boundary.
5 !!
6 !<
8  ! -- modules
9  use kindmodule, only: dp, i4b
11  use simvariablesmodule, only: errmsg
14  use bndmodule, only: bndtype
15  use bndextmodule, only: bndexttype
17  use observemodule, only: observetype
21  use basedismodule, only: disbasetype
22  use disv1dmodule, only: disv1dtype
23  use swfcxsmodule, only: swfcxstype
24  !
25  implicit none
26  !
27  private
28  public :: zdg_create
29  !
30  character(len=LENFTYPE) :: ftype = 'ZDG' !< package ftype
31  character(len=16) :: text = ' ZDG' !< package flow text string
32  !
33  type, extends(bndexttype) :: swfzdgtype
34 
35  integer(I4B), dimension(:), pointer, contiguous :: idcxs => null() !< cross section id
36  real(dp), dimension(:), pointer, contiguous :: width => null() !< channel width
37  real(dp), dimension(:), pointer, contiguous :: slope => null() !< channel slope
38  real(dp), dimension(:), pointer, contiguous :: rough => null() !< channel roughness
39  real(dp), pointer :: unitconv => null() !< conversion factor for roughness to length and time units of meters and seconds
40 
41  ! -- pointers other objects
42  type(disv1dtype), pointer :: disv1d
43  type(swfcxstype), pointer :: cxs
44 
45  contains
46  procedure :: allocate_scalars => zdg_allocate_scalars
47  procedure :: allocate_arrays => zdg_allocate_arrays
48  procedure :: source_options => zdg_options
49  procedure :: log_zdg_options
50  procedure :: bnd_cf => zdg_cf
51  procedure :: bnd_fc => zdg_fc
52  procedure :: bnd_da => zdg_da
53  procedure :: define_listlabel
54  procedure :: bound_value => zdg_bound_value
55  ! -- methods for observations
56  procedure, public :: bnd_obs_supported => zdg_obs_supported
57  procedure, public :: bnd_df_obs => zdg_df_obs
58  procedure, public :: bnd_bd_obs => zdg_bd_obs
59  ! -- methods for time series
60  procedure, public :: bnd_rp_ts => zdg_rp_ts
61  ! -- private
62  procedure, private :: qcalc
63  end type swfzdgtype
64 
65 contains
66 
67  !> @ brief Create a new package object
68  !!
69  !! Create a new ZDG Package object
70  !!
71  !<
72  subroutine zdg_create(packobj, id, ibcnum, inunit, iout, namemodel, pakname, &
73  mempath, dis, cxs, unitconv)
74  ! -- dummy variables
75  class(bndtype), pointer :: packobj !< pointer to default package type
76  integer(I4B), intent(in) :: id !< package id
77  integer(I4B), intent(in) :: ibcnum !< boundary condition number
78  integer(I4B), intent(in) :: inunit !< unit number of ZDG package input file
79  integer(I4B), intent(in) :: iout !< unit number of model listing file
80  character(len=*), intent(in) :: namemodel !< model name
81  character(len=*), intent(in) :: pakname !< package name
82  character(len=*), intent(in) :: mempath !< input mempath
83  class(disbasetype), pointer, intent(inout) :: dis !< the pointer to the discretization
84  type(swfcxstype), pointer, intent(in) :: cxs !< the pointer to the cxs package
85  real(dp), intent(in) :: unitconv !< unit conversion for roughness
86  ! -- local variables
87  type(swfzdgtype), pointer :: zdgobj
88  !
89  ! -- allocate the object and assign values to object variables
90  allocate (zdgobj)
91  packobj => zdgobj
92  !
93  ! -- create name and memory path
94  call packobj%set_names(ibcnum, namemodel, pakname, ftype, mempath)
95  packobj%text = text
96  !
97  ! -- allocate scalars
98  call zdgobj%allocate_scalars()
99  !
100  ! -- initialize package
101  call packobj%pack_initialize()
102 
103  packobj%inunit = inunit
104  packobj%iout = iout
105  packobj%id = id
106  packobj%ibcnum = ibcnum
107  packobj%ncolbnd = 1
108  packobj%iscloc = 1
109  packobj%ictMemPath = create_mem_path(namemodel, 'DFW')
110  !
111  ! -- store pointer to disv1d
112  select type (dis)
113  type is (disv1dtype)
114  zdgobj%disv1d => dis
115  end select
116  !
117  ! -- store pointer to cxs
118  zdgobj%cxs => cxs
119  !
120  ! -- store unit conversion
121  zdgobj%unitconv = unitconv
122  end subroutine zdg_create
123 
124  !> @ brief Allocate scalars
125  !!
126  !! Allocate and initialize scalars for the ZDG package. The base model
127  !! allocate scalars method is also called.
128  !!
129  !<
130  subroutine zdg_allocate_scalars(this)
131  ! -- modules
133  ! -- dummy variables
134  class(swfzdgtype) :: this !< SwfZdgType object
135  !
136  ! -- call base type allocate scalars
137  call this%BndExtType%allocate_scalars()
138  !
139  ! -- allocate the object and assign values to object variables
140  call mem_allocate(this%unitconv, 'UNITCONV', this%memoryPath)
141  !
142  ! -- Set values
143  this%unitconv = dzero
144  end subroutine zdg_allocate_scalars
145 
146  !> @ brief Allocate arrays
147  !!
148  !! Allocate and initialize arrays for the SWF package
149  !!
150  !<
151  subroutine zdg_allocate_arrays(this, nodelist, auxvar)
152  ! -- modules
154  ! -- dummy
155  class(swfzdgtype) :: this
156  integer(I4B), dimension(:), pointer, contiguous, optional :: nodelist
157  real(DP), dimension(:, :), pointer, contiguous, optional :: auxvar
158  ! -- local
159  !
160  ! -- call BndExtType allocate scalars
161  call this%BndExtType%allocate_arrays(nodelist, auxvar)
162  !
163  ! -- set array input context pointer
164  call mem_setptr(this%idcxs, 'IDCXS', this%input_mempath)
165  call mem_setptr(this%width, 'WIDTH', this%input_mempath)
166  call mem_setptr(this%slope, 'SLOPE', this%input_mempath)
167  call mem_setptr(this%rough, 'ROUGH', this%input_mempath)
168  !
169  ! -- checkin array input context pointer
170  call mem_checkin(this%idcxs, 'IDCXS', this%memoryPath, &
171  'IDCXS', this%input_mempath)
172  call mem_checkin(this%width, 'WIDTH', this%memoryPath, &
173  'WIDTH', this%input_mempath)
174  call mem_checkin(this%slope, 'SLOPE', this%memoryPath, &
175  'SLOPE', this%input_mempath)
176  call mem_checkin(this%rough, 'ROUGH', this%memoryPath, &
177  'ROUGH', this%input_mempath)
178  end subroutine zdg_allocate_arrays
179 
180  !> @ brief Deallocate package memory
181  !!
182  !! Deallocate SWF package scalars and arrays.
183  !!
184  !<
185  subroutine zdg_da(this)
186  ! -- modules
188  ! -- dummy variables
189  class(swfzdgtype) :: this !< SwfZdgType object
190  !
191  ! -- Deallocate parent package
192  call this%BndExtType%bnd_da()
193  !
194  ! -- arrays
195  call mem_deallocate(this%idcxs, 'IDCXS', this%memoryPath)
196  call mem_deallocate(this%width, 'WIDTH', this%memoryPath)
197  call mem_deallocate(this%slope, 'SLOPE', this%memoryPath)
198  call mem_deallocate(this%rough, 'ROUGH', this%memoryPath)
199  !
200  ! -- scalars
201  call mem_deallocate(this%unitconv)
202  end subroutine zdg_da
203 
204  !> @ brief Source additional options for package
205  !!
206  !! Source additional options for SWF package.
207  !!
208  !<
209  subroutine zdg_options(this)
210  ! -- modules
211  use inputoutputmodule, only: urword
213  ! -- dummy variables
214  class(swfzdgtype), intent(inout) :: this !< SwfZdgType object
215  ! -- formats
216  !
217  ! -- source base BndExtType options
218  call this%BndExtType%source_options()
219  !
220  ! -- source options from input context
221  ! none
222  !
223  ! -- log SWF specific options
224  call this%log_zdg_options()
225  end subroutine zdg_options
226 
227  !> @ brief Log SWF specific package options
228  !<
229  subroutine log_zdg_options(this)
230  ! -- dummy variables
231  class(swfzdgtype), intent(inout) :: this
232  ! -- local variables
233  ! -- format
234  !
235  ! -- log found options
236  write (this%iout, '(/1x,a)') 'PROCESSING '//trim(adjustl(this%text)) &
237  //' OPTIONS'
238  !
239  ! -- close logging block
240  write (this%iout, '(1x,a)') &
241  'END OF '//trim(adjustl(this%text))//' OPTIONS'
242  end subroutine log_zdg_options
243 
244  !> @ brief Formulate the package hcof and rhs terms.
245  !!
246  !! Formulate the hcof and rhs terms for the ZDG package that will be
247  !! added to the coefficient matrix and right-hand side vector.
248  !!
249  !<
250  subroutine zdg_cf(this)
251  ! modules
253  use smoothingmodule, only: squadratic
254  ! dummy variables
255  class(swfzdgtype) :: this !< SwfZdgType object
256  ! local variables
257  integer(I4B) :: i, node
258  real(DP) :: q
259  real(DP) :: qeps
260  real(DP) :: absdhdxsq
261  real(DP) :: depth
262  real(DP) :: derv
263  real(DP) :: eps
264  real(DP) :: range = 1.d-6
265  real(DP) :: dydx
266  real(DP) :: smooth_factor
267  !
268  ! -- Return if no inflows
269  if (this%nbound == 0) return
270  !
271  ! -- Calculate hcof and rhs for each zdg entry
272  do i = 1, this%nbound
273 
274  node = this%nodelist(i)
275  if (this%ibound(node) <= 0) then
276  this%hcof(i) = dzero
277  this%rhs(i) = dzero
278  cycle
279  end if
280 
281  ! -- calculate terms and add to hcof and rhs
282  absdhdxsq = this%slope(i)**dhalf
283  depth = this%xnew(node) - this%dis%bot(node)
284 
285  ! smooth the depth
286  call squadratic(depth, range, dydx, smooth_factor)
287  depth = depth * smooth_factor
288 
289  ! -- calculate unperturbed q
290  q = -this%qcalc(i, depth, this%unitconv)
291 
292  ! -- calculate perturbed q
293  eps = get_perturbation(depth)
294  qeps = -this%qcalc(i, depth + eps, this%unitconv)
295 
296  ! -- calculate derivative
297  derv = (qeps - q) / eps
298 
299  ! -- add terms to hcof and rhs
300  this%hcof(i) = derv
301  this%rhs(i) = -q + derv * this%xnew(node)
302 
303  end do
304  end subroutine zdg_cf
305 
306  ! !> @brief Calculate flow
307  !!
308  !! Calculate volumetric flow rate for the zero-depth gradient
309  !! condition. Flow is positive.
310  ! !<
311  function qcalc(this, i, depth, unitconv) result(q)
312  ! dummy
313  class(swfzdgtype) :: this
314  integer(I4B), intent(in) :: i !< boundary number
315  real(dp), intent(in) :: depth !< simulated depth (stage - elevation) in reach n for this iteration
316  real(dp), intent(in) :: unitconv !< conversion factor for roughness to length and time units of meters and seconds
317  ! return
318  real(dp) :: q
319  ! local
320  integer(I4B) :: idcxs
321  real(dp) :: width
322  real(dp) :: rough
323  real(dp) :: slope
324  real(dp) :: conveyance
325 
326  idcxs = this%idcxs(i)
327  width = this%width(i)
328  rough = this%rough(i)
329  slope = this%slope(i)
330  conveyance = this%cxs%get_conveyance(idcxs, width, depth, rough)
331  q = conveyance * slope**dhalf * unitconv
332 
333  end function qcalc
334 
335  !> @ brief Copy hcof and rhs terms into solution.
336  !!
337  !! Add the hcof and rhs terms for the ZDG package to the
338  !! coefficient matrix and right-hand side vector.
339  !!
340  !<
341  subroutine zdg_fc(this, rhs, ia, idxglo, matrix_sln)
342  ! -- dummy variables
343  class(swfzdgtype) :: this !< SwfZdgType object
344  real(DP), dimension(:), intent(inout) :: rhs !< right-hand side vector for model
345  integer(I4B), dimension(:), intent(in) :: ia !< solution CRS row pointers
346  integer(I4B), dimension(:), intent(in) :: idxglo !< mapping vector for model (local) to solution (global)
347  class(matrixbasetype), pointer :: matrix_sln !< solution coefficient matrix
348  ! -- local variables
349  integer(I4B) :: i
350  integer(I4B) :: n
351  integer(I4B) :: ipos
352  !
353  ! -- pakmvrobj fc
354  if (this%imover == 1) then
355  call this%pakmvrobj%fc()
356  end if
357  !
358  ! -- Copy package rhs and hcof into solution rhs and amat
359  do i = 1, this%nbound
360  n = this%nodelist(i)
361  rhs(n) = rhs(n) + this%rhs(i)
362  ipos = ia(n)
363  call matrix_sln%add_value_pos(idxglo(ipos), this%hcof(i))
364  !
365  ! -- If mover is active and this zdg item is discharging,
366  ! store available water (as positive value).
367  if (this%imover == 1 .and. this%rhs(i) > dzero) then
368  call this%pakmvrobj%accumulate_qformvr(i, this%rhs(i))
369  end if
370  end do
371  end subroutine zdg_fc
372 
373  !> @ brief Define the list label for the package
374  !!
375  !! Method defined the list label for the ZDG package. The list label is
376  !! the heading that is written to iout when PRINT_INPUT option is used.
377  !!
378  !<
379  subroutine define_listlabel(this)
380  ! -- dummy variables
381  class(swfzdgtype), intent(inout) :: this !< SwfZdgType object
382  !
383  ! -- create the header list label
384  this%listlabel = trim(this%filtyp)//' NO.'
385  if (this%dis%ndim == 3) then
386  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'LAYER'
387  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'ROW'
388  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'COL'
389  elseif (this%dis%ndim == 2) then
390  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'LAYER'
391  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'CELL2D'
392  else
393  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'NODE'
394  end if
395  write (this%listlabel, '(a, a16)') trim(this%listlabel), 'FLOW RATE'
396  if (this%inamedbound == 1) then
397  write (this%listlabel, '(a, a16)') trim(this%listlabel), 'BOUNDARY NAME'
398  end if
399  end subroutine define_listlabel
400 
401  ! -- Procedures related to observations
402 
403  !> @brief Determine if observations are supported.
404  !!
405  !! Function to determine if observations are supported by the ZDG package.
406  !! Observations are supported by the ZDG package.
407  !!
408  !! @return zdg_obs_supported boolean indicating if observations are supported
409  !!
410  !<
411  logical function zdg_obs_supported(this)
412  ! -- dummy variables
413  class(swfzdgtype) :: this !< SwfZdgType object
414  !
415  ! -- set boolean
416  zdg_obs_supported = .true.
417  end function zdg_obs_supported
418 
419  !> @brief Define the observation types available in the package
420  !!
421  !! Method to define the observation types available in the ZDG package.
422  !!
423  !<
424  subroutine zdg_df_obs(this)
425  ! -- dummy variables
426  class(swfzdgtype) :: this !< SwfZdgType object
427  ! -- local variables
428  integer(I4B) :: indx
429  !
430  ! -- initialize observations
431  call this%obs%StoreObsType('zdg', .true., indx)
432  this%obs%obsData(indx)%ProcessIdPtr => defaultobsidprocessor
433  !
434  ! -- Store obs type and assign procedure pointer
435  ! for to-mvr observation type.
436  call this%obs%StoreObsType('to-mvr', .true., indx)
437  this%obs%obsData(indx)%ProcessIdPtr => defaultobsidprocessor
438  end subroutine zdg_df_obs
439 
440  !> @brief Save observations for the package
441  !!
442  !! Method to save simulated values for the ZDG package.
443  !!
444  !<
445  subroutine zdg_bd_obs(this)
446  ! -- dummy variables
447  class(swfzdgtype) :: this !< SwfZdgType object
448  ! -- local variables
449  integer(I4B) :: i
450  integer(I4B) :: n
451  integer(I4B) :: jj
452  real(DP) :: v
453  type(observetype), pointer :: obsrv => null()
454  !
455  ! -- clear the observations
456  call this%obs%obs_bd_clear()
457  !
458  ! -- Save simulated values for all of package's observations.
459  do i = 1, this%obs%npakobs
460  obsrv => this%obs%pakobs(i)%obsrv
461  if (obsrv%BndFound) then
462  do n = 1, obsrv%indxbnds_count
463  v = dnodata
464  jj = obsrv%indxbnds(n)
465  select case (obsrv%ObsTypeId)
466  case ('TO-MVR')
467  if (this%imover == 1) then
468  v = this%pakmvrobj%get_qtomvr(jj)
469  if (v > dzero) then
470  v = -v
471  end if
472  end if
473  case ('ZDG')
474  v = this%simvals(jj)
475  case default
476  errmsg = 'Unrecognized observation type: '//trim(obsrv%ObsTypeId)
477  call store_error(errmsg)
478  end select
479  call this%obs%SaveOneSimval(obsrv, v)
480  end do
481  else
482  call this%obs%SaveOneSimval(obsrv, dnodata)
483  end if
484  end do
485  end subroutine zdg_bd_obs
486 
487  ! -- Procedure related to time series
488 
489  !> @brief Assign time series links for the package
490  !!
491  !! Assign the time series links for the ZDG package. Only
492  !! the Q variable can be defined with time series.
493  !!
494  !<
495  subroutine zdg_rp_ts(this)
496  ! -- dummy variables
497  class(swfzdgtype), intent(inout) :: this !< SwfZdgType object
498  ! -- local variables
499  integer(I4B) :: i, nlinks
500  type(timeserieslinktype), pointer :: tslink => null()
501  !
502  ! -- set up the time series links
503  nlinks = this%TsManager%boundtslinks%Count()
504  do i = 1, nlinks
505  tslink => gettimeserieslinkfromlist(this%TsManager%boundtslinks, i)
506  if (associated(tslink)) then
507  if (tslink%JCol == 1) then
508  tslink%Text = 'Q'
509  end if
510  end if
511  end do
512  end subroutine zdg_rp_ts
513 
514  !> @ brief Return a bound value
515  !!
516  !! Return a bound value associated with an ncolbnd index
517  !! and row.
518  !!
519  !<
520  function zdg_bound_value(this, col, row) result(bndval)
521  ! -- modules
522  use constantsmodule, only: dzero
523  ! -- dummy variables
524  class(swfzdgtype), intent(inout) :: this
525  integer(I4B), intent(in) :: col
526  integer(I4B), intent(in) :: row
527  ! -- result
528  real(dp) :: bndval
529  !
530  select case (col)
531  case (1)
532  bndval = this%idcxs(row)
533  case (2)
534  bndval = this%width(row)
535  case (3)
536  bndval = this%slope(row)
537  case (4)
538  bndval = this%rough(row)
539  case default
540  errmsg = 'Programming error. ZDG bound value requested column '&
541  &'outside range of ncolbnd (1).'
542  call store_error(errmsg)
543  call store_error_filename(this%input_fname)
544  end select
545  end function zdg_bound_value
546 
547 end module swfzdgmodule
This module contains the extended boundary package.
This module contains the base boundary package.
This module contains simulation constants.
Definition: Constants.f90:9
real(dp), parameter dnodata
real no data constant
Definition: Constants.f90:95
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 dzero
real constant zero
Definition: Constants.f90:65
subroutine, public urword(line, icol, istart, istop, ncode, n, r, iout, in)
Extract a word from a string.
This module defines variable data types.
Definition: kind.f90:8
real(dp) function, public get_perturbation(x)
Calculate a numerical perturbation given the value of x.
Definition: MathUtil.f90:372
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
This module contains the derived type ObsType.
Definition: Obs.f90:127
subroutine, public defaultobsidprocessor(obsrv, dis, inunitobs, iout)
@ brief Process IDstring provided for each observation
Definition: Obs.f90:246
This module contains simulation methods.
Definition: Sim.f90:10
subroutine, public store_error(msg, terminate)
Store an error message.
Definition: Sim.f90:92
subroutine, public store_error_filename(filename, terminate)
Store the erroring file name.
Definition: Sim.f90:203
This module contains simulation variables.
Definition: SimVariables.f90:9
character(len=maxcharlen) errmsg
error message string
subroutine squadratic(x, range, dydx, y)
@ brief sQuadratic
This module contains the ZDG package methods.
Definition: swf-zdg.f90:7
subroutine zdg_allocate_scalars(this)
@ brief Allocate scalars
Definition: swf-zdg.f90:131
subroutine define_listlabel(this)
@ brief Define the list label for the package
Definition: swf-zdg.f90:380
logical function zdg_obs_supported(this)
Determine if observations are supported.
Definition: swf-zdg.f90:412
subroutine zdg_cf(this)
@ brief Formulate the package hcof and rhs terms.
Definition: swf-zdg.f90:251
subroutine zdg_fc(this, rhs, ia, idxglo, matrix_sln)
@ brief Copy hcof and rhs terms into solution.
Definition: swf-zdg.f90:342
real(dp) function zdg_bound_value(this, col, row)
@ brief Return a bound value
Definition: swf-zdg.f90:521
subroutine, public zdg_create(packobj, id, ibcnum, inunit, iout, namemodel, pakname, mempath, dis, cxs, unitconv)
@ brief Create a new package object
Definition: swf-zdg.f90:74
subroutine zdg_rp_ts(this)
Assign time series links for the package.
Definition: swf-zdg.f90:496
character(len=16) text
package flow text string
Definition: swf-zdg.f90:31
subroutine zdg_da(this)
@ brief Deallocate package memory
Definition: swf-zdg.f90:186
subroutine zdg_options(this)
@ brief Source additional options for package
Definition: swf-zdg.f90:210
character(len=lenftype) ftype
package ftype
Definition: swf-zdg.f90:30
subroutine zdg_allocate_arrays(this, nodelist, auxvar)
@ brief Allocate arrays
Definition: swf-zdg.f90:152
subroutine log_zdg_options(this)
@ brief Log SWF specific package options
Definition: swf-zdg.f90:230
subroutine zdg_bd_obs(this)
Save observations for the package.
Definition: swf-zdg.f90:446
real(dp) function qcalc(this, i, depth, unitconv)
Definition: swf-zdg.f90:312
subroutine zdg_df_obs(this)
Define the observation types available in the package.
Definition: swf-zdg.f90:425
type(timeserieslinktype) function, pointer, public gettimeserieslinkfromlist(list, indx)
Get time series link from a list.
@ brief BndType