MODFLOW 6 version 6.9.0.dev0
USGS Modular Hydrologic Model
Loading...
Searching...
No Matches
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
28
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
78contains
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
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
1487end 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.
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
This class is used to store a single deferred-length character string. It was designed to work in an ...
Data structure to transfer input configuration to the.