MODFLOW 6  version 6.5.0.dev2
MODFLOW 6 Code Documentation
gwf-chd.f90
Go to the documentation of this file.
1 module chdmodule
2  !
3  use kindmodule, only: dp, i4b
6  use simvariablesmodule, only: errmsg
10  use bndmodule, only: bndtype
11  use bndextmodule, only: bndexttype
12  use observemodule, only: observetype
16  !
17  implicit none
18  !
19  private
20  public :: chd_create, chdtype
21  !
22  character(len=LENFTYPE) :: ftype = 'CHD'
23  character(len=LENPACKAGENAME) :: text = ' CHD'
24  !
25  type, extends(bndexttype) :: chdtype
26  real(dp), dimension(:), pointer, contiguous :: head => null() !< constant head array
27  real(dp), dimension(:), pointer, contiguous :: ratechdin => null() !simulated flows into constant head (excluding other chds)
28  real(dp), dimension(:), pointer, contiguous :: ratechdout => null() !simulated flows out of constant head (excluding to other chds)
29  contains
30  procedure :: bnd_rp => chd_rp
31  procedure :: bnd_ad => chd_ad
32  procedure :: bnd_ck => chd_ck
33  procedure :: bnd_fc => chd_fc
34  procedure :: bnd_cq => chd_cq
35  procedure :: bnd_bd => chd_bd
36  procedure :: bnd_da => chd_da
37  procedure :: allocate_arrays => chd_allocate_arrays
38  procedure :: define_listlabel
39  procedure :: bound_value => chd_bound_value
40  procedure :: head_mult
41  ! -- methods for observations
42  procedure, public :: bnd_obs_supported => chd_obs_supported
43  procedure, public :: bnd_df_obs => chd_df_obs
44  !
45  procedure, private :: calc_chd_rate
46  end type chdtype
47 
48 contains
49 
50  !> @brief Create a new constant head package
51  !!
52  !! Routine points packobj to the newly created package
53  !<
54  subroutine chd_create(packobj, id, ibcnum, inunit, iout, namemodel, pakname, &
55  mempath)
56  ! -- dummy
57  class(bndtype), pointer :: packobj
58  integer(I4B), intent(in) :: id
59  integer(I4B), intent(in) :: ibcnum
60  integer(I4B), intent(in) :: inunit
61  integer(I4B), intent(in) :: iout
62  character(len=*), intent(in) :: namemodel
63  character(len=*), intent(in) :: pakname
64  character(len=*), intent(in) :: mempath
65  ! -- local
66  type(chdtype), pointer :: chdobj
67  !
68  ! -- allocate the object and assign values to object variables
69  allocate (chdobj)
70  packobj => chdobj
71  !
72  ! -- create name and memory path
73  call packobj%set_names(ibcnum, namemodel, pakname, ftype, mempath)
74  packobj%text = text
75  !
76  ! -- allocate scalars
77  call chdobj%allocate_scalars()
78  !
79  ! -- initialize package
80  call packobj%pack_initialize()
81  !
82  ! -- store values
83  packobj%inunit = inunit
84  packobj%iout = iout
85  packobj%id = id
86  packobj%ibcnum = ibcnum
87  packobj%ictMemPath = create_mem_path(namemodel, 'NPF')
88  !
89  ! -- Return
90  return
91  end subroutine chd_create
92 
93  !> @brief Allocate arrays specific to the constant head package
94  !<
95  subroutine chd_allocate_arrays(this, nodelist, auxvar)
96  ! -- modules
98  ! -- dummy
99  class(chdtype) :: this
100  integer(I4B), dimension(:), pointer, contiguous, optional :: nodelist
101  real(DP), dimension(:, :), pointer, contiguous, optional :: auxvar
102  ! -- local
103  integer(I4B) :: i
104  !
105  ! -- call standard BndType allocate scalars
106  call this%BndExtType%allocate_arrays(nodelist, auxvar)
107  !
108  ! -- allocate ratechdex
109  call mem_allocate(this%ratechdin, this%maxbound, 'RATECHDIN', this%memoryPath)
110  call mem_allocate(this%ratechdout, this%maxbound, 'RATECHDOUT', &
111  this%memoryPath)
112  do i = 1, this%maxbound
113  this%ratechdin(i) = dzero
114  this%ratechdout(i) = dzero
115  end do
116  !
117  ! -- set constant head array input context pointer
118  call mem_setptr(this%head, 'HEAD', this%input_mempath)
119  !
120  ! -- checkin constant head array input context pointer
121  call mem_checkin(this%head, 'HEAD', this%memoryPath, &
122  'HEAD', this%input_mempath)
123  !
124  ! -- Return
125  return
126  end subroutine chd_allocate_arrays
127 
128  !> @brief Constant concentration/temperature read and prepare (rp) routine
129  !<
130  subroutine chd_rp(this)
131  !
132  use tdismodule, only: kper
133  ! -- dummy
134  class(chdtype), intent(inout) :: this
135  ! -- local
136  character(len=30) :: nodestr
137  integer(I4B) :: i, node, ibd, ierr
138  !
139  if (this%iper /= kper) return
140  !
141  ! -- Reset previous CHDs to active cell
142  do i = 1, this%nbound
143  node = this%nodelist(i)
144  this%ibound(node) = this%ibcnum
145  end do
146  !
147  ! -- Call the parent class read and prepare
148  call this%BndExtType%bnd_rp()
149  !
150  ! -- Set ibound to -(ibcnum + 1) for constant head cells
151  ierr = 0
152  do i = 1, this%nbound
153  node = this%nodelist(i)
154  ibd = this%ibound(node)
155  if (ibd < 0) then
156  call this%dis%noder_to_string(node, nodestr)
157  write (errmsg, '(3a)') &
158  'Cell is already a constant head (', trim(adjustl(nodestr)), ').'
159  call store_error(errmsg)
160  ierr = ierr + 1
161  else
162  this%ibound(node) = -this%ibcnum
163  end if
164  end do
165  !
166  ! -- Stop if errors detected
167  if (ierr > 0) then
168  call store_error_filename(this%input_fname)
169  end if
170  !
171  ! -- Write the list to iout if requested
172  if (this%iprpak /= 0) then
173  call this%write_list()
174  end if
175  !
176  ! -- Return
177  return
178  end subroutine chd_rp
179 
180  !> @brief Constant head package advance routine
181  !!
182  !! Add package connections to matrix
183  !<
184  subroutine chd_ad(this)
185  ! -- modules
186  ! -- dummy
187  class(chdtype) :: this
188  ! -- local
189  integer(I4B) :: i, node
190  real(DP) :: hb
191  ! -- formats
192  !
193  ! -- Process each entry in the specified-head cell list
194  do i = 1, this%nbound
195  node = this%nodelist(i)
196  hb = this%head_mult(i)
197  !
198  this%xnew(node) = hb
199  this%xold(node) = this%xnew(node)
200  end do
201  !
202  ! -- For each observation, push simulated value and corresponding
203  ! simulation time from "current" to "preceding" and reset
204  ! "current" value.
205  call this%obs%obs_ad()
206  !
207  ! -- Return
208  return
209  end subroutine chd_ad
210 
211  !> @brief Check constant concentration/temperature boundary condition data
212  !<
213  subroutine chd_ck(this)
214  ! -- modules
215  ! -- dummy
216  class(chdtype), intent(inout) :: this
217  ! -- local
218  character(len=30) :: nodestr
219  integer(I4B) :: i
220  integer(I4B) :: node
221  real(DP) :: bt
222  ! -- formats
223  character(len=*), parameter :: fmtchderr = &
224  "('CHD BOUNDARY ',i0,' HEAD (',g0,') IS LESS THAN CELL &
225  &BOTTOM (',g0,')',' FOR CELL ',a)"
226  !
227  ! -- check stress period data
228  do i = 1, this%nbound
229  node = this%nodelist(i)
230  bt = this%dis%bot(node)
231  ! -- accumulate errors
232  if (this%head_mult(i) < bt .and. this%icelltype(node) /= 0) then
233  call this%dis%noder_to_string(node, nodestr)
234  write (errmsg, fmt=fmtchderr) i, this%head_mult(i), bt, trim(nodestr)
235  call store_error(errmsg)
236  end if
237  end do
238  !
239  ! write summary of chd package error messages
240  if (count_errors() > 0) then
241  call store_error_filename(this%input_fname)
242  end if
243  !
244  ! -- Return
245  return
246  end subroutine chd_ck
247 
248  !> @brief Override bnd_fc and do nothing
249  !!
250  !! For constant head boundary type, the call to bnd_fc
251  !! needs to be overwritten to do nothing
252  !<
253  subroutine chd_fc(this, rhs, ia, idxglo, matrix_sln)
254  ! -- dummy
255  class(chdtype) :: this
256  real(DP), dimension(:), intent(inout) :: rhs
257  integer(I4B), dimension(:), intent(in) :: ia
258  integer(I4B), dimension(:), intent(in) :: idxglo
259  class(matrixbasetype), pointer :: matrix_sln
260  ! -- local
261  !
262  ! -- Return
263  return
264  end subroutine chd_fc
265 
266  !> @brief Calculate flow associated with constant head boundary
267  !!
268  !! This method overrides bnd_cq()
269  !<
270  subroutine chd_cq(this, x, flowja, iadv)
271  class(chdtype), intent(inout) :: this
272  real(DP), dimension(:), intent(in) :: x
273  real(DP), dimension(:), contiguous, intent(inout) :: flowja
274  integer(I4B), optional, intent(in) :: iadv
275 
276  ! NB: the rate calculation cannot be done until chd_bd below
277 
278  end subroutine chd_cq
279 
280  !> @brief Calculate the CHD cell rates, to be called
281  !< after all updates to the model flowja are done
282  subroutine calc_chd_rate(this)
283  ! -- modules
284  ! -- dummy
285  class(chdtype), intent(inout) :: this
286  ! -- local
287  integer(I4B) :: i
288  integer(I4B) :: ipos
289  integer(I4B) :: node
290  integer(I4B) :: n2
291  integer(I4B) :: idiag
292  real(DP) :: rate
293  real(DP) :: ratein, rateout
294  real(DP) :: q
295  !
296  ! -- If no boundaries, skip flow calculations.
297  if (this%nbound > 0) then
298  !
299  ! -- Loop through each boundary calculating flow.
300  do i = 1, this%nbound
301  node = this%nodelist(i)
302  idiag = this%dis%con%ia(node)
303  rate = dzero
304  ratein = dzero
305  rateout = dzero
306  !
307  ! -- Calculate the flow rate into the cell.
308  do ipos = this%dis%con%ia(node) + 1, &
309  this%dis%con%ia(node + 1) - 1
310  q = this%flowja(ipos)
311  rate = rate - q
312  ! -- only accumulate chin and chout for active
313  ! connected cells
314  n2 = this%dis%con%ja(ipos)
315  if (this%ibound(n2) > 0) then
316  if (q < dzero) then
317  ratein = ratein - q
318  else
319  rateout = rateout + q
320  end if
321  end if
322  end do
323  !
324  ! -- For chd, store total flow in rhs so it is available for other
325  ! calculations
326  this%rhs(i) = -rate
327  this%hcof(i) = dzero
328  !
329  ! -- Save simulated value to simvals array.
330  this%simvals(i) = rate
331  this%ratechdin(i) = ratein
332  this%ratechdout(i) = rateout
333  this%flowja(idiag) = this%flowja(idiag) + rate
334  !
335  end do
336  !
337  end if
338  !
339  ! -- Return
340  return
341  end subroutine calc_chd_rate
342 
343  !> @brief Add package ratin/ratout to model budget
344  !<
345  subroutine chd_bd(this, model_budget)
346  ! -- add package ratin/ratout to model budget
347  use tdismodule, only: delt
349  class(chdtype) :: this
350  type(budgettype), intent(inout) :: model_budget
351  real(DP) :: ratin
352  real(DP) :: ratout
353  real(DP) :: dum
354  integer(I4B) :: isuppress_output
355 
356  ! For CHDs at an exchange, under some conditions
357  ! (XT3D), the model flowja into the cell is not
358  ! finalized until after exg_cq. So we calculate
359  ! the CHD rate here
360  call this%calc_chd_rate()
361 
362  isuppress_output = 0
363  call rate_accumulator(this%ratechdin(1:this%nbound), ratin, dum)
364  call rate_accumulator(this%ratechdout(1:this%nbound), ratout, dum)
365  call model_budget%addentry(ratin, ratout, delt, this%text, &
366  isuppress_output, this%packName)
367  end subroutine chd_bd
368 
369  !> @brief Deallocate memory
370  !<
371  subroutine chd_da(this)
372  ! -- modules
374  ! -- dummy
375  class(chdtype) :: this
376  !
377  ! -- Deallocate parent package
378  call this%BndExtType%bnd_da()
379  !
380  ! -- arrays
381  call mem_deallocate(this%ratechdin)
382  call mem_deallocate(this%ratechdout)
383  call mem_deallocate(this%head, 'HEAD', this%memoryPath)
384  !
385  ! -- Return
386  return
387  end subroutine chd_da
388 
389  !> @brief Define the list heading that is written to iout when PRINT_INPUT
390  !! option is used.
391  !<
392  subroutine define_listlabel(this)
393  class(chdtype), intent(inout) :: this
394  !
395  ! -- create the header list label
396  this%listlabel = trim(this%filtyp)//' NO.'
397  if (this%dis%ndim == 3) then
398  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'LAYER'
399  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'ROW'
400  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'COL'
401  elseif (this%dis%ndim == 2) then
402  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'LAYER'
403  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'CELL2D'
404  else
405  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'NODE'
406  end if
407  write (this%listlabel, '(a, a16)') trim(this%listlabel), 'HEAD'
408  if (this%inamedbound == 1) then
409  write (this%listlabel, '(a, a16)') trim(this%listlabel), 'BOUNDARY NAME'
410  end if
411  !
412  ! -- Return
413  return
414  end subroutine define_listlabel
415 
416  ! -- Procedures related to observations
417 
418  !> @brief Overrides bnd_obs_supported from bndType class
419  !!
420  !! Return true since CHD package supports observations
421  !<
422  logical function chd_obs_supported(this)
423  implicit none
424  !
425  class(chdtype) :: this
426  !
427  chd_obs_supported = .true.
428  !
429  ! -- Return
430  return
431  end function chd_obs_supported
432 
433  !> @brief Overrides bnd_df_obs from bndType class
434  !!
435  !! (1) Store observation type supported by CHD package and (2) override
436  !! BndType%bnd_df_obs
437  !<
438  subroutine chd_df_obs(this)
439  implicit none
440  ! -- dummy
441  class(chdtype) :: this
442  ! -- local
443  integer(I4B) :: indx
444  !
445  call this%obs%StoreObsType('chd', .true., indx)
446  this%obs%obsData(indx)%ProcessIdPtr => defaultobsidprocessor
447  !
448  ! -- Return
449  return
450  end subroutine chd_df_obs
451 
452  !> @brief Apply auxiliary multiplier to specified head if appropriate
453  !<
454  function head_mult(this, row) result(head)
455  ! -- modules
456  use constantsmodule, only: dzero
457  ! -- dummy variables
458  class(chdtype), intent(inout) :: this !< BndExtType object
459  integer(I4B), intent(in) :: row
460  ! -- result
461  real(dp) :: head
462  !
463  if (this%iauxmultcol > 0) then
464  head = this%head(row) * this%auxvar(this%iauxmultcol, row)
465  else
466  head = this%head(row)
467  end if
468  !
469  ! -- Return
470  return
471  end function head_mult
472 
473  !> @ brief Return a bound value
474  !!
475  !! Return a bound value associated with an ncolbnd index
476  !! and row.
477  !<
478  function chd_bound_value(this, col, row) result(bndval)
479  ! -- modules
480  use constantsmodule, only: dzero
481  ! -- dummy variables
482  class(chdtype), intent(inout) :: this !< BndType object
483  integer(I4B), intent(in) :: col
484  integer(I4B), intent(in) :: row
485  ! -- result
486  real(dp) :: bndval
487  !
488  select case (col)
489  case (1)
490  bndval = this%head_mult(row)
491  case default
492  errmsg = 'Programming error. CHD bound value requested column '&
493  &'outside range of ncolbnd (1).'
494  call store_error(errmsg)
495  call store_error_filename(this%input_fname)
496  end select
497  !
498  ! -- Return
499  return
500  end function chd_bound_value
501 
502 end module chdmodule
This module contains the extended boundary package.
This module contains the base boundary package.
This module contains the BudgetModule.
Definition: Budget.f90:20
subroutine, public rate_accumulator(flow, rin, rout)
@ brief Rate accumulator subroutine
Definition: Budget.f90:664
subroutine chd_ck(this)
Check constant concentration/temperature boundary condition data.
Definition: gwf-chd.f90:214
character(len=lenpackagename) text
Definition: gwf-chd.f90:23
subroutine calc_chd_rate(this)
Calculate the CHD cell rates, to be called.
Definition: gwf-chd.f90:283
subroutine chd_da(this)
Deallocate memory.
Definition: gwf-chd.f90:372
subroutine define_listlabel(this)
Define the list heading that is written to iout when PRINT_INPUT option is used.
Definition: gwf-chd.f90:393
subroutine chd_cq(this, x, flowja, iadv)
Calculate flow associated with constant head boundary.
Definition: gwf-chd.f90:271
character(len=lenftype) ftype
Definition: gwf-chd.f90:22
real(dp) function chd_bound_value(this, col, row)
@ brief Return a bound value
Definition: gwf-chd.f90:479
subroutine chd_df_obs(this)
Overrides bnd_df_obs from bndType class.
Definition: gwf-chd.f90:439
subroutine chd_rp(this)
Constant concentration/temperature read and prepare (rp) routine.
Definition: gwf-chd.f90:131
subroutine chd_ad(this)
Constant head package advance routine.
Definition: gwf-chd.f90:185
subroutine, public chd_create(packobj, id, ibcnum, inunit, iout, namemodel, pakname, mempath)
Create a new constant head package.
Definition: gwf-chd.f90:56
real(dp) function head_mult(this, row)
Apply auxiliary multiplier to specified head if appropriate.
Definition: gwf-chd.f90:455
subroutine chd_allocate_arrays(this, nodelist, auxvar)
Allocate arrays specific to the constant head package.
Definition: gwf-chd.f90:96
logical function chd_obs_supported(this)
Overrides bnd_obs_supported from bndType class.
Definition: gwf-chd.f90:423
subroutine chd_bd(this, model_budget)
Add package ratin/ratout to model budget.
Definition: gwf-chd.f90:346
subroutine chd_fc(this, rhs, ia, idxglo, matrix_sln)
Override bnd_fc and do nothing.
Definition: gwf-chd.f90:254
This module contains simulation constants.
Definition: Constants.f90:9
integer(i4b), parameter linelength
maximum length of a standard line
Definition: Constants.f90:44
integer(i4b), parameter lenpackagename
maximum length of the package name
Definition: Constants.f90:22
integer(i4b), parameter namedboundflag
named bound flag
Definition: Constants.f90:48
integer(i4b), parameter lenftype
maximum length of a package type (DIS, WEL, OC, etc.)
Definition: Constants.f90:38
real(dp), parameter dzero
real constant zero
Definition: Constants.f90:64
real(dp), parameter done
real constant 1
Definition: Constants.f90:75
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
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:249
This module contains simulation methods.
Definition: Sim.f90:10
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 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
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
type(timeserieslinktype) function, pointer, public gettimeserieslinkfromlist(list, indx)
Get time series link from a list.
@ brief BndType
Derived type for the Budget object.
Definition: Budget.f90:39