MODFLOW 6  version 6.8.0.dev0
USGS Modular Hydrologic Model
gwt-cnc.f90
Go to the documentation of this file.
2  !
3  use kindmodule, only: dp, i4b
6  use simvariablesmodule, only: errmsg
9  use bndmodule, only: bndtype
10  use bndextmodule, only: bndexttype
11  use observemodule, only: observetype
15  !
16  implicit none
17  !
18  private
19  public :: cnc_create
20  !
21  character(len=LENFTYPE) :: ftype = 'CNC'
22  character(len=LENPACKAGENAME) :: text = ' CNC'
23  !
24  type, extends(bndexttype) :: gwtcnctype
25 
26  real(dp), dimension(:), pointer, contiguous :: tspvar => null() !< constant concentration array
27  real(dp), dimension(:), pointer, contiguous :: ratecncin => null() !simulated flows into constant conc (excluding other concs)
28  real(dp), dimension(:), pointer, contiguous :: ratecncout => null() !simulated flows out of constant conc (excluding to other concs)
29  character(len=LENVARNAME) :: depvartype = '' !< stores string of dependent variable type, depending on model type
30  contains
31  procedure :: bnd_rp => cnc_rp
32  procedure :: bnd_ad => cnc_ad
33  procedure :: bnd_ck => cnc_ck
34  procedure :: bnd_fc => cnc_fc
35  procedure :: bnd_cq => cnc_cq
36  procedure :: bnd_bd => cnc_bd
37  procedure :: bnd_da => cnc_da
38  procedure :: allocate_arrays => cnc_allocate_arrays
39  procedure :: define_listlabel
40  procedure :: bound_value => cnc_bound_value
41  procedure :: conc_mult
42  ! -- methods for observations
43  procedure, public :: bnd_obs_supported => cnc_obs_supported
44  procedure, public :: bnd_df_obs => cnc_df_obs
45  ! -- method for time series
46  procedure, public :: bnd_rp_ts => cnc_rp_ts
47  end type gwtcnctype
48 
49 contains
50 
51  !> @brief Create a new constant concentration or temperature package
52  !!
53  !! Routine points packobj to the newly created package
54  !<
55  subroutine cnc_create(packobj, id, ibcnum, inunit, iout, namemodel, pakname, &
56  depvartype, mempath)
57  ! -- dummy
58  class(bndtype), pointer :: packobj
59  integer(I4B), intent(in) :: id
60  integer(I4B), intent(in) :: ibcnum
61  integer(I4B), intent(in) :: inunit
62  integer(I4B), intent(in) :: iout
63  character(len=*), intent(in) :: namemodel
64  character(len=*), intent(in) :: pakname
65  character(len=LENVARNAME), intent(in) :: depvartype
66  character(len=*), intent(in) :: mempath
67  ! -- local
68  type(gwtcnctype), pointer :: cncobj
69  !
70  ! -- allocate the object and assign values to object variables
71  allocate (cncobj)
72  packobj => cncobj
73  !
74  ! -- create name and memory path
75  call packobj%set_names(ibcnum, namemodel, pakname, ftype, mempath)
76  packobj%text = text
77  !
78  ! -- allocate scalars
79  call cncobj%allocate_scalars()
80  !
81  ! -- initialize package
82  call packobj%pack_initialize()
83  !
84  ! -- store values
85  packobj%inunit = inunit
86  packobj%iout = iout
87  packobj%id = id
88  packobj%ibcnum = ibcnum
89  packobj%ncolbnd = 1
90  !
91  ! -- Store the appropriate label based on the dependent variable
92  cncobj%depvartype = depvartype
93  end subroutine cnc_create
94 
95  !> @brief Allocate arrays specific to the constant concentration/tempeature
96  !! package.
97  !<
98  subroutine cnc_allocate_arrays(this, nodelist, auxvar)
99  ! -- modules
101  ! -- dummy
102  class(gwtcnctype) :: this
103  integer(I4B), dimension(:), pointer, contiguous, optional :: nodelist
104  real(DP), dimension(:, :), pointer, contiguous, optional :: auxvar
105  ! -- local
106  integer(I4B) :: i
107  !
108  ! -- call standard BndType allocate scalars
109  call this%BndExtType%allocate_arrays(nodelist, auxvar)
110  !
111  ! -- allocate ratecncex
112  call mem_allocate(this%ratecncin, this%maxbound, 'RATECNCIN', this%memoryPath)
113  call mem_allocate(this%ratecncout, this%maxbound, 'RATECNCOUT', &
114  this%memoryPath)
115  do i = 1, this%maxbound
116  this%ratecncin(i) = dzero
117  this%ratecncout(i) = dzero
118  end do
119 
120  ! -- set input context pointers
121  call mem_setptr(this%tspvar, 'TSPVAR', this%input_mempath)
122 
123  ! -- checkin input context pointers
124  call mem_checkin(this%tspvar, 'TSPVAR', this%memoryPath, &
125  'TSPVAR', this%input_mempath)
126  end subroutine cnc_allocate_arrays
127 
128  !> @brief Constant concentration/temperature read and prepare (rp) routine
129  !<
130  subroutine cnc_rp(this)
131  ! -- modules
132  use simmodule, only: store_error
133  use inputoutputmodule, only: lowcase
134  implicit none
135  ! -- dummy
136  class(gwtcnctype), intent(inout) :: this
137  ! -- local
138  integer(I4B) :: i, node, ibd, ierr
139  character(len=30) :: nodestr
140  character(len=LENVARNAME) :: dvtype
141  !
142  ! -- Reset previous CNCs to active cell
143  do i = 1, this%nbound
144  node = this%nodelist(i)
145  this%ibound(node) = this%ibcnum
146  end do
147  !
148  ! -- Call the parent class read and prepare
149  call this%BndExtType%bnd_rp()
150  !
151  ! -- Set ibound to -(ibcnum + 1) for constant concentration cells
152  ierr = 0
153  do i = 1, this%nbound
154  node = this%nodelist(i)
155  ibd = this%ibound(node)
156  if (ibd < 0) then
157  call this%dis%noder_to_string(node, nodestr)
158  dvtype = trim(this%depvartype)
159  call lowcase(dvtype)
160  call store_error('Cell is already a constant ' &
161  //dvtype//': '//trim(adjustl(nodestr)))
162  ierr = ierr + 1
163  else
164  this%ibound(node) = -this%ibcnum
165  end if
166  end do
167  !
168  ! -- Stop if errors detected
169  if (ierr > 0) then
170  call store_error_filename(this%input_fname)
171  end if
172  end subroutine cnc_rp
173 
174  !> @brief Constant concentration/temperature package advance routine
175  !!
176  !! Add package connections to matrix
177  !<
178  subroutine cnc_ad(this)
179  ! -- modules
180  ! -- dummy
181  class(gwtcnctype) :: this
182  ! -- local
183  integer(I4B) :: i, node
184  real(DP) :: cb
185  ! -- formats
186  !
187  ! -- Advance the time series
188  call this%TsManager%ad()
189  !
190  ! -- Process each entry in the constant concentration cell list
191  do i = 1, this%nbound
192  node = this%nodelist(i)
193  cb = this%conc_mult(i)
194  !
195  this%xnew(node) = cb
196  this%xold(node) = this%xnew(node)
197  end do
198  !
199  ! -- For each observation, push simulated value and corresponding
200  ! simulation time from "current" to "preceding" and reset
201  ! "current" value.
202  call this%obs%obs_ad()
203  end subroutine cnc_ad
204 
205  !> @brief Check constant concentration/temperature boundary condition data
206  !<
207  subroutine cnc_ck(this)
208  ! -- modules
209  ! -- dummy
210  class(gwtcnctype), intent(inout) :: this
211  ! -- local
212  character(len=30) :: nodestr
213  integer(I4B) :: i
214  integer(I4B) :: node
215  ! -- formats
216  character(len=*), parameter :: fmtcncerr = &
217  &"('Specified dependent variable boundary ',i0, &
218  &' conc (',g0,') is less than zero for cell', a)"
219  !
220  ! -- check stress period data
221  do i = 1, this%nbound
222  node = this%nodelist(i)
223  ! -- accumulate errors
224  if (this%conc_mult(i) < dzero) then
225  call this%dis%noder_to_string(node, nodestr)
226  write (errmsg, fmt=fmtcncerr) i, this%tspvar(i), trim(nodestr)
227  call store_error(errmsg)
228  end if
229  end do
230  !
231  ! -- write summary of cnc package error messages
232  if (count_errors() > 0) then
233  call store_error_filename(this%input_fname)
234  end if
235  end subroutine cnc_ck
236 
237  !> @brief Override bnd_fc and do nothing
238  !!
239  !! For constant concentration/temperature boundary type, the call to bnd_fc
240  !! needs to be overwritten to prevent logic found in bnd from being executed
241  !<
242  subroutine cnc_fc(this, rhs, ia, idxglo, matrix_sln)
243  ! -- dummy
244  class(gwtcnctype) :: this
245  real(DP), dimension(:), intent(inout) :: rhs
246  integer(I4B), dimension(:), intent(in) :: ia
247  integer(I4B), dimension(:), intent(in) :: idxglo
248  class(matrixbasetype), pointer :: matrix_sln
249  ! -- local
250  end subroutine cnc_fc
251 
252  !> @brief Calculate flow associated with constant concentration/temperature
253  !! boundary
254  !!
255  !! This method overrides bnd_cq()
256  !<
257  subroutine cnc_cq(this, x, flowja, iadv)
258  ! -- modules
259  ! -- dummy
260  class(gwtcnctype), intent(inout) :: this
261  real(DP), dimension(:), intent(in) :: x
262  real(DP), dimension(:), contiguous, intent(inout) :: flowja
263  integer(I4B), optional, intent(in) :: iadv
264  ! -- local
265  integer(I4B) :: i
266  integer(I4B) :: ipos
267  integer(I4B) :: node
268  integer(I4B) :: n2
269  integer(I4B) :: idiag
270  real(DP) :: rate
271  real(DP) :: ratein, rateout
272  real(DP) :: q
273  !
274  ! -- If no boundaries, skip flow calculations.
275  if (this%nbound > 0) then
276  !
277  ! -- Loop through each boundary calculating flow.
278  do i = 1, this%nbound
279  node = this%nodelist(i)
280  idiag = this%dis%con%ia(node)
281  rate = dzero
282  ratein = dzero
283  rateout = dzero
284  !
285  ! -- Calculate the flow rate into the cell.
286  do ipos = this%dis%con%ia(node) + 1, &
287  this%dis%con%ia(node + 1) - 1
288  q = flowja(ipos)
289  rate = rate - q
290  ! -- only accumulate chin and chout for active
291  ! connected cells
292  n2 = this%dis%con%ja(ipos)
293  if (this%ibound(n2) > 0) then
294  if (q < dzero) then
295  ratein = ratein - q
296  else
297  rateout = rateout + q
298  end if
299  end if
300  end do
301  !
302  ! -- For CNC, store total flow in rhs so it is available for other
303  ! calculations
304  this%rhs(i) = -rate
305  this%hcof(i) = dzero
306  !
307  ! -- Save simulated value to simvals array.
308  this%simvals(i) = rate
309  this%ratecncin(i) = ratein
310  this%ratecncout(i) = rateout
311  flowja(idiag) = flowja(idiag) + rate
312  !
313  end do
314  !
315  end if
316  end subroutine cnc_cq
317 
318  !> @brief Add package ratin/ratout to model budget
319  !<
320  subroutine cnc_bd(this, model_budget)
321  ! -- modules
322  use tdismodule, only: delt
324  ! -- dummy
325  class(gwtcnctype) :: this
326  ! -- local
327  type(budgettype), intent(inout) :: model_budget
328  real(DP) :: ratin
329  real(DP) :: ratout
330  real(DP) :: dum
331  integer(I4B) :: isuppress_output
332  !
333  isuppress_output = 0
334  call rate_accumulator(this%ratecncin(1:this%nbound), ratin, dum)
335  call rate_accumulator(this%ratecncout(1:this%nbound), ratout, dum)
336  call model_budget%addentry(ratin, ratout, delt, this%text, &
337  isuppress_output, this%packName)
338  end subroutine cnc_bd
339 
340  !> @brief Deallocate memory
341  !!
342  !! Method to deallocate memory for the package.
343  !<
344  subroutine cnc_da(this)
345  ! -- modules
347  ! -- dummy
348  class(gwtcnctype) :: this
349  !
350  ! -- Deallocate parent package
351  call this%BndExtType%bnd_da()
352  !
353  ! -- arrays
354  call mem_deallocate(this%ratecncin)
355  call mem_deallocate(this%ratecncout)
356  call mem_deallocate(this%tspvar, 'TSPVAR', this%memoryPath)
357  end subroutine cnc_da
358 
359  !> @brief Define labels used in list file
360  !!
361  !! Define the list heading that is written to iout when PRINT_INPUT option
362  !! is used.
363  !<
364  subroutine define_listlabel(this)
365  ! -- dummy
366  class(gwtcnctype), intent(inout) :: this
367  !
368  ! -- create the header list label
369  this%listlabel = trim(this%filtyp)//' NO.'
370  if (this%dis%ndim == 3) then
371  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'LAYER'
372  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'ROW'
373  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'COL'
374  elseif (this%dis%ndim == 2) then
375  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'LAYER'
376  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'CELL2D'
377  else
378  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'NODE'
379  end if
380  write (this%listlabel, '(a, a16)') trim(this%listlabel), &
381  trim(this%depvartype)
382  if (this%inamedbound == 1) then
383  write (this%listlabel, '(a, a16)') trim(this%listlabel), 'BOUNDARY NAME'
384  end if
385  end subroutine define_listlabel
386 
387  !> @brief Procedure related to observation processing
388  !!
389  !! This routine:
390  !! - returns true because the SDV package supports observations,
391  !! - overrides packagetype%_obs_supported()
392  logical function cnc_obs_supported(this)
393  ! -- dummy
394  class(gwtcnctype) :: this
395  !
396  cnc_obs_supported = .true.
397  end function cnc_obs_supported
398 
399  !> @brief Procedure related to observation processing
400  !!
401  !! This routine:
402  !! - defines observations
403  !! - stores observation types supported by either of the SDV packages
404  !! (CNC or CNT),
405  !! - overrides BndExtType%bnd_df_obs
406  !<
407  subroutine cnc_df_obs(this)
408  ! -- dummy
409  class(gwtcnctype) :: this
410  ! -- local
411  integer(I4B) :: indx
412  !
413  call this%obs%StoreObsType(this%filtyp, .true., indx)
414  this%obs%obsData(indx)%ProcessIdPtr => defaultobsidprocessor
415  end subroutine cnc_df_obs
416 
417  ! -- Procedure related to time series
418 
419  !> @brief Procedure related to time series
420  !!
421  !! Assign tsLink%Text appropriately for all time series in use by package.
422  !! For any specified dependent variable package, for example either the
423  !! constant concentration or constant temperature packages, the dependent
424  !! variable can be controlled by time series.
425  !<
426  subroutine cnc_rp_ts(this)
427  ! -- dummy
428  class(gwtcnctype), intent(inout) :: this
429  ! -- local
430  integer(I4B) :: i, nlinks
431  type(timeserieslinktype), pointer :: tslink => null()
432  !
433  nlinks = this%TsManager%boundtslinks%Count()
434  do i = 1, nlinks
435  tslink => gettimeserieslinkfromlist(this%TsManager%boundtslinks, i)
436  if (associated(tslink)) then
437  select case (tslink%JCol)
438  case (1)
439  tslink%Text = trim(this%depvartype)
440  end select
441  end if
442  end do
443  end subroutine cnc_rp_ts
444 
445  !> @brief Apply auxiliary multiplier to specified concentration if
446  !< appropriate
447  function conc_mult(this, row) result(conc)
448  ! -- modules
449  use constantsmodule, only: dzero
450  ! -- dummy variables
451  class(gwtcnctype), intent(inout) :: this
452  integer(I4B), intent(in) :: row
453  ! -- result
454  real(dp) :: conc
455  !
456  if (this%iauxmultcol > 0) then
457  conc = this%tspvar(row) * this%auxvar(this%iauxmultcol, row)
458  else
459  conc = this%tspvar(row)
460  end if
461  end function conc_mult
462 
463  !> @ brief Return a bound value
464  !!
465  !! Return a bound value associated with an ncolbnd index and row.
466  !<
467  function cnc_bound_value(this, col, row) result(bndval)
468  ! -- modules
469  use constantsmodule, only: dzero
470  ! -- dummy variables
471  class(gwtcnctype), intent(inout) :: this
472  integer(I4B), intent(in) :: col
473  integer(I4B), intent(in) :: row
474  ! -- result
475  real(dp) :: bndval
476  !
477  select case (col)
478  case (1)
479  bndval = this%conc_mult(row)
480  case default
481  write (errmsg, '(3a)') 'Programming error. ', &
482  & adjustl(trim(this%filtyp)), ' bound value requested column '&
483  &'outside range of ncolbnd (1).'
484  call store_error(errmsg)
485  call store_error_filename(this%input_fname)
486  end select
487  end function cnc_bound_value
488 
489 end module gwtcncmodule
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:632
This module contains simulation constants.
Definition: Constants.f90:9
integer(i4b), parameter lenpackagename
maximum length of the package name
Definition: Constants.f90:23
integer(i4b), parameter namedboundflag
named bound flag
Definition: Constants.f90:49
integer(i4b), parameter lenvarname
maximum length of a variable name
Definition: Constants.f90:17
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
real(dp), parameter done
real constant 1
Definition: Constants.f90:76
logical function cnc_obs_supported(this)
Procedure related to observation processing.
Definition: gwt-cnc.f90:393
real(dp) function cnc_bound_value(this, col, row)
@ brief Return a bound value
Definition: gwt-cnc.f90:468
subroutine define_listlabel(this)
Define labels used in list file.
Definition: gwt-cnc.f90:365
character(len=lenpackagename) text
Definition: gwt-cnc.f90:22
subroutine cnc_df_obs(this)
Procedure related to observation processing.
Definition: gwt-cnc.f90:408
real(dp) function conc_mult(this, row)
Apply auxiliary multiplier to specified concentration if.
Definition: gwt-cnc.f90:448
character(len=lenftype) ftype
Definition: gwt-cnc.f90:21
subroutine cnc_ad(this)
Constant concentration/temperature package advance routine.
Definition: gwt-cnc.f90:179
subroutine cnc_cq(this, x, flowja, iadv)
Calculate flow associated with constant concentration/temperature boundary.
Definition: gwt-cnc.f90:258
subroutine cnc_rp_ts(this)
Procedure related to time series.
Definition: gwt-cnc.f90:427
subroutine cnc_ck(this)
Check constant concentration/temperature boundary condition data.
Definition: gwt-cnc.f90:208
subroutine, public cnc_create(packobj, id, ibcnum, inunit, iout, namemodel, pakname, depvartype, mempath)
Create a new constant concentration or temperature package.
Definition: gwt-cnc.f90:57
subroutine cnc_da(this)
Deallocate memory.
Definition: gwt-cnc.f90:345
subroutine cnc_allocate_arrays(this, nodelist, auxvar)
Allocate arrays specific to the constant concentration/tempeature package.
Definition: gwt-cnc.f90:99
subroutine cnc_rp(this)
Constant concentration/temperature read and prepare (rp) routine.
Definition: gwt-cnc.f90:131
subroutine cnc_bd(this, model_budget)
Add package ratin/ratout to model budget.
Definition: gwt-cnc.f90:321
subroutine cnc_fc(this, rhs, ia, idxglo, matrix_sln)
Override bnd_fc and do nothing.
Definition: gwt-cnc.f90:243
subroutine, public lowcase(word)
Convert to lower case.
This module defines variable data types.
Definition: kind.f90:8
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
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
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