MODFLOW 6  version 6.9.0.dev0
USGS Modular Hydrologic Model
gwf-buy.f90
Go to the documentation of this file.
1 ! Buoyancy Package for representing variable-density groundwater flow
2 ! The BUY Package does not work yet with the NPF XT3D option
3 
5 
6  use kindmodule, only: dp, i4b
13  use basedismodule, only: disbasetype
14  use gwfnpfmodule, only: gwfnpftype
17 
18  implicit none
19 
20  private
21  public :: gwfbuytype
22  public :: buy_cr
23 
25  real(dp), dimension(:), pointer :: conc => null() !< pointer to concentration array
26  integer(I4B), dimension(:), pointer :: icbund => null() !< store pointer to gwt ibound array
27  end type concentrationpointer
28 
29  type, extends(numericalpackagetype) :: gwfbuytype
30  type(gwfnpftype), pointer :: npf => null() !< npf object
31  integer(I4B), pointer :: ioutdense => null() !< unit number for saving density
32  integer(I4B), pointer :: iform => null() !< formulation: 0 freshwater head, 1 hh rhs, 2 hydraulic head
33  integer(I4B), pointer :: ireadelev => null() !< if 1 then elev has been allocated and filled
34  integer(I4B), pointer :: ireadconcbuy => null() !< if 1 then dense has been read from this buy input file
35  integer(I4B), pointer :: iconcset => null() !< if 1 then conc is pointed to a gwt model%x
36  real(dp), pointer :: denseref => null() !< reference fluid density
37  real(dp), dimension(:), pointer, contiguous :: dense => null() !< density
38  real(dp), dimension(:), pointer, contiguous :: concbuy => null() !< concentration array if specified in buy package
39  real(dp), dimension(:), pointer, contiguous :: elev => null() !< cell center elevation (optional; if not specified, then use (top+bot)/2)
40  integer(I4B), dimension(:), pointer :: ibound => null() !< store pointer to ibound
41 
42  integer(I4B), pointer :: nrhospecies => null() !< number of species used in equation of state to calculate density
43  real(dp), dimension(:), pointer, contiguous :: drhodc => null() !< change in density with change in concentration
44  real(dp), dimension(:), pointer, contiguous :: crhoref => null() !< reference concentration used in equation of state
45  real(dp), dimension(:), pointer, contiguous :: ctemp => null() !< temporary array of size (nrhospec) to pass to calcdens
46  character(len=LENMODELNAME), dimension(:), allocatable :: cmodelname !< names of gwt models used in equation of state
47  character(len=LENAUXNAME), dimension(:), allocatable :: cauxspeciesname !< names of gwt models used in equation of state
48 
49  type(concentrationpointer), allocatable, dimension(:) :: modelconc !< concentration pointer for each transport model
50 
51  contains
52  procedure :: buy_df
53  procedure :: buy_ar
54  procedure :: buy_ar_bnd
55  procedure :: buy_rp
56  procedure :: buy_ad
57  procedure :: buy_cf
58  procedure :: buy_cf_bnd
59  procedure :: buy_fc
60  procedure :: buy_ot_dv
61  procedure :: buy_cq
62  procedure :: buy_da
63  procedure, private :: calcbuy
64  procedure, private :: calchhterms
65  procedure, private :: buy_calcdens
66  procedure, private :: buy_calcelev
67  procedure :: allocate_scalars
68  procedure, private :: allocate_arrays
69  procedure, private :: source_options
70  procedure, private :: set_options
71  procedure, private :: log_options
72  procedure, private :: source_dimensions
73  procedure, private :: source_packagedata
74  procedure, private :: set_packagedata
76  end type gwfbuytype
77 
78 contains
79 
80  !> @brief Generic function to calculate fluid density from concentration
81  !<
82  function calcdens(denseref, drhodc, crhoref, conc) result(dense)
83  ! -- dummy
84  real(dp), intent(in) :: denseref
85  real(dp), dimension(:), intent(in) :: drhodc
86  real(dp), dimension(:), intent(in) :: crhoref
87  real(dp), dimension(:), intent(in) :: conc
88  ! -- return
89  real(dp) :: dense
90  ! -- local
91  integer(I4B) :: nrhospec
92  integer(I4B) :: i
93  !
94  nrhospec = size(drhodc)
95  dense = denseref
96  do i = 1, nrhospec
97  dense = dense + drhodc(i) * (conc(i) - crhoref(i))
98  end do
99  end function calcdens
100 
101  !> @brief Create a new BUY object
102  !<
103  subroutine buy_cr(buyobj, name_model, input_mempath, inunit, iout)
104  ! -- dummy
105  type(gwfbuytype), pointer :: buyobj
106  character(len=*), intent(in) :: name_model
107  character(len=*), intent(in) :: input_mempath
108  integer(I4B), intent(in) :: inunit
109  integer(I4B), intent(in) :: iout
110  !
111  ! -- Create the object
112  allocate (buyobj)
113  !
114  ! -- create name and memory path
115  call buyobj%set_names(1, name_model, 'BUY', 'BUY', input_mempath)
116  !
117  ! -- Allocate scalars
118  call buyobj%allocate_scalars()
119  !
120  ! -- Set variables
121  buyobj%inunit = inunit
122  buyobj%iout = iout
123  end subroutine buy_cr
124 
125  !> @brief Read options and package data, or set from argument
126  !<
127  subroutine buy_df(this, dis, buy_input)
128  ! -- dummy
129  class(gwfbuytype) :: this !< this buoyancy package
130  class(disbasetype), pointer, intent(in) :: dis !< pointer to discretization
131  type(gwfbuyinputdatatype), optional, intent(in) :: buy_input !< optional buy input data, otherwise read from file
132  ! -- local
133  ! -- formats
134  character(len=*), parameter :: fmtbuy = &
135  "(1x,/1x,'BUY -- Buoyancy Package, Version 1, 5/16/2018', &
136  &' input read from mempath: ', a, /)"
137  !
138  ! --print a message identifying the buoyancy package.
139  if (.not. present(buy_input)) then
140  write (this%iout, fmtbuy) this%input_mempath
141  end if
142  !
143  ! -- store pointers to arguments that were passed in
144  this%dis => dis
145 
146  if (.not. present(buy_input)) then
147  !
148  ! -- Read buoyancy options
149  call this%source_options()
150  !
151  ! -- Read buoyancy dimensions
152  call this%source_dimensions()
153  else
154  ! set from input data instead
155  call this%set_options(buy_input)
156  this%nrhospecies = buy_input%nrhospecies
157  end if
158  !
159  ! -- Allocate arrays
160  call this%allocate_arrays(dis%nodes)
161 
162  if (.not. present(buy_input)) then
163  !
164  ! -- Read buoyancy packagedata
165  call this%source_packagedata()
166  else
167  ! set from input data instead
168  call this%set_packagedata(buy_input)
169  end if
170  end subroutine buy_df
171 
172  !> @brief Allocate and Read
173  !<
174  subroutine buy_ar(this, npf, ibound)
175  ! -- dummy
176  class(gwfbuytype) :: this
177  type(gwfnpftype), pointer, intent(in) :: npf
178  integer(I4B), dimension(:), pointer :: ibound
179  !
180  ! -- store pointers to arguments that were passed in
181  this%npf => npf
182  this%ibound => ibound
183  !
184  ! -- Ensure NPF XT3D is not on
185  if (this%npf%ixt3d /= 0) then
186  call store_error('Error in model '//trim(this%name_model)// &
187  '. The XT3D option cannot be used with the BUY Package.')
188  call store_error_filename(this%input_fname)
189  end if
190  !
191  ! -- Calculate cell elevations
192  call this%buy_calcelev()
193  end subroutine buy_ar
194 
195  !> @brief Buoyancy ar_bnd routine to activate density in packages
196  !!
197  !! This routine is called from gwf_ar() as it goes through each package
198  !<
199  subroutine buy_ar_bnd(this, packobj, hnew)
200  ! -- modules
201  use bndmodule, only: bndtype
202  use lakmodule, only: laktype
203  use sfrmodule, only: sfrtype
204  use mawmodule, only: mawtype
205  ! -- dummy
206  class(gwfbuytype) :: this
207  class(bndtype), pointer :: packobj
208  real(DP), intent(in), dimension(:) :: hnew
209  !
210  ! -- Add density terms based on boundary package type
211  select case (packobj%filtyp)
212  case ('LAK')
213  !
214  ! -- activate density for lake package
215  select type (packobj)
216  type is (laktype)
217  call packobj%lak_activate_density()
218  end select
219  !
220  case ('SFR')
221  !
222  ! -- activate density for sfr package
223  select type (packobj)
224  type is (sfrtype)
225  call packobj%sfr_activate_density()
226  end select
227  !
228  case ('MAW')
229  !
230  ! -- activate density for maw package
231  select type (packobj)
232  type is (mawtype)
233  call packobj%maw_activate_density()
234  end select
235  !
236  case default
237  !
238  ! -- nothing
239  end select
240  end subroutine buy_ar_bnd
241 
242  !> @brief Check for new buy period data
243  !<
244  subroutine buy_rp(this)
245  ! -- modules
246  use tdismodule, only: kstp, kper
247  ! -- dummy
248  class(gwfbuytype) :: this
249  ! -- local
250  character(len=LINELENGTH) :: errmsg
251  integer(I4B) :: i
252  ! -- formats
253  character(len=*), parameter :: fmtc = &
254  "('Buoyancy Package does not have a concentration set &
255  &for species ',i0,'. One or more model names may be specified &
256  &incorrectly in the PACKAGEDATA block or a gwf-gwt exchange may need &
257  &to be activated.')"
258  !
259  ! -- Check to make sure all concentration pointers have been set
260  if (kstp * kper == 1) then
261  do i = 1, this%nrhospecies
262  if (.not. associated(this%modelconc(i)%conc)) then
263  write (errmsg, fmtc) i
264  call store_error(errmsg)
265  end if
266  end do
267  if (count_errors() > 0) then
268  call store_error_filename(this%input_fname)
269  end if
270  end if
271  end subroutine buy_rp
272 
273  !> @brief Advance
274  !<
275  subroutine buy_ad(this)
276  ! -- dummy
277  class(gwfbuytype) :: this
278  !
279  ! -- update density using the last concentration
280  call this%buy_calcdens()
281  end subroutine buy_ad
282 
283  !> @brief Fill coefficients
284  !<
285  subroutine buy_cf(this, kiter)
286  ! -- dummy
287  class(gwfbuytype) :: this
288  integer(I4B) :: kiter
289  !
290  ! -- Recalculate the elev array for this iteration
291  if (this%ireadelev == 0) then
292  if (this%iform == 1 .or. this%iform == 2) then
293  call this%buy_calcelev()
294  end if
295  end if
296  end subroutine buy_cf
297 
298  !> @brief Fill coefficients
299  !<
300  subroutine buy_cf_bnd(this, packobj, hnew) !, hcof, rhs, auxnam, auxvar)
301  ! -- modules
302  use bndmodule, only: bndtype
303  ! -- dummy
304  class(gwfbuytype) :: this
305  class(bndtype), pointer :: packobj
306  real(DP), intent(in), dimension(:) :: hnew
307  ! -- local
308  integer(I4B) :: i, j
309  integer(I4B) :: n, locdense, locelev
310  integer(I4B), dimension(:), allocatable :: locconc
311  !
312  ! -- Return if freshwater head formulation; all boundary heads must be
313  ! entered as freshwater equivalents
314  if (this%iform == 0) return
315  !
316  ! -- initialize
317  locdense = 0
318  locelev = 0
319  allocate (locconc(this%nrhospecies))
320  locconc(:) = 0
321  !
322  ! -- Add buoyancy terms for head-dependent boundaries
323  do n = 1, packobj%naux
324  if (packobj%auxname(n) == 'DENSITY') then
325  locdense = n
326  else if (packobj%auxname(n) == 'ELEVATION') then
327  locelev = n
328  end if
329  end do
330  !
331  ! -- find aux columns for concentrations that affect density
332  do i = 1, this%nrhospecies
333  locconc(i) = 0
334  do j = 1, packobj%naux
335  if (this%cauxspeciesname(i) == packobj%auxname(j)) then
336  locconc(i) = j
337  exit
338  end if
339  end do
340  if (locconc(i) == 0) then
341  ! -- one not found, so don't use and mark all as 0
342  locconc(:) = 0
343  exit
344  end if
345  end do
346  !
347  ! -- Add density terms based on boundary package type
348  select case (packobj%filtyp)
349  case ('GHB')
350  !
351  ! -- general head boundary
352  call buy_cf_ghb(packobj, this%dense, this%elev, this%denseref, &
353  locelev, locdense, locconc, this%drhodc, this%crhoref, &
354  this%ctemp)
355  case ('RIV')
356  !
357  ! -- river
358  call buy_cf_riv(packobj, hnew, this%dense, this%elev, this%denseref, &
359  locelev, locdense, locconc, this%drhodc, this%crhoref, &
360  this%ctemp)
361  case ('DRN')
362  !
363  ! -- drain
364  call buy_cf_drn(packobj, this%dense, this%denseref)
365  case ('LAK')
366  !
367  ! -- lake
368  call buy_cf_lak(packobj, hnew, this%dense, this%elev, this%denseref, &
369  locdense, locconc, this%drhodc, this%crhoref, &
370  this%ctemp, this%iform)
371  case ('SFR')
372  !
373  ! -- sfr
374  call buy_cf_sfr(packobj, hnew, this%dense, this%elev, this%denseref, &
375  locdense, locconc, this%drhodc, this%crhoref, &
376  this%ctemp, this%iform)
377  case ('MAW')
378  !
379  ! -- maw
380  call buy_cf_maw(packobj, hnew, this%dense, this%elev, this%denseref, &
381  locdense, locconc, this%drhodc, this%crhoref, &
382  this%ctemp, this%iform)
383  case default
384  !
385  ! -- nothing
386  end select
387  !
388  ! -- deallocate
389  deallocate (locconc)
390  end subroutine buy_cf_bnd
391 
392  !> @brief Return the density of the boundary package using one of several
393  !! different options in the following order of priority:
394  !! 1. Assign as aux variable in column with name 'DENSITY'
395  !! 2. Calculate using equation of state and nrhospecies aux columns
396  !! 3. If neither of those, then assign as denseref
397  !<
398  function get_bnd_density(n, locdense, locconc, denseref, drhodc, crhoref, &
399  ctemp, auxvar) result(densebnd)
400  ! -- dummy
401  integer(I4B), intent(in) :: n
402  integer(I4B), intent(in) :: locdense
403  integer(I4B), dimension(:), intent(in) :: locconc
404  real(dp), intent(in) :: denseref
405  real(dp), dimension(:), intent(in) :: drhodc
406  real(dp), dimension(:), intent(in) :: crhoref
407  real(dp), dimension(:), intent(inout) :: ctemp
408  real(dp), dimension(:, :), intent(in) :: auxvar
409  ! -- return
410  real(dp) :: densebnd
411  ! -- local
412  integer(I4B) :: i
413  !
414  ! -- assign boundary density based on one of three options
415  if (locdense > 0) then
416  ! -- assign density to an aux column named 'DENSITY'
417  densebnd = auxvar(locdense, n)
418  else if (locconc(1) > 0) then
419  ! -- calculate density using one or more concentration auxcolumns
420  do i = 1, size(locconc)
421  ctemp(i) = dzero
422  if (locconc(i) > 0) then
423  ctemp(i) = auxvar(locconc(i), n)
424  end if
425  end do
426  densebnd = calcdens(denseref, drhodc, crhoref, ctemp)
427  else
428  ! -- neither of the above, so assign as denseref
429  densebnd = denseref
430  end if
431  end function get_bnd_density
432 
433  !> @brief Fill ghb coefficients
434  !<
435  subroutine buy_cf_ghb(packobj, dense, elev, denseref, locelev, &
436  locdense, locconc, drhodc, crhoref, ctemp)
437  ! -- modules
438  use bndmodule, only: bndtype
439  use ghbmodule, only: ghbtype
440  class(bndtype), pointer :: packobj
441  ! -- dummy
442  real(DP), intent(in), dimension(:) :: dense
443  real(DP), intent(in), dimension(:) :: elev
444  real(DP), intent(in) :: denseref
445  integer(I4B), intent(in) :: locelev
446  integer(I4B), intent(in) :: locdense
447  integer(I4B), dimension(:), intent(in) :: locconc
448  real(DP), dimension(:), intent(in) :: drhodc
449  real(DP), dimension(:), intent(in) :: crhoref
450  real(DP), dimension(:), intent(inout) :: ctemp
451  ! -- local
452  integer(I4B) :: n
453  integer(I4B) :: node
454  real(DP) :: denseghb
455  real(DP) :: elevghb
456  real(DP) :: hghb
457  real(DP) :: cond
458  real(DP) :: hcofterm, rhsterm
459  !
460  ! -- Process density terms for each GHB
461  select type (packobj)
462  type is (ghbtype)
463  do n = 1, packobj%nbound
464  node = packobj%nodelist(n)
465  if (packobj%ibound(node) <= 0) cycle
466  !
467  ! -- density
468  denseghb = get_bnd_density(n, locdense, locconc, denseref, &
469  drhodc, crhoref, ctemp, packobj%auxvar)
470  !
471  ! -- elevation
472  elevghb = elev(node)
473  if (locelev > 0) elevghb = packobj%auxvar(locelev, n)
474  !
475  ! -- boundary head and conductance
476  hghb = packobj%bhead(n)
477  cond = packobj%cond_mult(n)
478  !
479  ! -- calculate HCOF and RHS terms
480  call calc_ghb_hcof_rhs_terms(denseref, denseghb, dense(node), &
481  elevghb, elev(node), hghb, cond, &
482  rhsterm, hcofterm)
483  packobj%hcof(n) = packobj%hcof(n) + hcofterm
484  packobj%rhs(n) = packobj%rhs(n) - rhsterm
485  !
486  end do
487  end select
488  end subroutine buy_cf_ghb
489 
490  !> @brief Calculate density hcof and rhs terms for ghb conditions
491  !!
492  !! These terms only affect the diagonal and cannot make the matrix
493  !! asymmetric, so they are added to the matrix for both hydraulic head
494  !! formulations. Lagging them on the right-hand side for HHFORMULATION_RHS
495  !! caused outer iterations to cycle when a RIV switched across rbot.
496  !<
497  subroutine calc_ghb_hcof_rhs_terms(denseref, denseghb, densenode, &
498  elevghb, elevnode, hghb, &
499  cond, rhsterm, hcofterm)
500  ! -- dummy
501  real(DP), intent(in) :: denseref
502  real(DP), intent(in) :: denseghb
503  real(DP), intent(in) :: densenode
504  real(DP), intent(in) :: elevghb
505  real(DP), intent(in) :: elevnode
506  real(DP), intent(in) :: hghb
507  real(DP), intent(in) :: cond
508  real(DP), intent(inout) :: rhsterm
509  real(DP), intent(inout) :: hcofterm
510  ! -- local
511  real(DP) :: t1, t2
512  real(DP) :: avgdense, avgelev
513  !
514  ! -- Calculate common terms
515  avgdense = dhalf * denseghb + dhalf * densenode
516  avgelev = dhalf * elevghb + dhalf * elevnode
517  t1 = avgdense / denseref - done
518  t2 = (denseghb - densenode) / denseref
519  !
520  ! -- Add hcof terms
521  hcofterm = -cond * t1
522  hcofterm = hcofterm + dhalf * cond * t2
523  !
524  ! -- Add rhs terms
525  rhsterm = cond * t1 * hghb
526  rhsterm = rhsterm - cond * t2 * avgelev
527  rhsterm = rhsterm + dhalf * cond * t2 * hghb
528  end subroutine calc_ghb_hcof_rhs_terms
529 
530  !> @brief Fill riv coefficients
531  !<
532  subroutine buy_cf_riv(packobj, hnew, dense, elev, denseref, locelev, &
533  locdense, locconc, drhodc, crhoref, ctemp)
534  ! -- modules
535  use bndmodule, only: bndtype
536  use rivmodule, only: rivtype
537  class(bndtype), pointer :: packobj
538  ! -- dummy
539  real(DP), intent(in), dimension(:) :: hnew
540  real(DP), intent(in), dimension(:) :: dense
541  real(DP), intent(in), dimension(:) :: elev
542  real(DP), intent(in) :: denseref
543  integer(I4B), intent(in) :: locelev
544  integer(I4B), intent(in) :: locdense
545  integer(I4B), dimension(:), intent(in) :: locconc
546  real(DP), dimension(:), intent(in) :: drhodc
547  real(DP), dimension(:), intent(in) :: crhoref
548  real(DP), dimension(:), intent(inout) :: ctemp
549  ! -- local
550  integer(I4B) :: n
551  integer(I4B) :: node
552  real(DP) :: denseriv
553  real(DP) :: elevriv
554  real(DP) :: hriv
555  real(DP) :: rbot
556  real(DP) :: cond
557  real(DP) :: hcofterm
558  real(DP) :: rhsterm
559  !
560  ! -- Process density terms for each RIV
561  select type (packobj)
562  type is (rivtype)
563  do n = 1, packobj%nbound
564  node = packobj%nodelist(n)
565  if (packobj%ibound(node) <= 0) cycle
566  !
567  ! -- density
568  denseriv = get_bnd_density(n, locdense, locconc, denseref, &
569  drhodc, crhoref, ctemp, packobj%auxvar)
570  !
571  ! -- elevation
572  elevriv = elev(node)
573  if (locelev > 0) elevriv = packobj%auxvar(locelev, n)
574  !
575  ! -- boundary head and conductance
576  hriv = packobj%stage(n)
577  cond = packobj%cond_mult(n)
578  rbot = packobj%rbot(n)
579  !
580  ! -- calculate and add terms depending on whether head is above rbot
581  if (hnew(node) > rbot) then
582  !
583  ! --calculate HCOF and RHS terms, similar to GHB in this case
584  call calc_ghb_hcof_rhs_terms(denseref, denseriv, dense(node), &
585  elevriv, elev(node), hriv, cond, &
586  rhsterm, hcofterm)
587  else
588  hcofterm = dzero
589  rhsterm = cond * (denseriv / denseref - done) * (hriv - rbot)
590  end if
591  !
592  ! -- Add terms to package hcof and rhs accumulators
593  packobj%hcof(n) = packobj%hcof(n) + hcofterm
594  packobj%rhs(n) = packobj%rhs(n) - rhsterm
595  end do
596  end select
597  end subroutine buy_cf_riv
598 
599  !> @brief Fill drn coefficients
600  !<
601  subroutine buy_cf_drn(packobj, dense, denseref)
602  ! -- modules
603  use bndmodule, only: bndtype
604  use drnmodule, only: drntype
605  class(bndtype), pointer :: packobj
606  ! -- dummy
607  real(DP), intent(in), dimension(:) :: dense
608  real(DP), intent(in) :: denseref
609  ! -- local
610  integer(I4B) :: n
611  integer(I4B) :: node
612  real(DP) :: rho
613  !
614  ! -- Process density terms for each DRN
615  select type (packobj)
616  type is (drntype)
617  do n = 1, packobj%nbound
618  node = packobj%nodelist(n)
619  if (packobj%ibound(node) <= 0) cycle
620  ! -- DRN uses the density of the discharging water. Scale the
621  ! assembled coefficients so AUXMULTNAME, AUXDEPTHNAME, and the
622  ! corresponding discharge elevation apply to the entire flux.
623  ! The Newton term for AUXDEPTHNAME in drn_fn is not scaled, so
624  ! the Jacobian is approximate, as for the other density terms.
625  rho = dense(node) / denseref
626  packobj%hcof(n) = rho * packobj%hcof(n)
627  packobj%rhs(n) = rho * packobj%rhs(n)
628  end do
629  end select
630  end subroutine buy_cf_drn
631 
632  !> @brief Pass density information into lak package; density terms are
633  !! calculated in the lake package as part of lak_calculate_density_exchange
634  !! method
635  !<
636  subroutine buy_cf_lak(packobj, hnew, dense, elev, denseref, locdense, &
637  locconc, drhodc, crhoref, ctemp, iform)
638  ! -- modules
639  use bndmodule, only: bndtype
640  use lakmodule, only: laktype
641  class(bndtype), pointer :: packobj
642  ! -- dummy
643  real(DP), intent(in), dimension(:) :: hnew
644  real(DP), intent(in), dimension(:) :: dense
645  real(DP), intent(in), dimension(:) :: elev
646  real(DP), intent(in) :: denseref
647  integer(I4B), intent(in) :: locdense
648  integer(I4B), dimension(:), intent(in) :: locconc
649  real(DP), dimension(:), intent(in) :: drhodc
650  real(DP), dimension(:), intent(in) :: crhoref
651  real(DP), dimension(:), intent(inout) :: ctemp
652  integer(I4B), intent(in) :: iform
653  ! -- local
654  integer(I4B) :: n
655  integer(I4B) :: node
656  real(DP) :: denselak
657  !
658  ! -- Insert the lake and gwf relative densities into col 1 and 2 and the
659  ! gwf elevation into col 3 of the lake package denseterms array
660  select type (packobj)
661  type is (laktype)
662  do n = 1, packobj%nbound
663  !
664  ! -- get gwf node number
665  node = packobj%nodelist(n)
666  if (packobj%ibound(node) <= 0) cycle
667  !
668  ! -- Determine lak density
669  denselak = get_bnd_density(n, locdense, locconc, denseref, &
670  drhodc, crhoref, ctemp, packobj%auxvar)
671  !
672  ! -- fill lak relative density into column 1 of denseterms
673  packobj%denseterms(1, n) = denselak / denseref
674  !
675  ! -- fill gwf relative density into column 2 of denseterms
676  packobj%denseterms(2, n) = dense(node) / denseref
677  !
678  ! -- fill gwf elevation into column 3 of denseterms
679  packobj%denseterms(3, n) = elev(node)
680  !
681  end do
682  end select
683  end subroutine buy_cf_lak
684 
685  !> @brief Pass density information into sfr package; density terms are
686  !! calculated in the sfr package as part of sfr_calculate_density_exchange
687  !! method
688  !<
689  subroutine buy_cf_sfr(packobj, hnew, dense, elev, denseref, locdense, &
690  locconc, drhodc, crhoref, ctemp, iform)
691  ! -- modules
692  use bndmodule, only: bndtype
693  use sfrmodule, only: sfrtype
694  class(bndtype), pointer :: packobj
695  ! -- dummy
696  real(DP), intent(in), dimension(:) :: hnew
697  real(DP), intent(in), dimension(:) :: dense
698  real(DP), intent(in), dimension(:) :: elev
699  real(DP), intent(in) :: denseref
700  integer(I4B), intent(in) :: locdense
701  integer(I4B), dimension(:), intent(in) :: locconc
702  real(DP), dimension(:), intent(in) :: drhodc
703  real(DP), dimension(:), intent(in) :: crhoref
704  real(DP), dimension(:), intent(inout) :: ctemp
705  integer(I4B), intent(in) :: iform
706  ! -- local
707  integer(I4B) :: n
708  integer(I4B) :: node
709  real(DP) :: densesfr
710  !
711  ! -- Insert the sfr and gwf relative densities into col 1 and 2 and the
712  ! gwf elevation into col 3 of the sfr package denseterms array
713  select type (packobj)
714  type is (sfrtype)
715  do n = 1, packobj%nbound
716  !
717  ! -- get gwf node number
718  node = packobj%nodelist(n)
719  if (packobj%ibound(node) <= 0) cycle
720  !
721  ! -- Determine sfr density
722  densesfr = get_bnd_density(n, locdense, locconc, denseref, &
723  drhodc, crhoref, ctemp, packobj%auxvar)
724  !
725  ! -- fill sfr relative density into column 1 of denseterms
726  packobj%denseterms(1, n) = densesfr / denseref
727  !
728  ! -- fill gwf relative density into column 2 of denseterms
729  packobj%denseterms(2, n) = dense(node) / denseref
730  !
731  ! -- fill gwf elevation into column 3 of denseterms
732  packobj%denseterms(3, n) = elev(node)
733  !
734  end do
735  end select
736  end subroutine buy_cf_sfr
737 
738  !> @brief Pass density information into maw package; density terms are
739  !! calculated in the maw package as part of maw_calculate_density_exchange
740  !! method
741  !<
742  subroutine buy_cf_maw(packobj, hnew, dense, elev, denseref, locdense, &
743  locconc, drhodc, crhoref, ctemp, iform)
744  ! -- modules
745  use bndmodule, only: bndtype
746  use mawmodule, only: mawtype
747  class(bndtype), pointer :: packobj
748  ! -- dummy
749  real(DP), intent(in), dimension(:) :: hnew
750  real(DP), intent(in), dimension(:) :: dense
751  real(DP), intent(in), dimension(:) :: elev
752  real(DP), intent(in) :: denseref
753  integer(I4B), intent(in) :: locdense
754  integer(I4B), dimension(:), intent(in) :: locconc
755  real(DP), dimension(:), intent(in) :: drhodc
756  real(DP), dimension(:), intent(in) :: crhoref
757  real(DP), dimension(:), intent(inout) :: ctemp
758  integer(I4B), intent(in) :: iform
759  ! -- local
760  integer(I4B) :: n
761  integer(I4B) :: node
762  real(DP) :: densemaw
763  !
764  ! -- Insert the maw and gwf relative densities into col 1 and 2 and the
765  ! gwf elevation into col 3 of the maw package denseterms array
766  select type (packobj)
767  type is (mawtype)
768  do n = 1, packobj%nbound
769  !
770  ! -- get gwf node number
771  node = packobj%nodelist(n)
772  if (packobj%ibound(node) <= 0) cycle
773  !
774  ! -- Determine maw density
775  densemaw = get_bnd_density(n, locdense, locconc, denseref, &
776  drhodc, crhoref, ctemp, packobj%auxvar)
777  !
778  ! -- fill maw relative density into column 1 of denseterms
779  packobj%denseterms(1, n) = densemaw / denseref
780  !
781  ! -- fill gwf relative density into column 2 of denseterms
782  packobj%denseterms(2, n) = dense(node) / denseref
783  !
784  ! -- fill gwf elevation into column 3 of denseterms
785  packobj%denseterms(3, n) = elev(node)
786  !
787  end do
788  end select
789  end subroutine buy_cf_maw
790 
791  !> @brief Fill coefficients
792  !<
793  subroutine buy_fc(this, kiter, matrix_sln, idxglo, rhs, hnew)
794  ! -- dummy
795  class(gwfbuytype) :: this
796  integer(I4B) :: kiter
797  class(matrixbasetype), pointer :: matrix_sln
798  integer(I4B), intent(in), dimension(:) :: idxglo
799  real(DP), dimension(:), intent(inout) :: rhs
800  real(DP), intent(inout), dimension(:) :: hnew
801  ! -- local
802  integer(I4B) :: n, m, ipos, idiag
803  real(DP) :: rhsterm, amatnn, amatnm
804  !
805  ! -- initialize
806  amatnn = dzero
807  amatnm = dzero
808  !
809  ! -- fill buoyancy flow term
810  do n = 1, this%dis%nodes
811  if (this%ibound(n) == 0) cycle
812  idiag = this%dis%con%ia(n)
813  do ipos = this%dis%con%ia(n) + 1, this%dis%con%ia(n + 1) - 1
814  m = this%dis%con%ja(ipos)
815  if (this%ibound(m) == 0) cycle
816  if (this%iform == 0) then
817  call this%calcbuy(n, m, ipos, hnew(n), hnew(m), rhsterm)
818  else
819  call this%calchhterms(n, m, ipos, hnew(n), hnew(m), rhsterm, &
820  amatnn, amatnm)
821  end if
822  !
823  ! -- Add terms to rhs, diagonal, and off diagonal
824  rhs(n) = rhs(n) - rhsterm
825  call matrix_sln%add_value_pos(idxglo(idiag), -amatnn)
826  call matrix_sln%add_value_pos(idxglo(ipos), amatnm)
827  end do
828  end do
829  end subroutine buy_fc
830 
831  !> @brief Save density array to binary file
832  !<
833  subroutine buy_ot_dv(this, idvfl)
834  ! -- dummy
835  class(gwfbuytype) :: this
836  integer(I4B), intent(in) :: idvfl
837  ! -- local
838  character(len=1) :: cdatafmp = ' ', editdesc = ' '
839  integer(I4B) :: ibinun
840  integer(I4B) :: iprint
841  integer(I4B) :: nvaluesp
842  integer(I4B) :: nwidthp
843  real(DP) :: dinact
844  !
845  ! -- Set unit number for density output
846  if (this%ioutdense /= 0) then
847  ibinun = 1
848  else
849  ibinun = 0
850  end if
851  if (idvfl == 0) ibinun = 0
852  !
853  ! -- save density array
854  if (ibinun /= 0) then
855  iprint = 0
856  dinact = dhnoflo
857  !
858  ! -- write density to binary file
859  if (this%ioutdense /= 0) then
860  ibinun = this%ioutdense
861  call this%dis%record_array(this%dense, this%iout, iprint, ibinun, &
862  ' DENSITY', cdatafmp, nvaluesp, &
863  nwidthp, editdesc, dinact)
864  end if
865  end if
866  end subroutine buy_ot_dv
867 
868  !> @brief Add buy term to flowja
869  !<
870  subroutine buy_cq(this, hnew, flowja)
871  implicit none
872  class(gwfbuytype) :: this
873  real(DP), intent(in), dimension(:) :: hnew
874  real(DP), intent(inout), dimension(:) :: flowja
875  integer(I4B) :: n, m, ipos
876  real(DP) :: deltaQ
877  real(DP) :: rhsterm, amatnn, amatnm
878  !
879  ! -- Calculate the flow across each cell face and store in flowja
880  do n = 1, this%dis%nodes
881  do ipos = this%dis%con%ia(n) + 1, this%dis%con%ia(n + 1) - 1
882  m = this%dis%con%ja(ipos)
883  if (m < n) cycle
884  if (this%iform == 0) then
885  ! -- equivalent freshwater head formulation
886  call this%calcbuy(n, m, ipos, hnew(n), hnew(m), deltaq)
887  else
888  ! -- hydraulic head formulation
889  call this%calchhterms(n, m, ipos, hnew(n), hnew(m), rhsterm, &
890  amatnn, amatnm)
891  deltaq = amatnm * hnew(m) - amatnn * hnew(n) + rhsterm
892  end if
893  flowja(ipos) = flowja(ipos) + deltaq
894  flowja(this%dis%con%isym(ipos)) = flowja(this%dis%con%isym(ipos)) - &
895  deltaq
896  end do
897  end do
898  end subroutine buy_cq
899 
900  !> @brief Deallocate
901  !<
902  subroutine buy_da(this)
903  ! -- dummy
904  class(gwfbuytype) :: this
905  !
906  ! -- Deallocate arrays if package was active
907  if (this%inunit > 0) then
908  call mem_deallocate(this%elev)
909  call mem_deallocate(this%dense)
910  call mem_deallocate(this%concbuy)
911  call mem_deallocate(this%drhodc)
912  call mem_deallocate(this%crhoref)
913  call mem_deallocate(this%ctemp)
914  deallocate (this%cmodelname)
915  deallocate (this%cauxspeciesname)
916  deallocate (this%modelconc)
917  end if
918  !
919  ! -- Scalars
920  call mem_deallocate(this%ioutdense)
921  call mem_deallocate(this%iform)
922  call mem_deallocate(this%ireadelev)
923  call mem_deallocate(this%ireadconcbuy)
924  call mem_deallocate(this%iconcset)
925  call mem_deallocate(this%denseref)
926  !
927  call mem_deallocate(this%nrhospecies)
928  !
929  ! -- deallocate parent
930  call this%NumericalPackageType%da()
931  end subroutine buy_da
932 
933  !> @ brief Source dimensions for package
934  !<
935  subroutine source_dimensions(this)
936  ! -- modules
939  ! -- dummy
940  class(gwfbuytype), intent(inout) :: this
941  ! -- local
942  type(gwfbuyparamfoundtype) :: found
943 
944  ! update defaults from input context
945  call mem_set_value(this%nrhospecies, 'NRHOSPECIES', this%input_mempath, &
946  found%nrhospecies)
947 
948  write (this%iout, '(/1x,a)') 'Processing BUY DIMENSIONS block'
949  write (this%iout, '(4x,a,i0)') 'NRHOSPECIES = ', this%nrhospecies
950  write (this%iout, '(1x,a)') 'End of BUY DIMENSIONS block'
951 
952  ! check dimension
953  if (this%nrhospecies < 1) then
954  call store_error('NRHOSPECIES must be greater than zero.')
955  call store_error_filename(this%input_fname)
956  end if
957  end subroutine source_dimensions
958 
959  !> @ brief source packagedata for package
960  !<
961  subroutine source_packagedata(this)
962  ! -- modules
966  ! -- dummy
967  class(gwfbuytype), intent(inout) :: this
968  ! -- local
969  integer(I4B), dimension(:), pointer, contiguous :: irhospec
970  type(characterstringtype), dimension(:), pointer, &
971  contiguous :: modelnames, auxspeciesnames
972  real(DP), dimension(:), pointer, contiguous :: drhodc, crhoref
973  integer(I4B), dimension(:), allocatable :: itemp
974  character(len=LINELENGTH) :: modelname, auxspeciesname, line, errmsg
975  character(len=10) :: c10
976  character(len=16) :: c16
977  integer(I4B) :: n
978  ! -- format
979  character(len=*), parameter :: fmterr = &
980  "('Invalid value for IRHOSPEC (',i0,') detected in BUY Package. &
981  &IRHOSPEC must be > 0 and <= NRHOSPECIES, and duplicate values &
982  &are not allowed.')"
983 
984  ! initialize
985  allocate (itemp(this%nrhospecies))
986  itemp(:) = 0
987 
988  ! set input context pointers
989  call mem_setptr(irhospec, 'IRHOSPEC', this%input_mempath)
990  call mem_setptr(drhodc, 'DRHODC', this%input_mempath)
991  call mem_setptr(crhoref, 'CRHOREF', this%input_mempath)
992  call mem_setptr(modelnames, 'MODELNAME', this%input_mempath)
993  call mem_setptr(auxspeciesnames, 'AUXSPECIESNAME', this%input_mempath)
994 
995  ! process package data
996  do n = 1, size(irhospec)
997  modelname = modelnames(n)
998  auxspeciesname = auxspeciesnames(n)
999 
1000  if (irhospec(n) < 1 .or. irhospec(n) > this%nrhospecies) then
1001  write (errmsg, fmterr) irhospec(n)
1002  call store_error(errmsg)
1003  end if
1004  if (itemp(irhospec(n)) /= 0) then
1005  write (errmsg, fmterr) irhospec(n)
1006  call store_error(errmsg)
1007  end if
1008  itemp(irhospec(n)) = 1
1009 
1010  this%drhodc(irhospec(n)) = drhodc(n)
1011  this%crhoref(irhospec(n)) = crhoref(n)
1012  this%cmodelname(irhospec(n)) = trim(modelname)
1013  this%cauxspeciesname(irhospec(n)) = trim(auxspeciesname)
1014  end do
1015 
1016  ! Check for errors.
1017  if (count_errors() > 0) then
1018  call store_error_filename(this%input_fname)
1019  end if
1020 
1021  ! log package data
1022  write (this%iout, '(/,1x,a)') 'Processing BUY PACKAGEDATA block'
1023 
1024  ! write packagedata information
1025  write (this%iout, '(1x,a)') 'Summary of species information in BUY Package'
1026  write (this%iout, '(1a11, 4a17)') &
1027  'SPECIES', 'DRHODC', 'CRHOREF', 'MODEL', &
1028  'AUXSPECIESNAME'
1029  do n = 1, this%nrhospecies
1030  write (c10, '(i0)') n
1031  line = ' '//adjustr(c10)
1032  write (c16, '(g15.6)') this%drhodc(n)
1033  line = trim(line)//' '//adjustr(c16)
1034  write (c16, '(g15.6)') this%crhoref(n)
1035  line = trim(line)//' '//adjustr(c16)
1036  write (c16, '(a)') this%cmodelname(n)
1037  line = trim(line)//' '//adjustr(c16)
1038  write (c16, '(a)') this%cauxspeciesname(n)
1039  line = trim(line)//' '//adjustr(c16)
1040  write (this%iout, '(a)') trim(line)
1041  end do
1042 
1043  write (this%iout, '(1x,a)') 'End of BUY PACKAGEDATA block'
1044 
1045  ! cleanup
1046  deallocate (itemp)
1047  call memorystore_release('IRHOSPEC', this%input_mempath)
1048  call memorystore_release('DRHODC', this%input_mempath)
1049  call memorystore_release('CRHOREF', this%input_mempath)
1050  call memorystore_release('MODELNAME', this%input_mempath)
1051  call memorystore_release('AUXSPECIESNAME', this%input_mempath)
1052  end subroutine source_packagedata
1053 
1054  !> @brief Sets package data instead of reading from file
1055  !<
1056  subroutine set_packagedata(this, input_data)
1057  ! -- dummy
1058  class(gwfbuytype) :: this !< this buyoancy pkg
1059  type(gwfbuyinputdatatype), intent(in) :: input_data !< the input data to be set
1060  ! -- local
1061  integer(I4B) :: ispec
1062 
1063  do ispec = 1, this%nrhospecies
1064  this%drhodc(ispec) = input_data%drhodc(ispec)
1065  this%crhoref(ispec) = input_data%crhoref(ispec)
1066  this%cmodelname(ispec) = input_data%cmodelname(ispec)
1067  this%cauxspeciesname(ispec) = input_data%cauxspeciesname(ispec)
1068  end do
1069  end subroutine set_packagedata
1070 
1071  !> @brief Calculate buyancy term for this connection
1072  !<
1073  subroutine calcbuy(this, n, m, icon, hn, hm, buy)
1074  ! -- modules
1076  ! -- dummy
1077  class(gwfbuytype) :: this
1078  integer(I4B), intent(in) :: n
1079  integer(I4B), intent(in) :: m
1080  integer(I4B), intent(in) :: icon
1081  real(DP), intent(in) :: hn
1082  real(DP), intent(in) :: hm
1083  real(DP), intent(inout) :: buy
1084  ! -- local
1085  integer(I4B) :: ihc
1086  real(DP) :: densen, densem, cl1, cl2, avgdense, wt, elevn, elevm, &
1087  cond, tp, bt
1088  real(DP) :: hyn
1089  real(DP) :: hym
1090  !
1091  ! -- Average density
1092  densen = this%dense(n)
1093  densem = this%dense(m)
1094  if (m > n) then
1095  cl1 = this%dis%con%cl1(this%dis%con%jas(icon))
1096  cl2 = this%dis%con%cl2(this%dis%con%jas(icon))
1097  else
1098  cl1 = this%dis%con%cl2(this%dis%con%jas(icon))
1099  cl2 = this%dis%con%cl1(this%dis%con%jas(icon))
1100  end if
1101  wt = cl1 / (cl1 + cl2)
1102  avgdense = wt * densen + (done - wt) * densem
1103  !
1104  ! -- Elevations
1105  if (this%ireadelev == 0) then
1106  tp = this%dis%top(n)
1107  bt = this%dis%bot(n)
1108  elevn = bt + dhalf * this%npf%sat(n) * (tp - bt)
1109  tp = this%dis%top(m)
1110  bt = this%dis%bot(m)
1111  elevm = bt + dhalf * this%npf%sat(m) * (tp - bt)
1112  else
1113  elevn = this%elev(n)
1114  elevm = this%elev(m)
1115  end if
1116  !
1117  ihc = this%dis%con%ihc(this%dis%con%jas(icon))
1118  hyn = this%npf%hy_eff(n, m, ihc, ipos=icon)
1119  hym = this%npf%hy_eff(m, n, ihc, ipos=icon)
1120  !
1121  ! -- Conductance
1122  if (this%dis%con%ihc(this%dis%con%jas(icon)) == 0) then
1123  cond = vcond(this%ibound(n), this%ibound(m), &
1124  this%npf%icelltype(n), this%npf%icelltype(m), &
1125  this%npf%inewton, &
1126  this%npf%ivarcv, this%npf%idewatcv, &
1127  this%npf%condsat(this%dis%con%jas(icon)), hn, hm, &
1128  hyn, hym, &
1129  this%npf%sat(n), this%npf%sat(m), &
1130  this%dis%top(n), this%dis%top(m), &
1131  this%dis%bot(n), this%dis%bot(m), &
1132  this%dis%con%hwva(this%dis%con%jas(icon)))
1133  else
1134  cond = hcond(this%ibound(n), this%ibound(m), &
1135  this%npf%icelltype(n), this%npf%icelltype(m), &
1136  this%npf%inewton, &
1137  this%dis%con%ihc(this%dis%con%jas(icon)), &
1138  this%npf%icellavg, &
1139  this%npf%condsat(this%dis%con%jas(icon)), &
1140  hn, hm, this%npf%sat(n), this%npf%sat(m), &
1141  hyn, hym, &
1142  this%dis%top(n), this%dis%top(m), &
1143  this%dis%bot(n), this%dis%bot(m), &
1144  this%dis%con%cl1(this%dis%con%jas(icon)), &
1145  this%dis%con%cl2(this%dis%con%jas(icon)), &
1146  this%dis%con%hwva(this%dis%con%jas(icon)))
1147  end if
1148  !
1149  ! -- Calculate buoyancy term
1150  buy = cond * (avgdense - this%denseref) / this%denseref * (elevm - elevn)
1151  end subroutine calcbuy
1152 
1153  !> @brief Calculate hydraulic head term for this connection
1154  !<
1155  subroutine calchhterms(this, n, m, icon, hn, hm, rhsterm, amatnn, amatnm)
1156  ! -- modules
1158  ! -- dummy
1159  class(gwfbuytype) :: this
1160  integer(I4B), intent(in) :: n
1161  integer(I4B), intent(in) :: m
1162  integer(I4B), intent(in) :: icon
1163  real(DP), intent(in) :: hn
1164  real(DP), intent(in) :: hm
1165  real(DP), intent(inout) :: rhsterm
1166  real(DP), intent(inout) :: amatnn
1167  real(DP), intent(inout) :: amatnm
1168  ! -- local
1169  integer(I4B) :: ihc
1170  real(DP) :: densen, densem, cl1, cl2, avgdense, wt, elevn, elevm, cond
1171  real(DP) :: rhonormn, rhonormm
1172  real(DP) :: rhoterm
1173  real(DP) :: elevnm
1174  real(DP) :: hphi
1175  real(DP) :: hyn
1176  real(DP) :: hym
1177  !
1178  ! -- Average density
1179  densen = this%dense(n)
1180  densem = this%dense(m)
1181  if (m > n) then
1182  cl1 = this%dis%con%cl1(this%dis%con%jas(icon))
1183  cl2 = this%dis%con%cl2(this%dis%con%jas(icon))
1184  else
1185  cl1 = this%dis%con%cl2(this%dis%con%jas(icon))
1186  cl2 = this%dis%con%cl1(this%dis%con%jas(icon))
1187  end if
1188  wt = cl1 / (cl1 + cl2)
1189  avgdense = wt * densen + (1.0 - wt) * densem
1190  !
1191  ! -- Elevations
1192  elevn = this%elev(n)
1193  elevm = this%elev(m)
1194  elevnm = (done - wt) * elevn + wt * elevm
1195  !
1196  ihc = this%dis%con%ihc(this%dis%con%jas(icon))
1197  hyn = this%npf%hy_eff(n, m, ihc, ipos=icon)
1198  hym = this%npf%hy_eff(m, n, ihc, ipos=icon)
1199  !
1200  ! -- Conductance
1201  if (ihc == 0) then
1202  cond = vcond(this%ibound(n), this%ibound(m), &
1203  this%npf%icelltype(n), this%npf%icelltype(m), &
1204  this%npf%inewton, &
1205  this%npf%ivarcv, this%npf%idewatcv, &
1206  this%npf%condsat(this%dis%con%jas(icon)), hn, hm, &
1207  hyn, hym, &
1208  this%npf%sat(n), this%npf%sat(m), &
1209  this%dis%top(n), this%dis%top(m), &
1210  this%dis%bot(n), this%dis%bot(m), &
1211  this%dis%con%hwva(this%dis%con%jas(icon)))
1212  else
1213  cond = hcond(this%ibound(n), this%ibound(m), &
1214  this%npf%icelltype(n), this%npf%icelltype(m), &
1215  this%npf%inewton, &
1216  this%dis%con%ihc(this%dis%con%jas(icon)), &
1217  this%npf%icellavg, &
1218  this%npf%condsat(this%dis%con%jas(icon)), &
1219  hn, hm, this%npf%sat(n), this%npf%sat(m), &
1220  hyn, hym, &
1221  this%dis%top(n), this%dis%top(m), &
1222  this%dis%bot(n), this%dis%bot(m), &
1223  this%dis%con%cl1(this%dis%con%jas(icon)), &
1224  this%dis%con%cl2(this%dis%con%jas(icon)), &
1225  this%dis%con%hwva(this%dis%con%jas(icon)))
1226  end if
1227  !
1228  ! -- Calculate terms
1229  rhonormn = densen / this%denseref
1230  rhonormm = densem / this%denseref
1231  rhoterm = wt * rhonormn + (done - wt) * rhonormm
1232  amatnn = cond * (rhoterm - done)
1233  amatnm = amatnn
1234  rhsterm = -cond * (rhonormm - rhonormn) * elevnm
1235  if (this%iform == 1) then
1236  ! -- rhs (lag the h terms and keep matrix symmetric)
1237  hphi = (done - wt) * hn + wt * hm
1238  rhsterm = rhsterm + cond * hphi * (rhonormm - rhonormn)
1239  else
1240  ! -- lhs, results in asymmetric matrix due to weight term
1241  amatnn = amatnn - cond * (done - wt) * (rhonormm - rhonormn)
1242  amatnm = amatnm + cond * wt * (rhonormm - rhonormn)
1243  end if
1244  end subroutine calchhterms
1245 
1246  !> @brief calculate fluid density from concentration
1247  !<
1248  subroutine buy_calcdens(this)
1249  ! -- dummy
1250  class(gwfbuytype) :: this
1251 
1252  ! -- local
1253  integer(I4B) :: n
1254  integer(I4B) :: i
1255  !
1256  ! -- Calculate the density using the specified concentration array
1257  do n = 1, this%dis%nodes
1258  do i = 1, this%nrhospecies
1259  if (this%modelconc(i)%icbund(n) == 0) then
1260  this%ctemp(i) = dzero
1261  else
1262  this%ctemp(i) = this%modelconc(i)%conc(n)
1263  end if
1264  end do
1265  this%dense(n) = calcdens(this%denseref, this%drhodc, this%crhoref, &
1266  this%ctemp)
1267  end do
1268  end subroutine buy_calcdens
1269 
1270  !> @brief Calculate cell elevations to use in density flow equations
1271  !<
1272  subroutine buy_calcelev(this)
1273  ! -- dummy
1274  class(gwfbuytype) :: this
1275  ! -- local
1276  integer(I4B) :: n
1277  real(DP) :: tp, bt, frac
1278  !
1279  ! -- Calculate the elev array
1280  do n = 1, this%dis%nodes
1281  tp = this%dis%top(n)
1282  bt = this%dis%bot(n)
1283  frac = this%npf%sat(n)
1284  this%elev(n) = bt + dhalf * frac * (tp - bt)
1285  end do
1286  end subroutine buy_calcelev
1287 
1288  !> @brief Allocate scalars used by the package
1289  !<
1290  subroutine allocate_scalars(this)
1291  ! -- modules
1292  use constantsmodule, only: dzero
1293  ! -- dummy
1294  class(gwfbuytype) :: this
1295  ! -- local
1296  !
1297  ! -- allocate scalars in NumericalPackageType
1298  call this%NumericalPackageType%allocate_scalars()
1299  !
1300  ! -- Allocate
1301  call mem_allocate(this%ioutdense, 'IOUTDENSE', this%memoryPath)
1302  call mem_allocate(this%iform, 'IFORM', this%memoryPath)
1303  call mem_allocate(this%ireadelev, 'IREADELEV', this%memoryPath)
1304  call mem_allocate(this%ireadconcbuy, 'IREADCONCBUY', this%memoryPath)
1305  call mem_allocate(this%iconcset, 'ICONCSET', this%memoryPath)
1306  call mem_allocate(this%denseref, 'DENSEREF', this%memoryPath)
1307  !
1308  call mem_allocate(this%nrhospecies, 'NRHOSPECIES', this%memoryPath)
1309  !
1310  ! -- Initialize
1311  this%ioutdense = 0
1312  this%ireadelev = 0
1313  this%iconcset = 0
1314  this%ireadconcbuy = 0
1315  this%denseref = 1000.d0
1316  !
1317  this%nrhospecies = 0
1318  !
1319  ! -- Initialize default to LHS implementation of hydraulic head formulation
1320  this%iform = 2
1321  this%iasym = 1
1322  end subroutine allocate_scalars
1323 
1324  !> @brief Allocate arrays used by the package
1325  !<
1326  subroutine allocate_arrays(this, nodes)
1327  ! -- dummy
1328  class(gwfbuytype) :: this
1329  integer(I4B), intent(in) :: nodes
1330  ! -- local
1331  integer(I4B) :: i
1332  !
1333  ! -- Allocate
1334  call mem_allocate(this%dense, nodes, 'DENSE', this%memoryPath)
1335  call mem_allocate(this%concbuy, 0, 'CONCBUY', this%memoryPath)
1336  call mem_allocate(this%elev, nodes, 'ELEV', this%memoryPath)
1337  call mem_allocate(this%drhodc, this%nrhospecies, 'DRHODC', this%memoryPath)
1338  call mem_allocate(this%crhoref, this%nrhospecies, 'CRHOREF', this%memoryPath)
1339  call mem_allocate(this%ctemp, this%nrhospecies, 'CTEMP', this%memoryPath)
1340  allocate (this%cmodelname(this%nrhospecies))
1341  allocate (this%cauxspeciesname(this%nrhospecies))
1342  allocate (this%modelconc(this%nrhospecies))
1343  !
1344  ! -- Initialize
1345  do i = 1, nodes
1346  this%dense(i) = this%denseref
1347  this%elev(i) = dzero
1348  end do
1349  !
1350  ! -- Initialize nrhospecies arrays
1351  do i = 1, this%nrhospecies
1352  this%drhodc(i) = dzero
1353  this%crhoref(i) = dzero
1354  this%ctemp(i) = dzero
1355  this%cmodelname(i) = ''
1356  this%cauxspeciesname(i) = ''
1357  end do
1358  end subroutine allocate_arrays
1359 
1360  !> @ brief Source input options
1361  !<
1362  subroutine source_options(this)
1363  ! -- modules
1365  use openspecmodule, only: access, form
1366  use inputoutputmodule, only: getunit, openfile
1368  ! -- dummy
1369  class(gwfbuytype), intent(inout) :: this
1370  ! -- local
1371  character(len=LINELENGTH) :: densityfile
1372  type(gwfbuyparamfoundtype) :: found
1373 
1374  ! initialize variables
1375  densityfile = ''
1376 
1377  ! update defaults from input context
1378  call mem_set_value(this%iform, 'HHFORM_RHS', this%input_mempath, &
1379  found%hhform_rhs)
1380  call mem_set_value(this%denseref, 'DENSEREF', this%input_mempath, &
1381  found%denseref)
1382  call mem_set_value(this%iform, 'DEV_EFH_FORM', this%input_mempath, &
1383  found%dev_efh_form)
1384  call mem_set_value(densityfile, 'DENSITYFILE', this%input_mempath, &
1385  found%densityfile)
1386 
1387  ! update input dependent internal state
1388  if (found%hhform_rhs) this%iasym = 0
1389  if (found%dev_efh_form) then
1390  this%iform = 0
1391  this%iasym = 0
1392  end if
1393 
1394  ! fileout options
1395  if (found%densityfile) then
1396  this%ioutdense = getunit()
1397  call openfile(this%ioutdense, this%iout, densityfile, 'DATA(BINARY)', &
1398  form, access, 'REPLACE')
1399  end if
1400 
1401  ! log options
1402  call this%log_options(found, densityfile)
1403  end subroutine source_options
1404 
1405  !> @ brief log input options
1406  !<
1407  subroutine log_options(this, found, densityfile)
1408  ! -- modules
1410  ! -- dummy variables
1411  class(gwfbuytype), intent(inout) :: this
1412  type(gwfbuyparamfoundtype), intent(in) :: found
1413  character(len=*), intent(in) :: densityfile
1414  ! -- local variables
1415  ! -- formats
1416  character(len=*), parameter :: fmtfileout = &
1417  "(4x, 'BUY ', 1x, a, 1x, ' will be saved to file: ', &
1418  &a, ' opened on unit: ', I7)"
1419  !
1420  write (this%iout, '(1x,a)') 'Processing BUY OPTIONS block'
1421 
1422  if (found%hhform_rhs) then
1423  write (this%iout, '(4x,a)') &
1424  'Hydraulic head formulation set to right-hand side'
1425  end if
1426  if (found%denseref) then
1427  write (this%iout, '(4x,a,1pg15.6)') &
1428  'Reference density has been set to: ', this%denseref
1429  end if
1430  if (found%dev_efh_form) then
1431  write (this%iout, '(4x,a)') &
1432  'Formulation set to equivalent freshwater head'
1433  end if
1434  if (found%densityfile) then
1435  write (this%iout, fmtfileout) &
1436  'DENSITY', trim(densityfile), this%ioutdense
1437  end if
1438 
1439  write (this%iout, '(1x,a)') 'End of BUY OPTIONS block'
1440  end subroutine log_options
1441 
1442  !> @brief Sets options as opposed to reading them from a file
1443  !<
1444  subroutine set_options(this, input_data)
1445  ! -- dummy
1446  class(gwfbuytype) :: this
1447  type(gwfbuyinputdatatype), intent(in) :: input_data !< the input data to be set
1448  !
1449  this%iform = input_data%iform
1450  this%denseref = input_data%denseref
1451  !
1452  ! derived option:
1453  ! if not iform==2, there is no asymmetry
1454  if (this%iform == 0 .or. this%iform == 1) then
1455  this%iasym = 0
1456  end if
1457  end subroutine set_options
1458 
1459  !> @brief Pass in a gwt model name, concentration array and ibound, and store
1460  !! a pointer to these in the BUY package so that density can be calculated
1461  !! from them
1462  !!
1463  !! This routine is called from the gwfgwt exchange in the exg_ar() method
1464  !<
1465  subroutine set_concentration_pointer(this, modelname, conc, icbund)
1466  ! -- dummy
1467  class(gwfbuytype) :: this
1468  character(len=LENMODELNAME), intent(in) :: modelname
1469  real(DP), dimension(:), pointer :: conc
1470  integer(I4B), dimension(:), pointer :: icbund
1471  ! -- local
1472  integer(I4B) :: i
1473  logical :: found
1474  !
1475  this%iconcset = 1
1476  found = .false.
1477  do i = 1, this%nrhospecies
1478  if (this%cmodelname(i) == modelname) then
1479  this%modelconc(i)%conc => conc
1480  this%modelconc(i)%icbund => icbund
1481  found = .true.
1482  exit
1483  end if
1484  end do
1485  end subroutine set_concentration_pointer
1486 
1487 end module gwfbuymodule
This module contains the base boundary package.
This module contains simulation constants.
Definition: Constants.f90:9
integer(i4b), parameter linelength
maximum length of a standard line
Definition: Constants.f90:45
integer(i4b), parameter lenmodelname
maximum length of the model name
Definition: Constants.f90:22
real(dp), parameter dhnoflo
real no flow constant
Definition: Constants.f90:93
real(dp), parameter dhalf
real constant 1/2
Definition: Constants.f90:68
integer(i4b), parameter lenauxname
maximum length of a aux variable
Definition: Constants.f90:35
real(dp), parameter dzero
real constant zero
Definition: Constants.f90:65
integer(i4b), parameter maxcharlen
maximum length of char string
Definition: Constants.f90:47
real(dp), parameter done
real constant 1
Definition: Constants.f90:76
real(dp) function calcdens(denseref, drhodc, crhoref, conc)
Generic function to calculate fluid density from concentration.
Definition: gwf-buy.f90:83
subroutine buy_cf(this, kiter)
Fill coefficients.
Definition: gwf-buy.f90:286
subroutine buy_cf_bnd(this, packobj, hnew)
Fill coefficients.
Definition: gwf-buy.f90:301
subroutine buy_cf_lak(packobj, hnew, dense, elev, denseref, locdense, locconc, drhodc, crhoref, ctemp, iform)
Pass density information into lak package; density terms are calculated in the lake package as part o...
Definition: gwf-buy.f90:638
subroutine set_options(this, input_data)
Sets options as opposed to reading them from a file.
Definition: gwf-buy.f90:1445
subroutine calchhterms(this, n, m, icon, hn, hm, rhsterm, amatnn, amatnm)
Calculate hydraulic head term for this connection.
Definition: gwf-buy.f90:1156
subroutine buy_rp(this)
Check for new buy period data.
Definition: gwf-buy.f90:245
subroutine buy_cf_maw(packobj, hnew, dense, elev, denseref, locdense, locconc, drhodc, crhoref, ctemp, iform)
Pass density information into maw package; density terms are calculated in the maw package as part of...
Definition: gwf-buy.f90:744
subroutine buy_fc(this, kiter, matrix_sln, idxglo, rhs, hnew)
Fill coefficients.
Definition: gwf-buy.f90:794
subroutine, public buy_cr(buyobj, name_model, input_mempath, inunit, iout)
Create a new BUY object.
Definition: gwf-buy.f90:104
subroutine allocate_scalars(this)
Allocate scalars used by the package.
Definition: gwf-buy.f90:1291
subroutine buy_cq(this, hnew, flowja)
Add buy term to flowja.
Definition: gwf-buy.f90:871
subroutine buy_calcelev(this)
Calculate cell elevations to use in density flow equations.
Definition: gwf-buy.f90:1273
subroutine set_concentration_pointer(this, modelname, conc, icbund)
Pass in a gwt model name, concentration array and ibound, and store a pointer to these in the BUY pac...
Definition: gwf-buy.f90:1466
subroutine set_packagedata(this, input_data)
Sets package data instead of reading from file.
Definition: gwf-buy.f90:1057
subroutine buy_df(this, dis, buy_input)
Read options and package data, or set from argument.
Definition: gwf-buy.f90:128
subroutine source_dimensions(this)
@ brief Source dimensions for package
Definition: gwf-buy.f90:936
subroutine buy_cf_sfr(packobj, hnew, dense, elev, denseref, locdense, locconc, drhodc, crhoref, ctemp, iform)
Pass density information into sfr package; density terms are calculated in the sfr package as part of...
Definition: gwf-buy.f90:691
subroutine buy_ot_dv(this, idvfl)
Save density array to binary file.
Definition: gwf-buy.f90:834
real(dp) function get_bnd_density(n, locdense, locconc, denseref, drhodc, crhoref, ctemp, auxvar)
Return the density of the boundary package using one of several different options in the following or...
Definition: gwf-buy.f90:400
subroutine calc_ghb_hcof_rhs_terms(denseref, denseghb, densenode, elevghb, elevnode, hghb, cond, rhsterm, hcofterm)
Calculate density hcof and rhs terms for ghb conditions.
Definition: gwf-buy.f90:500
subroutine buy_ar(this, npf, ibound)
Allocate and Read.
Definition: gwf-buy.f90:175
subroutine buy_da(this)
Deallocate.
Definition: gwf-buy.f90:903
subroutine buy_cf_drn(packobj, dense, denseref)
Fill drn coefficients.
Definition: gwf-buy.f90:602
subroutine buy_cf_riv(packobj, hnew, dense, elev, denseref, locelev, locdense, locconc, drhodc, crhoref, ctemp)
Fill riv coefficients.
Definition: gwf-buy.f90:534
subroutine source_options(this)
@ brief Source input options
Definition: gwf-buy.f90:1363
subroutine buy_ad(this)
Advance.
Definition: gwf-buy.f90:276
subroutine log_options(this, found, densityfile)
@ brief log input options
Definition: gwf-buy.f90:1408
subroutine source_packagedata(this)
@ brief source packagedata for package
Definition: gwf-buy.f90:962
subroutine buy_cf_ghb(packobj, dense, elev, denseref, locelev, locdense, locconc, drhodc, crhoref, ctemp)
Fill ghb coefficients.
Definition: gwf-buy.f90:437
subroutine allocate_arrays(this, nodes)
Allocate arrays used by the package.
Definition: gwf-buy.f90:1327
subroutine buy_ar_bnd(this, packobj, hnew)
Buoyancy ar_bnd routine to activate density in packages.
Definition: gwf-buy.f90:200
subroutine calcbuy(this, n, m, icon, hn, hm, buy)
Calculate buyancy term for this connection.
Definition: gwf-buy.f90:1074
subroutine buy_calcdens(this)
calculate fluid density from concentration
Definition: gwf-buy.f90:1249
This module contains stateless conductance functions.
real(dp) function, public hcond(ibdn, ibdm, ictn, ictm, iupstream, ihc, icellavg, condsat, hn, hm, satn, satm, hkn, hkm, topn, topm, botn, botm, cln, clm, fawidth)
Horizontal conductance between two cells.
real(dp) function, public vcond(ibdn, ibdm, ictn, ictm, inewton, ivarcv, idewatcv, condsat, hn, hm, vkn, vkm, satn, satm, topn, topm, botn, botm, flowarea)
Vertical conductance between two cells.
integer(i4b) function, public getunit()
Get a free unit number.
subroutine, public openfile(iu, iout, fname, ftype, fmtarg_opt, accarg_opt, filstat_opt, mode_opt)
Open a file.
Definition: InputOutput.f90:30
This module defines variable data types.
Definition: kind.f90:8
subroutine, public memorystore_release(varname, memory_path)
Release a single variable from the memory store.
This module contains the base numerical package type.
character(len=20) access
Definition: OpenSpec.f90:7
character(len=20) form
Definition: OpenSpec.f90:7
This module contains the SFR package methods.
Definition: gwf-sfr.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_filename(filename, terminate)
Store the erroring file name.
Definition: Sim.f90:204
integer(i4b), pointer, public kstp
current time step number
Definition: tdis.f90:27
integer(i4b), pointer, public kper
current stress period number
Definition: tdis.f90:26
@ brief BndType
This class is used to store a single deferred-length character string. It was designed to work in an ...
Definition: CharString.f90:23
Data structure to transfer input configuration to the.