MODFLOW 6  version 6.6.0.dev0
USGS Modular Hydrologic Model
tsp-apt.f90
Go to the documentation of this file.
1 ! -- Advanced Package Transport Module
2 ! -- This module contains most of the routines for simulating transport
3 ! -- through the advanced packages.
4 ! -- Future work:
5 ! * support decay, sorption
6 ! * dispersion in SFT and UZT?
7 !
8 ! AFP flows (flowbudptr) index var ATP term Transport Type
9 !---------------------------------------------------------------------------------
10 
11 ! -- specialized terms in the flow budget
12 ! FLOW-JA-FACE idxbudfjf FLOW-JA-FACE cv2cv
13 ! GWF (aux FLOW-AREA) idxbudgwf GWF cv2gwf
14 ! STORAGE (aux VOLUME) idxbudsto none used for cv volumes
15 ! FROM-MVR idxbudfmvr FROM-MVR q * cext = this%qfrommvr(:) ! rhow*cpw is applied to various terms for heat transport
16 ! TO-MVR idxbudtmvr TO-MVR q * cfeat
17 
18 ! -- generalized source/sink terms (except ET?)
19 ! RAINFALL idxbudrain RAINFALL q * crain
20 ! EVAPORATION idxbudevap EVAPORATION cfeat<cevap: q*cfeat, else: q*cevap ! latent heat may be applied for evaporative cooling
21 ! RUNOFF idxbudroff RUNOFF q * croff
22 ! EXT-INFLOW idxbudiflw EXT-INFLOW q * ciflw
23 ! WITHDRAWAL idxbudwdrl WITHDRAWAL q * cfeat
24 ! EXT-OUTFLOW idxbudoutf EXT-OUTFLOW q * cfeat
25 
26 ! -- terms from a flow file that should be skipped
27 ! CONSTANT none none none
28 ! AUXILIARY none none none
29 
30 ! -- terms that are written to the transport budget file
31 ! none none STORAGE (aux MASS) dM/dt
32 ! none none AUXILIARY none
33 ! none none CONSTANT accumulate
34 !
35 !
37 
38  use kindmodule, only: dp, i4b, lgp
45  use simvariablesmodule, only: errmsg
46  use bndmodule, only: bndtype
47  use tspfmimodule, only: tspfmitype
50  use tablemodule, only: tabletype, table_cr
51  use observemodule, only: observetype
53  use basedismodule, only: disbasetype
55 
56  implicit none
57 
58  public :: tspapttype
59  public :: apt_process_obsid
60  public :: apt_process_obsid12
61 
62  character(len=LENFTYPE) :: ftype = 'APT'
63  character(len=LENVARNAME) :: text = ' APT'
64 
65  type, extends(bndtype) :: tspapttype
66 
67  character(len=LENPACKAGENAME) :: flowpackagename = '' !< name of corresponding flow package
68  character(len=8), &
69  dimension(:), pointer, contiguous :: status => null() !< active, inactive, constant
70  character(len=LENAUXNAME) :: cauxfpconc = '' !< name of aux column in flow package auxvar array for concentration (or temperature)
71  integer(I4B), pointer :: iauxfpconc => null() !< column in flow package bound array to insert concs
72  integer(I4B), pointer :: imatrows => null() !< if active, add new rows to matrix
73  integer(I4B), pointer :: iprconc => null() !< print conc to listing file
74  integer(I4B), pointer :: iconcout => null() !< unit number for conc output file
75  integer(I4B), pointer :: ibudgetout => null() !< unit number for budget output file
76  integer(I4B), pointer :: ibudcsv => null() !< unit number for csv budget output file
77  integer(I4B), pointer :: ncv => null() !< number of control volumes
78  integer(I4B), pointer :: igwfaptpak => null() !< package number of corresponding this package
79  integer(I4B), pointer :: idxprepak => null() !< budget-object index that precedes package-specific budget objects
80  integer(I4B), pointer :: idxlastpak => null() !< budget-object index of last package-specific budget object
81  real(dp), dimension(:), pointer, contiguous :: strt => null() !< starting feature concentration (or temperature)
82  real(dp), dimension(:), pointer, contiguous :: ktf => null() !< thermal conductivity between the apt and groundwater cell
83  real(dp), dimension(:), pointer, contiguous :: rfeatthk => null() !< thickness of streambed/lakebed/filter-pack material through which thermal conduction occurs
84  integer(I4B), dimension(:), pointer, contiguous :: idxlocnode => null() !< map position in global rhs and x array of pack entry
85  integer(I4B), dimension(:), pointer, contiguous :: idxpakdiag => null() !< map diag position of feature in global amat
86  integer(I4B), dimension(:), pointer, contiguous :: idxdglo => null() !< map position in global array of package diagonal row entries
87  integer(I4B), dimension(:), pointer, contiguous :: idxoffdglo => null() !< map position in global array of package off diagonal row entries
88  integer(I4B), dimension(:), pointer, contiguous :: idxsymdglo => null() !< map position in global array of package diagonal entries to model rows
89  integer(I4B), dimension(:), pointer, contiguous :: idxsymoffdglo => null() !< map position in global array of package off diagonal entries to model rows
90  integer(I4B), dimension(:), pointer, contiguous :: idxfjfdglo => null() !< map diagonal feature to feature in global amat
91  integer(I4B), dimension(:), pointer, contiguous :: idxfjfoffdglo => null() !< map off diagonal feature to feature in global amat
92  integer(I4B), dimension(:), pointer, contiguous :: iboundpak => null() !< package ibound
93  real(dp), dimension(:), pointer, contiguous :: xnewpak => null() !< feature concentration (or temperature) for current time step
94  real(dp), dimension(:), pointer, contiguous :: xoldpak => null() !< feature concentration (or temperature) from previous time step
95  real(dp), dimension(:), pointer, contiguous :: dbuff => null() !< temporary storage array
96  character(len=LENBOUNDNAME), &
97  dimension(:), pointer, contiguous :: featname => null()
98  real(dp), dimension(:), pointer, contiguous :: concfeat => null() !< concentration (or temperature) of the feature
99  real(dp), dimension(:, :), pointer, contiguous :: lauxvar => null() !< auxiliary variable
100  type(tspfmitype), pointer :: fmi => null() !< pointer to fmi object
101  real(dp), dimension(:), pointer, contiguous :: qsto => null() !< mass (or energy) flux due to storage change
102  real(dp), dimension(:), pointer, contiguous :: ccterm => null() !< mass (or energy) flux required to maintain constant concentration (or temperature)
103  integer(I4B), pointer :: idxbudfjf => null() !< index of flow ja face in flowbudptr
104  integer(I4B), pointer :: idxbudgwf => null() !< index of gwf terms in flowbudptr
105  integer(I4B), pointer :: idxbudsto => null() !< index of storage terms in flowbudptr
106  integer(I4B), pointer :: idxbudtmvr => null() !< index of to mover terms in flowbudptr
107  integer(I4B), pointer :: idxbudfmvr => null() !< index of from mover terms in flowbudptr
108  integer(I4B), pointer :: idxbudaux => null() !< index of auxiliary terms in flowbudptr
109  integer(I4B), dimension(:), pointer, contiguous :: idxbudssm => null() !< flag that flowbudptr%buditem is a general solute source/sink
110  integer(I4B), pointer :: nconcbudssm => null() !< number of concbudssm terms (columns)
111  real(dp), dimension(:, :), pointer, contiguous :: concbudssm => null() !< user specified concentrations (or temperatures) for flow terms
112  real(dp), dimension(:), pointer, contiguous :: qmfrommvr => null() !< a mass or energy flow coming from the mover that needs to be added
113  real(dp), pointer :: eqnsclfac => null() !< governing equation scale factor; =1. for solute; =rhow*cpw for energy
114  character(len=LENVARNAME) :: depvartype = '' !< stores string identifying dependent variable type, depending on model type
115  character(len=LENVARNAME) :: depvarunit = '' !< "mass" or "energy"
116  character(len=LENVARNAME) :: depvarunitabbrev = '' !< "M" or "E"
117  !
118  ! -- pointer to flow package boundary
119  type(bndtype), pointer :: flowpackagebnd => null()
120  !
121  ! -- budget objects
122  type(budgetobjecttype), pointer :: budobj => null() !< apt solute budget object
123  type(budgetobjecttype), pointer :: flowbudptr => null() !< GWF flow budget object
124  !
125  ! -- table objects
126  type(tabletype), pointer :: dvtab => null()
127 
128  contains
129 
130  procedure :: set_pointers => apt_set_pointers
131  procedure :: bnd_ac => apt_ac
132  procedure :: bnd_mc => apt_mc
133  procedure :: bnd_ar => apt_ar
134  procedure :: bnd_rp => apt_rp
135  procedure :: bnd_ad => apt_ad
136  procedure :: bnd_reset => apt_reset
137  procedure :: bnd_fc => apt_fc
138  procedure, public :: apt_fc_expanded ! Made public for uze
139  procedure :: pak_fc_expanded
140  procedure, private :: apt_fc_nonexpanded
141  procedure, public :: apt_cfupdate ! Made public for uze
142  procedure :: apt_check_valid
143  procedure :: apt_set_stressperiod
144  procedure :: pak_set_stressperiod
146  procedure :: bnd_cq => apt_cq
147  procedure :: bnd_ot_package_flows => apt_ot_package_flows
148  procedure :: bnd_ot_dv => apt_ot_dv
149  procedure :: bnd_ot_bdsummary => apt_ot_bdsummary
150  procedure :: bnd_da => apt_da
151  procedure :: allocate_scalars
153  procedure :: apt_allocate_arrays
154  procedure :: find_apt_package
155  procedure :: apt_solve
156  procedure :: pak_solve
157  procedure :: bnd_options => apt_options
158  procedure :: read_dimensions => apt_read_dimensions
159  procedure :: apt_read_cvs
160  procedure :: read_initial_attr => apt_read_initial_attr
161  procedure :: define_listlabel
162  ! -- methods for observations
163  procedure :: bnd_obs_supported => apt_obs_supported
164  procedure :: bnd_df_obs => apt_df_obs
165  procedure :: pak_df_obs
166  procedure :: pak_rp_obs
167  procedure :: bnd_rp_obs => apt_rp_obs
168  procedure :: rp_obs_byfeature
169  procedure :: rp_obs_budterm
170  procedure :: rp_obs_flowjaface
171  procedure :: bnd_bd_obs => apt_bd_obs
172  procedure :: pak_bd_obs
173  procedure :: get_volumes
174  procedure :: pak_get_nbudterms
175  procedure :: apt_setup_budobj
176  procedure :: pak_setup_budobj
177  procedure :: apt_fill_budobj
178  procedure :: pak_fill_budobj
179  procedure, public :: apt_stor_term
180  procedure, public :: apt_tmvr_term
181  procedure, public :: apt_fmvr_term ! Made public for uze
182  procedure, public :: apt_fjf_term ! Made public for uze
183  procedure, private :: apt_copy2flowp
184  procedure, private :: apt_setup_tableobj
185  procedure, public :: get_mvr_depvar
186 
187  end type tspapttype
188 
189 contains
190 
191  !> @brief Add package connection to matrix
192  !<
193  subroutine apt_ac(this, moffset, sparse)
195  use sparsemodule, only: sparsematrix
196  ! -- dummy
197  class(tspapttype), intent(inout) :: this
198  integer(I4B), intent(in) :: moffset
199  type(sparsematrix), intent(inout) :: sparse
200  ! -- local
201  integer(I4B) :: i, n
202  integer(I4B) :: jj, jglo
203  integer(I4B) :: nglo
204  ! -- format
205  !
206  ! -- Add package rows to sparse
207  if (this%imatrows /= 0) then
208  !
209  ! -- diagonal
210  do n = 1, this%ncv
211  nglo = moffset + this%dis%nodes + this%ioffset + n
212  call sparse%addconnection(nglo, nglo, 1)
213  end do
214  !
215  ! -- apt-gwf connections
216  do i = 1, this%flowbudptr%budterm(this%idxbudgwf)%nlist
217  n = this%flowbudptr%budterm(this%idxbudgwf)%id1(i)
218  jj = this%flowbudptr%budterm(this%idxbudgwf)%id2(i)
219  nglo = moffset + this%dis%nodes + this%ioffset + n
220  jglo = jj + moffset
221  call sparse%addconnection(nglo, jglo, 1)
222  call sparse%addconnection(jglo, nglo, 1)
223  end do
224  !
225  ! -- apt-apt connections
226  if (this%idxbudfjf /= 0) then
227  do i = 1, this%flowbudptr%budterm(this%idxbudfjf)%maxlist
228  n = this%flowbudptr%budterm(this%idxbudfjf)%id1(i)
229  jj = this%flowbudptr%budterm(this%idxbudfjf)%id2(i)
230  nglo = moffset + this%dis%nodes + this%ioffset + n
231  jglo = moffset + this%dis%nodes + this%ioffset + jj
232  call sparse%addconnection(nglo, jglo, 1)
233  end do
234  end if
235  end if
236  end subroutine apt_ac
237 
238  !> @brief Advanced package transport map package connections to matrix
239  !<
240  subroutine apt_mc(this, moffset, matrix_sln)
241  use sparsemodule, only: sparsematrix
242  ! -- dummy
243  class(tspapttype), intent(inout) :: this
244  integer(I4B), intent(in) :: moffset
245  class(matrixbasetype), pointer :: matrix_sln
246  ! -- local
247  integer(I4B) :: n, j, iglo, jglo
248  integer(I4B) :: ipos
249  ! -- format
250  !
251  ! -- allocate memory for index arrays
252  call this%apt_allocate_index_arrays()
253  !
254  ! -- store index positions
255  if (this%imatrows /= 0) then
256  !
257  ! -- Find the position of each connection in the global ia, ja structure
258  ! and store them in idxglo. idxglo allows this model to insert or
259  ! retrieve values into or from the global A matrix
260  ! -- apt rows
261  do n = 1, this%ncv
262  this%idxlocnode(n) = this%dis%nodes + this%ioffset + n
263  iglo = moffset + this%dis%nodes + this%ioffset + n
264  this%idxpakdiag(n) = matrix_sln%get_position_diag(iglo)
265  end do
266  do ipos = 1, this%flowbudptr%budterm(this%idxbudgwf)%nlist
267  n = this%flowbudptr%budterm(this%idxbudgwf)%id1(ipos)
268  j = this%flowbudptr%budterm(this%idxbudgwf)%id2(ipos)
269  iglo = moffset + this%dis%nodes + this%ioffset + n
270  jglo = j + moffset
271  this%idxdglo(ipos) = matrix_sln%get_position_diag(iglo)
272  this%idxoffdglo(ipos) = matrix_sln%get_position(iglo, jglo)
273  end do
274  !
275  ! -- apt contributions to gwf portion of global matrix
276  do ipos = 1, this%flowbudptr%budterm(this%idxbudgwf)%nlist
277  n = this%flowbudptr%budterm(this%idxbudgwf)%id1(ipos)
278  j = this%flowbudptr%budterm(this%idxbudgwf)%id2(ipos)
279  iglo = j + moffset
280  jglo = moffset + this%dis%nodes + this%ioffset + n
281  this%idxsymdglo(ipos) = matrix_sln%get_position_diag(iglo)
282  this%idxsymoffdglo(ipos) = matrix_sln%get_position(iglo, jglo)
283  end do
284  !
285  ! -- apt-apt contributions to gwf portion of global matrix
286  if (this%idxbudfjf /= 0) then
287  do ipos = 1, this%flowbudptr%budterm(this%idxbudfjf)%nlist
288  n = this%flowbudptr%budterm(this%idxbudfjf)%id1(ipos)
289  j = this%flowbudptr%budterm(this%idxbudfjf)%id2(ipos)
290  iglo = moffset + this%dis%nodes + this%ioffset + n
291  jglo = moffset + this%dis%nodes + this%ioffset + j
292  this%idxfjfdglo(ipos) = matrix_sln%get_position_diag(iglo)
293  this%idxfjfoffdglo(ipos) = matrix_sln%get_position(iglo, jglo)
294  end do
295  end if
296  end if
297  end subroutine apt_mc
298 
299  !> @brief Advanced package transport allocate and read (ar) routine
300  !<
301  subroutine apt_ar(this)
302  ! -- modules
303  ! -- dummy
304  class(tspapttype), intent(inout) :: this
305  ! -- local
306  integer(I4B) :: j
307  logical :: found
308  ! -- formats
309  character(len=*), parameter :: fmtapt = &
310  "(1x,/1x,'APT -- ADVANCED PACKAGE TRANSPORT, VERSION 1, 3/5/2020', &
311  &' INPUT READ FROM UNIT ', i0, //)"
312  !
313  ! -- Get obs setup
314  call this%obs%obs_ar()
315  !
316  ! --print a message identifying the apt package.
317  write (this%iout, fmtapt) this%inunit
318  !
319  ! -- Allocate arrays
320  call this%apt_allocate_arrays()
321  !
322  ! -- read optional initial package parameters
323  call this%read_initial_attr()
324  !
325  ! -- Find the package index in the GWF model or GWF budget file
326  ! for the corresponding apt flow package
327  call this%fmi%get_package_index(this%flowpackagename, this%igwfaptpak)
328  !
329  ! -- Tell fmi that this package is being handled by APT, otherwise
330  ! SSM would handle the flows into GWT from this pack. Then point the
331  ! fmi data for an advanced package to xnewpak and qmfrommvr
332  this%fmi%iatp(this%igwfaptpak) = 1
333  this%fmi%datp(this%igwfaptpak)%concpack => this%get_mvr_depvar()
334  this%fmi%datp(this%igwfaptpak)%qmfrommvr => this%qmfrommvr
335  !
336  ! -- If there is an associated flow package and the user wishes to put
337  ! simulated concentrations (or temperatures) into a aux variable
338  ! column, then find the column number.
339  if (associated(this%flowpackagebnd)) then
340  if (this%cauxfpconc /= '') then
341  found = .false.
342  do j = 1, this%flowpackagebnd%naux
343  if (this%flowpackagebnd%auxname(j) == this%cauxfpconc) then
344  this%iauxfpconc = j
345  found = .true.
346  exit
347  end if
348  end do
349  if (this%iauxfpconc == 0) then
350  errmsg = 'Could not find auxiliary variable '// &
351  trim(adjustl(this%cauxfpconc))//' in flow package '// &
352  trim(adjustl(this%flowpackagename))
353  call store_error(errmsg)
354  call this%parser%StoreErrorUnit()
355  else
356  ! -- tell package not to update this auxiliary variable
357  this%flowpackagebnd%noupdateauxvar(this%iauxfpconc) = 1
358  call this%apt_copy2flowp()
359  end if
360  end if
361  end if
362  end subroutine apt_ar
363 
364  !> @brief Advanced package transport read and prepare (rp) routine
365  !!
366  !! This subroutine calls the attached packages' read and prepare routines.
367  !<
368  subroutine apt_rp(this)
369  use tdismodule, only: kper, nper
370  ! -- dummy
371  class(tspapttype), intent(inout) :: this
372  ! -- local
373  integer(I4B) :: ierr
374  integer(I4B) :: n
375  logical :: isfound, endOfBlock
376  character(len=LINELENGTH) :: title
377  character(len=LINELENGTH) :: line
378  integer(I4B) :: itemno
379  integer(I4B) :: igwfnode
380  ! -- formats
381  character(len=*), parameter :: fmtblkerr = &
382  &"('Error. Looking for BEGIN PERIOD iper. Found ', a, ' instead.')"
383  character(len=*), parameter :: fmtlsp = &
384  &"(1X,/1X,'REUSING ',A,'S FROM LAST STRESS PERIOD')"
385  !
386  ! -- set nbound to maxbound
387  this%nbound = this%maxbound
388  !
389  ! -- Set ionper to the stress period number for which a new block of data
390  ! will be read.
391  if (this%inunit == 0) return
392  !
393  ! -- get stress period data
394  if (this%ionper < kper) then
395  !
396  ! -- get period block
397  call this%parser%GetBlock('PERIOD', isfound, ierr, &
398  supportopenclose=.true., &
399  blockrequired=.false.)
400  if (isfound) then
401  !
402  ! -- read ionper and check for increasing period numbers
403  call this%read_check_ionper()
404  else
405  !
406  ! -- PERIOD block not found
407  if (ierr < 0) then
408  ! -- End of file found; data applies for remainder of simulation.
409  this%ionper = nper + 1
410  else
411  ! -- Found invalid block
412  call this%parser%GetCurrentLine(line)
413  write (errmsg, fmtblkerr) adjustl(trim(line))
414  call store_error(errmsg)
415  call this%parser%StoreErrorUnit()
416  end if
417  end if
418  end if
419  !
420  ! -- Read data if ionper == kper
421  if (this%ionper == kper) then
422  !
423  ! -- setup table for period data
424  if (this%iprpak /= 0) then
425  !
426  ! -- reset the input table object
427  title = trim(adjustl(this%text))//' PACKAGE ('// &
428  trim(adjustl(this%packName))//') DATA FOR PERIOD'
429  write (title, '(a,1x,i6)') trim(adjustl(title)), kper
430  call table_cr(this%inputtab, this%packName, title)
431  call this%inputtab%table_df(1, 4, this%iout, finalize=.false.)
432  text = 'NUMBER'
433  call this%inputtab%initialize_column(text, 10, alignment=tabcenter)
434  text = 'KEYWORD'
435  call this%inputtab%initialize_column(text, 20, alignment=tableft)
436  do n = 1, 2
437  write (text, '(a,1x,i6)') 'VALUE', n
438  call this%inputtab%initialize_column(text, 15, alignment=tabcenter)
439  end do
440  end if
441  !
442  ! -- read data
443  stressperiod: do
444  call this%parser%GetNextLine(endofblock)
445  if (endofblock) exit
446  !
447  ! -- get feature number
448  itemno = this%parser%GetInteger()
449  !
450  ! -- read data from the rest of the line
451  call this%apt_set_stressperiod(itemno)
452  !
453  ! -- write line to table
454  if (this%iprpak /= 0) then
455  call this%parser%GetCurrentLine(line)
456  call this%inputtab%line_to_columns(line)
457  end if
458  end do stressperiod
459 
460  if (this%iprpak /= 0) then
461  call this%inputtab%finalize_table()
462  end if
463  !
464  ! -- using stress period data from the previous stress period
465  else
466  write (this%iout, fmtlsp) trim(this%filtyp)
467  end if
468  !
469  ! -- write summary of stress period error messages
470  ierr = count_errors()
471  if (ierr > 0) then
472  call this%parser%StoreErrorUnit()
473  end if
474  !
475  ! -- fill arrays
476  do n = 1, this%flowbudptr%budterm(this%idxbudgwf)%nlist
477  igwfnode = this%flowbudptr%budterm(this%idxbudgwf)%id2(n)
478  this%nodelist(n) = igwfnode
479  end do
480  end subroutine apt_rp
481 
482  !> @brief Advanced package transport set stress period routine.
483  !!
484  !! Set a stress period attribute for an advanced transport package feature
485  !! (itemno) using keywords.
486  !<
487  subroutine apt_set_stressperiod(this, itemno)
488  ! -- module
490  ! -- dummy
491  class(tspapttype), intent(inout) :: this
492  integer(I4B), intent(in) :: itemno
493  ! -- local
494  character(len=LINELENGTH) :: text
495  character(len=LINELENGTH) :: caux
496  character(len=LINELENGTH) :: keyword
497  integer(I4B) :: ierr
498  integer(I4B) :: ii
499  integer(I4B) :: jj
500  real(DP), pointer :: bndElem => null()
501  logical :: found
502  ! -- formats
503  !
504  ! -- Support these general options in LKT, SFT, MWT, UZT
505  ! STATUS <status>
506  ! CONCENTRATION <concentration> or TEMPERATURE <temperature>
507  ! WITHDRAWAL <withdrawal>
508  ! AUXILIARY <auxname> <auxval>
509  !
510  ! -- read line
511  call this%parser%GetStringCaps(keyword)
512  select case (keyword)
513  case ('STATUS')
514  ierr = this%apt_check_valid(itemno)
515  if (ierr /= 0) then
516  goto 999
517  end if
518  call this%parser%GetStringCaps(text)
519  this%status(itemno) = text(1:8)
520  if (text == 'CONSTANT') then
521  this%iboundpak(itemno) = -1
522  else if (text == 'INACTIVE') then
523  this%iboundpak(itemno) = 0
524  else if (text == 'ACTIVE') then
525  this%iboundpak(itemno) = 1
526  else
527  write (errmsg, '(a,a)') &
528  'Unknown '//trim(this%text)//' status keyword: ', text//'.'
529  call store_error(errmsg)
530  end if
531  case ('CONCENTRATION', 'TEMPERATURE')
532  ierr = this%apt_check_valid(itemno)
533  if (ierr /= 0) then
534  goto 999
535  end if
536  call this%parser%GetString(text)
537  jj = 1 ! For feature concentration
538  bndelem => this%concfeat(itemno)
539  call read_value_or_time_series_adv(text, itemno, jj, bndelem, &
540  this%packName, 'BND', this%tsManager, &
541  this%iprpak, this%depvartype)
542  case ('AUXILIARY')
543  ierr = this%apt_check_valid(itemno)
544  if (ierr /= 0) then
545  goto 999
546  end if
547  call this%parser%GetStringCaps(caux)
548  do jj = 1, this%naux
549  if (trim(adjustl(caux)) /= trim(adjustl(this%auxname(jj)))) cycle
550  call this%parser%GetString(text)
551  ii = itemno
552  bndelem => this%lauxvar(jj, ii)
553  call read_value_or_time_series_adv(text, itemno, jj, bndelem, &
554  this%packName, 'AUX', &
555  this%tsManager, this%iprpak, &
556  this%auxname(jj))
557  exit
558  end do
559  case default
560  !
561  ! -- call the specific package to look for stress period data
562  call this%pak_set_stressperiod(itemno, keyword, found)
563  !
564  ! -- terminate with error if data not valid
565  if (.not. found) then
566  write (errmsg, '(2a)') &
567  'Unknown '//trim(adjustl(this%text))//' data keyword: ', &
568  trim(keyword)//'.'
569  call store_error(errmsg)
570  end if
571  end select
572  !
573  ! -- terminate if any errors were detected
574 999 if (count_errors() > 0) then
575  call this%parser%StoreErrorUnit()
576  end if
577  end subroutine apt_set_stressperiod
578 
579  !> @brief Advanced package transport set stress period routine.
580  !!
581  !! Set a stress period attribute for an individual package. This routine
582  !! must be overridden.
583  !<
584  subroutine pak_set_stressperiod(this, itemno, keyword, found)
585  ! -- dummy
586  class(tspapttype), intent(inout) :: this
587  integer(I4B), intent(in) :: itemno
588  character(len=*), intent(in) :: keyword
589  logical, intent(inout) :: found
590  ! -- local
591 
592  ! -- formats
593  !
594  ! -- this routine should never be called
595  found = .false.
596  call store_error('Program error: pak_set_stressperiod not implemented.', &
597  terminate=.true.)
598  end subroutine pak_set_stressperiod
599 
600  !> @brief Advanced package transport routine
601  !!
602  !! Determine if a valid feature number has been specified.
603  !<
604  function apt_check_valid(this, itemno) result(ierr)
605  ! -- return
606  integer(I4B) :: ierr
607  ! -- dummy
608  class(tspapttype), intent(inout) :: this
609  integer(I4B), intent(in) :: itemno
610  ! -- formats
611  ierr = 0
612  if (itemno < 1 .or. itemno > this%ncv) then
613  write (errmsg, '(a,1x,i6,1x,a,1x,i6)') &
614  'Featureno ', itemno, 'must be > 0 and <= ', this%ncv
615  call store_error(errmsg)
616  ierr = 1
617  end if
618  end function apt_check_valid
619 
620  !> @brief Advanced package transport utility function
621  !!
622  !! Set the concentration (or temperature) to be used by either MVT or MVE
623  !<
624  function get_mvr_depvar(this)
625  ! -- dummy
626  class(tspapttype) :: this
627  ! -- return
628  real(dp), dimension(:), contiguous, pointer :: get_mvr_depvar
629  !
630  get_mvr_depvar => this%xnewpak
631  end function get_mvr_depvar
632 
633  !> @brief Advanced package transport routine
634  !!
635  !! Add package connections to matrix
636  !<
637  subroutine apt_ad(this)
638  ! -- modules
640  ! -- dummy
641  class(tspapttype) :: this
642  ! -- local
643  integer(I4B) :: n
644  integer(I4B) :: j, iaux
645  !
646  ! -- Advance the time series
647  call this%TsManager%ad()
648  !
649  ! -- update auxiliary variables by copying from the derived-type time
650  ! series variable into the bndpackage auxvar variable so that this
651  ! information is properly written to the GWF budget file
652  if (this%naux > 0) then
653  do j = 1, this%flowbudptr%budterm(this%idxbudgwf)%nlist
654  n = this%flowbudptr%budterm(this%idxbudgwf)%id1(j)
655  do iaux = 1, this%naux
656  this%auxvar(iaux, j) = this%lauxvar(iaux, n)
657  end do
658  end do
659  end if
660  !
661  ! -- copy xnew into xold and set xnewpak to specified concentration (or
662  ! temperature) for constant concentration/temperature features
663  if (ifailedstepretry == 0) then
664  do n = 1, this%ncv
665  this%xoldpak(n) = this%xnewpak(n)
666  if (this%iboundpak(n) < 0) then
667  this%xnewpak(n) = this%concfeat(n)
668  end if
669  end do
670  else
671  do n = 1, this%ncv
672  this%xnewpak(n) = this%xoldpak(n)
673  if (this%iboundpak(n) < 0) then
674  this%xnewpak(n) = this%concfeat(n)
675  end if
676  end do
677  end if
678  !
679  ! -- pakmvrobj ad
680  !if (this%imover == 1) then
681  ! call this%pakmvrobj%ad()
682  !end if
683  !
684  ! -- For each observation, push simulated value and corresponding
685  ! simulation time from "current" to "preceding" and reset
686  ! "current" value.
687  call this%obs%obs_ad()
688  end subroutine apt_ad
689 
690  !> @brief Override bnd reset for custom mover logic
691  subroutine apt_reset(this)
692  class(tspapttype) :: this !< GwtAptType object
693  ! local
694  integer(I4B) :: i
695  !
696  do i = 1, size(this%qmfrommvr)
697  this%qmfrommvr(i) = dzero
698  end do
699  end subroutine apt_reset
700 
701  subroutine apt_fc(this, rhs, ia, idxglo, matrix_sln)
702  ! -- modules
703  ! -- dummy
704  class(tspapttype) :: this
705  real(DP), dimension(:), intent(inout) :: rhs
706  integer(I4B), dimension(:), intent(in) :: ia
707  integer(I4B), dimension(:), intent(in) :: idxglo
708  class(matrixbasetype), pointer :: matrix_sln
709  ! -- local
710  !
711  ! -- Call fc depending on whether or not a matrix is expanded or not
712  if (this%imatrows == 0) then
713  call this%apt_fc_nonexpanded(rhs, ia, idxglo, matrix_sln)
714  else
715  call this%apt_fc_expanded(rhs, ia, idxglo, matrix_sln)
716  end if
717  end subroutine apt_fc
718 
719  !> @brief Advanced package transport fill coefficient (fc) method
720  !!
721  !! Routine to formulate the nonexpanded matrix case in which feature
722  !! concentrations (or temperatures) are solved explicitly
723  !<
724  subroutine apt_fc_nonexpanded(this, rhs, ia, idxglo, matrix_sln)
725  ! -- modules
726  ! -- dummy
727  class(tspapttype) :: this
728  real(DP), dimension(:), intent(inout) :: rhs
729  integer(I4B), dimension(:), intent(in) :: ia
730  integer(I4B), dimension(:), intent(in) :: idxglo
731  class(matrixbasetype), pointer :: matrix_sln
732  ! -- local
733  integer(I4B) :: j, igwfnode, idiag
734  !
735  ! -- solve for concentration (or temperatures) in the features
736  call this%apt_solve()
737  !
738  ! -- add hcof and rhs terms (from apt_solve) to the gwf matrix
739  do j = 1, this%flowbudptr%budterm(this%idxbudgwf)%nlist
740  igwfnode = this%flowbudptr%budterm(this%idxbudgwf)%id2(j)
741  if (this%ibound(igwfnode) < 1) cycle
742  idiag = idxglo(ia(igwfnode))
743  call matrix_sln%add_value_pos(idiag, this%hcof(j))
744  rhs(igwfnode) = rhs(igwfnode) + this%rhs(j)
745  end do
746  end subroutine apt_fc_nonexpanded
747 
748  !> @brief Advanced package transport fill coefficient (fc) method
749  !!
750  !! Routine to formulate the expanded matrix case in which new rows are added
751  !! to the system of equations for each advanced package transport feature
752  !<
753  subroutine apt_fc_expanded(this, rhs, ia, idxglo, matrix_sln)
754  ! -- modules
755  ! -- dummy
756  class(tspapttype) :: this
757  real(DP), dimension(:), intent(inout) :: rhs
758  integer(I4B), dimension(:), intent(in) :: ia
759  integer(I4B), dimension(:), intent(in) :: idxglo
760  class(matrixbasetype), pointer :: matrix_sln
761  ! -- local
762  integer(I4B) :: j, n, n1, n2
763  integer(I4B) :: iloc
764  integer(I4B) :: iposd, iposoffd
765  integer(I4B) :: ipossymd, ipossymoffd
766  real(DP) :: cold
767  real(DP) :: qbnd, qbnd_scaled
768  real(DP) :: omega
769  real(DP) :: rrate
770  real(DP) :: rhsval
771  real(DP) :: hcofval
772  !
773  ! -- call the specific method for the advanced transport package, such as
774  ! what would be overridden by
775  ! GwtLktType, GwtSftType, GwtMwtType, GwtUztType
776  ! This routine will add terms for rainfall, runoff, or other terms
777  ! specific to the package
778  call this%pak_fc_expanded(rhs, ia, idxglo, matrix_sln)
779  !
780  ! -- mass (or energy) storage in features
781  do n = 1, this%ncv
782  cold = this%xoldpak(n)
783  iloc = this%idxlocnode(n)
784  iposd = this%idxpakdiag(n)
785  call this%apt_stor_term(n, n1, n2, rrate, rhsval, hcofval)
786  call matrix_sln%add_value_pos(iposd, hcofval)
787  rhs(iloc) = rhs(iloc) + rhsval
788  end do
789  !
790  ! -- add to mover contribution
791  if (this%idxbudtmvr /= 0) then
792  do j = 1, this%flowbudptr%budterm(this%idxbudtmvr)%nlist
793  call this%apt_tmvr_term(j, n1, n2, rrate, rhsval, hcofval)
794  iloc = this%idxlocnode(n1)
795  iposd = this%idxpakdiag(n1)
796  call matrix_sln%add_value_pos(iposd, hcofval)
797  rhs(iloc) = rhs(iloc) + rhsval
798  end do
799  end if
800  !
801  ! -- add from mover contribution
802  if (this%idxbudfmvr /= 0) then
803  do n = 1, this%ncv
804  rhsval = this%qmfrommvr(n) ! this will already be in terms of energy for heat transport
805  iloc = this%idxlocnode(n)
806  rhs(iloc) = rhs(iloc) - rhsval
807  end do
808  end if
809  !
810  ! -- go through each apt-gwf connection
811  do j = 1, this%flowbudptr%budterm(this%idxbudgwf)%nlist
812  !
813  ! -- set n to feature number and process if active feature
814  n = this%flowbudptr%budterm(this%idxbudgwf)%id1(j)
815  if (this%iboundpak(n) /= 0) then
816  !
817  ! -- set acoef and rhs to negative so they are relative to apt and not gwt
818  qbnd = this%flowbudptr%budterm(this%idxbudgwf)%flow(j)
819  omega = dzero
820  if (qbnd < dzero) omega = done
821  qbnd_scaled = qbnd * this%eqnsclfac
822  !
823  ! -- add to apt row
824  iposd = this%idxdglo(j)
825  iposoffd = this%idxoffdglo(j)
826  call matrix_sln%add_value_pos(iposd, omega * qbnd_scaled)
827  call matrix_sln%add_value_pos(iposoffd, (done - omega) * qbnd_scaled)
828  !
829  ! -- add to gwf row for apt connection
830  ipossymd = this%idxsymdglo(j)
831  ipossymoffd = this%idxsymoffdglo(j)
832  call matrix_sln%add_value_pos(ipossymd, -(done - omega) * qbnd_scaled)
833  call matrix_sln%add_value_pos(ipossymoffd, -omega * qbnd_scaled)
834  end if
835  end do
836  !
837  ! -- go through each apt-apt connection
838  if (this%idxbudfjf /= 0) then
839  do j = 1, this%flowbudptr%budterm(this%idxbudfjf)%nlist
840  n1 = this%flowbudptr%budterm(this%idxbudfjf)%id1(j)
841  n2 = this%flowbudptr%budterm(this%idxbudfjf)%id2(j)
842  qbnd = this%flowbudptr%budterm(this%idxbudfjf)%flow(j)
843  if (qbnd <= dzero) then
844  omega = done
845  else
846  omega = dzero
847  end if
848  qbnd_scaled = qbnd * this%eqnsclfac
849  iposd = this%idxfjfdglo(j)
850  iposoffd = this%idxfjfoffdglo(j)
851  call matrix_sln%add_value_pos(iposd, omega * qbnd_scaled)
852  call matrix_sln%add_value_pos(iposoffd, (done - omega) * qbnd_scaled)
853  end do
854  end if
855  end subroutine apt_fc_expanded
856 
857  !> @brief Advanced package transport fill coefficient (fc) method
858  !!
859  !! Routine to allow a subclass advanced transport package to inject
860  !! terms into the matrix assembly. This method must be overridden.
861  !<
862  subroutine pak_fc_expanded(this, rhs, ia, idxglo, matrix_sln)
863  ! -- modules
864  ! -- dummy
865  class(tspapttype) :: this
866  real(DP), dimension(:), intent(inout) :: rhs
867  integer(I4B), dimension(:), intent(in) :: ia
868  integer(I4B), dimension(:), intent(in) :: idxglo
869  class(matrixbasetype), pointer :: matrix_sln
870  ! -- local
871  !
872  ! -- this routine should never be called
873  call store_error('Program error: pak_fc_expanded not implemented.', &
874  terminate=.true.)
875  end subroutine pak_fc_expanded
876 
877  !> @brief Advanced package transport routine
878  !!
879  !! Calculate advanced package transport hcof and rhs so transport budget is
880  !! calculated.
881  !<
882  subroutine apt_cfupdate(this)
883  ! -- modules
884  ! -- dummy
885  class(tspapttype) :: this
886  ! -- local
887  integer(I4B) :: j, n
888  real(DP) :: qbnd
889  real(DP) :: omega
890  !
891  ! -- Calculate hcof and rhs terms so GWF exchanges are calculated correctly
892  ! -- go through each apt-gwf connection and calculate
893  ! rhs and hcof terms for gwt/gwe matrix rows
894  do j = 1, this%flowbudptr%budterm(this%idxbudgwf)%nlist
895  n = this%flowbudptr%budterm(this%idxbudgwf)%id1(j)
896  this%hcof(j) = dzero
897  this%rhs(j) = dzero
898  if (this%iboundpak(n) /= 0) then
899  qbnd = this%flowbudptr%budterm(this%idxbudgwf)%flow(j)
900  omega = dzero
901  if (qbnd < dzero) omega = done
902  this%hcof(j) = -(done - omega) * qbnd * this%eqnsclfac
903  this%rhs(j) = omega * qbnd * this%xnewpak(n) * this%eqnsclfac
904  end if
905  end do
906  end subroutine apt_cfupdate
907 
908  !> @brief Advanced package transport calculate flows (cq) routine
909  !!
910  !! Calculate flows for the advanced package transport feature
911  !<
912  subroutine apt_cq(this, x, flowja, iadv)
913  ! -- modules
914  ! -- dummy
915  class(tspapttype), intent(inout) :: this
916  real(DP), dimension(:), intent(in) :: x
917  real(DP), dimension(:), contiguous, intent(inout) :: flowja
918  integer(I4B), optional, intent(in) :: iadv
919  ! -- local
920  integer(I4B) :: n, n1, n2
921  real(DP) :: rrate
922  !
923  ! -- Solve the feature concentrations (or temperatures) again or update
924  ! the feature hcof and rhs terms
925  if (this%imatrows == 0) then
926  call this%apt_solve()
927  else
928  call this%apt_cfupdate()
929  end if
930  !
931  ! -- call base functionality in bnd_cq
932  call this%BndType%bnd_cq(x, flowja)
933  !
934  ! -- calculate storage term
935  do n = 1, this%ncv
936  rrate = dzero
937  if (this%iboundpak(n) > 0) then
938  call this%apt_stor_term(n, n1, n2, rrate)
939  end if
940  this%qsto(n) = rrate
941  end do
942  !
943  ! -- Copy concentrations (or temperatures) into the flow package auxiliary variable
944  call this%apt_copy2flowp()
945  !
946  ! -- fill the budget object
947  call this%apt_fill_budobj(x, flowja)
948  end subroutine apt_cq
949 
950  !> @brief Save advanced package flows routine
951  !<
952  subroutine apt_ot_package_flows(this, icbcfl, ibudfl)
953  use tdismodule, only: kstp, kper, delt, pertim, totim
954  class(tspapttype) :: this
955  integer(I4B), intent(in) :: icbcfl
956  integer(I4B), intent(in) :: ibudfl
957  integer(I4B) :: ibinun
958  !
959  ! -- write the flows from the budobj
960  ibinun = 0
961  if (this%ibudgetout /= 0) then
962  ibinun = this%ibudgetout
963  end if
964  if (icbcfl == 0) ibinun = 0
965  if (ibinun > 0) then
966  call this%budobj%save_flows(this%dis, ibinun, kstp, kper, delt, &
967  pertim, totim, this%iout)
968  end if
969  !
970  ! -- Print lake flows table
971  if (ibudfl /= 0 .and. this%iprflow /= 0) then
972  call this%budobj%write_flowtable(this%dis, kstp, kper)
973  end if
974  end subroutine apt_ot_package_flows
975 
976  subroutine apt_ot_dv(this, idvsave, idvprint)
977  ! -- modules
978  use constantsmodule, only: lenbudtxt
979  use tdismodule, only: kstp, kper, pertim, totim
981  use inputoutputmodule, only: ulasav
982  ! -- dummy
983  class(tspapttype) :: this
984  integer(I4B), intent(in) :: idvsave
985  integer(I4B), intent(in) :: idvprint
986  ! -- local
987  integer(I4B) :: ibinun
988  integer(I4B) :: n
989  real(DP) :: c
990  character(len=LENBUDTXT) :: text
991  !
992  ! -- set unit number for binary dependent variable output
993  ibinun = 0
994  if (this%iconcout /= 0) then
995  ibinun = this%iconcout
996  end if
997  if (idvsave == 0) ibinun = 0
998  !
999  ! -- write binary output
1000  if (ibinun > 0) then
1001  do n = 1, this%ncv
1002  c = this%xnewpak(n)
1003  if (this%iboundpak(n) == 0) then
1004  c = dhnoflo
1005  end if
1006  this%dbuff(n) = c
1007  end do
1008  write (text, '(a)') str_pad_left(this%depvartype, lenvarname)
1009  call ulasav(this%dbuff, text, kstp, kper, pertim, totim, &
1010  this%ncv, 1, 1, ibinun)
1011  end if
1012  !
1013  ! -- write apt conc table
1014  if (idvprint /= 0 .and. this%iprconc /= 0) then
1015  !
1016  ! -- set table kstp and kper
1017  call this%dvtab%set_kstpkper(kstp, kper)
1018  !
1019  ! -- fill concentration data
1020  do n = 1, this%ncv
1021  if (this%inamedbound == 1) then
1022  call this%dvtab%add_term(this%featname(n))
1023  end if
1024  call this%dvtab%add_term(n)
1025  call this%dvtab%add_term(this%xnewpak(n))
1026  end do
1027  end if
1028  end subroutine apt_ot_dv
1029 
1030  !> @brief Print advanced package transport dependent variables
1031  !<
1032  subroutine apt_ot_bdsummary(this, kstp, kper, iout, ibudfl)
1033  ! -- module
1034  use tdismodule, only: totim, delt
1035  ! -- dummy
1036  class(tspapttype) :: this !< TspAptType object
1037  integer(I4B), intent(in) :: kstp !< time step number
1038  integer(I4B), intent(in) :: kper !< period number
1039  integer(I4B), intent(in) :: iout !< flag and unit number for the model listing file
1040  integer(I4B), intent(in) :: ibudfl !< flag indicating budget should be written
1041  !
1042  call this%budobj%write_budtable(kstp, kper, iout, ibudfl, totim, delt)
1043  end subroutine apt_ot_bdsummary
1044 
1045  !> @ brief Allocate scalars
1046  !!
1047  !! Allocate scalar variables for an advanced package
1048  !<
1049  subroutine allocate_scalars(this)
1050  ! -- modules
1052  ! -- dummy
1053  class(tspapttype) :: this
1054  ! -- local
1055  !
1056  ! -- allocate scalars in NumericalPackageType
1057  call this%BndType%allocate_scalars()
1058  !
1059  ! -- Allocate
1060  call mem_allocate(this%iauxfpconc, 'IAUXFPCONC', this%memoryPath)
1061  call mem_allocate(this%imatrows, 'IMATROWS', this%memoryPath)
1062  call mem_allocate(this%iprconc, 'IPRCONC', this%memoryPath)
1063  call mem_allocate(this%iconcout, 'ICONCOUT', this%memoryPath)
1064  call mem_allocate(this%ibudgetout, 'IBUDGETOUT', this%memoryPath)
1065  call mem_allocate(this%ibudcsv, 'IBUDCSV', this%memoryPath)
1066  call mem_allocate(this%igwfaptpak, 'IGWFAPTPAK', this%memoryPath)
1067  call mem_allocate(this%ncv, 'NCV', this%memoryPath)
1068  call mem_allocate(this%idxbudfjf, 'IDXBUDFJF', this%memoryPath)
1069  call mem_allocate(this%idxbudgwf, 'IDXBUDGWF', this%memoryPath)
1070  call mem_allocate(this%idxbudsto, 'IDXBUDSTO', this%memoryPath)
1071  call mem_allocate(this%idxbudtmvr, 'IDXBUDTMVR', this%memoryPath)
1072  call mem_allocate(this%idxbudfmvr, 'IDXBUDFMVR', this%memoryPath)
1073  call mem_allocate(this%idxbudaux, 'IDXBUDAUX', this%memoryPath)
1074  call mem_allocate(this%nconcbudssm, 'NCONCBUDSSM', this%memoryPath)
1075  call mem_allocate(this%idxprepak, 'IDXPREPAK', this%memoryPath)
1076  call mem_allocate(this%idxlastpak, 'IDXLASTPAK', this%memoryPath)
1077  !
1078  ! -- Initialize
1079  this%iauxfpconc = 0
1080  this%imatrows = 1
1081  this%iprconc = 0
1082  this%iconcout = 0
1083  this%ibudgetout = 0
1084  this%ibudcsv = 0
1085  this%igwfaptpak = 0
1086  this%ncv = 0
1087  this%idxbudfjf = 0
1088  this%idxbudgwf = 0
1089  this%idxbudsto = 0
1090  this%idxbudtmvr = 0
1091  this%idxbudfmvr = 0
1092  this%idxbudaux = 0
1093  this%nconcbudssm = 0
1094  this%idxprepak = 0
1095  this%idxlastpak = 0
1096  !
1097  ! -- set this package as causing asymmetric matrix terms
1098  this%iasym = 1
1099  end subroutine allocate_scalars
1100 
1101  !> @ brief Allocate index arrays
1102  !!
1103  !! Allocate arrays that map to locations in the numerical solution
1104  !<
1105  subroutine apt_allocate_index_arrays(this)
1106  ! -- modules
1108  ! -- dummy
1109  class(tspapttype), intent(inout) :: this
1110  ! -- local
1111  integer(I4B) :: n
1112  !
1113  if (this%imatrows /= 0) then
1114  !
1115  ! -- count number of flow-ja-face connections
1116  n = 0
1117  if (this%idxbudfjf /= 0) then
1118  n = this%flowbudptr%budterm(this%idxbudfjf)%maxlist
1119  end if
1120  !
1121  ! -- allocate pointers to global matrix
1122  call mem_allocate(this%idxlocnode, this%ncv, 'IDXLOCNODE', &
1123  this%memoryPath)
1124  call mem_allocate(this%idxpakdiag, this%ncv, 'IDXPAKDIAG', &
1125  this%memoryPath)
1126  call mem_allocate(this%idxdglo, this%maxbound, 'IDXGLO', &
1127  this%memoryPath)
1128  call mem_allocate(this%idxoffdglo, this%maxbound, 'IDXOFFDGLO', &
1129  this%memoryPath)
1130  call mem_allocate(this%idxsymdglo, this%maxbound, 'IDXSYMDGLO', &
1131  this%memoryPath)
1132  call mem_allocate(this%idxsymoffdglo, this%maxbound, 'IDXSYMOFFDGLO', &
1133  this%memoryPath)
1134  call mem_allocate(this%idxfjfdglo, n, 'IDXFJFDGLO', &
1135  this%memoryPath)
1136  call mem_allocate(this%idxfjfoffdglo, n, 'IDXFJFOFFDGLO', &
1137  this%memoryPath)
1138  else
1139  call mem_allocate(this%idxlocnode, 0, 'IDXLOCNODE', &
1140  this%memoryPath)
1141  call mem_allocate(this%idxpakdiag, 0, 'IDXPAKDIAG', &
1142  this%memoryPath)
1143  call mem_allocate(this%idxdglo, 0, 'IDXGLO', &
1144  this%memoryPath)
1145  call mem_allocate(this%idxoffdglo, 0, 'IDXOFFDGLO', &
1146  this%memoryPath)
1147  call mem_allocate(this%idxsymdglo, 0, 'IDXSYMDGLO', &
1148  this%memoryPath)
1149  call mem_allocate(this%idxsymoffdglo, 0, 'IDXSYMOFFDGLO', &
1150  this%memoryPath)
1151  call mem_allocate(this%idxfjfdglo, 0, 'IDXFJFDGLO', &
1152  this%memoryPath)
1153  call mem_allocate(this%idxfjfoffdglo, 0, 'IDXFJFOFFDGLO', &
1154  this%memoryPath)
1155  end if
1156  end subroutine apt_allocate_index_arrays
1157 
1158  !> @ brief Allocate arrays
1159  !!
1160  !! Allocate advanced package transport arrays
1161  !<
1162  subroutine apt_allocate_arrays(this)
1163  ! -- modules
1165  ! -- dummy
1166  class(tspapttype), intent(inout) :: this
1167  ! -- local
1168  integer(I4B) :: n
1169  !
1170  ! -- call standard BndType allocate scalars
1171  call this%BndType%allocate_arrays()
1172  !
1173  ! -- Allocate
1174  !
1175  ! -- allocate and initialize dbuff
1176  if (this%iconcout > 0) then
1177  call mem_allocate(this%dbuff, this%ncv, 'DBUFF', this%memoryPath)
1178  do n = 1, this%ncv
1179  this%dbuff(n) = dzero
1180  end do
1181  else
1182  call mem_allocate(this%dbuff, 0, 'DBUFF', this%memoryPath)
1183  end if
1184  !
1185  ! -- allocate character array for status
1186  allocate (this%status(this%ncv))
1187  !
1188  ! -- time series
1189  call mem_allocate(this%concfeat, this%ncv, 'CONCFEAT', this%memoryPath)
1190  !
1191  ! -- budget terms
1192  call mem_allocate(this%qsto, this%ncv, 'QSTO', this%memoryPath)
1193  call mem_allocate(this%ccterm, this%ncv, 'CCTERM', this%memoryPath)
1194  !
1195  ! -- concentration for budget terms
1196  call mem_allocate(this%concbudssm, this%nconcbudssm, this%ncv, &
1197  'CONCBUDSSM', this%memoryPath)
1198  !
1199  ! -- mass (or energy) added from the mover transport package
1200  call mem_allocate(this%qmfrommvr, this%ncv, 'QMFROMMVR', this%memoryPath)
1201  !
1202  ! -- initialize arrays
1203  do n = 1, this%ncv
1204  this%status(n) = 'ACTIVE'
1205  this%qsto(n) = dzero
1206  this%ccterm(n) = dzero
1207  this%qmfrommvr(n) = dzero
1208  this%concbudssm(:, n) = dzero
1209  this%concfeat(n) = dzero
1210  end do
1211  end subroutine apt_allocate_arrays
1212 
1213  !> @ brief Deallocate memory
1214  !!
1215  !! Deallocate memory associated with this package
1216  !<
1217  subroutine apt_da(this)
1218  ! -- modules
1220  ! -- dummy
1221  class(tspapttype) :: this
1222  ! -- local
1223  !
1224  ! -- deallocate arrays
1225  call mem_deallocate(this%dbuff)
1226  call mem_deallocate(this%qsto)
1227  call mem_deallocate(this%ccterm)
1228  call mem_deallocate(this%strt)
1229  call mem_deallocate(this%ktf)
1230  call mem_deallocate(this%rfeatthk)
1231  call mem_deallocate(this%lauxvar)
1232  call mem_deallocate(this%xoldpak)
1233  if (this%imatrows == 0) then
1234  call mem_deallocate(this%iboundpak)
1235  call mem_deallocate(this%xnewpak)
1236  end if
1237  call mem_deallocate(this%concbudssm)
1238  call mem_deallocate(this%concfeat)
1239  call mem_deallocate(this%qmfrommvr)
1240  deallocate (this%status)
1241  deallocate (this%featname)
1242  !
1243  ! -- budobj
1244  call this%budobj%budgetobject_da()
1245  deallocate (this%budobj)
1246  nullify (this%budobj)
1247  !
1248  ! -- conc table
1249  if (this%iprconc > 0) then
1250  call this%dvtab%table_da()
1251  deallocate (this%dvtab)
1252  nullify (this%dvtab)
1253  end if
1254  !
1255  ! -- index pointers
1256  call mem_deallocate(this%idxlocnode)
1257  call mem_deallocate(this%idxpakdiag)
1258  call mem_deallocate(this%idxdglo)
1259  call mem_deallocate(this%idxoffdglo)
1260  call mem_deallocate(this%idxsymdglo)
1261  call mem_deallocate(this%idxsymoffdglo)
1262  call mem_deallocate(this%idxfjfdglo)
1263  call mem_deallocate(this%idxfjfoffdglo)
1264  !
1265  ! -- deallocate scalars
1266  call mem_deallocate(this%iauxfpconc)
1267  call mem_deallocate(this%imatrows)
1268  call mem_deallocate(this%iprconc)
1269  call mem_deallocate(this%iconcout)
1270  call mem_deallocate(this%ibudgetout)
1271  call mem_deallocate(this%ibudcsv)
1272  call mem_deallocate(this%igwfaptpak)
1273  call mem_deallocate(this%ncv)
1274  call mem_deallocate(this%idxbudfjf)
1275  call mem_deallocate(this%idxbudgwf)
1276  call mem_deallocate(this%idxbudsto)
1277  call mem_deallocate(this%idxbudtmvr)
1278  call mem_deallocate(this%idxbudfmvr)
1279  call mem_deallocate(this%idxbudaux)
1280  call mem_deallocate(this%idxbudssm)
1281  call mem_deallocate(this%nconcbudssm)
1282  call mem_deallocate(this%idxprepak)
1283  call mem_deallocate(this%idxlastpak)
1284  !
1285  ! -- deallocate scalars in NumericalPackageType
1286  call this%BndType%bnd_da()
1287  end subroutine apt_da
1288 
1289  !> @brief Find corresponding advanced package transport package
1290  !<
1291  subroutine find_apt_package(this)
1292  ! -- modules
1294  ! -- dummy
1295  class(tspapttype) :: this
1296  ! -- local
1297  !
1298  ! -- this routine should never be called
1299  call store_error('Program error: pak_solve not implemented.', &
1300  terminate=.true.)
1301  end subroutine find_apt_package
1302 
1303  !> @brief Set options specific to the TspAptType
1304  !!
1305  !! This routine overrides BndType%bnd_options
1306  !<
1307  subroutine apt_options(this, option, found)
1308  use constantsmodule, only: maxcharlen, dzero
1309  use openspecmodule, only: access, form
1311  ! -- dummy
1312  class(tspapttype), intent(inout) :: this
1313  character(len=*), intent(inout) :: option
1314  logical, intent(inout) :: found
1315  ! -- local
1316  character(len=MAXCHARLEN) :: fname, keyword
1317  ! -- formats
1318  character(len=*), parameter :: fmtaptbin = &
1319  "(4x, a, 1x, a, 1x, ' WILL BE SAVED TO FILE: ', a, &
1320  &/4x, 'OPENED ON UNIT: ', I0)"
1321  !
1322  found = .true.
1323  select case (option)
1324  case ('FLOW_PACKAGE_NAME')
1325  call this%parser%GetStringCaps(this%flowpackagename)
1326  write (this%iout, '(4x,a)') &
1327  'THIS '//trim(adjustl(this%text))//' PACKAGE CORRESPONDS TO A GWF &
1328  &PACKAGE WITH THE NAME '//trim(adjustl(this%flowpackagename))
1329  case ('FLOW_PACKAGE_AUXILIARY_NAME')
1330  call this%parser%GetStringCaps(this%cauxfpconc)
1331  write (this%iout, '(4x,a)') &
1332  'SIMULATED CONCENTRATIONS WILL BE COPIED INTO THE FLOW PACKAGE &
1333  &AUXILIARY VARIABLE WITH THE NAME '//trim(adjustl(this%cauxfpconc))
1334  case ('DEV_NONEXPANDING_MATRIX')
1335  ! -- use an iterative solution where concentration is not solved
1336  ! as part of the matrix. It is instead solved separately with a
1337  ! general mixing equation and then added to the RHS of the GWT
1338  ! equations
1339  call this%parser%DevOpt()
1340  this%imatrows = 0
1341  write (this%iout, '(4x,a)') &
1342  trim(adjustl(this%text))// &
1343  ' WILL NOT ADD ADDITIONAL ROWS TO THE A MATRIX.'
1344  case ('PRINT_CONCENTRATION', 'PRINT_TEMPERATURE')
1345  this%iprconc = 1
1346  write (this%iout, '(4x,a,1x,a,1x,a)') trim(adjustl(this%text))// &
1347  trim(adjustl(this%depvartype))//'S WILL BE PRINTED TO LISTING &
1348  &FILE.'
1349  case ('CONCENTRATION', 'TEMPERATURE')
1350  call this%parser%GetStringCaps(keyword)
1351  if (keyword == 'FILEOUT') then
1352  call this%parser%GetString(fname)
1353  this%iconcout = getunit()
1354  call openfile(this%iconcout, this%iout, fname, 'DATA(BINARY)', &
1355  form, access, 'REPLACE')
1356  write (this%iout, fmtaptbin) &
1357  trim(adjustl(this%text)), trim(adjustl(this%depvartype)), &
1358  trim(fname), this%iconcout
1359  else
1360  write (errmsg, "('Optional', 1x, a, 1X, 'keyword must &
1361  &be followed by FILEOUT')") this%depvartype
1362  call store_error(errmsg)
1363  end if
1364  case ('BUDGET')
1365  call this%parser%GetStringCaps(keyword)
1366  if (keyword == 'FILEOUT') then
1367  call this%parser%GetString(fname)
1368  this%ibudgetout = getunit()
1369  call openfile(this%ibudgetout, this%iout, fname, 'DATA(BINARY)', &
1370  form, access, 'REPLACE')
1371  write (this%iout, fmtaptbin) trim(adjustl(this%text)), 'BUDGET', &
1372  trim(fname), this%ibudgetout
1373  else
1374  call store_error('Optional BUDGET keyword must be followed by FILEOUT')
1375  end if
1376  case ('BUDGETCSV')
1377  call this%parser%GetStringCaps(keyword)
1378  if (keyword == 'FILEOUT') then
1379  call this%parser%GetString(fname)
1380  this%ibudcsv = getunit()
1381  call openfile(this%ibudcsv, this%iout, fname, 'CSV', &
1382  filstat_opt='REPLACE')
1383  write (this%iout, fmtaptbin) trim(adjustl(this%text)), 'BUDGET CSV', &
1384  trim(fname), this%ibudcsv
1385  else
1386  call store_error('Optional BUDGETCSV keyword must be followed by &
1387  &FILEOUT')
1388  end if
1389  case default
1390  !
1391  ! -- No options found
1392  found = .false.
1393  end select
1394  end subroutine apt_options
1395 
1396  !> @brief Determine dimensions for this advanced package
1397  !<
1398  subroutine apt_read_dimensions(this)
1399  ! -- dummy
1400  class(tspapttype), intent(inout) :: this
1401  ! -- local
1402  integer(I4B) :: ierr
1403  ! -- format
1404  !
1405  ! -- Set a pointer to the GWF LAK Package budobj
1406  if (this%flowpackagename == '') then
1407  this%flowpackagename = this%packName
1408  write (this%iout, '(4x,a)') &
1409  'THE FLOW PACKAGE NAME FOR '//trim(adjustl(this%text))//' WAS NOT &
1410  &SPECIFIED. SETTING FLOW PACKAGE NAME TO '// &
1411  &trim(adjustl(this%flowpackagename))
1412 
1413  end if
1414  call this%find_apt_package()
1415  !
1416  ! -- Set dimensions from the GWF advanced package
1417  this%ncv = this%flowbudptr%ncv
1418  this%maxbound = this%flowbudptr%budterm(this%idxbudgwf)%maxlist
1419  this%nbound = this%maxbound
1420  write (this%iout, '(a, a)') 'SETTING DIMENSIONS FOR PACKAGE ', this%packName
1421  write (this%iout, '(2x,a,i0)') 'NUMBER OF CONTROL VOLUMES = ', this%ncv
1422  write (this%iout, '(2x,a,i0)') 'MAXBOUND = ', this%maxbound
1423  write (this%iout, '(2x,a,i0)') 'NBOUND = ', this%nbound
1424  if (this%imatrows /= 0) then
1425  this%npakeq = this%ncv
1426  write (this%iout, '(2x,a)') trim(adjustl(this%text))// &
1427  ' SOLVED AS PART OF GWT MATRIX EQUATIONS'
1428  else
1429  write (this%iout, '(2x,a)') trim(adjustl(this%text))// &
1430  ' SOLVED SEPARATELY FROM GWT MATRIX EQUATIONS '
1431  end if
1432  write (this%iout, '(a, //)') 'DONE SETTING DIMENSIONS FOR '// &
1433  trim(adjustl(this%text))
1434  !
1435  ! -- Check for errors
1436  if (this%ncv < 0) then
1437  write (errmsg, '(a)') &
1438  'Number of control volumes could not be determined correctly.'
1439  call store_error(errmsg)
1440  end if
1441  !
1442  ! -- stop if errors were encountered in the DIMENSIONS block
1443  ierr = count_errors()
1444  if (ierr > 0) then
1445  call store_error_unit(this%inunit)
1446  end if
1447  !
1448  ! -- read packagedata block
1449  call this%apt_read_cvs()
1450  !
1451  ! -- Call define_listlabel to construct the list label that is written
1452  ! when PRINT_INPUT option is used.
1453  call this%define_listlabel()
1454  !
1455  ! -- setup the budget object
1456  call this%apt_setup_budobj()
1457  !
1458  ! -- setup the conc table object
1459  call this%apt_setup_tableobj()
1460  end subroutine apt_read_dimensions
1461 
1462  !> @brief Read feature information for this advanced package
1463  !<
1464  subroutine apt_read_cvs(this)
1465  ! -- modules
1468  ! -- dummy
1469  class(tspapttype), intent(inout) :: this
1470  ! -- local
1471  character(len=LINELENGTH) :: text
1472  character(len=LENBOUNDNAME) :: bndName, bndNameTemp
1473  character(len=9) :: cno
1474  character(len=50), dimension(:), allocatable :: caux
1475  integer(I4B) :: ierr
1476  logical :: isfound, endOfBlock
1477  integer(I4B) :: n
1478  integer(I4B) :: ii, jj
1479  integer(I4B) :: iaux
1480  integer(I4B) :: itmp
1481  integer(I4B) :: nlak
1482  integer(I4B) :: nconn
1483  integer(I4B), dimension(:), pointer, contiguous :: nboundchk
1484  real(DP), pointer :: bndElem => null()
1485  !
1486  ! -- initialize itmp
1487  itmp = 0
1488  !
1489  ! -- allocate apt data
1490  call mem_allocate(this%strt, this%ncv, 'STRT', this%memoryPath)
1491  call mem_allocate(this%ktf, this%ncv, 'KTF', this%memoryPath)
1492  call mem_allocate(this%rfeatthk, this%ncv, 'RFEATTHK', this%memoryPath)
1493  call mem_allocate(this%lauxvar, this%naux, this%ncv, 'LAUXVAR', &
1494  this%memoryPath)
1495  !
1496  ! -- lake boundary and concentrations
1497  if (this%imatrows == 0) then
1498  call mem_allocate(this%iboundpak, this%ncv, 'IBOUND', this%memoryPath)
1499  call mem_allocate(this%xnewpak, this%ncv, 'XNEWPAK', this%memoryPath)
1500  end if
1501  call mem_allocate(this%xoldpak, this%ncv, 'XOLDPAK', this%memoryPath)
1502  !
1503  ! -- allocate character storage not managed by the memory manager
1504  allocate (this%featname(this%ncv)) ! ditch after boundnames allocated??
1505  !allocate(this%status(this%ncv))
1506  !
1507  do n = 1, this%ncv
1508  this%strt(n) = dep20
1509  this%ktf(n) = dzero
1510  this%rfeatthk(n) = dzero
1511  this%lauxvar(:, n) = dzero
1512  this%xoldpak(n) = dep20
1513  if (this%imatrows == 0) then
1514  this%iboundpak(n) = 1
1515  this%xnewpak(n) = dep20
1516  end if
1517  end do
1518  !
1519  ! -- allocate local storage for aux variables
1520  if (this%naux > 0) then
1521  allocate (caux(this%naux))
1522  end if
1523  !
1524  ! -- allocate and initialize temporary variables
1525  allocate (nboundchk(this%ncv))
1526  do n = 1, this%ncv
1527  nboundchk(n) = 0
1528  end do
1529  !
1530  ! -- get packagedata block
1531  call this%parser%GetBlock('PACKAGEDATA', isfound, ierr, &
1532  supportopenclose=.true.)
1533  !
1534  ! -- parse locations block if detected
1535  if (isfound) then
1536  write (this%iout, '(/1x,a)') 'PROCESSING '//trim(adjustl(this%text))// &
1537  ' PACKAGEDATA'
1538  nlak = 0
1539  nconn = 0
1540  do
1541  call this%parser%GetNextLine(endofblock)
1542  if (endofblock) exit
1543  n = this%parser%GetInteger()
1544 
1545  if (n < 1 .or. n > this%ncv) then
1546  write (errmsg, '(a,1x,i6)') &
1547  'Itemno must be > 0 and <= ', this%ncv
1548  call store_error(errmsg)
1549  cycle
1550  end if
1551  !
1552  ! -- increment nboundchk
1553  nboundchk(n) = nboundchk(n) + 1
1554  !
1555  ! -- strt
1556  this%strt(n) = this%parser%GetDouble()
1557  !
1558  ! -- If GWE model, read additional thermal conductivity terms
1559  if (this%depvartype == 'TEMPERATURE') then
1560  ! -- Skip for UZE
1561  if (trim(adjustl(this%text)) /= 'UZE') then
1562  this%ktf(n) = this%parser%GetDouble()
1563  this%rfeatthk(n) = this%parser%GetDouble()
1564  if (this%rfeatthk(n) <= dzero) then
1565  write (errmsg, '(4x,a)') &
1566  '****ERROR. Specified thickness used for thermal &
1567  &conduction MUST BE > 0 else divide by zero error occurs'
1568  call store_error(errmsg)
1569  cycle
1570  end if
1571  end if
1572  end if
1573  !
1574  ! -- get aux data
1575  do iaux = 1, this%naux
1576  call this%parser%GetString(caux(iaux))
1577  end do
1578 
1579  ! -- set default bndName
1580  write (cno, '(i9.9)') n
1581  bndname = 'Feature'//cno
1582 
1583  ! -- featname
1584  if (this%inamedbound /= 0) then
1585  call this%parser%GetStringCaps(bndnametemp)
1586  if (bndnametemp /= '') then
1587  bndname = bndnametemp
1588  end if
1589  end if
1590  this%featname(n) = bndname
1591 
1592  ! -- fill time series aware data
1593  ! -- fill aux data
1594  do jj = 1, this%naux
1595  text = caux(jj)
1596  ii = n
1597  bndelem => this%lauxvar(jj, ii)
1598  call read_value_or_time_series_adv(text, ii, jj, bndelem, &
1599  this%packName, 'AUX', &
1600  this%tsManager, this%iprpak, &
1601  this%auxname(jj))
1602  end do
1603  !
1604  nlak = nlak + 1
1605  end do
1606  !
1607  ! -- check for duplicate or missing lakes
1608  do n = 1, this%ncv
1609  if (nboundchk(n) == 0) then
1610  write (errmsg, '(a,1x,i0)') 'No data specified for feature', n
1611  call store_error(errmsg)
1612  else if (nboundchk(n) > 1) then
1613  write (errmsg, '(a,1x,i0,1x,a,1x,i0,1x,a)') &
1614  'Data for feature', n, 'specified', nboundchk(n), 'times'
1615  call store_error(errmsg)
1616  end if
1617  end do
1618  !
1619  write (this%iout, '(1x,a)') &
1620  'END OF '//trim(adjustl(this%text))//' PACKAGEDATA'
1621  else
1622  call store_error('Required packagedata block not found.')
1623  end if
1624  !
1625  ! -- terminate if any errors were detected
1626  if (count_errors() > 0) then
1627  call this%parser%StoreErrorUnit()
1628  end if
1629  !
1630  ! -- deallocate local storage for aux variables
1631  if (this%naux > 0) then
1632  deallocate (caux)
1633  end if
1634  !
1635  ! -- deallocate local storage for nboundchk
1636  deallocate (nboundchk)
1637  end subroutine apt_read_cvs
1638 
1639  !> @brief Read the initial parameters for an advanced package
1640  !<
1641  subroutine apt_read_initial_attr(this)
1642  use constantsmodule, only: linelength
1643  use budgetmodule, only: budget_cr
1644  ! -- dummy
1645  class(tspapttype), intent(inout) :: this
1646  ! -- local
1647  !character(len=LINELENGTH) :: text
1648  integer(I4B) :: j, n
1649 
1650  !
1651  ! -- initialize xnewpak and set feature concentration (or temperature)
1652  ! -- todo: this should be a time series?
1653  do n = 1, this%ncv
1654  this%xnewpak(n) = this%strt(n)
1655  !
1656  ! -- todo: read aux
1657  !
1658  ! -- todo: read boundname
1659  end do
1660  !
1661  ! -- initialize status (iboundpak) of lakes to active
1662  do n = 1, this%ncv
1663  if (this%status(n) == 'CONSTANT') then
1664  this%iboundpak(n) = -1
1665  else if (this%status(n) == 'INACTIVE') then
1666  this%iboundpak(n) = 0
1667  else if (this%status(n) == 'ACTIVE ') then
1668  this%iboundpak(n) = 1
1669  end if
1670  end do
1671  !
1672  ! -- set boundname for each connection
1673  if (this%inamedbound /= 0) then
1674  do j = 1, this%flowbudptr%budterm(this%idxbudgwf)%nlist
1675  n = this%flowbudptr%budterm(this%idxbudgwf)%id1(j)
1676  this%boundname(j) = this%featname(n)
1677  end do
1678  end if
1679  !
1680  ! -- copy boundname into boundname_cst
1681  call this%copy_boundname()
1682  end subroutine apt_read_initial_attr
1683 
1684  !> @brief Add terms specific to advanced package transport to the explicit
1685  !! solve
1686  !!
1687  !! Explicit solve for concentration (or temperature) in advaced package
1688  !! features, which is an alternative to the iterative implicit solve.
1689  !<
1690  subroutine apt_solve(this)
1691  use constantsmodule, only: linelength
1692  ! -- dummy
1693  class(tspapttype) :: this
1694  ! -- local
1695  integer(I4B) :: n, j, igwfnode
1696  integer(I4B) :: n1, n2
1697  real(DP) :: rrate
1698  real(DP) :: ctmp
1699  real(DP) :: c1, qbnd
1700  real(DP) :: hcofval, rhsval
1701  !
1702  ! -- initialize dbuff
1703  do n = 1, this%ncv
1704  this%dbuff(n) = dzero
1705  end do
1706  !
1707  ! -- call the individual package routines to add terms specific to the
1708  ! advanced transport package
1709  call this%pak_solve()
1710  !
1711  ! -- add to mover contribution
1712  if (this%idxbudtmvr /= 0) then
1713  do j = 1, this%flowbudptr%budterm(this%idxbudtmvr)%nlist
1714  call this%apt_tmvr_term(j, n1, n2, rrate)
1715  this%dbuff(n1) = this%dbuff(n1) + rrate
1716  end do
1717  end if
1718  !
1719  ! -- add from mover contribution
1720  if (this%idxbudfmvr /= 0) then
1721  do n1 = 1, size(this%qmfrommvr)
1722  rrate = this%qmfrommvr(n1) ! Will be in terms of energy for heat transport
1723  this%dbuff(n1) = this%dbuff(n1) + rrate
1724  end do
1725  end if
1726  !
1727  ! -- go through each gwf connection and accumulate
1728  ! total mass (or energy) in dbuff mass
1729  do j = 1, this%flowbudptr%budterm(this%idxbudgwf)%nlist
1730  n = this%flowbudptr%budterm(this%idxbudgwf)%id1(j)
1731  this%hcof(j) = dzero
1732  this%rhs(j) = dzero
1733  igwfnode = this%flowbudptr%budterm(this%idxbudgwf)%id2(j)
1734  qbnd = this%flowbudptr%budterm(this%idxbudgwf)%flow(j)
1735  if (qbnd <= dzero) then
1736  ctmp = this%xnewpak(n)
1737  this%rhs(j) = qbnd * ctmp * this%eqnsclfac
1738  else
1739  ctmp = this%xnew(igwfnode)
1740  this%hcof(j) = -qbnd * this%eqnsclfac
1741  end if
1742  c1 = qbnd * ctmp * this%eqnsclfac
1743  this%dbuff(n) = this%dbuff(n) + c1
1744  end do
1745  !
1746  ! -- go through each "within apt-apt" connection (e.g., lak-lak) and
1747  ! accumulate total mass (or energy) in dbuff mass
1748  if (this%idxbudfjf /= 0) then
1749  do j = 1, this%flowbudptr%budterm(this%idxbudfjf)%nlist
1750  call this%apt_fjf_term(j, n1, n2, rrate)
1751  c1 = rrate
1752  this%dbuff(n1) = this%dbuff(n1) + c1
1753  end do
1754  end if
1755  !
1756  ! -- calculate the feature concentration/temperature
1757  do n = 1, this%ncv
1758  call this%apt_stor_term(n, n1, n2, rrate, rhsval, hcofval)
1759  !
1760  ! -- at this point, dbuff has q * c for all sources, so now
1761  ! add Vold / dt * Cold
1762  this%dbuff(n) = this%dbuff(n) - rhsval
1763  !
1764  ! -- Now to calculate c, need to divide dbuff by hcofval
1765  c1 = -this%dbuff(n) / hcofval
1766  if (this%iboundpak(n) > 0) then
1767  this%xnewpak(n) = c1
1768  end if
1769  end do
1770  end subroutine apt_solve
1771 
1772  !> @brief Add terms specific to advanced package transport features to the
1773  !! explicit solve routine
1774  !!
1775  !! This routine must be overridden by the specific apt package
1776  !<
1777  subroutine pak_solve(this)
1778  ! -- dummy
1779  class(tspapttype) :: this
1780  ! -- local
1781  !
1782  ! -- this routine should never be called
1783  call store_error('Program error: pak_solve not implemented.', &
1784  terminate=.true.)
1785  end subroutine pak_solve
1786 
1787  !> @brief Accumulate constant concentration (or temperature) terms for budget
1788  !<
1789  subroutine apt_accumulate_ccterm(this, ilak, rrate, ccratin, ccratout)
1790  ! -- dummy
1791  class(tspapttype) :: this
1792  integer(I4B), intent(in) :: ilak
1793  real(DP), intent(in) :: rrate
1794  real(DP), intent(inout) :: ccratin
1795  real(DP), intent(inout) :: ccratout
1796  ! -- locals
1797  real(DP) :: q
1798  ! format
1799  ! code
1800  !
1801  if (this%iboundpak(ilak) < 0) then
1802  q = -rrate
1803  this%ccterm(ilak) = this%ccterm(ilak) + q
1804  !
1805  ! -- See if flow is into lake or out of lake.
1806  if (q < dzero) then
1807  !
1808  ! -- Flow is out of lake subtract rate from ratout.
1809  ccratout = ccratout - q
1810  else
1811  !
1812  ! -- Flow is into lake; add rate to ratin.
1813  ccratin = ccratin + q
1814  end if
1815  end if
1816  end subroutine apt_accumulate_ccterm
1817 
1818  !> @brief Define the list heading that is written to iout when PRINT_INPUT
1819  !! option is used.
1820  !<
1821  subroutine define_listlabel(this)
1822  class(tspapttype), intent(inout) :: this
1823  !
1824  ! -- create the header list label
1825  this%listlabel = trim(this%filtyp)//' NO.'
1826  if (this%dis%ndim == 3) then
1827  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'LAYER'
1828  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'ROW'
1829  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'COL'
1830  elseif (this%dis%ndim == 2) then
1831  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'LAYER'
1832  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'CELL2D'
1833  else
1834  write (this%listlabel, '(a, a7)') trim(this%listlabel), 'NODE'
1835  end if
1836  write (this%listlabel, '(a, a16)') trim(this%listlabel), 'STRESS RATE'
1837  if (this%inamedbound == 1) then
1838  write (this%listlabel, '(a, a16)') trim(this%listlabel), 'BOUNDARY NAME'
1839  end if
1840  end subroutine define_listlabel
1841 
1842  !> @brief Set pointers to model arrays and variables so that a package has
1843  !! access to these items.
1844  !<
1845  subroutine apt_set_pointers(this, neq, ibound, xnew, xold, flowja)
1846  class(tspapttype) :: this
1847  integer(I4B), pointer :: neq
1848  integer(I4B), dimension(:), pointer, contiguous :: ibound
1849  real(DP), dimension(:), pointer, contiguous :: xnew
1850  real(DP), dimension(:), pointer, contiguous :: xold
1851  real(DP), dimension(:), pointer, contiguous :: flowja
1852  ! -- local
1853  integer(I4B) :: istart, iend
1854  !
1855  ! -- call base BndType set_pointers
1856  call this%BndType%set_pointers(neq, ibound, xnew, xold, flowja)
1857  !
1858  ! -- Set the pointers
1859  !
1860  ! -- set package pointers
1861  if (this%imatrows /= 0) then
1862  istart = this%dis%nodes + this%ioffset + 1
1863  iend = istart + this%ncv - 1
1864  this%iboundpak => this%ibound(istart:iend)
1865  this%xnewpak => this%xnew(istart:iend)
1866  end if
1867  end subroutine apt_set_pointers
1868 
1869  !> @brief Return the feature new volume and old volume
1870  !<
1871  subroutine get_volumes(this, icv, vnew, vold, delt)
1872  ! -- modules
1873  ! -- dummy
1874  class(tspapttype) :: this
1875  integer(I4B), intent(in) :: icv
1876  real(DP), intent(inout) :: vnew, vold
1877  real(DP), intent(in) :: delt
1878  ! -- local
1879  real(DP) :: qss
1880  !
1881  ! -- get volumes
1882  vold = dzero
1883  vnew = vold
1884  if (this%idxbudsto /= 0) then
1885  qss = this%flowbudptr%budterm(this%idxbudsto)%flow(icv)
1886  vnew = this%flowbudptr%budterm(this%idxbudsto)%auxvar(1, icv)
1887  vold = vnew + qss * delt
1888  end if
1889  end subroutine get_volumes
1890 
1891  !> @brief Function to return the number of budget terms just for this package
1892  !!
1893  !! This function must be overridden.
1894  !<
1895  function pak_get_nbudterms(this) result(nbudterms)
1896  ! -- modules
1897  ! -- dummy
1898  class(tspapttype) :: this
1899  ! -- return
1900  integer(I4B) :: nbudterms
1901  ! -- local
1902  !
1903  ! -- this routine should never be called
1904  call store_error('Program error: pak_get_nbudterms not implemented.', &
1905  terminate=.true.)
1906  nbudterms = 0
1907  end function pak_get_nbudterms
1908 
1909  !> @brief Set up the budget object that stores advanced package flow terms
1910  !<
1911  subroutine apt_setup_budobj(this)
1912  ! -- modules
1913  use constantsmodule, only: lenbudtxt
1914  ! -- dummy
1915  class(tspapttype) :: this
1916  ! -- local
1917  integer(I4B) :: nbudterm
1918  integer(I4B) :: nlen
1919  integer(I4B) :: n, n1, n2
1920  integer(I4B) :: maxlist, naux
1921  integer(I4B) :: idx
1922  logical :: ordered_id1
1923  real(DP) :: q
1924  character(len=LENBUDTXT) :: bddim_opt
1925  character(len=LENBUDTXT) :: text, textt
1926  character(len=LENBUDTXT), dimension(1) :: auxtxt
1927  !
1928  ! -- initialize nbudterm
1929  nbudterm = 0
1930  !
1931  ! -- Determine if there are flow-ja-face terms
1932  nlen = 0
1933  if (this%idxbudfjf /= 0) then
1934  nlen = this%flowbudptr%budterm(this%idxbudfjf)%maxlist
1935  end if
1936  !
1937  ! -- Determine the number of budget terms associated with apt.
1938  ! These are fixed for the simulation and cannot change
1939  !
1940  ! -- add one if flow-ja-face present
1941  if (this%idxbudfjf /= 0) nbudterm = nbudterm + 1
1942  !
1943  ! -- All the APT packages have GWF, STORAGE, and CONSTANT
1944  nbudterm = nbudterm + 3
1945  !
1946  ! -- add terms for the specific package
1947  nbudterm = nbudterm + this%pak_get_nbudterms()
1948  !
1949  ! -- add for mover terms and auxiliary
1950  if (this%idxbudtmvr /= 0) nbudterm = nbudterm + 1
1951  if (this%idxbudfmvr /= 0) nbudterm = nbudterm + 1
1952  if (this%naux > 0) nbudterm = nbudterm + 1
1953  !
1954  ! -- set up budobj
1955  call budgetobject_cr(this%budobj, this%packName)
1956  !
1957  bddim_opt = this%depvarunitabbrev
1958  call this%budobj%budgetobject_df(this%ncv, nbudterm, 0, 0, &
1959  bddim_opt=bddim_opt, ibudcsv=this%ibudcsv)
1960  idx = 0
1961  !
1962  ! -- Go through and set up each budget term
1963  if (nlen > 0) then
1964  text = ' FLOW-JA-FACE'
1965  idx = idx + 1
1966  maxlist = this%flowbudptr%budterm(this%idxbudfjf)%maxlist
1967  naux = 0
1968  ordered_id1 = this%flowbudptr%budterm(this%idxbudfjf)%ordered_id1
1969  call this%budobj%budterm(idx)%initialize(text, &
1970  this%name_model, &
1971  this%packName, &
1972  this%name_model, &
1973  this%packName, &
1974  maxlist, .false., .false., &
1975  naux, ordered_id1=ordered_id1)
1976  !
1977  ! -- store outlet connectivity
1978  call this%budobj%budterm(idx)%reset(maxlist)
1979  q = dzero
1980  do n = 1, maxlist
1981  n1 = this%flowbudptr%budterm(this%idxbudfjf)%id1(n)
1982  n2 = this%flowbudptr%budterm(this%idxbudfjf)%id2(n)
1983  call this%budobj%budterm(idx)%update_term(n1, n2, q)
1984  end do
1985  end if
1986  !
1987  ! --
1988  text = ' GWF'
1989  idx = idx + 1
1990  maxlist = this%flowbudptr%budterm(this%idxbudgwf)%maxlist
1991  naux = 0
1992  call this%budobj%budterm(idx)%initialize(text, &
1993  this%name_model, &
1994  this%packName, &
1995  this%name_model, &
1996  this%name_model, &
1997  maxlist, .false., .true., &
1998  naux)
1999  call this%budobj%budterm(idx)%reset(maxlist)
2000  q = dzero
2001  do n = 1, maxlist
2002  n1 = this%flowbudptr%budterm(this%idxbudgwf)%id1(n)
2003  n2 = this%flowbudptr%budterm(this%idxbudgwf)%id2(n)
2004  call this%budobj%budterm(idx)%update_term(n1, n2, q)
2005  end do
2006  !
2007  ! -- Reserve space for the package specific terms
2008  this%idxprepak = idx
2009  call this%pak_setup_budobj(idx)
2010  this%idxlastpak = idx
2011  !
2012  ! --
2013  text = ' STORAGE'
2014  idx = idx + 1
2015  maxlist = this%flowbudptr%budterm(this%idxbudsto)%maxlist
2016  naux = 1
2017  write (textt, '(a)') str_pad_left(this%depvarunit, 16)
2018  auxtxt(1) = textt ! ' MASS' or ' ENERGY'
2019  call this%budobj%budterm(idx)%initialize(text, &
2020  this%name_model, &
2021  this%packName, &
2022  this%name_model, &
2023  this%packName, &
2024  maxlist, .false., .false., &
2025  naux, auxtxt)
2026  if (this%idxbudtmvr /= 0) then
2027  !
2028  ! --
2029  text = ' TO-MVR'
2030  idx = idx + 1
2031  maxlist = this%flowbudptr%budterm(this%idxbudtmvr)%maxlist
2032  naux = 0
2033  ordered_id1 = this%flowbudptr%budterm(this%idxbudtmvr)%ordered_id1
2034  call this%budobj%budterm(idx)%initialize(text, &
2035  this%name_model, &
2036  this%packName, &
2037  this%name_model, &
2038  this%packName, &
2039  maxlist, .false., .false., &
2040  naux, ordered_id1=ordered_id1)
2041  end if
2042  if (this%idxbudfmvr /= 0) then
2043  !
2044  ! --
2045  text = ' FROM-MVR'
2046  idx = idx + 1
2047  maxlist = this%ncv
2048  naux = 0
2049  call this%budobj%budterm(idx)%initialize(text, &
2050  this%name_model, &
2051  this%packName, &
2052  this%name_model, &
2053  this%packName, &
2054  maxlist, .false., .false., &
2055  naux)
2056  end if
2057  !
2058  ! --
2059  text = ' CONSTANT'
2060  idx = idx + 1
2061  maxlist = this%ncv
2062  naux = 0
2063  call this%budobj%budterm(idx)%initialize(text, &
2064  this%name_model, &
2065  this%packName, &
2066  this%name_model, &
2067  this%packName, &
2068  maxlist, .false., .false., &
2069  naux)
2070 
2071  !
2072  ! --
2073  naux = this%naux
2074  if (naux > 0) then
2075  !
2076  ! --
2077  text = ' AUXILIARY'
2078  idx = idx + 1
2079  maxlist = this%ncv
2080  call this%budobj%budterm(idx)%initialize(text, &
2081  this%name_model, &
2082  this%packName, &
2083  this%name_model, &
2084  this%packName, &
2085  maxlist, .false., .false., &
2086  naux, this%auxname)
2087  end if
2088  !
2089  ! -- if flow for each control volume are written to the listing file
2090  if (this%iprflow /= 0) then
2091  call this%budobj%flowtable_df(this%iout)
2092  end if
2093  end subroutine apt_setup_budobj
2094 
2095  !> @brief Set up a budget object that stores an advanced package flows
2096  !!
2097  !! Individual packages set up their budget terms. Must be overridden.
2098  !<
2099  subroutine pak_setup_budobj(this, idx)
2100  ! -- modules
2101  ! -- dummy
2102  class(tspapttype) :: this
2103  integer(I4B), intent(inout) :: idx
2104  ! -- local
2105  !
2106  ! -- this routine should never be called
2107  call store_error('Program error: pak_setup_budobj not implemented.', &
2108  terminate=.true.)
2109  end subroutine pak_setup_budobj
2110 
2111  !> @brief Copy flow terms into this%budobj
2112  !<
2113  subroutine apt_fill_budobj(this, x, flowja)
2114  ! -- modules
2115  use tdismodule, only: delt
2116  ! -- dummy
2117  class(tspapttype) :: this
2118  real(DP), dimension(:), intent(in) :: x
2119  real(DP), dimension(:), contiguous, intent(inout) :: flowja
2120  ! -- local
2121  integer(I4B) :: naux
2122  real(DP), dimension(:), allocatable :: auxvartmp
2123  integer(I4B) :: i, j, n1, n2
2124  integer(I4B) :: idx
2125  integer(I4B) :: nlen
2126  integer(I4B) :: nlist
2127  integer(I4B) :: igwfnode
2128  real(DP) :: q
2129  real(DP) :: v0, v1
2130  real(DP) :: ccratin, ccratout
2131  ! -- formats
2132  !
2133  ! -- initialize counter
2134  idx = 0
2135  !
2136  ! -- initialize ccterm, which is used to sum up all mass (or energy) flows
2137  ! into a constant concentration (or temperature) cell
2138  ccratin = dzero
2139  ccratout = dzero
2140  do n1 = 1, this%ncv
2141  this%ccterm(n1) = dzero
2142  end do
2143  !
2144  ! -- FLOW JA FACE
2145  nlen = 0
2146  if (this%idxbudfjf /= 0) then
2147  nlen = this%flowbudptr%budterm(this%idxbudfjf)%maxlist
2148  end if
2149  if (nlen > 0) then
2150  idx = idx + 1
2151  nlist = this%flowbudptr%budterm(this%idxbudfjf)%maxlist
2152  call this%budobj%budterm(idx)%reset(nlist)
2153  q = dzero
2154  do j = 1, nlist
2155  call this%apt_fjf_term(j, n1, n2, q)
2156  call this%budobj%budterm(idx)%update_term(n1, n2, q)
2157  call this%apt_accumulate_ccterm(n1, q, ccratin, ccratout)
2158  end do
2159  end if
2160  !
2161  ! -- GWF (LEAKAGE)
2162  idx = idx + 1
2163  call this%budobj%budterm(idx)%reset(this%maxbound)
2164  do j = 1, this%flowbudptr%budterm(this%idxbudgwf)%nlist
2165  q = dzero
2166  n1 = this%flowbudptr%budterm(this%idxbudgwf)%id1(j)
2167  if (this%iboundpak(n1) /= 0) then
2168  igwfnode = this%flowbudptr%budterm(this%idxbudgwf)%id2(j)
2169  q = this%hcof(j) * x(igwfnode) - this%rhs(j)
2170  q = -q ! flip sign so relative to advanced package feature
2171  end if
2172  call this%budobj%budterm(idx)%update_term(n1, igwfnode, q)
2173  call this%apt_accumulate_ccterm(n1, q, ccratin, ccratout)
2174  end do
2175  !
2176  ! -- skip individual package terms for now and process them last
2177  ! -- in case they depend on the other terms (as for uze)
2178  idx = this%idxlastpak
2179  !
2180  ! -- STORAGE
2181  idx = idx + 1
2182  call this%budobj%budterm(idx)%reset(this%ncv)
2183  allocate (auxvartmp(1))
2184  do n1 = 1, this%ncv
2185  call this%get_volumes(n1, v1, v0, delt)
2186  auxvartmp(1) = v1 * this%xnewpak(n1) ! Note: When GWE is added, check if this needs a factor of eqnsclfac
2187  q = this%qsto(n1)
2188  call this%budobj%budterm(idx)%update_term(n1, n1, q, auxvartmp)
2189  call this%apt_accumulate_ccterm(n1, q, ccratin, ccratout)
2190  end do
2191  deallocate (auxvartmp)
2192  !
2193  ! -- TO MOVER
2194  if (this%idxbudtmvr /= 0) then
2195  idx = idx + 1
2196  nlist = this%flowbudptr%budterm(this%idxbudtmvr)%nlist
2197  call this%budobj%budterm(idx)%reset(nlist)
2198  do j = 1, nlist
2199  call this%apt_tmvr_term(j, n1, n2, q)
2200  call this%budobj%budterm(idx)%update_term(n1, n2, q)
2201  call this%apt_accumulate_ccterm(n1, q, ccratin, ccratout)
2202  end do
2203  end if
2204  !
2205  ! -- FROM MOVER
2206  if (this%idxbudfmvr /= 0) then
2207  idx = idx + 1
2208  nlist = this%ncv
2209  call this%budobj%budterm(idx)%reset(nlist)
2210  do j = 1, nlist
2211  call this%apt_fmvr_term(j, n1, n2, q)
2212  call this%budobj%budterm(idx)%update_term(n1, n1, q)
2213  call this%apt_accumulate_ccterm(n1, q, ccratin, ccratout)
2214  end do
2215  end if
2216  !
2217  ! -- CONSTANT FLOW
2218  idx = idx + 1
2219  call this%budobj%budterm(idx)%reset(this%ncv)
2220  do n1 = 1, this%ncv
2221  q = this%ccterm(n1)
2222  call this%budobj%budterm(idx)%update_term(n1, n1, q)
2223  end do
2224  !
2225  ! -- AUXILIARY VARIABLES
2226  naux = this%naux
2227  if (naux > 0) then
2228  idx = idx + 1
2229  allocate (auxvartmp(naux))
2230  call this%budobj%budterm(idx)%reset(this%ncv)
2231  do n1 = 1, this%ncv
2232  q = dzero
2233  do i = 1, naux
2234  auxvartmp(i) = this%lauxvar(i, n1)
2235  end do
2236  call this%budobj%budterm(idx)%update_term(n1, n1, q, auxvartmp)
2237  end do
2238  deallocate (auxvartmp)
2239  end if
2240  !
2241  ! -- individual package terms processed last
2242  idx = this%idxprepak
2243  call this%pak_fill_budobj(idx, x, flowja, ccratin, ccratout)
2244  !
2245  ! --Terms are filled, now accumulate them for this time step
2246  call this%budobj%accumulate_terms()
2247  end subroutine apt_fill_budobj
2248 
2249  !> @brief Copy flow terms into this%budobj, must be overridden
2250  !<
2251  subroutine pak_fill_budobj(this, idx, x, flowja, ccratin, ccratout)
2252  ! -- modules
2253  ! -- dummy
2254  class(tspapttype) :: this
2255  integer(I4B), intent(inout) :: idx
2256  real(DP), dimension(:), intent(in) :: x
2257  real(DP), dimension(:), contiguous, intent(inout) :: flowja
2258  real(DP), intent(inout) :: ccratin
2259  real(DP), intent(inout) :: ccratout
2260  ! -- local
2261  ! -- formats
2262  !
2263  ! -- this routine should never be called
2264  call store_error('Program error: pak_fill_budobj not implemented.', &
2265  terminate=.true.)
2266  end subroutine pak_fill_budobj
2267 
2268  !> @brief Account for mass or energy storage in advanced package features
2269  !<
2270  subroutine apt_stor_term(this, ientry, n1, n2, rrate, &
2271  rhsval, hcofval)
2272  use tdismodule, only: delt
2273  class(tspapttype) :: this
2274  integer(I4B), intent(in) :: ientry
2275  integer(I4B), intent(inout) :: n1
2276  integer(I4B), intent(inout) :: n2
2277  real(DP), intent(inout), optional :: rrate
2278  real(DP), intent(inout), optional :: rhsval
2279  real(DP), intent(inout), optional :: hcofval
2280  real(DP) :: v0, v1
2281  real(DP) :: c0, c1
2282  !
2283  n1 = ientry
2284  n2 = ientry
2285  call this%get_volumes(n1, v1, v0, delt)
2286  c0 = this%xoldpak(n1)
2287  c1 = this%xnewpak(n1)
2288  if (present(rrate)) then
2289  rrate = (-c1 * v1 / delt + c0 * v0 / delt) * this%eqnsclfac
2290  end if
2291  if (present(rhsval)) rhsval = -c0 * v0 * this%eqnsclfac / delt
2292  if (present(hcofval)) hcofval = -v1 * this%eqnsclfac / delt
2293  end subroutine apt_stor_term
2294 
2295  !> @brief Account for mass or energy transferred to the MVR package
2296  !<
2297  subroutine apt_tmvr_term(this, ientry, n1, n2, rrate, &
2298  rhsval, hcofval)
2299  ! -- modules
2300  ! -- dummy
2301  class(tspapttype) :: this
2302  integer(I4B), intent(in) :: ientry
2303  integer(I4B), intent(inout) :: n1
2304  integer(I4B), intent(inout) :: n2
2305  real(DP), intent(inout), optional :: rrate
2306  real(DP), intent(inout), optional :: rhsval
2307  real(DP), intent(inout), optional :: hcofval
2308  ! -- local
2309  real(DP) :: qbnd
2310  real(DP) :: ctmp
2311  !
2312  ! -- Calculate MVR-related terms
2313  n1 = this%flowbudptr%budterm(this%idxbudtmvr)%id1(ientry)
2314  n2 = this%flowbudptr%budterm(this%idxbudtmvr)%id2(ientry)
2315  qbnd = this%flowbudptr%budterm(this%idxbudtmvr)%flow(ientry)
2316  ctmp = this%xnewpak(n1)
2317  if (present(rrate)) rrate = ctmp * qbnd * this%eqnsclfac
2318  if (present(rhsval)) rhsval = dzero
2319  if (present(hcofval)) hcofval = qbnd * this%eqnsclfac
2320  end subroutine apt_tmvr_term
2321 
2322  !> @brief Account for mass or energy transferred to this package from the
2323  !! MVR package
2324  !<
2325  subroutine apt_fmvr_term(this, ientry, n1, n2, rrate, &
2326  rhsval, hcofval)
2327  ! -- modules
2328  ! -- dummy
2329  class(tspapttype) :: this
2330  integer(I4B), intent(in) :: ientry
2331  integer(I4B), intent(inout) :: n1
2332  integer(I4B), intent(inout) :: n2
2333  real(DP), intent(inout), optional :: rrate
2334  real(DP), intent(inout), optional :: rhsval
2335  real(DP), intent(inout), optional :: hcofval
2336  !
2337  ! -- Calculate MVR-related terms
2338  n1 = ientry
2339  n2 = n1
2340  if (present(rrate)) rrate = this%qmfrommvr(n1) ! NOTE: When bringing in GWE, ensure this is in terms of energy. Might need to apply eqnsclfac here.
2341  if (present(rhsval)) rhsval = this%qmfrommvr(n1)
2342  if (present(hcofval)) hcofval = dzero
2343  end subroutine apt_fmvr_term
2344 
2345  !> @brief Go through each "within apt-apt" connection (e.g., lkt-lkt, or
2346  !! sft-sft) and accumulate total mass (or energy) in dbuff mass
2347  !<
2348  subroutine apt_fjf_term(this, ientry, n1, n2, rrate, &
2349  rhsval, hcofval)
2350  ! -- modules
2351  ! -- dummy
2352  class(tspapttype) :: this
2353  integer(I4B), intent(in) :: ientry
2354  integer(I4B), intent(inout) :: n1
2355  integer(I4B), intent(inout) :: n2
2356  real(DP), intent(inout), optional :: rrate
2357  real(DP), intent(inout), optional :: rhsval
2358  real(DP), intent(inout), optional :: hcofval
2359  ! -- local
2360  real(DP) :: qbnd
2361  real(DP) :: ctmp
2362  !
2363  n1 = this%flowbudptr%budterm(this%idxbudfjf)%id1(ientry)
2364  n2 = this%flowbudptr%budterm(this%idxbudfjf)%id2(ientry)
2365  qbnd = this%flowbudptr%budterm(this%idxbudfjf)%flow(ientry)
2366  if (qbnd <= 0) then
2367  ctmp = this%xnewpak(n1)
2368  else
2369  ctmp = this%xnewpak(n2)
2370  end if
2371  if (present(rrate)) rrate = ctmp * qbnd * this%eqnsclfac
2372  if (present(rhsval)) rhsval = -rrate * this%eqnsclfac
2373  if (present(hcofval)) hcofval = dzero
2374  end subroutine apt_fjf_term
2375 
2376  !> @brief Copy concentrations (or temperatures) into flow package aux
2377  !! variable
2378  !<
2379  subroutine apt_copy2flowp(this)
2380  ! -- modules
2381  ! -- dummy
2382  class(tspapttype) :: this
2383  ! -- local
2384  integer(I4B) :: n, j
2385  !
2386  ! -- copy
2387  if (this%iauxfpconc /= 0) then
2388  !
2389  ! -- go through each apt-gwf connection
2390  do j = 1, this%flowbudptr%budterm(this%idxbudgwf)%nlist
2391  !
2392  ! -- set n to feature number and process if active feature
2393  n = this%flowbudptr%budterm(this%idxbudgwf)%id1(j)
2394  this%flowpackagebnd%auxvar(this%iauxfpconc, j) = this%xnewpak(n)
2395  end do
2396  end if
2397  end subroutine apt_copy2flowp
2398 
2399  !> @brief Determine whether an obs type is supported
2400  !!
2401  !! This function:
2402  !! - returns true if APT package supports named observation.
2403  !! - overrides BndType%bnd_obs_supported()
2404  !<
2405  logical function apt_obs_supported(this)
2406  ! -- modules
2407  ! -- dummy
2408  class(tspapttype) :: this
2409  !
2410  ! -- Set to true
2411  apt_obs_supported = .true.
2412  end function apt_obs_supported
2413 
2414  !> @brief Define observation type
2415  !!
2416  !! This routine:
2417  !! - stores observation types supported by APT package.
2418  !! - overrides BndType%bnd_df_obs
2419  !<
2420  subroutine apt_df_obs(this)
2421  ! -- modules
2422  ! -- dummy
2423  class(tspapttype) :: this
2424  ! -- local
2425  !
2426  ! -- call additional specific observations for lkt, sft, mwt, and uzt
2427  call this%pak_df_obs()
2428  end subroutine apt_df_obs
2429 
2430  !> @brief Define apt observation type
2431  !!
2432  !! This routine:
2433  !! - stores observations supported by the APT package
2434  !! - must be overridden by child class
2435  subroutine pak_df_obs(this)
2436  ! -- modules
2437  ! -- dummy
2438  class(tspapttype) :: this
2439  ! -- local
2440  !
2441  ! -- this routine should never be called
2442  call store_error('Program error: pak_df_obs not implemented.', &
2443  terminate=.true.)
2444  end subroutine pak_df_obs
2445 
2446  !> @brief Process package specific obs
2447  !!
2448  !! Method to process specific observations for this package.
2449  !<
2450  subroutine pak_rp_obs(this, obsrv, found)
2451  ! -- dummy
2452  class(tspapttype), intent(inout) :: this !< package class
2453  type(observetype), intent(inout) :: obsrv !< observation object
2454  logical, intent(inout) :: found !< indicate whether observation was found
2455  ! -- local
2456  !
2457  ! -- this routine should never be called
2458  call store_error('Program error: pak_rp_obs not implemented.', &
2459  terminate=.true.)
2460  end subroutine pak_rp_obs
2461 
2462  !> @brief Prepare observation
2463  !!
2464  !! Find the indices for this observation assuming they are indexed by
2465  !! feature number
2466  !<
2467  subroutine rp_obs_byfeature(this, obsrv)
2468  class(tspapttype), intent(inout) :: this !< object
2469  type(observetype), intent(inout) :: obsrv !< observation
2470  integer(I4B) :: nn1
2471  integer(I4B) :: j
2472  logical :: jfound
2473  character(len=*), parameter :: fmterr = &
2474  "('Boundary ', a, ' for observation ', a, &
2475  &' is invalid in package ', a)"
2476  nn1 = obsrv%NodeNumber
2477  if (nn1 == namedboundflag) then
2478  jfound = .false.
2479  do j = 1, this%ncv
2480  if (this%featname(j) == obsrv%FeatureName) then
2481  jfound = .true.
2482  call obsrv%AddObsIndex(j)
2483  end if
2484  end do
2485  if (.not. jfound) then
2486  write (errmsg, fmterr) trim(obsrv%FeatureName), trim(obsrv%Name), &
2487  trim(this%packName)
2488  call store_error(errmsg)
2489  end if
2490  else
2491  !
2492  ! -- ensure nn1 is > 0 and < ncv
2493  if (nn1 < 0 .or. nn1 > this%ncv) then
2494  write (errmsg, '(7a, i0, a, i0, a)') &
2495  'Observation ', trim(obsrv%Name), ' of type ', &
2496  trim(adjustl(obsrv%ObsTypeId)), ' in package ', &
2497  trim(this%packName), ' was assigned ID = ', nn1, &
2498  '. ID must be >= 1 and <= ', this%ncv, '.'
2499  call store_error(errmsg)
2500  end if
2501  call obsrv%AddObsIndex(nn1)
2502  end if
2503  end subroutine rp_obs_byfeature
2504 
2505  !> @brief Prepare observation
2506  !!
2507  !! Find the indices for this observation assuming they are first indexed
2508  !! by feature number and secondly by a connection number
2509  !<
2510  subroutine rp_obs_budterm(this, obsrv, budterm)
2511  class(tspapttype), intent(inout) :: this !< object
2512  type(observetype), intent(inout) :: obsrv !< observation
2513  type(budgettermtype), intent(in) :: budterm !< budget term
2514  integer(I4B) :: nn1
2515  integer(I4B) :: iconn
2516  integer(I4B) :: icv
2517  integer(I4B) :: idx
2518  integer(I4B) :: j
2519  logical :: jfound
2520  character(len=*), parameter :: fmterr = &
2521  "('Boundary ', a, ' for observation ', a, &
2522  &' is invalid in package ', a)"
2523  nn1 = obsrv%NodeNumber
2524  if (nn1 == namedboundflag) then
2525  jfound = .false.
2526  do j = 1, budterm%nlist
2527  icv = budterm%id1(j)
2528  if (this%featname(icv) == obsrv%FeatureName) then
2529  jfound = .true.
2530  call obsrv%AddObsIndex(j)
2531  end if
2532  end do
2533  if (.not. jfound) then
2534  write (errmsg, fmterr) trim(obsrv%FeatureName), trim(obsrv%Name), &
2535  trim(this%packName)
2536  call store_error(errmsg)
2537  end if
2538  else
2539  !
2540  ! -- ensure nn1 is > 0 and < ncv
2541  if (nn1 < 0 .or. nn1 > this%ncv) then
2542  write (errmsg, '(7a, i0, a, i0, a)') &
2543  'Observation ', trim(obsrv%Name), ' of type ', &
2544  trim(adjustl(obsrv%ObsTypeId)), ' in package ', &
2545  trim(this%packName), ' was assigned ID = ', nn1, &
2546  '. ID must be >= 1 and <= ', this%ncv, '.'
2547  call store_error(errmsg)
2548  end if
2549  iconn = obsrv%NodeNumber2
2550  do j = 1, budterm%nlist
2551  if (budterm%id1(j) == nn1) then
2552  ! -- Look for the first occurrence of nn1, then set indxbnds
2553  ! to the iconn record after that
2554  idx = j + iconn - 1
2555  call obsrv%AddObsIndex(idx)
2556  exit
2557  end if
2558  end do
2559  if (idx < 1 .or. idx > budterm%nlist) then
2560  write (errmsg, '(7a, i0, a, i0, a)') &
2561  'Observation ', trim(obsrv%Name), ' of type ', &
2562  trim(adjustl(obsrv%ObsTypeId)), ' in package ', &
2563  trim(this%packName), ' specifies iconn = ', iconn, &
2564  ', but this is not a valid connection for ID ', nn1, '.'
2565  call store_error(errmsg)
2566  else if (budterm%id1(idx) /= nn1) then
2567  write (errmsg, '(7a, i0, a, i0, a)') &
2568  'Observation ', trim(obsrv%Name), ' of type ', &
2569  trim(adjustl(obsrv%ObsTypeId)), ' in package ', &
2570  trim(this%packName), ' specifies iconn = ', iconn, &
2571  ', but this is not a valid connection for ID ', nn1, '.'
2572  call store_error(errmsg)
2573  end if
2574  end if
2575  end subroutine rp_obs_budterm
2576 
2577  !> @brief Prepare observation
2578  !!
2579  !! Find the indices for this observation assuming they are first indexed
2580  !! by a feature number and secondly by a second feature number
2581  !<
2582  subroutine rp_obs_flowjaface(this, obsrv, budterm)
2583  class(tspapttype), intent(inout) :: this !< object
2584  type(observetype), intent(inout) :: obsrv !< observation
2585  type(budgettermtype), intent(in) :: budterm !< budget term
2586  integer(I4B) :: nn1
2587  integer(I4B) :: nn2
2588  integer(I4B) :: icv
2589  integer(I4B) :: j
2590  logical :: jfound
2591  character(len=*), parameter :: fmterr = &
2592  "('Boundary ', a, ' for observation ', a, &
2593  &' is invalid in package ', a)"
2594  nn1 = obsrv%NodeNumber
2595  if (nn1 == namedboundflag) then
2596  jfound = .false.
2597  do j = 1, budterm%nlist
2598  icv = budterm%id1(j)
2599  if (this%featname(icv) == obsrv%FeatureName) then
2600  jfound = .true.
2601  call obsrv%AddObsIndex(j)
2602  end if
2603  end do
2604  if (.not. jfound) then
2605  write (errmsg, fmterr) trim(obsrv%FeatureName), trim(obsrv%Name), &
2606  trim(this%packName)
2607  call store_error(errmsg)
2608  end if
2609  else
2610  !
2611  ! -- ensure nn1 is > 0 and < ncv
2612  if (nn1 < 0 .or. nn1 > this%ncv) then
2613  write (errmsg, '(7a, i0, a, i0, a)') &
2614  'Observation ', trim(obsrv%Name), ' of type ', &
2615  trim(adjustl(obsrv%ObsTypeId)), ' in package ', &
2616  trim(this%packName), ' was assigned ID = ', nn1, &
2617  '. ID must be >= 1 and <= ', this%ncv, '.'
2618  call store_error(errmsg)
2619  end if
2620  nn2 = obsrv%NodeNumber2
2621  !
2622  ! -- ensure nn2 is > 0 and < ncv
2623  if (nn2 < 0 .or. nn2 > this%ncv) then
2624  write (errmsg, '(7a, i0, a, i0, a)') &
2625  'Observation ', trim(obsrv%Name), ' of type ', &
2626  trim(adjustl(obsrv%ObsTypeId)), ' in package ', &
2627  trim(this%packName), ' was assigned ID2 = ', nn2, &
2628  '. ID must be >= 1 and <= ', this%ncv, '.'
2629  call store_error(errmsg)
2630  end if
2631  ! -- Look for nn1 and nn2 in id1 and id2
2632  jfound = .false.
2633  do j = 1, budterm%nlist
2634  if (budterm%id1(j) == nn1 .and. budterm%id2(j) == nn2) then
2635  call obsrv%AddObsIndex(j)
2636  jfound = .true.
2637  end if
2638  end do
2639  if (.not. jfound) then
2640  write (errmsg, '(7a, i0, a, i0, a)') &
2641  'Observation ', trim(obsrv%Name), ' of type ', &
2642  trim(adjustl(obsrv%ObsTypeId)), ' in package ', &
2643  trim(this%packName), &
2644  ' specifies a connection between feature ', nn1, &
2645  ' feature ', nn2, ', but these features are not connected.'
2646  call store_error(errmsg)
2647  end if
2648  end if
2649  end subroutine rp_obs_flowjaface
2650 
2651  !> @brief Read and prepare apt-related observations
2652  !!
2653  !! Method to process specific observations for an apt package
2654  !<
2655  subroutine apt_rp_obs(this)
2656  ! -- modules
2657  use tdismodule, only: kper
2658  ! -- dummy
2659  class(tspapttype), intent(inout) :: this
2660  ! -- local
2661  integer(I4B) :: i
2662  logical :: found
2663  class(observetype), pointer :: obsrv => null()
2664  !
2665  if (kper == 1) then
2666  do i = 1, this%obs%npakobs
2667  obsrv => this%obs%pakobs(i)%obsrv
2668  select case (obsrv%ObsTypeId)
2669  case ('CONCENTRATION', 'TEMPERATURE')
2670  call this%rp_obs_byfeature(obsrv)
2671  !
2672  ! -- catch non-cumulative observation assigned to observation defined
2673  ! by a boundname that is assigned to more than one element
2674  if (obsrv%indxbnds_count > 1) then
2675  write (errmsg, '(a, a, a, a)') &
2676  trim(adjustl(this%depvartype))// &
2677  ' for observation', trim(adjustl(obsrv%Name)), &
2678  ' must be assigned to a feature with a unique boundname.'
2679  call store_error(errmsg)
2680  end if
2681  case ('LKT', 'SFT', 'MWT', 'UZT', 'LKE', 'SFE', 'MWE', 'UZE')
2682  call this%rp_obs_budterm(obsrv, &
2683  this%flowbudptr%budterm(this%idxbudgwf))
2684  case ('FLOW-JA-FACE')
2685  if (this%idxbudfjf > 0) then
2686  call this%rp_obs_flowjaface(obsrv, &
2687  this%flowbudptr%budterm(this%idxbudfjf))
2688  else
2689  write (errmsg, '(7a)') &
2690  'Observation ', trim(obsrv%Name), ' of type ', &
2691  trim(adjustl(obsrv%ObsTypeId)), ' in package ', &
2692  trim(this%packName), &
2693  ' cannot be processed because there are no flow connections.'
2694  call store_error(errmsg)
2695  end if
2696  case ('STORAGE')
2697  call this%rp_obs_byfeature(obsrv)
2698  case ('CONSTANT')
2699  call this%rp_obs_byfeature(obsrv)
2700  case ('FROM-MVR')
2701  call this%rp_obs_byfeature(obsrv)
2702  case default
2703  !
2704  ! -- check the child package for any specific obs
2705  found = .false.
2706  call this%pak_rp_obs(obsrv, found)
2707  !
2708  ! -- if none found then terminate with an error
2709  if (.not. found) then
2710  errmsg = 'Unrecognized observation type "'// &
2711  trim(obsrv%ObsTypeId)//'" for '// &
2712  trim(adjustl(this%text))//' package '// &
2713  trim(this%packName)
2714  call store_error(errmsg, terminate=.true.)
2715  end if
2716  end select
2717 
2718  end do
2719  !
2720  ! -- check for errors
2721  if (count_errors() > 0) then
2722  call store_error_unit(this%obs%inunitobs)
2723  end if
2724  end if
2725  end subroutine apt_rp_obs
2726 
2727  !> @brief Calculate observation values
2728  !!
2729  !! Routine calculates observations common to SFT/LKT/MWT/UZT
2730  !! (or SFE/LKE/MWE/UZE) for as many TspAptType observations that are common
2731  !! among the advanced transport packages
2732  !<
2733  subroutine apt_bd_obs(this)
2734  ! -- modules
2735  ! -- dummy
2736  class(tspapttype) :: this
2737  ! -- local
2738  integer(I4B) :: i
2739  integer(I4B) :: igwfnode
2740  integer(I4B) :: j
2741  integer(I4B) :: jj
2742  integer(I4B) :: n
2743  integer(I4B) :: n1
2744  integer(I4B) :: n2
2745  real(DP) :: v
2746  type(observetype), pointer :: obsrv => null()
2747  logical :: found
2748  !
2749  ! -- Write simulated values for all Advanced Package observations
2750  if (this%obs%npakobs > 0) then
2751  call this%obs%obs_bd_clear()
2752  do i = 1, this%obs%npakobs
2753  obsrv => this%obs%pakobs(i)%obsrv
2754  do j = 1, obsrv%indxbnds_count
2755  v = dnodata
2756  jj = obsrv%indxbnds(j)
2757  select case (obsrv%ObsTypeId)
2758  case ('CONCENTRATION', 'TEMPERATURE')
2759  if (this%iboundpak(jj) /= 0) then
2760  v = this%xnewpak(jj)
2761  end if
2762  case ('LKT', 'SFT', 'MWT', 'UZT', 'LKE', 'SFE', 'MWE', 'UZE')
2763  n = this%flowbudptr%budterm(this%idxbudgwf)%id1(jj)
2764  if (this%iboundpak(n) /= 0) then
2765  igwfnode = this%flowbudptr%budterm(this%idxbudgwf)%id2(jj)
2766  v = this%hcof(jj) * this%xnew(igwfnode) - this%rhs(jj)
2767  v = -v
2768  end if
2769  case ('FLOW-JA-FACE')
2770  n = this%flowbudptr%budterm(this%idxbudfjf)%id1(jj)
2771  if (this%iboundpak(n) /= 0) then
2772  call this%apt_fjf_term(jj, n1, n2, v)
2773  end if
2774  case ('STORAGE')
2775  if (this%iboundpak(jj) /= 0) then
2776  v = this%qsto(jj)
2777  end if
2778  case ('CONSTANT')
2779  if (this%iboundpak(jj) /= 0) then
2780  v = this%ccterm(jj)
2781  end if
2782  case ('FROM-MVR')
2783  if (this%iboundpak(jj) /= 0 .and. this%idxbudfmvr > 0) then
2784  call this%apt_fmvr_term(jj, n1, n2, v)
2785  end if
2786  case ('TO-MVR')
2787  if (this%idxbudtmvr > 0) then
2788  n = this%flowbudptr%budterm(this%idxbudtmvr)%id1(jj)
2789  if (this%iboundpak(n) /= 0) then
2790  call this%apt_tmvr_term(jj, n1, n2, v)
2791  end if
2792  end if
2793  case default
2794  found = .false.
2795  !
2796  ! -- check the child package for any specific obs
2797  call this%pak_bd_obs(obsrv%ObsTypeId, jj, v, found)
2798  !
2799  ! -- if none found then terminate with an error
2800  if (.not. found) then
2801  errmsg = 'Unrecognized observation type "'// &
2802  trim(obsrv%ObsTypeId)//'" for '// &
2803  trim(adjustl(this%text))//' package '// &
2804  trim(this%packName)
2805  call store_error(errmsg, terminate=.true.)
2806  end if
2807  end select
2808  call this%obs%SaveOneSimval(obsrv, v)
2809  end do
2810  end do
2811  !
2812  ! -- write summary of error messages
2813  if (count_errors() > 0) then
2814  call store_error_unit(this%obs%inunitobs)
2815  end if
2816  end if
2817  end subroutine apt_bd_obs
2818 
2819  !> @brief Check if observation exists in an advanced package
2820  !<
2821  subroutine pak_bd_obs(this, obstypeid, jj, v, found)
2822  ! -- dummy
2823  class(tspapttype), intent(inout) :: this
2824  character(len=*), intent(in) :: obstypeid
2825  integer(I4B), intent(in) :: jj
2826  real(DP), intent(inout) :: v
2827  logical, intent(inout) :: found
2828  ! -- local
2829  !
2830  ! -- set found = .false. because obstypeid is not known
2831  found = .false.
2832  end subroutine pak_bd_obs
2833 
2834  !> @brief Process observation IDs for an advanced package
2835  !!
2836  !! Method to process observation ID strings for an APT package.
2837  !! This processor is only for observation types that support ID1
2838  !! and not ID2.
2839  !<
2840  subroutine apt_process_obsid(obsrv, dis, inunitobs, iout)
2841  ! -- dummy variables
2842  type(observetype), intent(inout) :: obsrv !< Observation object
2843  class(disbasetype), intent(in) :: dis !< Discretization object
2844  integer(I4B), intent(in) :: inunitobs !< file unit number for the package observation file
2845  integer(I4B), intent(in) :: iout !< model listing file unit number
2846  ! -- local variables
2847  integer(I4B) :: nn1
2848  integer(I4B) :: icol
2849  integer(I4B) :: istart
2850  integer(I4B) :: istop
2851  character(len=LINELENGTH) :: string
2852  character(len=LENBOUNDNAME) :: bndname
2853  !
2854  ! -- initialize local variables
2855  string = obsrv%IDstring
2856  !
2857  ! -- Extract reach number from string and store it.
2858  ! If 1st item is not an integer(I4B), it should be a
2859  ! boundary name--deal with it.
2860  icol = 1
2861  !
2862  ! -- get reach number or boundary name
2863  call extract_idnum_or_bndname(string, icol, istart, istop, nn1, bndname)
2864  if (nn1 == namedboundflag) then
2865  obsrv%FeatureName = bndname
2866  end if
2867  !
2868  ! -- store reach number (NodeNumber)
2869  obsrv%NodeNumber = nn1
2870  !
2871  ! -- store NodeNumber2 as 1 so that this can be used
2872  ! as the iconn value for SFT. This works for SFT
2873  ! because there is only one reach per GWT connection.
2874  obsrv%NodeNumber2 = 1
2875  end subroutine apt_process_obsid
2876 
2877  !> @brief Process observation IDs for a package
2878  !!
2879  !! Method to process observation ID strings for an APT package. This
2880  !! processor is for the case where if ID1 is an integer then ID2 must be
2881  !! provided.
2882  !<
2883  subroutine apt_process_obsid12(obsrv, dis, inunitobs, iout)
2884  ! -- dummy variables
2885  type(observetype), intent(inout) :: obsrv !< Observation object
2886  class(disbasetype), intent(in) :: dis !< Discretization object
2887  integer(I4B), intent(in) :: inunitobs !< file unit number for the package observation file
2888  integer(I4B), intent(in) :: iout !< model listing file unit number
2889  ! -- local variables
2890  integer(I4B) :: nn1
2891  integer(I4B) :: iconn
2892  integer(I4B) :: icol
2893  integer(I4B) :: istart
2894  integer(I4B) :: istop
2895  character(len=LINELENGTH) :: string
2896  character(len=LENBOUNDNAME) :: bndname
2897  !
2898  ! -- initialize local variables
2899  string = obsrv%IDstring
2900  !
2901  ! -- Extract reach number from string and store it.
2902  ! If 1st item is not an integer(I4B), it should be a
2903  ! boundary name--deal with it.
2904  icol = 1
2905  !
2906  ! -- get reach number or boundary name
2907  call extract_idnum_or_bndname(string, icol, istart, istop, nn1, bndname)
2908  if (nn1 == namedboundflag) then
2909  obsrv%FeatureName = bndname
2910  else
2911  call extract_idnum_or_bndname(string, icol, istart, istop, iconn, bndname)
2912  if (len_trim(bndname) < 1 .and. iconn < 0) then
2913  write (errmsg, '(a,1x,a,a,1x,a,1x,a)') &
2914  'For observation type', trim(adjustl(obsrv%ObsTypeId)), &
2915  ', ID given as an integer and not as boundname,', &
2916  'but ID2 is missing. Either change ID to valid', &
2917  'boundname or supply valid entry for ID2.'
2918  call store_error(errmsg)
2919  end if
2920  obsrv%NodeNumber2 = iconn
2921  end if
2922  !
2923  ! -- store reach number (NodeNumber)
2924  obsrv%NodeNumber = nn1
2925  end subroutine apt_process_obsid12
2926 
2927  !> @brief Setup a table object an advanced package
2928  !!
2929  !! Set up the table object that is used to write the apt concentration
2930  !! (or temperature) data. The terms listed here must correspond in the
2931  !! apt_ot method.
2932  !<
2933  subroutine apt_setup_tableobj(this)
2934  ! -- modules
2936  ! -- dummy
2937  class(tspapttype) :: this
2938  ! -- local
2939  integer(I4B) :: nterms
2940  character(len=LINELENGTH) :: title
2941  character(len=LINELENGTH) :: text_temp
2942  !
2943  ! -- setup well head table
2944  if (this%iprconc > 0) then
2945  !
2946  ! -- Determine the number of head table columns
2947  nterms = 2
2948  if (this%inamedbound == 1) nterms = nterms + 1
2949  !
2950  ! -- set up table title
2951  title = trim(adjustl(this%text))//' PACKAGE ('// &
2952  trim(adjustl(this%packName))// &
2953  ') '//trim(adjustl(this%depvartype))// &
2954  &' FOR EACH CONTROL VOLUME'
2955  !
2956  ! -- set up dv tableobj
2957  call table_cr(this%dvtab, this%packName, title)
2958  call this%dvtab%table_df(this%ncv, nterms, this%iout, &
2959  transient=.true.)
2960  !
2961  ! -- Go through and set up table budget term
2962  if (this%inamedbound == 1) then
2963  text_temp = 'NAME'
2964  call this%dvtab%initialize_column(text_temp, 20, alignment=tableft)
2965  end if
2966  !
2967  ! -- feature number
2968  text_temp = 'NUMBER'
2969  call this%dvtab%initialize_column(text_temp, 10, alignment=tabcenter)
2970  !
2971  ! -- feature conc
2972  text_temp = this%depvartype(1:4)
2973  call this%dvtab%initialize_column(text_temp, 12, alignment=tabcenter)
2974  end if
2975  end subroutine apt_setup_tableobj
2976 
2977 end module tspaptmodule
This module contains the base boundary package.
This module contains the BudgetModule.
Definition: Budget.f90:20
subroutine, public budget_cr(this, name_model)
@ brief Create a new budget object
Definition: Budget.f90:84
subroutine, public budgetobject_cr(this, name)
Create a new budget object.
This module contains simulation constants.
Definition: Constants.f90:9
integer(i4b), parameter linelength
maximum length of a standard line
Definition: Constants.f90:45
real(dp), parameter dhdry
real dry cell constant
Definition: Constants.f90:94
@ tabcenter
centered table column
Definition: Constants.f90:172
@ tabright
right justified table column
Definition: Constants.f90:173
@ tableft
left justified table column
Definition: Constants.f90:171
@ tabucstring
upper case string table data
Definition: Constants.f90:180
@ tabstring
string table data
Definition: Constants.f90:179
@ tabreal
real table data
Definition: Constants.f90:182
@ tabinteger
integer table data
Definition: Constants.f90:181
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
real(dp), parameter dnodata
real no data constant
Definition: Constants.f90:95
real(dp), parameter dhnoflo
real no flow constant
Definition: Constants.f90:93
real(dp), parameter dep20
real constant 1e20
Definition: Constants.f90:91
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
integer(i4b), parameter lenauxname
maximum length of a aux variable
Definition: Constants.f90:35
integer(i4b), parameter lenboundname
maximum length of a bound name
Definition: Constants.f90:36
real(dp), parameter dzero
real constant zero
Definition: Constants.f90:65
integer(i4b), parameter maxcharlen
maximum length of char string
Definition: Constants.f90:47
integer(i4b), parameter lenbudtxt
maximum length of a budget component names
Definition: Constants.f90:37
real(dp), parameter done
real constant 1
Definition: Constants.f90:76
subroutine, public extract_idnum_or_bndname(line, icol, istart, istop, idnum, bndname)
Starting at position icol, define string as line(istart:istop).
integer(i4b) function, public getunit()
Get a free unit number.
character(len=max(len_trim(str), width)) function, public str_pad_left(str, width)
Function for string manipulation.
subroutine, public ulasav(buf, text, kstp, kper, pertim, totim, ncol, nrow, ilay, ichn)
Save 1 layer array on disk.
subroutine, public openfile(iu, iout, fname, ftype, fmtarg_opt, accarg_opt, filstat_opt, mode_opt)
Open a file.
Definition: InputOutput.f90:30
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
This module contains the derived types ObserveType and ObsDataType.
Definition: Observe.f90:15
character(len=20) access
Definition: OpenSpec.f90:7
character(len=20) form
Definition: OpenSpec.f90:7
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_unit(iunit, terminate)
Store the file unit number.
Definition: Sim.f90:168
This module contains simulation variables.
Definition: SimVariables.f90:9
character(len=maxcharlen) errmsg
error message string
integer(i4b) ifailedstepretry
current retry for this time step
subroutine, public table_cr(this, name, title)
Definition: Table.f90:87
real(dp), pointer, public pertim
time relative to start of stress period
Definition: tdis.f90:30
real(dp), pointer, public totim
time relative to start of simulation
Definition: tdis.f90:32
integer(i4b), pointer, public kstp
current time step number
Definition: tdis.f90:24
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
integer(i4b), pointer, public nper
number of stress period
Definition: tdis.f90:21
subroutine, public read_value_or_time_series_adv(textInput, ii, jj, bndElem, pkgName, auxOrBnd, tsManager, iprpak, varName)
Call this subroutine from advanced packages to define timeseries link for a variable (varName).
subroutine apt_ot_bdsummary(this, kstp, kper, iout, ibudfl)
Print advanced package transport dependent variables.
Definition: tsp-apt.f90:1033
subroutine apt_cfupdate(this)
Advanced package transport routine.
Definition: tsp-apt.f90:883
subroutine pak_setup_budobj(this, idx)
Set up a budget object that stores an advanced package flows.
Definition: tsp-apt.f90:2100
subroutine apt_ar(this)
Advanced package transport allocate and read (ar) routine.
Definition: tsp-apt.f90:302
subroutine pak_fill_budobj(this, idx, x, flowja, ccratin, ccratout)
Copy flow terms into thisbudobj, must be overridden.
Definition: tsp-apt.f90:2252
subroutine rp_obs_flowjaface(this, obsrv, budterm)
Prepare observation.
Definition: tsp-apt.f90:2583
subroutine pak_set_stressperiod(this, itemno, keyword, found)
Advanced package transport set stress period routine.
Definition: tsp-apt.f90:585
subroutine pak_bd_obs(this, obstypeid, jj, v, found)
Check if observation exists in an advanced package.
Definition: tsp-apt.f90:2822
subroutine apt_fc_expanded(this, rhs, ia, idxglo, matrix_sln)
Advanced package transport fill coefficient (fc) method.
Definition: tsp-apt.f90:754
subroutine pak_fc_expanded(this, rhs, ia, idxglo, matrix_sln)
Advanced package transport fill coefficient (fc) method.
Definition: tsp-apt.f90:863
subroutine apt_fjf_term(this, ientry, n1, n2, rrate, rhsval, hcofval)
Go through each "within apt-apt" connection (e.g., lkt-lkt, or sft-sft) and accumulate total mass (or...
Definition: tsp-apt.f90:2350
subroutine rp_obs_budterm(this, obsrv, budterm)
Prepare observation.
Definition: tsp-apt.f90:2511
subroutine allocate_scalars(this)
@ brief Allocate scalars
Definition: tsp-apt.f90:1050
subroutine apt_read_initial_attr(this)
Read the initial parameters for an advanced package.
Definition: tsp-apt.f90:1642
subroutine apt_setup_budobj(this)
Set up the budget object that stores advanced package flow terms.
Definition: tsp-apt.f90:1912
subroutine apt_allocate_index_arrays(this)
@ brief Allocate index arrays
Definition: tsp-apt.f90:1106
subroutine apt_rp_obs(this)
Read and prepare apt-related observations.
Definition: tsp-apt.f90:2656
character(len=lenvarname) text
Definition: tsp-apt.f90:63
subroutine apt_ot_package_flows(this, icbcfl, ibudfl)
Save advanced package flows routine.
Definition: tsp-apt.f90:953
real(dp) function, dimension(:), pointer, contiguous get_mvr_depvar(this)
Advanced package transport utility function.
Definition: tsp-apt.f90:625
subroutine get_volumes(this, icv, vnew, vold, delt)
Return the feature new volume and old volume.
Definition: tsp-apt.f90:1872
subroutine apt_allocate_arrays(this)
@ brief Allocate arrays
Definition: tsp-apt.f90:1163
integer(i4b) function pak_get_nbudterms(this)
Function to return the number of budget terms just for this package.
Definition: tsp-apt.f90:1896
subroutine apt_set_stressperiod(this, itemno)
Advanced package transport set stress period routine.
Definition: tsp-apt.f90:488
subroutine apt_df_obs(this)
Define observation type.
Definition: tsp-apt.f90:2421
character(len=lenftype) ftype
Definition: tsp-apt.f90:62
subroutine apt_fmvr_term(this, ientry, n1, n2, rrate, rhsval, hcofval)
Account for mass or energy transferred to this package from the MVR package.
Definition: tsp-apt.f90:2327
subroutine apt_da(this)
@ brief Deallocate memory
Definition: tsp-apt.f90:1218
subroutine apt_read_dimensions(this)
Determine dimensions for this advanced package.
Definition: tsp-apt.f90:1399
subroutine apt_mc(this, moffset, matrix_sln)
Advanced package transport map package connections to matrix.
Definition: tsp-apt.f90:241
subroutine apt_fill_budobj(this, x, flowja)
Copy flow terms into thisbudobj.
Definition: tsp-apt.f90:2114
subroutine pak_rp_obs(this, obsrv, found)
Process package specific obs.
Definition: tsp-apt.f90:2451
logical function apt_obs_supported(this)
Determine whether an obs type is supported.
Definition: tsp-apt.f90:2406
subroutine apt_read_cvs(this)
Read feature information for this advanced package.
Definition: tsp-apt.f90:1465
subroutine apt_bd_obs(this)
Calculate observation values.
Definition: tsp-apt.f90:2734
subroutine apt_solve(this)
Add terms specific to advanced package transport to the explicit solve.
Definition: tsp-apt.f90:1691
subroutine apt_tmvr_term(this, ientry, n1, n2, rrate, rhsval, hcofval)
Account for mass or energy transferred to the MVR package.
Definition: tsp-apt.f90:2299
subroutine apt_set_pointers(this, neq, ibound, xnew, xold, flowja)
Set pointers to model arrays and variables so that a package has access to these items.
Definition: tsp-apt.f90:1846
subroutine apt_accumulate_ccterm(this, ilak, rrate, ccratin, ccratout)
Accumulate constant concentration (or temperature) terms for budget.
Definition: tsp-apt.f90:1790
subroutine apt_setup_tableobj(this)
Setup a table object an advanced package.
Definition: tsp-apt.f90:2934
subroutine find_apt_package(this)
Find corresponding advanced package transport package.
Definition: tsp-apt.f90:1292
subroutine apt_rp(this)
Advanced package transport read and prepare (rp) routine.
Definition: tsp-apt.f90:369
subroutine apt_stor_term(this, ientry, n1, n2, rrate, rhsval, hcofval)
Account for mass or energy storage in advanced package features.
Definition: tsp-apt.f90:2272
subroutine apt_options(this, option, found)
Set options specific to the TspAptType.
Definition: tsp-apt.f90:1308
subroutine rp_obs_byfeature(this, obsrv)
Prepare observation.
Definition: tsp-apt.f90:2468
subroutine apt_copy2flowp(this)
Copy concentrations (or temperatures) into flow package aux variable.
Definition: tsp-apt.f90:2380
subroutine apt_cq(this, x, flowja, iadv)
Advanced package transport calculate flows (cq) routine.
Definition: tsp-apt.f90:913
subroutine apt_ac(this, moffset, sparse)
Add package connection to matrix.
Definition: tsp-apt.f90:194
subroutine, public apt_process_obsid(obsrv, dis, inunitobs, iout)
Process observation IDs for an advanced package.
Definition: tsp-apt.f90:2841
subroutine apt_ad(this)
Advanced package transport routine.
Definition: tsp-apt.f90:638
integer(i4b) function apt_check_valid(this, itemno)
Advanced package transport routine.
Definition: tsp-apt.f90:605
subroutine define_listlabel(this)
Define the list heading that is written to iout when PRINT_INPUT option is used.
Definition: tsp-apt.f90:1822
subroutine pak_solve(this)
Add terms specific to advanced package transport features to the explicit solve routine.
Definition: tsp-apt.f90:1778
subroutine apt_fc_nonexpanded(this, rhs, ia, idxglo, matrix_sln)
Advanced package transport fill coefficient (fc) method.
Definition: tsp-apt.f90:725
subroutine apt_reset(this)
Override bnd reset for custom mover logic.
Definition: tsp-apt.f90:692
subroutine apt_fc(this, rhs, ia, idxglo, matrix_sln)
Definition: tsp-apt.f90:702
subroutine apt_ot_dv(this, idvsave, idvprint)
Definition: tsp-apt.f90:977
subroutine pak_df_obs(this)
Define apt observation type.
Definition: tsp-apt.f90:2436
subroutine, public apt_process_obsid12(obsrv, dis, inunitobs, iout)
Process observation IDs for a package.
Definition: tsp-apt.f90:2884
@ brief BndType