MODFLOW 6 version 6.9.0.dev0
USGS Modular Hydrologic Model
Loading...
Searching...
No Matches
gwf-vsc.f90
Go to the documentation of this file.
1! Viscosity Package for representing variable-viscosity groundwater flow
2
4
5 use kindmodule, only: dp, i4b
14 use tdismodule, only: kper, kstp
16 use basedismodule, only: disbasetype
18 use listsmodule, only: basemodellist
19
20 implicit none
21
22 private
23 public :: gwfvsctype
24 public :: vsc_cr
25
27 real(dp), dimension(:), pointer :: conc => null() !< pointer to concentration array
28 integer(I4B), dimension(:), pointer :: icbund => null() !< store pointer to gwt ibound array
30
32 integer(I4B), pointer :: thermivisc => null() !< viscosity formulation flag (1:Linear, 2:Nonlinear)
33 integer(I4B), pointer :: idxtmpr => null() !< if greater than 0 then an index for identifying whether the "species" array is temperature
34 integer(I4B), pointer :: ioutvisc => null() !< unit number for saving viscosity
35 integer(I4B), pointer :: iconcset => null() !< if 1 then conc points to a gwt (or gwe) model%x array
36 integer(I4B), pointer :: ireadelev => null() !< if 1 then elev has been allocated and filled
37 integer(I4B), dimension(:), pointer, contiguous :: ivisc => null() !< viscosity formulation flag for each species (1:Linear, 2:Nonlinear)
38 real(dp), pointer :: viscref => null() !< reference fluid viscosity
39 real(dp), dimension(:), pointer, contiguous :: visc => null() !< viscosity
40 real(dp), dimension(:), pointer, contiguous :: elev => null() !< cell center elevation (optional; if not specified, then use (top+bot)/2)
41 integer(I4B), dimension(:), pointer :: ibound => null() !< store pointer to ibound
42
43 integer(I4B), pointer :: nviscspecies => null() !< number of concentration species used in viscosity equation
44 real(dp), dimension(:), pointer, contiguous :: dviscdc => null() !< linear change in viscosity with change in concentration
45 real(dp), dimension(:), pointer, contiguous :: cviscref => null() !< reference concentration used in viscosity equation
46 real(dp), dimension(:), pointer, contiguous :: ctemp => null() !< temporary array of size (nviscspec) to pass to calc_visc_x
47 character(len=LENMODELNAME), dimension(:), allocatable :: cmodelname !< names of gwt (or gwe) models used in viscosity equation
48 character(len=LENAUXNAME), dimension(:), allocatable :: cauxspeciesname !< names of aux columns used in viscosity equation
49 character(len=LENAUXNAME) :: name_temp_spec = 'TEMPERATURE'
50 !
51 ! -- Viscosity constants
52 real(dp), pointer :: a2 => null() !< an empirical parameter specified by the user for calculating viscosity
53 real(dp), pointer :: a3 => null() !< an empirical parameter specified by the user for calculating viscosity
54 real(dp), pointer :: a4 => null() !< an empirical parameter specified by the user for calculating viscosity
55
56 type(concentrationpointer), allocatable, dimension(:) :: modelconc !< concentration (or temperature) pointer for each solute (or heat) transport model
57
58 real(dp), dimension(:), pointer, contiguous :: k11 => null() !< NPF hydraulic conductivity; if anisotropic, then this is Kx prior to rotation
59 real(dp), dimension(:), pointer, contiguous :: k22 => null() !< NPF hydraulic conductivity; if specified then this is Ky prior to rotation
60 real(dp), dimension(:), pointer, contiguous :: k33 => null() !< NPF hydraulic conductivity; if specified then this is Kz prior to rotation
61 real(dp), dimension(:), pointer, contiguous :: k11input => null() !< NPF hydraulic conductivity as originally specified by the user
62 real(dp), dimension(:), pointer, contiguous :: k22input => null() !< NPF hydraulic conductivity as originally specified by the user
63 real(dp), dimension(:), pointer, contiguous :: k33input => null() !< NPF hydraulic conductivity as originally specified by the user
64 integer(I4B), pointer :: kchangeper => null() ! last stress period in which any node K (or K22, or K33) values were changed (0 if unchanged from start of simulation)
65 integer(I4B), pointer :: kchangestp => null() ! last time step in which any node K (or K22, or K33) values were changed (0 if unchanged from start of simulation)
66 integer(I4B), dimension(:), pointer, contiguous :: nodekchange => null() ! grid array of flags indicating for each node whether its K (or K22, or K33) value changed (1) at (kchangeper, kchangestp) or not (0)
67
68 contains
69
70 procedure :: vsc_df
71 procedure :: vsc_ar
72 procedure, public :: vsc_ar_bnd
73 procedure :: vsc_rp
74 procedure :: vsc_ad
75 procedure, public :: vsc_ad_bnd
76 procedure :: vsc_ot_dv
77 procedure :: vsc_da
78 procedure, private :: vsc_calcvisc
79 procedure :: allocate_scalars
80 procedure, private :: allocate_arrays
81 procedure, private :: source_options
82 procedure, private :: set_options
83 procedure, private :: log_options
84 procedure, private :: source_dimensions
85 procedure, private :: source_packagedata
86 procedure, private :: set_packagedata
87 procedure, private :: set_npf_pointers
88 procedure, public :: update_k_with_vsc
89 procedure, private :: vsc_set_changed_at
90 procedure, public :: calc_q_visc
91 procedure, public :: get_visc_ratio
93 end type gwfvsctype
94
95contains
96
97 !> @brief Generic function to calculate changes in fluid viscosity using a
98 !! linear formulation
99 !<
100 function calc_visc(ivisc, viscref, dviscdc, cviscref, conc, &
101 a2, a3, a4) result(visc)
102 ! -- dummy
103 integer(I4B), dimension(:), intent(in) :: ivisc
104 real(dp), intent(in) :: viscref
105 real(dp), dimension(:), intent(in) :: dviscdc
106 real(dp), dimension(:), intent(in) :: cviscref
107 real(dp), dimension(:), intent(in) :: conc
108 real(dp), intent(in) :: a2, a3, a4
109 ! -- return
110 real(dp) :: visc
111 ! -- local
112 integer(I4B) :: nviscspec
113 integer(I4B) :: i
114 real(dp) :: mu_t
115 real(dp) :: expon
116 !
117 nviscspec = size(dviscdc)
118 visc = viscref
119 !
120 do i = 1, nviscspec
121 if (ivisc(i) == 1) then
122 visc = visc + dviscdc(i) * (conc(i) - cviscref(i))
123 else
124 expon = -1 * a3 * ((conc(i) - cviscref(i)) / &
125 ((conc(i) + a4) * (cviscref(i) + a4)))
126 mu_t = viscref * a2**expon
127 ! Order matters!! (This assumes we apply the temperature correction after
128 ! accounting for solute concentrations)
129 ! If a nonlinear correction is applied, then b/c it takes into account
130 ! viscref, need to subtract it in this case
131 ! At most, there will only ever be 1 nonlinear correction
132 visc = (visc - viscref) + mu_t
133 end if
134 ! end if
135 end do
136 end function calc_visc
137
138 !> @ brief Create a new package object
139 !!
140 !! Create a new VSC Package object.
141 !<
142 subroutine vsc_cr(vscobj, name_model, input_mempath, inunit, iout)
143 ! -- dummy
144 type(gwfvsctype), pointer :: vscobj
145 character(len=*), intent(in) :: name_model
146 character(len=*), intent(in) :: input_mempath
147 integer(I4B), intent(in) :: inunit
148 integer(I4B), intent(in) :: iout
149 !
150 ! -- Create the object
151 allocate (vscobj)
152 !
153 ! -- create name and memory path
154 call vscobj%set_names(1, name_model, 'VSC', 'VSC', input_mempath)
155 !
156 ! -- Allocate scalars
157 call vscobj%allocate_scalars()
158 !
159 ! -- Set variables
160 vscobj%inunit = inunit
161 vscobj%iout = iout
162 end subroutine vsc_cr
163
164 !> @ brief Define viscosity package options and dimensions
165 !!
166 !! Define viscosity package options and dimensions
167 !<
168 subroutine vsc_df(this, dis, vsc_input)
169 ! -- dummy
170 class(gwfvsctype) :: this !< this viscosity package
171 class(disbasetype), pointer, intent(in) :: dis !< pointer to discretization
172 type(gwfvscinputdatatype), optional, intent(in) :: vsc_input !< optional vsc input data, otherwise read from file
173 ! -- formats
174 character(len=*), parameter :: fmtvsc = &
175 "(1x,/1x,'VSC -- Viscosity Package, version 1, 11/15/2022', &
176 &' input read from mempath: ', a, /)"
177 !
178 ! --print a message identifying the viscosity package
179 write (this%iout, fmtvsc) this%input_mempath
180 !
181 ! -- store pointers to arguments that were passed in
182 this%dis => dis
183 !
184 if (.not. present(vsc_input)) then
185 !
186 ! -- Read viscosity options
187 call this%source_options()
188 !
189 ! -- Read viscosity dimensions
190 call this%source_dimensions()
191 else
192 ! set from input data instead
193 call this%set_options(vsc_input)
194 this%nviscspecies = vsc_input%nviscspecies
195 end if
196 !
197 ! -- Allocate arrays
198 call this%allocate_arrays(dis%nodes)
199 !
200 if (.not. present(vsc_input)) then
201 !
202 ! -- Read viscosity packagedata
203 call this%source_packagedata()
204 else
205 ! set from input data instead
206 call this%set_packagedata(vsc_input)
207 end if
208 end subroutine vsc_df
209
210 !> @ brief Allocate and read method for viscosity package
211 !!
212 !! Generic method to allocate and read static data for the viscosity
213 !! package available within the GWF model type.
214 !<
215 subroutine vsc_ar(this, ibound)
216 ! -- dummy
217 class(gwfvsctype) :: this
218 integer(I4B), dimension(:), pointer :: ibound
219 !
220 ! -- store pointers to arguments that were passed in
221 this%ibound => ibound
222 !
223 ! -- Set pointers to npf variables
224 call this%set_npf_pointers()
225 end subroutine vsc_ar
226
227 !> @brief Activate viscosity in advanced packages
228 !!
229 !! Viscosity ar_bnd routine to activate viscosity in the advanced
230 !! packages. This routine is called from gwf_ar() as it moves through each
231 !! package
232 !<
233 subroutine vsc_ar_bnd(this, packobj)
234 ! -- modules
235 use bndmodule, only: bndtype
236 use drnmodule, only: drntype
237 use ghbmodule, only: ghbtype
238 use rivmodule, only: rivtype
239 use lakmodule, only: laktype
240 use sfrmodule, only: sfrtype
241 use mawmodule, only: mawtype
242 ! -- dummy
243 class(gwfvsctype) :: this
244 class(bndtype), pointer :: packobj
245 !
246 ! -- Add density terms based on boundary package type
247 select case (packobj%filtyp)
248 case ('DRN')
249 !
250 ! -- activate viscosity for the drain package
251 select type (packobj)
252 type is (drntype)
253 call packobj%bnd_activate_viscosity()
254 end select
255 case ('GHB')
256 !
257 ! -- activate viscosity for the drain package
258 select type (packobj)
259 type is (ghbtype)
260 call packobj%bnd_activate_viscosity()
261 end select
262 case ('RIV')
263 !
264 ! -- activate viscosity for the drain package
265 select type (packobj)
266 type is (rivtype)
267 call packobj%bnd_activate_viscosity()
268 end select
269 case ('LAK')
270 !
271 ! -- activate viscosity for lake package
272 select type (packobj)
273 type is (laktype)
274 call packobj%lak_activate_viscosity()
275 end select
276 case ('SFR')
277 !
278 ! -- activate viscosity for sfr package
279 select type (packobj)
280 type is (sfrtype)
281 call packobj%sfr_activate_viscosity()
282 end select
283 case ('MAW')
284 !
285 ! -- activate viscosity for maw package
286 select type (packobj)
287 type is (mawtype)
288 call packobj%maw_activate_viscosity()
289 end select
290 case default
291 !
292 ! -- nothing
293 end select
294 end subroutine vsc_ar_bnd
295
296 !> @brief Set pointers to NPF variables
297 !!
298 !! Set array and variable pointers from the NPF
299 !! package for access by VSC.
300 !<
301 subroutine set_npf_pointers(this)
302 ! -- dummy
303 class(gwfvsctype) :: this
304 ! -- local
305 character(len=LENMEMPATH) :: npfMemoryPath
306 !
307 ! -- Set pointers to other package variables
308 ! -- NPF
309 npfmemorypath = create_mem_path(this%name_model, 'NPF')
310 call mem_setptr(this%k11, 'K11', npfmemorypath)
311 call mem_setptr(this%k22, 'K22', npfmemorypath)
312 call mem_setptr(this%k33, 'K33', npfmemorypath)
313 call mem_setptr(this%k11input, 'K11INPUT', npfmemorypath)
314 call mem_setptr(this%k22input, 'K22INPUT', npfmemorypath)
315 call mem_setptr(this%k33input, 'K33INPUT', npfmemorypath)
316 call mem_setptr(this%kchangeper, 'KCHANGEPER', npfmemorypath)
317 call mem_setptr(this%kchangestp, 'KCHANGESTP', npfmemorypath)
318 call mem_setptr(this%nodekchange, 'NODEKCHANGE', npfmemorypath)
319 end subroutine set_npf_pointers
320
321 !> @ brief Read new period data in viscosity package
322 !!
323 !! Method to read and prepare period data for the VSC package.
324 !<
325 subroutine vsc_rp(this)
326 ! -- modules
327 use tdismodule, only: kstp, kper
328 ! -- dummy
329 class(gwfvsctype) :: this
330 ! -- local
331 integer(I4B) :: i
332 ! -- formats
333 character(len=*), parameter :: fmtc = &
334 "('Viscosity Package does not have a concentration set &
335 &for species ',i0,'. One or more model names may be specified &
336 &incorrectly in the PACKAGEDATA block or a GWF-GWT exchange may need &
337 &to be activated.')"
338 !
339 ! -- Check to make sure all concentration pointers have been set
340 if (kstp * kper == 1) then
341 do i = 1, this%nviscspecies
342 if (.not. associated(this%modelconc(i)%conc)) then
343 write (errmsg, fmtc) i
344 call store_error(errmsg)
345 end if
346 end do
347 if (count_errors() > 0) then
348 call store_error_filename(this%input_fname)
349 end if
350 end if
351 end subroutine vsc_rp
352
353 !> @ brief Advance the viscosity package
354 !!
355 !! Advance data in the VSC package. The method sets or advances time series,
356 !! time array series, and observation data.
357 !<
358 subroutine vsc_ad(this)
359 ! -- dummy
360 class(gwfvsctype) :: this
361 !
362 ! -- update viscosity using the latest concentration/temperature
363 call this%vsc_calcvisc()
364 end subroutine vsc_ad
365
366 !> @brief Advance the boundary packages when viscosity is active
367 !!
368 !! Update the conductance values associate with inflow from a boundary
369 !! when VSC package is active.
370 !<
371 subroutine vsc_ad_bnd(this, packobj, hnew)
372 ! -- modules
373 use bndmodule, only: bndtype
374 ! -- dummy
375 class(gwfvsctype) :: this
376 class(bndtype), pointer :: packobj
377 real(DP), intent(in), dimension(:) :: hnew
378 ! -- local
379 integer(I4B) :: i, j
380 integer(I4B) :: n, locvisc, locelev
381 integer(I4B), dimension(:), allocatable :: locconc
382 !
383 ! -- initialize
384 locvisc = 0
385 locelev = 0
386 allocate (locconc(this%nviscspecies))
387 locconc(:) = 0
388 !
389 ! -- Add viscosity terms for conductance-dependent boundaries
390 do n = 1, packobj%naux
391 if (packobj%auxname(n) == 'VISCOSITY') then
392 locvisc = n
393 else if (packobj%auxname(n) == 'ELEVATION') then
394 locelev = n
395 end if
396 end do
397 !
398 ! -- find aux columns for conc (or temp.) that affect viscosity
399 do i = 1, this%nviscspecies
400 locconc(i) = 0
401 do j = 1, packobj%naux
402 if (this%cauxspeciesname(i) == packobj%auxname(j)) then
403 locconc(i) = j
404 exit
405 end if
406 end do
407 if (locconc(i) == 0) then
408 ! -- one not found, so don't use and mark all as 0
409 locconc(:) = 0
410 exit
411 end if
412 end do
413 !
414 ! -- apply viscosity terms to inflow from boundary based on package type
415 select case (packobj%filtyp)
416 case ('GHB', 'DRN', 'RIV')
417 !
418 ! -- general head, drain, and river boundary
419 call vsc_ad_standard_bnd(packobj, hnew, this%visc, this%viscref, &
420 locelev, locvisc, locconc, this%dviscdc, &
421 this%cviscref, this%ivisc, this%a2, this%a3, &
422 this%a4, this%ctemp)
423 case ('LAK')
424 !
425 ! -- lake
426 ! Update 'viscratios' internal to lak such that they are
427 ! automatically applied in the LAK calc_cond() routine
428 call vsc_ad_lak(packobj, this%visc, this%viscref, this%elev, locvisc, &
429 locconc, this%dviscdc, this%cviscref, this%ivisc, &
430 this%a2, this%a3, this%a4, this%ctemp)
431 case ('SFR')
432 !
433 ! -- streamflow routing
434 ! Update 'viscratios' internal to sfr such that they are
435 ! automatically applied in the SFR calc_cond() routine
436 call vsc_ad_sfr(packobj, this%visc, this%viscref, this%elev, locvisc, &
437 locconc, this%dviscdc, this%cviscref, this%ivisc, &
438 this%a2, this%a3, this%a4, this%ctemp)
439 case ('MAW')
440 !
441 ! -- multi-aquifer well
442 call vsc_ad_maw(packobj, this%visc, this%viscref, this%elev, locvisc, &
443 locconc, this%dviscdc, this%cviscref, this%ivisc, &
444 this%a2, this%a3, this%a4, this%ctemp)
445 case ('UZF')
446 !
447 ! -- unsaturated-zone flow
448 case default
449 !
450 ! -- nothing
451 end select
452 !
453 ! -- deallocate
454 deallocate (locconc)
455 end subroutine vsc_ad_bnd
456
457 !> @brief advance ghb while accounting for viscosity
458 !!
459 !! When flow enters from ghb boundary type, take into account the effects
460 !! of viscosity on the user-specified conductance terms
461 !<
462 subroutine vsc_ad_standard_bnd(packobj, hnew, visc, viscref, locelev, &
463 locvisc, locconc, dviscdc, cviscref, &
464 ivisc, a2, a3, a4, ctemp)
465 ! -- modules
466 use bndmodule, only: bndtype
467 use drnmodule, only: drntype
468 use rivmodule, only: rivtype
469 use ghbmodule, only: ghbtype
470 class(bndtype), pointer :: packobj
471 ! -- dummy
472 real(DP), intent(in), dimension(:) :: hnew
473 real(DP), intent(in), dimension(:) :: visc
474 real(DP), intent(in) :: a2, a3, a4
475 real(DP), intent(in) :: viscref
476 integer(I4B), intent(in) :: locelev
477 integer(I4B), intent(in) :: locvisc
478 integer(I4B), dimension(:), intent(in) :: locconc
479 integer(I4B), dimension(:), intent(in) :: ivisc
480 real(DP), dimension(:), intent(in) :: dviscdc
481 real(DP), dimension(:), intent(in) :: cviscref
482 real(DP), dimension(:), intent(inout) :: ctemp
483 ! -- local
484 integer(I4B) :: n
485 integer(I4B) :: node
486 real(DP) :: viscbnd
487 !
488 ! -- Process density terms for each GHB
489 do n = 1, packobj%nbound
490 node = packobj%nodelist(n)
491 !
492 ! -- Check if boundary cell is active, cycle if not
493 if (packobj%ibound(node) <= 0) cycle
494 !
495 ! -- calculate the viscosity associated with the boundary
496 viscbnd = calc_bnd_viscosity(n, locvisc, locconc, viscref, dviscdc, &
497 cviscref, ctemp, ivisc, a2, a3, a4, &
498 packobj%auxvar)
499 !
500 ! -- update boundary conductance based on viscosity effects
501 select case (packobj%filtyp)
502 case ('DRN')
503 select type (packobj)
504 type is (drntype)
505 packobj%cond(n) = update_bnd_cond(viscbnd, viscref, &
506 packobj%condinput(n))
507 end select
508 case ('GHB')
509 select type (packobj)
510 type is (ghbtype)
511 packobj%cond(n) = update_bnd_cond(viscbnd, viscref, &
512 packobj%condinput(n))
513 end select
514 case ('RIV')
515 select type (packobj)
516 type is (rivtype)
517 packobj%cond(n) = update_bnd_cond(viscbnd, viscref, &
518 packobj%condinput(n))
519 end select
520 case default
521 packobj%bound(2, n) = update_bnd_cond(viscbnd, viscref, &
522 packobj%condinput(n))
523 end select
524 !
525 end do
526 end subroutine vsc_ad_standard_bnd
527
528 !> @brief Update sfr-related viscosity ratios
529 !!
530 !! When the viscosity package is active, update the viscosity ratio that is
531 !! applied to the hydraulic conductivity specified in the SFR package
532 !<
533 subroutine vsc_ad_sfr(packobj, visc, viscref, elev, locvisc, locconc, &
534 dviscdc, cviscref, ivisc, a2, a3, a4, ctemp)
535 ! -- modules
536 use bndmodule, only: bndtype
537 use sfrmodule, only: sfrtype
538 class(bndtype), pointer :: packobj
539 ! -- dummy
540 real(DP), intent(in) :: viscref
541 real(DP), intent(in) :: a2, a3, a4
542 integer(I4B), intent(in) :: locvisc
543 integer(I4B), dimension(:), intent(in) :: locconc
544 integer(I4B), dimension(:), intent(in) :: ivisc
545 real(DP), dimension(:), intent(in) :: visc
546 real(DP), dimension(:), intent(in) :: elev
547 real(DP), dimension(:), intent(in) :: dviscdc
548 real(DP), dimension(:), intent(in) :: cviscref
549 real(DP), dimension(:), intent(inout) :: ctemp
550 ! -- local
551 integer(I4B) :: n
552 integer(I4B) :: node
553 real(DP) :: viscsfr
554 !
555 ! -- update viscosity ratios for updating hyd. cond (and conductance)
556 select type (packobj)
557 type is (sfrtype)
558 do n = 1, packobj%nbound
559 !
560 ! -- get gwf node number
561 node = packobj%nodelist(n)
562 !
563 ! -- Check if boundary cell is active, cycle if not
564 if (packobj%ibound(node) <= 0) cycle
565 !
566 ! --
567 !
568 ! -- calculate the viscosity associated with the boundary
569 viscsfr = calc_bnd_viscosity(n, locvisc, locconc, viscref, dviscdc, &
570 cviscref, ctemp, ivisc, a2, a3, a4, &
571 packobj%auxvar)
572 !
573 ! -- fill sfr relative viscosity into column 1 of viscratios
574 packobj%viscratios(1, n) = calc_vsc_ratio(viscref, viscsfr)
575 !
576 ! -- fill gwf relative viscosity into column 2 of viscratios
577 packobj%viscratios(2, n) = calc_vsc_ratio(viscref, visc(node))
578 end do
579 end select
580 end subroutine vsc_ad_sfr
581
582 !> @brief Update lak-related viscosity ratios
583 !!
584 !! When the viscosity package is active, update the viscosity ratio that is
585 !! applied to the lakebed conductance calculated in the LAK package
586 !<
587 subroutine vsc_ad_lak(packobj, visc, viscref, elev, locvisc, locconc, &
588 dviscdc, cviscref, ivisc, a2, a3, a4, ctemp)
589 ! -- modules
590 use bndmodule, only: bndtype
591 use lakmodule, only: laktype
592 class(bndtype), pointer :: packobj
593 ! -- dummy
594 real(DP), intent(in) :: viscref
595 real(DP), intent(in) :: a2, a3, a4
596 integer(I4B), intent(in) :: locvisc
597 integer(I4B), dimension(:), intent(in) :: locconc
598 integer(I4B), dimension(:), intent(in) :: ivisc
599 real(DP), dimension(:), intent(in) :: visc
600 real(DP), dimension(:), intent(in) :: elev
601 real(DP), dimension(:), intent(in) :: dviscdc
602 real(DP), dimension(:), intent(in) :: cviscref
603 real(DP), dimension(:), intent(inout) :: ctemp
604 ! -- local
605 integer(I4B) :: n
606 integer(I4B) :: node
607 real(DP) :: visclak
608 !
609 ! -- update viscosity ratios for updating hyd. cond (and conductance)
610 select type (packobj)
611 type is (laktype)
612 do n = 1, packobj%nbound
613 !
614 ! -- get gwf node number
615 node = packobj%nodelist(n)
616 !
617 ! -- Check if boundary cell is active, cycle if not
618 if (packobj%ibound(node) <= 0) cycle
619 !
620 ! --
621 !
622 ! -- calculate the viscosity associated with the boundary
623 visclak = calc_bnd_viscosity(n, locvisc, locconc, viscref, dviscdc, &
624 cviscref, ctemp, ivisc, a2, a3, a4, &
625 packobj%auxvar)
626 !
627 ! -- fill lak relative viscosity into column 1 of viscratios
628 packobj%viscratios(1, n) = calc_vsc_ratio(viscref, visclak)
629 !
630 ! -- fill gwf relative viscosity into column 2 of viscratios
631 packobj%viscratios(2, n) = calc_vsc_ratio(viscref, visc(node))
632 end do
633 end select
634 end subroutine vsc_ad_lak
635
636 !> @brief Update maw-related viscosity ratios
637 !!
638 !! When the viscosity package is active, update the viscosity ratio that is
639 !! applied to the conductance calculated in the MAW package
640 !<
641 subroutine vsc_ad_maw(packobj, visc, viscref, elev, locvisc, locconc, &
642 dviscdc, cviscref, ivisc, a2, a3, a4, ctemp)
643 ! -- modules
644 use bndmodule, only: bndtype
645 use mawmodule, only: mawtype
646 class(bndtype), pointer :: packobj
647 ! -- dummy
648 real(DP), intent(in) :: viscref
649 real(DP), intent(in) :: a2, a3, a4
650 integer(I4B), intent(in) :: locvisc
651 integer(I4B), dimension(:), intent(in) :: locconc
652 integer(I4B), dimension(:), intent(in) :: ivisc
653 real(DP), dimension(:), intent(in) :: visc
654 real(DP), dimension(:), intent(in) :: elev
655 real(DP), dimension(:), intent(in) :: dviscdc
656 real(DP), dimension(:), intent(in) :: cviscref
657 real(DP), dimension(:), intent(inout) :: ctemp
658 ! -- local
659 integer(I4B) :: n
660 integer(I4B) :: node
661 real(DP) :: viscmaw
662 !
663 ! -- update viscosity ratios for updating hyd. cond (and conductance)
664 select type (packobj)
665 type is (mawtype)
666 do n = 1, packobj%nbound
667 !
668 ! -- get gwf node number
669 node = packobj%nodelist(n)
670 !
671 ! -- Check if boundary cell is active, cycle if not
672 if (packobj%ibound(node) <= 0) cycle
673 !
674 ! --
675 !
676 ! -- calculate the viscosity associated with the boundary
677 viscmaw = calc_bnd_viscosity(n, locvisc, locconc, viscref, dviscdc, &
678 cviscref, ctemp, ivisc, a2, a3, a4, &
679 packobj%auxvar)
680 !
681 ! -- fill lak relative viscosity into column 1 of viscratios
682 packobj%viscratios(1, n) = calc_vsc_ratio(viscref, viscmaw)
683 !
684 ! -- fill gwf relative viscosity into column 2 of viscratios
685 packobj%viscratios(2, n) = calc_vsc_ratio(viscref, visc(node))
686 end do
687 end select
688 end subroutine vsc_ad_maw
689
690 !> @brief Apply viscosity to the conductance term
691 !!
692 !! When the viscosity package is active apply the viscosity ratio to the
693 !! active boundary package's conductance term.
694 !<
695 function update_bnd_cond(bndvisc, viscref, spcfdcond) result(updatedcond)
696 ! -- dummy
697 real(dp), intent(in) :: viscref
698 real(dp), intent(in) :: bndvisc
699 real(dp), intent(in) :: spcfdcond
700 ! -- local
701 real(dp) :: vscratio
702 real(dp) :: updatedcond
703 !
704 vscratio = calc_vsc_ratio(viscref, bndvisc)
705 !
706 ! -- calculate new conductance here
707 updatedcond = vscratio * spcfdcond
708 end function update_bnd_cond
709
710 !> @brief calculate and return the viscosity ratio
711 !<
712 function calc_vsc_ratio(viscref, bndvisc) result(viscratio)
713 ! -- dummy
714 real(dp), intent(in) :: viscref
715 real(dp), intent(in) :: bndvisc
716 ! -- local
717 real(dp) :: viscratio
718 !
719 viscratio = viscref / bndvisc
720 end function calc_vsc_ratio
721
722 !> @ brief Calculate the boundary viscosity
723 !!
724 !! Return the viscosity of the boundary package using one of
725 !! the options in the following order of priority:
726 !! 1. Assign as aux variable in column with name 'VISCOSITY'
727 !! 2. Calculate using viscosity equation and nviscspecies aux columns
728 !! 3. If neither of those, then assign as viscref !!
729 !<
730 function calc_bnd_viscosity(n, locvisc, locconc, viscref, dviscdc, cviscref, &
731 ctemp, ivisc, a2, a3, a4, auxvar) result(viscbnd)
732 ! -- modules
733 ! -- dummy
734 integer(I4B), intent(in) :: n
735 integer(I4B), intent(in) :: locvisc
736 real(dp), intent(in) :: a2, a3, a4
737 integer(I4B), dimension(:), intent(in) :: ivisc
738 integer(I4B), dimension(:), intent(in) :: locconc
739 real(dp), intent(in) :: viscref
740 real(dp), dimension(:), intent(in) :: dviscdc
741 real(dp), dimension(:), intent(in) :: cviscref
742 real(dp), dimension(:), intent(inout) :: ctemp
743 real(dp), dimension(:, :), intent(in) :: auxvar
744 ! -- Return
745 real(dp) :: viscbnd
746 ! -- local
747 integer(I4B) :: i
748 !
749 ! -- assign boundary viscosity based on one of three options
750 if (locvisc > 0) then
751 ! -- assign viscosity to an aux column named 'VISCOSITY'
752 viscbnd = auxvar(locvisc, n)
753 else if (locconc(1) > 0) then
754 ! -- calculate viscosity using one or more concentration auxcolumns
755 do i = 1, size(locconc)
756 ctemp(i) = dzero
757 if (locconc(i) > 0) then
758 ctemp(i) = auxvar(locconc(i), n)
759 end if
760 end do
761 viscbnd = calc_visc(ivisc, viscref, dviscdc, cviscref, ctemp, a2, a3, a4)
762 else
763 ! -- neither of the above, so assign as viscref
764 viscbnd = viscref
765 end if
766 end function calc_bnd_viscosity
767
768 !> @brief Calculate the viscosity ratio
769 !!
770 !! Calculate the viscosity ratio applied to the hydraulic characteristic
771 !! provided by the user. The viscosity ratio is applicable only
772 !! when the hydraulic characteristic is specified as positive and will not
773 !! be applied when the hydchr is negative
774 !<
775 subroutine get_visc_ratio(this, n, m, gwhdn, gwhdm, viscratio)
776 ! -- modules
777 use constantsmodule, only: done
778 ! -- dummy
779 class(gwfvsctype) :: this
780 integer(I4B), intent(in) :: n, m
781 real(DP), intent(in) :: gwhdn, gwhdm
782 real(DP), intent(inout) :: viscratio
783 ! -- loca
784 integer(I4B) :: cellid
785 !
786 viscratio = done
787 if (gwhdm > gwhdn) then
788 cellid = m
789 else if (gwhdn >= gwhdm) then
790 cellid = n
791 end if
792 call this%calc_q_visc(cellid, viscratio)
793 end subroutine get_visc_ratio
794
795 !> @brief Account for viscosity in the aquifer hydraulic flow barriers
796 !!
797 !! Will return the viscosity associated with the upgradient node (cell)
798 !! to the HFB package for adjusting the hydraulic characteristic (hydchr)
799 !! of the barrier
800 !<
801 subroutine calc_q_visc(this, cellid, viscratio)
802 ! -- dummy variables
803 class(gwfvsctype) :: this
804 integer(I4B), intent(in) :: cellid
805 ! -- Return
806 real(DP), intent(inout) :: viscratio
807 ! -- local
808 real(DP) :: visc
809 !
810 ! -- Retrieve viscosity for the passed node number
811 visc = this%visc(cellid)
812 !
813 ! -- Calculate the viscosity ratio for the
814 viscratio = calc_vsc_ratio(this%viscref, visc)
815 end subroutine calc_q_visc
816
817 !> @brief Appled the viscosity ratio (mu_o/mu) to the hydraulic conductivity
818 !!
819 !! This routine called after updating the viscosity values using the latest
820 !! concentration and/or temperature values. The ratio mu_o/mu, reference
821 !! viscosity divided by the updated viscosity value, is multiplied by K
822 !! for each cell.
823 !<
824 subroutine update_k_with_vsc(this)
825 ! -- dummy
826 class(gwfvsctype) :: this
827 ! -- local
828 integer(I4B) :: n
829 real(DP) :: viscratio
830 !
831 ! -- For viscosity-based K's, apply change of K to K11 by starting with
832 ! user-specified K values and not the K's leftover from the last viscosity
833 ! update.
834 do n = 1, this%dis%nodes
835 call this%calc_q_visc(n, viscratio)
836 this%k11(n) = this%k11input(n) * viscratio
837 this%k22(n) = this%k22input(n) * viscratio
838 this%k33(n) = this%k33input(n) * viscratio
839 this%nodekchange(n) = 1
840 end do
841 !
842 ! -- Flag kchange
843 call this%vsc_set_changed_at(kper, kstp)
844 end subroutine update_k_with_vsc
845
846 !> @brief Mark K changes as having occurred at (kper, kstp)
847 !!
848 !! Procedure called by VSC code when K updated due to viscosity changes.
849 !! K values changed at (kper, kstp).
850 !<
851 subroutine vsc_set_changed_at(this, kper, kstp)
852 ! -- dummy variables
853 class(gwfvsctype) :: this
854 integer(I4B), intent(in) :: kper
855 integer(I4B), intent(in) :: kstp
856 !
857 this%kchangeper = kper
858 this%kchangestp = kstp
859 end subroutine vsc_set_changed_at
860
861 !> @ brief Output viscosity package dependent-variable terms.
862 !!
863 !! Save calculated viscosity array to binary file
864 !<
865 subroutine vsc_ot_dv(this, idvfl)
866 ! -- dummy
867 class(gwfvsctype) :: this
868 integer(I4B), intent(in) :: idvfl
869 ! -- local
870 character(len=1) :: cdatafmp = ' ', editdesc = ' '
871 integer(I4B) :: ibinun
872 integer(I4B) :: iprint
873 integer(I4B) :: nvaluesp
874 integer(I4B) :: nwidthp
875 real(DP) :: dinact
876 !
877 ! -- Set unit number for viscosity output
878 if (this%ioutvisc /= 0) then
879 ibinun = 1
880 else
881 ibinun = 0
882 end if
883 if (idvfl == 0) ibinun = 0
884 !
885 ! -- save viscosity array
886 if (ibinun /= 0) then
887 iprint = 0
888 dinact = dhnoflo
889 !
890 ! -- write viscosity to binary file
891 if (this%ioutvisc /= 0) then
892 ibinun = this%ioutvisc
893 call this%dis%record_array(this%visc, this%iout, iprint, ibinun, &
894 ' VISCOSITY', cdatafmp, nvaluesp, &
895 nwidthp, editdesc, dinact)
896 end if
897 end if
898 end subroutine vsc_ot_dv
899
900 !> @ brief Deallocate viscosity package memory
901 !!
902 !! Deallocate viscosity package scalars and arrays.
903 !<
904 subroutine vsc_da(this)
905 ! -- dummy
906 class(gwfvsctype) :: this
907 !
908 ! -- Deallocate arrays if package was active
909 if (this%inunit > 0) then
910 call mem_deallocate(this%visc)
911 call mem_deallocate(this%ivisc)
912 call mem_deallocate(this%dviscdc)
913 call mem_deallocate(this%cviscref)
914 call mem_deallocate(this%ctemp)
915 deallocate (this%cmodelname)
916 deallocate (this%cauxspeciesname)
917 deallocate (this%modelconc)
918 end if
919 !
920 ! -- Scalars
921 call mem_deallocate(this%thermivisc)
922 call mem_deallocate(this%idxtmpr)
923 call mem_deallocate(this%ioutvisc)
924 call mem_deallocate(this%ireadelev)
925 call mem_deallocate(this%iconcset)
926 call mem_deallocate(this%viscref)
927 call mem_deallocate(this%nviscspecies)
928 call mem_deallocate(this%a2)
929 call mem_deallocate(this%a3)
930 call mem_deallocate(this%a4)
931 !
932 ! -- Nullify pointers to other package variables
933 nullify (this%k11)
934 nullify (this%k22)
935 nullify (this%k33)
936 nullify (this%k11input)
937 nullify (this%k22input)
938 nullify (this%k33input)
939 nullify (this%kchangeper)
940 nullify (this%kchangestp)
941 nullify (this%nodekchange)
942 !
943 ! -- deallocate parent
944 call this%NumericalPackageType%da()
945 end subroutine vsc_da
946
947 !> @ brief Source dimensions for package
948 !<
949 subroutine source_dimensions(this)
950 ! -- modules
953 ! -- dummy
954 class(gwfvsctype), intent(inout) :: this
955 ! -- local
956 type(gwfvscparamfoundtype) :: found
957
958 ! update defaults from input context
959 call mem_set_value(this%nviscspecies, 'NVISCSPECIES', this%input_mempath, &
960 found%nviscspecies)
961
962 ! log dimensions
963 write (this%iout, '(/1x,a)') 'Processing VSC DIMENSIONS block'
964 write (this%iout, '(4x,a,i0)') 'NVISCSPECIES = ', this%nviscspecies
965 write (this%iout, '(1x,a)') 'End of VSC DIMENSIONS block'
966
967 ! check dimension
968 if (this%nviscspecies < 1) then
969 call store_error('NVISCSPECIES must be greater than zero.')
970 call store_error_filename(this%input_fname)
971 end if
972 end subroutine source_dimensions
973
974 !> @ brief source packagedata for package
975 !<
976 subroutine source_packagedata(this)
977 ! -- modules
981 ! -- dummy
982 class(gwfvsctype), intent(inout) :: this
983 integer(I4B), dimension(:), pointer, contiguous :: iviscspec
984 type(characterstringtype), dimension(:), pointer, &
985 contiguous :: modelnames, auxspeciesnames
986 real(DP), dimension(:), pointer, contiguous :: dviscdc, cviscref
987 integer(I4B), dimension(:), allocatable :: itemp
988 character(len=LINELENGTH) :: modelname, auxspeciesname, line
989 character(len=10) :: c10
990 character(len=16) :: c16
991 integer(I4B) :: n
992 ! -- format
993 character(len=*), parameter :: fmterr = &
994 "('Invalid value for IRHOSPEC (',i0,') detected in VSC Package. &
995 &IRHOSPEC must be > 0 and <= NVISCSPECIES, and duplicate values &
996 &are not allowed.')"
997
998 ! initialize
999 allocate (itemp(this%nviscspecies))
1000 itemp(:) = 0
1001
1002 ! set input context pointers
1003 call mem_setptr(iviscspec, 'IVISCSPEC', this%input_mempath)
1004 call mem_setptr(dviscdc, 'DVISCDC', this%input_mempath)
1005 call mem_setptr(cviscref, 'CVISCREF', this%input_mempath)
1006 call mem_setptr(modelnames, 'MODELNAME', this%input_mempath)
1007 call mem_setptr(auxspeciesnames, 'AUXSPECIESNAME', this%input_mempath)
1008
1009 ! process package data
1010 do n = 1, size(iviscspec)
1011 modelname = modelnames(n)
1012 auxspeciesname = auxspeciesnames(n)
1013
1014 if (iviscspec(n) < 1 .or. iviscspec(n) > this%nviscspecies) then
1015 write (errmsg, fmterr) iviscspec(n)
1016 call store_error(errmsg)
1017 end if
1018 if (itemp(iviscspec(n)) /= 0) then
1019 write (errmsg, fmterr) iviscspec(n)
1020 call store_error(errmsg)
1021 end if
1022 itemp(iviscspec(n)) = 1
1023 !
1024 this%dviscdc(iviscspec(n)) = dviscdc(n)
1025 this%cviscref(iviscspec(n)) = cviscref(n)
1026 this%cmodelname(iviscspec(n)) = trim(modelname)
1027 this%cauxspeciesname(iviscspec(n)) = trim(auxspeciesname)
1028 !
1029 if (auxspeciesname == this%name_temp_spec) then
1030 if (this%idxtmpr > 0) then
1031 write (errmsg, '(a)') 'More than one species in VSC input identified &
1032 &as '//trim(this%name_temp_spec)//'. Only one species may be &
1033 &designated to represent temperature.'
1034 call store_error(errmsg)
1035 else
1036 this%idxtmpr = iviscspec(n)
1037 if (this%thermivisc == 2) then
1038 this%ivisc(iviscspec(n)) = 2
1039 end if
1040 end if
1041 end if
1042 end do
1043
1044 ! Check for errors.
1045 if (count_errors() > 0) then
1046 call store_error_filename(this%input_fname)
1047 end if
1048
1049 ! log package data
1050 write (this%iout, '(/,1x,a)') 'Processing VSC PACKAGEDATA block'
1051
1052 ! write packagedata information
1053 write (this%iout, '(1x,a)') 'Summary of species information in VSC Package'
1054 write (this%iout, '(1a11,5a17)') &
1055 'Species', 'DVISCDC', 'CVISCREF', 'Model', 'AUXSPECIESNAME'
1056 do n = 1, this%nviscspecies
1057 write (c10, '(i0)') n
1058 line = ' '//adjustr(c10)
1059
1060 write (c16, '(g15.6)') this%dviscdc(n)
1061 line = trim(line)//' '//adjustr(c16)
1062 write (c16, '(g15.6)') this%cviscref(n)
1063 line = trim(line)//' '//adjustr(c16)
1064 write (c16, '(a)') this%cmodelname(n)
1065 line = trim(line)//' '//adjustr(c16)
1066 write (c16, '(a)') this%cauxspeciesname(n)
1067 line = trim(line)//' '//adjustr(c16)
1068 write (this%iout, '(a)') trim(line)
1069 end do
1070
1071 write (this%iout, '(1x,a)') 'End of VSC PACKAGEDATA block'
1072
1073 ! deallocate
1074 deallocate (itemp)
1075
1076 call memorystore_release('IVISCSPEC', this%input_mempath)
1077 call memorystore_release('DVISCDC', this%input_mempath)
1078 call memorystore_release('CVISCREF', this%input_mempath)
1079 call memorystore_release('MODELNAME', this%input_mempath)
1080 call memorystore_release('AUXSPECIESNAME', this%input_mempath)
1081 end subroutine source_packagedata
1082
1083 !> @brief Sets package data instead of reading from file
1084 !<
1085 subroutine set_packagedata(this, input_data)
1086 ! -- dummy
1087 class(gwfvsctype) :: this !< this vscoancy pkg
1088 type(gwfvscinputdatatype), intent(in) :: input_data !< the input data to be set
1089 ! -- local
1090 integer(I4B) :: ispec
1091 !
1092 do ispec = 1, this%nviscspecies
1093 this%dviscdc(ispec) = input_data%dviscdc(ispec)
1094 this%cviscref(ispec) = input_data%cviscref(ispec)
1095 this%cmodelname(ispec) = input_data%cmodelname(ispec)
1096 this%cauxspeciesname(ispec) = input_data%cauxspeciesname(ispec)
1097 end do
1098 end subroutine set_packagedata
1099
1100 !> @brief Calculate fluid viscosity
1101 !!
1102 !! Calculates fluid viscosity based on concentration or
1103 !! temperature
1104 !<
1105 subroutine vsc_calcvisc(this)
1106 ! -- dummy
1107 class(gwfvsctype) :: this
1108 ! -- local
1109 integer(I4B) :: n
1110 integer(I4B) :: i
1111 !
1112 ! -- Calculate the viscosity using the specified concentration and/or
1113 ! temperature arrays
1114 do n = 1, this%dis%nodes
1115 do i = 1, this%nviscspecies
1116 if (this%modelconc(i)%icbund(n) == 0) then
1117 this%ctemp(i) = dzero
1118 else
1119 this%ctemp(i) = this%modelconc(i)%conc(n)
1120 end if
1121 end do
1122 !
1123 this%visc(n) = calc_visc(this%ivisc, this%viscref, this%dviscdc, &
1124 this%cviscref, this%ctemp, this%a2, &
1125 this%a3, this%a4)
1126 end do
1127 end subroutine vsc_calcvisc
1128
1129 !> @ brief Allocate scalars
1130 !!
1131 !! Allocate and initialize scalars for the VSC package. The base model
1132 !! allocate scalars method is also called.
1133 !<
1134 subroutine allocate_scalars(this)
1135 ! -- modules
1136 use constantsmodule, only: dzero, dten, dep3
1137 ! -- dummy
1138 class(gwfvsctype) :: this
1139 !
1140 ! -- allocate scalars in NumericalPackageType
1141 call this%NumericalPackageType%allocate_scalars()
1142 !
1143 ! -- Allocate
1144 call mem_allocate(this%thermivisc, 'THERMIVISC', this%memoryPath)
1145 call mem_allocate(this%idxtmpr, 'IDXTMPR', this%memoryPath)
1146 call mem_allocate(this%ioutvisc, 'IOUTVISC', this%memoryPath)
1147 call mem_allocate(this%ireadelev, 'IREADELEV', this%memoryPath)
1148 call mem_allocate(this%iconcset, 'ICONCSET', this%memoryPath)
1149 call mem_allocate(this%viscref, 'VISCREF', this%memoryPath)
1150 call mem_allocate(this%a2, 'A2', this%memoryPath)
1151 call mem_allocate(this%a3, 'A3', this%memoryPath)
1152 call mem_allocate(this%a4, 'A4', this%memoryPath)
1153 !
1154 call mem_allocate(this%nviscspecies, 'NVISCSPECIES', this%memoryPath)
1155 !
1156 ! -- Initialize
1157 this%thermivisc = 0
1158 this%idxtmpr = 0
1159 this%ioutvisc = 0
1160 this%ireadelev = 0
1161 this%iconcset = 0
1162 this%viscref = dep3
1163 this%A2 = dten
1164 this%A3 = 248.37_dp
1165 this%A4 = 133.15_dp
1166 !
1167 this%nviscspecies = 0
1168 end subroutine allocate_scalars
1169
1170 !> @ brief Allocate arrays
1171 !!
1172 !! Allocate and initialize arrays for the VSC package.
1173 !<
1174 subroutine allocate_arrays(this, nodes)
1175 ! -- dummy
1176 class(gwfvsctype) :: this
1177 integer(I4B), intent(in) :: nodes
1178 ! -- local
1179 integer(I4B) :: i
1180 !
1181 ! -- Allocate
1182 call mem_allocate(this%visc, nodes, 'VISC', this%memoryPath)
1183 call mem_allocate(this%ivisc, this%nviscspecies, 'IVISC', this%memoryPath)
1184 call mem_allocate(this%dviscdc, this%nviscspecies, 'DRHODC', &
1185 this%memoryPath)
1186 call mem_allocate(this%cviscref, this%nviscspecies, 'CRHOREF', &
1187 this%memoryPath)
1188 call mem_allocate(this%ctemp, this%nviscspecies, 'CTEMP', this%memoryPath)
1189 allocate (this%cmodelname(this%nviscspecies))
1190 allocate (this%cauxspeciesname(this%nviscspecies))
1191 allocate (this%modelconc(this%nviscspecies))
1192 !
1193 ! -- Initialize
1194 do i = 1, nodes
1195 this%visc(i) = this%viscref
1196 end do
1197 !
1198 ! -- Initialize nviscspecies arrays
1199 do i = 1, this%nviscspecies
1200 this%ivisc(i) = 1
1201 this%dviscdc(i) = dzero
1202 this%cviscref(i) = dzero
1203 this%ctemp(i) = dzero
1204 this%cmodelname(i) = ''
1205 this%cauxspeciesname(i) = ''
1206 end do
1207 end subroutine allocate_arrays
1208
1209 !> @ brief Source VSC options
1210 !<
1211 subroutine source_options(this)
1212 ! -- modules
1213 use constantsmodule, only: lenvarname
1215 use openspecmodule, only: access, form
1218 ! -- dummy
1219 class(gwfvsctype), intent(inout) :: this
1220 ! -- local
1221 character(len=LENVARNAME), dimension(2) :: thermal_form = &
1222 &[character(len=LENVARNAME) :: 'LINEAR', 'NONLINEAR']
1223 character(len=linelength) :: viscosityfile
1224 type(gwfvscparamfoundtype) :: found
1225
1226 ! initialize variables
1227 viscosityfile = ''
1228
1229 ! update defaults from input context
1230 call mem_set_value(this%viscref, 'VISCREF', this%input_mempath, &
1231 found%viscref)
1232 call mem_set_value(viscosityfile, 'VISCOSITYFILE', this%input_mempath, &
1233 found%viscosityfile)
1234 call mem_set_value(this%name_temp_spec, 'TEMP_SPECNAME', this%input_mempath, &
1235 found%temp_specname)
1236 call mem_set_value(this%thermivisc, 'THERMAL_FORM', this%input_mempath, &
1237 thermal_form, found%thermal_form)
1238 call mem_set_value(this%a2, 'THERMAL_A2', this%input_mempath, &
1239 found%thermal_a2)
1240 call mem_set_value(this%a3, 'THERMAL_A3', this%input_mempath, &
1241 found%thermal_a3)
1242 call mem_set_value(this%a4, 'THERMAL_A4', this%input_mempath, &
1243 found%thermal_a4)
1244
1245 ! fileout options
1246 if (found%viscosityfile) then
1247 this%ioutvisc = getunit()
1248 call openfile(this%ioutvisc, this%iout, viscosityfile, 'DATA(BINARY)', &
1249 form, access, 'REPLACE')
1250 end if
1251
1252 ! -- verify THERMAL_FORM input value is supported
1253 if (found%thermal_form) then
1254 if (this%thermivisc == 0) then
1255 call store_error('Unrecognized input value for THERMAL_FORM option.')
1256 call store_error_filename(this%input_fname)
1257 end if
1258 end if
1259
1260 ! set warnings and errors
1261 if (this%thermivisc == 1) then
1262 if (this%a2 == 0.0) then
1263 write (errmsg, '(a)') 'LINEAR option selected for varying &
1264 &viscosity with temperature, but A1, a surrogate for &
1265 &dVISC/dT, set equal to 0.0'
1266 call store_error(errmsg)
1267 call store_error_filename(this%input_fname)
1268 end if
1269 end if
1270 if (this%thermivisc > 1) then
1271 if (this%a2 == 0) then
1272 write (warnmsg, '(a)') 'NONLINEAR option selected for &
1273 &varying viscosity with temperature, but A2 set equal to &
1274 &zero which may lead to unintended values for viscosity'
1276 end if
1277 if (this%a3 == 0) then
1278 write (warnmsg, '(a)') 'NONLINEAR option selected for &
1279 &varying viscosity with temperature,, but A3 set equal to &
1280 &zero which may lead to unintended values for viscosity'
1282 end if
1283 if (this%a4 == 0) then
1284 write (warnmsg, '(a)') 'NONLINEAR option selected for &
1285 &varying viscosity with temperature, BUT A4 SET EQUAL TO &
1286 &zero which may lead to unintended values for viscosity'
1288 end if
1289 end if
1290
1291 ! log options
1292 call this%log_options(found, viscosityfile)
1293 end subroutine source_options
1294
1295 !> @ brief log VSC options
1296 !<
1297 subroutine log_options(this, found, viscosityfile)
1298 ! -- modules
1300 ! -- dummy variables
1301 class(gwfvsctype), intent(inout) :: this
1302 type(gwfvscparamfoundtype), intent(in) :: found
1303 character(len=*), intent(in) :: viscosityfile
1304 ! -- local variables
1305 ! -- formats
1306 character(len=*), parameter :: fmtfileout = &
1307 "(4x, 'VSC', 1x, a, 1x, 'Will be saved to file: ', &
1308 &a, ' opened on unit: ', I7)"
1309 character(len=*), parameter :: fmtlinear = &
1310 "(4x,'Viscosity will vary linearly with temperature &
1311 &change ')"
1312 character(len=*), parameter :: fmtnonlinear = &
1313 "(4x,'Viscosity will vary non-linearly with temperature &
1314 &change ')"
1315
1316 write (this%iout, '(1x,a)') 'Processing VSC OPTIONS block'
1317
1318 if (found%viscref) then
1319 write (this%iout, '(4x,a,1pg15.6)') &
1320 'Reference viscosity has been set to: ', this%viscref
1321 end if
1322 if (found%viscosityfile) then
1323 write (this%iout, fmtfileout) &
1324 'VISCOSITY', trim(viscosityfile), this%ioutvisc
1325 end if
1326 if (found%temp_specname) then
1327 write (this%iout, '(4x, a)') 'Temperature species name set to: '// &
1328 trim(this%name_temp_spec)
1329 end if
1330 if (found%thermal_form) then
1331 select case (this%thermivisc)
1332 case (1)
1333 write (this%iout, fmtlinear)
1334 case (2)
1335 write (this%iout, fmtnonlinear)
1336 end select
1337 end if
1338 if (found%thermal_a2) then
1339 if (this%thermivisc == 2) then
1340 write (this%iout, '(4x,a,1pg15.6)') &
1341 'A2 in nonlinear viscosity formulation has been set to: ', &
1342 this%a2
1343 else
1344 write (this%iout, '(4x,a,/,4x,a,/,4x,a)') 'THERMAL_A2 specified by user &
1345 &in VSC Package input file. LINEAR viscosity ', 'formulation also &
1346 &specified. THERMAL_A2 will not affect ', 'viscosity calculations.'
1347 end if
1348 end if
1349 if (found%thermal_a3) then
1350 if (this%thermivisc == 2) then
1351 write (this%iout, '(4x,a,1pg15.6)') &
1352 'A3 in nonlinear viscosity formulation has been set to: ', &
1353 this%a3
1354 else
1355 write (this%iout, '(4x,a,/,4x,a,/,4x,a)') 'THERMAL_A3 specified by user &
1356 &in VSC Package input file. LINEAR viscosity ', 'formulation also &
1357 &specified. THERMAL_A3 will not affect ', 'viscosity calculations.'
1358 end if
1359 end if
1360 if (found%thermal_a4) then
1361 if (this%thermivisc == 2) then
1362 write (this%iout, '(4x,a,1pg15.6)') &
1363 'A4 in nonlinear viscosity formulation has been set to: ', &
1364 this%a4
1365 else
1366 write (this%iout, '(4x,a,/,4x,a,/,4x,a)') 'THERMAL_A4 specified by user &
1367 &in VSC Package input file. LINEAR viscosity ', 'formulation also &
1368 &specified. THERMAL_A4 will not affect ', 'viscosity calculations.'
1369 end if
1370 end if
1371
1372 write (this%iout, '(1x,a)') 'end of VSC options block'
1373 end subroutine log_options
1374
1375 !> @brief Sets options as opposed to reading them from a file
1376 !<
1377 subroutine set_options(this, input_data)
1378 ! -- dummy
1379 class(gwfvsctype) :: this
1380 type(gwfvscinputdatatype), intent(in) :: input_data !< the input data to be set
1381 !
1382 this%viscref = input_data%viscref
1383 end subroutine set_options
1384
1385 !> @ brief Set pointers to concentration(s)
1386 !!
1387 !! Pass in a gwt model name, concentration array, and ibound,
1388 !! and store a pointer to these in the VSC package so that
1389 !! viscosity can be calculated from them. This routine is called
1390 !! from the gwfgwt exchange in the exg_ar() method.
1391 !<
1392 subroutine set_concentration_pointer(this, modelname, conc, icbund, istmpr)
1393 ! -- dummy
1394 class(gwfvsctype) :: this
1395 character(len=LENMODELNAME), intent(in) :: modelname
1396 real(DP), dimension(:), pointer :: conc
1397 integer(I4B), dimension(:), pointer :: icbund
1398 integer(I4B), optional, intent(in) :: istmpr
1399 ! -- local
1400 integer(I4B) :: i
1401 logical :: found
1402 !
1403 this%iconcset = 1
1404 found = .false.
1405 do i = 1, this%nviscspecies
1406 if (this%cmodelname(i) == modelname) then
1407 this%modelconc(i)%conc => conc
1408 this%modelconc(i)%icbund => icbund
1409 found = .true.
1410 exit
1411 end if
1412 end do
1413 end subroutine set_concentration_pointer
1414
1415end module gwfvscmodule
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
real(dp), parameter dep3
real constant 1000
Definition Constants.f90:88
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
integer(i4b), parameter lenvarname
maximum length of a variable name
Definition Constants.f90:17
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
real(dp), parameter dten
real constant 10
Definition Constants.f90:84
integer(i4b), parameter maxcharlen
maximum length of char string
Definition Constants.f90:47
integer(i4b), parameter lenmempath
maximum length of the memory path
Definition Constants.f90:27
real(dp), parameter done
real constant 1
Definition Constants.f90:76
subroutine source_options(this)
@ brief Source VSC options
Definition gwf-vsc.f90:1212
subroutine vsc_da(this)
@ brief Deallocate viscosity package memory
Definition gwf-vsc.f90:905
subroutine allocate_arrays(this, nodes)
@ brief Allocate arrays
Definition gwf-vsc.f90:1175
subroutine, public vsc_cr(vscobj, name_model, input_mempath, inunit, iout)
@ brief Create a new package object
Definition gwf-vsc.f90:143
subroutine vsc_set_changed_at(this, kper, kstp)
Mark K changes as having occurred at (kper, kstp).
Definition gwf-vsc.f90:852
subroutine update_k_with_vsc(this)
Appled the viscosity ratio (mu_o/mu) to the hydraulic conductivity.
Definition gwf-vsc.f90:825
subroutine vsc_ad_standard_bnd(packobj, hnew, visc, viscref, locelev, locvisc, locconc, dviscdc, cviscref, ivisc, a2, a3, a4, ctemp)
advance ghb while accounting for viscosity
Definition gwf-vsc.f90:465
subroutine allocate_scalars(this)
@ brief Allocate scalars
Definition gwf-vsc.f90:1135
subroutine vsc_ad_lak(packobj, visc, viscref, elev, locvisc, locconc, dviscdc, cviscref, ivisc, a2, a3, a4, ctemp)
Update lak-related viscosity ratios.
Definition gwf-vsc.f90:589
subroutine calc_q_visc(this, cellid, viscratio)
Account for viscosity in the aquifer hydraulic flow barriers.
Definition gwf-vsc.f90:802
real(dp) function calc_vsc_ratio(viscref, bndvisc)
calculate and return the viscosity ratio
Definition gwf-vsc.f90:713
subroutine source_packagedata(this)
@ brief source packagedata for package
Definition gwf-vsc.f90:977
subroutine vsc_calcvisc(this)
Calculate fluid viscosity.
Definition gwf-vsc.f90:1106
subroutine vsc_ad(this)
@ brief Advance the viscosity package
Definition gwf-vsc.f90:359
subroutine vsc_ot_dv(this, idvfl)
@ brief Output viscosity package dependent-variable terms.
Definition gwf-vsc.f90:866
real(dp) function calc_bnd_viscosity(n, locvisc, locconc, viscref, dviscdc, cviscref, ctemp, ivisc, a2, a3, a4, auxvar)
@ brief Calculate the boundary viscosity
Definition gwf-vsc.f90:732
real(dp) function update_bnd_cond(bndvisc, viscref, spcfdcond)
Apply viscosity to the conductance term.
Definition gwf-vsc.f90:696
subroutine vsc_ar_bnd(this, packobj)
Activate viscosity in advanced packages.
Definition gwf-vsc.f90:234
subroutine set_packagedata(this, input_data)
Sets package data instead of reading from file.
Definition gwf-vsc.f90:1086
subroutine vsc_df(this, dis, vsc_input)
@ brief Define viscosity package options and dimensions
Definition gwf-vsc.f90:169
subroutine vsc_ad_sfr(packobj, visc, viscref, elev, locvisc, locconc, dviscdc, cviscref, ivisc, a2, a3, a4, ctemp)
Update sfr-related viscosity ratios.
Definition gwf-vsc.f90:535
subroutine source_dimensions(this)
@ brief Source dimensions for package
Definition gwf-vsc.f90:950
subroutine vsc_ar(this, ibound)
@ brief Allocate and read method for viscosity package
Definition gwf-vsc.f90:216
subroutine set_options(this, input_data)
Sets options as opposed to reading them from a file.
Definition gwf-vsc.f90:1378
subroutine vsc_rp(this)
@ brief Read new period data in viscosity package
Definition gwf-vsc.f90:326
subroutine vsc_ad_bnd(this, packobj, hnew)
Advance the boundary packages when viscosity is active.
Definition gwf-vsc.f90:372
subroutine get_visc_ratio(this, n, m, gwhdn, gwhdm, viscratio)
Calculate the viscosity ratio.
Definition gwf-vsc.f90:776
subroutine set_npf_pointers(this)
Set pointers to NPF variables.
Definition gwf-vsc.f90:302
subroutine vsc_ad_maw(packobj, visc, viscref, elev, locvisc, locconc, dviscdc, cviscref, ivisc, a2, a3, a4, ctemp)
Update maw-related viscosity ratios.
Definition gwf-vsc.f90:643
subroutine log_options(this, found, viscosityfile)
@ brief log VSC options
Definition gwf-vsc.f90:1298
subroutine set_concentration_pointer(this, modelname, conc, icbund, istmpr)
@ brief Set pointers to concentration(s)
Definition gwf-vsc.f90:1393
real(dp) function calc_visc(ivisc, viscref, dviscdc, cviscref, conc, a2, a3, a4)
Generic function to calculate changes in fluid viscosity using a linear formulation.
Definition gwf-vsc.f90:102
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
type(listtype), public basemodellist
Definition mf6lists.f90:16
character(len=lenmempath) function create_mem_path(component, subcomponent, context)
returns the path to the memory object
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_warning(msg, substring)
Store warning message.
Definition Sim.f90:237
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
This module contains simulation variables.
character(len=maxcharlen) errmsg
error message string
character(len=maxcharlen) warnmsg
warning message string
integer(i4b) iout
file unit number for simulation output
character(len=lenmempath), pointer input_mempath
input context mempath for tdis
Definition tdis.f90:45
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.