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