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