MODFLOW 6 version 6.9.0.dev0
USGS Modular Hydrologic Model
Loading...
Searching...
No Matches
gwe-cnd.f90
Go to the documentation of this file.
2
3 use kindmodule, only: dp, i4b
7 use tspfmimodule, only: tspfmitype
8 use xt3dmodule, only: xt3dtype, xt3d_cr
12
13 implicit none
14 private
15 public :: gwecndtype
16 public :: cnd_cr
17
19
20 integer(I4B), dimension(:), pointer, contiguous :: ibound => null() ! pointer to GWE model ibound
21 type(tspfmitype), pointer :: fmi => null() ! pointer to GWE fmi object
22 type(gweinputdatatype), pointer :: gwecommon => null() !< pointer to shared gwe data used by multiple packages but set in est
23 real(dp), dimension(:), pointer, contiguous :: porosity => null() ! pointer to GWE storage porosity
24 real(dp), dimension(:), pointer, contiguous :: alh => null() ! longitudinal horizontal dispersivity
25 real(dp), dimension(:), pointer, contiguous :: alv => null() ! longitudinal vertical dispersivity
26 real(dp), dimension(:), pointer, contiguous :: ath1 => null() ! transverse horizontal dispersivity
27 real(dp), dimension(:), pointer, contiguous :: ath2 => null() ! transverse horizontal dispersivity
28 real(dp), dimension(:), pointer, contiguous :: atv => null() ! transverse vertical dispersivity
29 real(dp), dimension(:), pointer, contiguous :: ktw => null() ! thermal conductivity of water
30 real(dp), dimension(:), pointer, contiguous :: kts => null() ! thermal conductivity of aquifer material
31 integer(I4B), pointer :: idisp => null() ! flag indicating mechanical dispersion is active
32 integer(I4B), pointer :: ialh => null() ! longitudinal horizontal dispersivity data flag
33 integer(I4B), pointer :: ialv => null() ! longitudinal vertical dispersivity data flag
34 integer(I4B), pointer :: iath1 => null() ! transverse horizontal dispersivity data flag
35 integer(I4B), pointer :: iath2 => null() ! transverse horizontal dispersivity data flag
36 integer(I4B), pointer :: iatv => null() ! transverse vertical dispersivity data flag
37 integer(I4B), pointer :: ixt3doff => null() ! xt3d off flag, xt3d is set inactive if 1
38 integer(I4B), pointer :: ixt3drhs => null() ! xt3d rhs flag, xt3d rhs is set active if 1
39 integer(I4B), pointer :: iktw => null() ! thermal conductivity of water data flag
40 integer(I4B), pointer :: ikts => null() ! thermal conductivity of aquifer material data flag
41 integer(I4B), pointer :: ixt3d => null() ! flag indicating xt3d is active
42 type(xt3dtype), pointer :: xt3d => null() ! xt3d object
43 real(dp), dimension(:), pointer, contiguous :: dispcoef => null() ! disp coefficient (only if xt3d not active)
44 integer(I4B), pointer :: id22 => null() ! flag indicating d22 is available
45 integer(I4B), pointer :: id33 => null() ! flag indicating d33 is available
46 real(dp), dimension(:), pointer, contiguous :: d11 => null() ! dispersion coefficient
47 real(dp), dimension(:), pointer, contiguous :: d22 => null() ! dispersion coefficient
48 real(dp), dimension(:), pointer, contiguous :: d33 => null() ! dispersion coefficient
49 real(dp), dimension(:), pointer, contiguous :: angle1 => null() ! rotation angle 1
50 real(dp), dimension(:), pointer, contiguous :: angle2 => null() ! rotation angle 2
51 real(dp), dimension(:), pointer, contiguous :: angle3 => null() ! rotation angle 3
52 integer(I4B), pointer :: iangle1 => null() ! flag indicating angle1 is available
53 integer(I4B), pointer :: iangle2 => null() ! flag indicating angle2 is available
54 integer(I4B), pointer :: iangle3 => null() ! flag indicating angle3 is available
55 real(dp), pointer :: eqnsclfac => null() !< governing equation scale factor; =rhow*cpw for energy
56
57 contains
58
59 procedure :: cnd_df
60 procedure :: cnd_ac
61 procedure :: cnd_mc
62 procedure :: cnd_ar
63 procedure :: cnd_ad
64 procedure :: cnd_fc
65 procedure :: cnd_cq
66 procedure :: cnd_da
67 procedure :: allocate_scalars
68 procedure :: allocate_arrays
69 procedure, private :: source_options
70 procedure, private :: source_griddata
71 procedure, private :: log_options
72 procedure, private :: log_griddata
73 procedure, private :: calcdispellipse
74 procedure, private :: calcdispcoef
75
76 end type gwecndtype
77
78contains
79
80 !> @brief Create a new CND object
81 !!
82 !! Create a new CND package
83 !<
84 subroutine cnd_cr(cndobj, name_model, input_mempath, inunit, iout, fmi, &
85 eqnsclfac, gwecommon)
86 ! -- modules
87 use kindmodule, only: lgp
89 ! -- dummy
90 type(gwecndtype), pointer :: cndobj
91 character(len=*), intent(in) :: name_model
92 character(len=*), intent(in) :: input_mempath
93 integer(I4B), intent(in) :: inunit
94 integer(I4B), intent(in) :: iout
95 type(tspfmitype), intent(in), target :: fmi
96 real(dp), intent(in), pointer :: eqnsclfac !< governing equation scale factor
97 type(gweinputdatatype), intent(in), target, optional :: gwecommon !< shared data container for use by multiple GWE packages
98 ! -- formats
99 character(len=*), parameter :: fmtcnd = &
100 "(1x,/1x,'CND-- THERMAL CONDUCTION AND DISPERSION PACKAGE, VERSION 1, ', &
101 &'01/01/2024, INPUT READ FROM MEMPATH ', A, //)"
102 !
103 ! -- Create the object
104 allocate (cndobj)
105 !
106 ! -- create name and memory path
107 call cndobj%set_names(1, name_model, 'CND', 'CND', input_mempath)
108 !
109 ! -- Allocate scalars
110 call cndobj%allocate_scalars()
111 !
112 ! -- Set variables
113 cndobj%inunit = inunit
114 cndobj%iout = iout
115 cndobj%fmi => fmi
116 cndobj%eqnsclfac => eqnsclfac
117 if (present(gwecommon)) then
118 cndobj%gwecommon => gwecommon
119 end if
120 !
121 if (cndobj%inunit > 0) then
122 !
123 ! -- Print a message identifying the dispersion package.
124 if (cndobj%iout > 0) then
125 write (cndobj%iout, fmtcnd) input_mempath
126 end if
127 end if
128 end subroutine cnd_cr
129
130 !> @brief Define CND object
131 !<
132 subroutine cnd_df(this, dis, cndOptions)
133 ! -- modules
134 ! -- dummy
135 class(gwecndtype) :: this
136 class(disbasetype), pointer :: dis
137 type(gwecndoptionstype), optional, intent(in) :: cndOptions !< the optional CND options, used when not
138 !! creating CND from file
139 !
140 ! -- Store pointer to dis
141 this%dis => dis
142 !
143 !
144 ! -- set default xt3d representation to on and lhs
145 this%ixt3d = 1
146 !
147 ! -- Read dispersion options
148 if (present(cndoptions)) then
149 this%ixt3d = cndoptions%ixt3d
150 !
151 ! -- Allocate only, grid data will not be read from file
152 call this%allocate_arrays(this%dis%nodes)
153 else
154 !
155 ! -- Source options
156 call this%source_options()
157 call this%allocate_arrays(this%dis%nodes)
158 !
159 ! -- Source dispersion data
160 call this%source_griddata()
161 end if
162 !
163 ! -- xt3d create
164 if (this%ixt3d > 0) then
165 call xt3d_cr(this%xt3d, this%name_model, this%inunit, this%iout, &
166 ldispopt=.true.)
167 this%xt3d%ixt3d = this%ixt3d
168 call this%xt3d%xt3d_df(dis)
169 end if
170 end subroutine cnd_df
171
172 !> @brief Add connections to CND
173 !!
174 !! Add connections for extended neighbors to the sparse matrix
175 !<
176 subroutine cnd_ac(this, moffset, sparse)
177 ! -- modules
178 use sparsemodule, only: sparsematrix
180 ! -- dummy
181 class(gwecndtype) :: this
182 integer(I4B), intent(in) :: moffset
183 type(sparsematrix), intent(inout) :: sparse
184 !
185 ! -- Add extended neighbors (neighbors of neighbors)
186 if (this%ixt3d > 0) call this%xt3d%xt3d_ac(moffset, sparse)
187 end subroutine cnd_ac
188
189 !> @brief Map CND connections
190 !!
191 !! Map connections and construct iax, jax, and idxglox
192 !<
193 subroutine cnd_mc(this, moffset, matrix_sln)
194 ! -- modules
196 ! -- dummy
197 class(gwecndtype) :: this
198 integer(I4B), intent(in) :: moffset
199 class(matrixbasetype), pointer :: matrix_sln
200 !
201 ! -- Call xt3d map connections
202 if (this%ixt3d > 0) call this%xt3d%xt3d_mc(moffset, matrix_sln)
203 end subroutine cnd_mc
204
205 !> @brief Allocate and read method for package
206 !!
207 !! Method to allocate and read static data for the package.
208 !<
209 subroutine cnd_ar(this, ibound, porosity)
210 ! -- modules
211 ! -- dummy
212 class(gwecndtype) :: this
213 integer(I4B), dimension(:), pointer, contiguous :: ibound
214 real(DP), dimension(:), pointer, contiguous :: porosity
215 ! -- local
216 ! -- formats
217 character(len=*), parameter :: fmtcnd = &
218 "(1x,/1x,'CND-- THERMAL CONDUCTION AND DISPERSION PACKAGE, VERSION 1, ', &
219 &'5/01/2023, INPUT READ FROM UNIT ', i0, //)"
220 !
221 ! -- cnd pointers to arguments that were passed in
222 this%ibound => ibound
223 this%porosity => porosity
224 end subroutine cnd_ar
225
226 !> @brief Advance method for the package
227 !<
228 subroutine cnd_ad(this)
229 ! -- modules
230 use tdismodule, only: kstp, kper
231 ! -- dummy
232 class(gwecndtype) :: this
233 !
234 ! -- xt3d
235 ! TODO: might consider adding a new mf6 level set pointers method, and
236 ! doing this stuff there instead of in the time step loop.
237 if (kstp * kper == 1) then
238 if (this%ixt3d > 0) then
239 call this%xt3d%xt3d_ar(this%fmi%ibdgwfsat0, this%d11, this%id33, &
240 this%d33, this%fmi%gwfsat, this%id22, this%d22, &
241 this%iangle1, this%iangle2, this%iangle3, &
242 this%angle1, this%angle2, this%angle3)
243 end if
244 end if
245 !
246 ! -- Fill d11, d22, d33, angle1, angle2, angle3 using specific discharge
247 call this%calcdispellipse()
248 !
249 ! -- Recalculate dispersion coefficients if the flows were updated
250 if (this%fmi%iflowsupdated == 1) then
251 if (this%ixt3d == 0) then
252 call this%calcdispcoef()
253 else if (this%ixt3d > 0) then
254 call this%xt3d%xt3d_fcpc(this%dis%nodes, .true.)
255 end if
256 end if
257 end subroutine cnd_ad
258
259 !> @brief Fill coefficient method for package
260 !!
261 !! Method to calculate and fill coefficients for the package.
262 !<
263 subroutine cnd_fc(this, kiter, nodes, nja, matrix_sln, idxglo, rhs, cnew)
264 ! -- dummy
265 class(gwecndtype) :: this
266 integer(I4B) :: kiter
267 integer(I4B), intent(in) :: nodes
268 integer(I4B), intent(in) :: nja
269 class(matrixbasetype), pointer :: matrix_sln
270 integer(I4B), intent(in), dimension(nja) :: idxglo
271 real(DP), intent(inout), dimension(nodes) :: rhs
272 real(DP), intent(inout), dimension(nodes) :: cnew
273 ! -- local
274 integer(I4B) :: n, m, idiag, idiagm, ipos, isympos, isymcon
275 real(DP) :: dnm
276 !
277 if (this%ixt3d > 0) then
278 call this%xt3d%xt3d_fc(kiter, matrix_sln, idxglo, rhs, cnew)
279 else
280 do n = 1, nodes
281 if (this%fmi%ibdgwfsat0(n) == 0) cycle
282 idiag = this%dis%con%ia(n)
283 do ipos = this%dis%con%ia(n) + 1, this%dis%con%ia(n + 1) - 1
284 if (this%dis%con%mask(ipos) == 0) cycle
285 m = this%dis%con%ja(ipos)
286 if (m < n) cycle
287 if (this%fmi%ibdgwfsat0(m) == 0) cycle
288 isympos = this%dis%con%jas(ipos)
289 dnm = this%dispcoef(isympos)
290 !
291 ! -- Contribution to row n
292 call matrix_sln%add_value_pos(idxglo(ipos), dnm)
293 call matrix_sln%add_value_pos(idxglo(idiag), -dnm)
294 !
295 ! -- Contribution to row m
296 idiagm = this%dis%con%ia(m)
297 isymcon = this%dis%con%isym(ipos)
298 call matrix_sln%add_value_pos(idxglo(isymcon), dnm)
299 call matrix_sln%add_value_pos(idxglo(idiagm), -dnm)
300 end do
301 end do
302 end if
303 end subroutine cnd_fc
304
305 !> @ brief Calculate flows for package
306 !!
307 !! Method to calculate dispersion contribution to flowja
308 !<
309 subroutine cnd_cq(this, cnew, flowja)
310 ! -- modules
311 ! -- dummy
312 class(gwecndtype) :: this
313 real(DP), intent(inout), dimension(:) :: cnew
314 real(DP), intent(inout), dimension(:) :: flowja
315 ! -- local
316 integer(I4B) :: n, m, ipos, isympos
317 real(DP) :: dnm, qnm
318 !
319 ! -- Calculate dispersion and add to flowja
320 if (this%ixt3d > 0) then
321 call this%xt3d%xt3d_flowja(cnew, flowja)
322 else
323 do n = 1, this%dis%nodes
324 if (this%fmi%ibdgwfsat0(n) == 0) cycle
325 do ipos = this%dis%con%ia(n) + 1, this%dis%con%ia(n + 1) - 1
326 m = this%dis%con%ja(ipos)
327 if (this%fmi%ibdgwfsat0(m) == 0) cycle
328 isympos = this%dis%con%jas(ipos)
329 dnm = this%dispcoef(isympos)
330!! qnm = dnm * (cnew(m) - cnew(n)) * this%eqnsclfac
331 qnm = dnm * (cnew(m) - cnew(n))
332 flowja(ipos) = flowja(ipos) + qnm
333 end do
334 end do
335 end if
336 end subroutine cnd_cq
337
338 !> @ brief Allocate scalar variables for package
339 !!
340 !! Method to allocate scalar variables for the package.
341 !<
342 subroutine allocate_scalars(this)
343 ! -- modules
345 use constantsmodule, only: dzero
346 ! -- dummy
347 class(gwecndtype) :: this
348 !
349 ! -- allocate scalars in NumericalPackageType
350 call this%NumericalPackageType%allocate_scalars()
351 !
352 ! -- Allocate
353 call mem_allocate(this%idisp, 'IDISP', this%memoryPath)
354 call mem_allocate(this%ialh, 'IALH', this%memoryPath)
355 call mem_allocate(this%ialv, 'IALV', this%memoryPath)
356 call mem_allocate(this%iath1, 'IATH1', this%memoryPath)
357 call mem_allocate(this%iath2, 'IATH2', this%memoryPath)
358 call mem_allocate(this%iatv, 'IATV', this%memoryPath)
359 call mem_allocate(this%ixt3doff, 'IXT3DOFF', this%memoryPath)
360 call mem_allocate(this%ixt3drhs, 'IXT3DRHS', this%memoryPath)
361 call mem_allocate(this%ixt3d, 'IXT3D', this%memoryPath)
362 call mem_allocate(this%id22, 'ID22', this%memoryPath)
363 call mem_allocate(this%id33, 'ID33', this%memoryPath)
364 call mem_allocate(this%iangle1, 'IANGLE1', this%memoryPath)
365 call mem_allocate(this%iangle2, 'IANGLE2', this%memoryPath)
366 call mem_allocate(this%iangle3, 'IANGLE3', this%memoryPath)
367 call mem_allocate(this%iktw, 'IKTW', this%memoryPath)
368 call mem_allocate(this%ikts, 'IKTS', this%memoryPath)
369 !
370 ! -- Initialize
371 this%idisp = 0
372 this%ialh = 0
373 this%ialv = 0
374 this%iath1 = 0
375 this%iath2 = 0
376 this%iatv = 0
377 this%ixt3doff = 0
378 this%ixt3drhs = 0
379 this%ixt3d = 0
380 this%id22 = 1
381 this%id33 = 1
382 this%iangle1 = 1
383 this%iangle2 = 1
384 this%iangle3 = 1
385 this%iktw = 1
386 this%ikts = 1
387 end subroutine allocate_scalars
388
389 !> @ brief Allocate arrays for package
390 !!
391 !! Method to allocate arrays for the package.
392 !<
393 subroutine allocate_arrays(this, nodes)
394 ! -- modules
396 use constantsmodule, only: dzero
397 ! -- dummy
398 class(gwecndtype) :: this
399 integer(I4B), intent(in) :: nodes
400 !
401 ! -- Allocate
402 call mem_allocate(this%alh, nodes, 'ALH', trim(this%memoryPath))
403 call mem_allocate(this%alv, nodes, 'ALV', trim(this%memoryPath))
404 call mem_allocate(this%ath1, nodes, 'ATH1', trim(this%memoryPath))
405 call mem_allocate(this%ath2, nodes, 'ATH2', trim(this%memoryPath))
406 call mem_allocate(this%atv, nodes, 'ATV', trim(this%memoryPath))
407 call mem_allocate(this%d11, nodes, 'D11', trim(this%memoryPath))
408 call mem_allocate(this%d22, nodes, 'D22', trim(this%memoryPath))
409 call mem_allocate(this%d33, nodes, 'D33', trim(this%memoryPath))
410 call mem_allocate(this%angle1, nodes, 'ANGLE1', trim(this%memoryPath))
411 call mem_allocate(this%angle2, nodes, 'ANGLE2', trim(this%memoryPath))
412 call mem_allocate(this%angle3, nodes, 'ANGLE3', trim(this%memoryPath))
413 call mem_allocate(this%ktw, nodes, 'KTW', trim(this%memoryPath))
414 call mem_allocate(this%kts, nodes, 'KTS', trim(this%memoryPath))
415 !
416 ! -- Allocate dispersion coefficient array if xt3d not in use
417 if (this%ixt3d == 0) then
418 call mem_allocate(this%dispcoef, this%dis%njas, 'DISPCOEF', &
419 trim(this%memoryPath))
420 else
421 call mem_allocate(this%dispcoef, 0, 'DISPCOEF', trim(this%memoryPath))
422 end if
423 end subroutine allocate_arrays
424
425 !> @ brief Deallocate memory
426 !!
427 !! Method to deallocate memory for the package.
428 !<
429 subroutine cnd_da(this)
430 ! -- modules
434 ! -- dummy
435 class(gwecndtype) :: this
436 ! -- local
437 !
438 ! -- Deallocate input memory
439 call memorystore_remove(this%name_model, 'CND', idm_context)
440 !
441 ! -- deallocate arrays
442 if (this%inunit /= 0) then
443 call mem_deallocate(this%alh, 'ALH', trim(this%memoryPath))
444 call mem_deallocate(this%alv, 'ALV', trim(this%memoryPath))
445 call mem_deallocate(this%ath1, 'ATH1', trim(this%memoryPath))
446 call mem_deallocate(this%ath2, 'ATH2', trim(this%memoryPath))
447 call mem_deallocate(this%atv, 'ATV', trim(this%memoryPath))
448 call mem_deallocate(this%d11)
449 call mem_deallocate(this%d22)
450 call mem_deallocate(this%d33)
451 call mem_deallocate(this%angle1)
452 call mem_deallocate(this%angle2)
453 call mem_deallocate(this%angle3)
454 call mem_deallocate(this%ktw)
455 call mem_deallocate(this%kts)
456 call mem_deallocate(this%dispcoef)
457 if (this%ixt3d > 0) call this%xt3d%xt3d_da()
458 end if
459 !
460 ! -- deallocate objects
461 if (this%ixt3d > 0) deallocate (this%xt3d)
462 nullify (this%gwecommon)
463 !
464 ! -- deallocate scalars
465 call mem_deallocate(this%idisp)
466 call mem_deallocate(this%ialh)
467 call mem_deallocate(this%ialv)
468 call mem_deallocate(this%iath1)
469 call mem_deallocate(this%iath2)
470 call mem_deallocate(this%iatv)
471 call mem_deallocate(this%ixt3doff)
472 call mem_deallocate(this%ixt3drhs)
473 call mem_deallocate(this%ixt3d)
474 call mem_deallocate(this%id22)
475 call mem_deallocate(this%id33)
476 call mem_deallocate(this%iangle1)
477 call mem_deallocate(this%iangle2)
478 call mem_deallocate(this%iangle3)
479 call mem_deallocate(this%iktw)
480 call mem_deallocate(this%ikts)
481 !
482 ! -- deallocate variables in NumericalPackageType
483 call this%NumericalPackageType%da()
484 end subroutine cnd_da
485
486 !> @brief Write user options to list file
487 !<
488 subroutine log_options(this, found)
490 class(gwecndtype) :: this
491 type(gwecndparamfoundtype), intent(in) :: found
492 !
493 write (this%iout, '(1x,a)') 'Setting CND Options'
494 write (this%iout, '(4x,a,i0)') 'XT3D formulation [0=INACTIVE, 1=ACTIVE, &
495 &3=ACTIVE RHS] set to: ', this%ixt3d
496 write (this%iout, '(1x,a,/)') 'End Setting CND Options'
497 end subroutine log_options
498
499 !> @brief Update simulation mempath options
500 !<
501 subroutine source_options(this)
502 ! -- modules
505 ! -- dummy
506 class(gwecndtype) :: this
507 ! -- locals
508 type(gwecndparamfoundtype) :: found
509 !
510 ! -- update defaults with idm sourced values
511 call mem_set_value(this%ixt3doff, 'XT3D_OFF', this%input_mempath, &
512 found%xt3d_off)
513 call mem_set_value(this%ixt3drhs, 'XT3D_RHS', this%input_mempath, &
514 found%xt3d_rhs)
515 !
516 ! -- set xt3d state flag
517 if (found%xt3d_off) this%ixt3d = 0
518 if (found%xt3d_rhs) this%ixt3d = 2
519 !
520 ! -- log options
521 if (this%iout > 0) then
522 call this%log_options(found)
523 end if
524 end subroutine source_options
525
526 !> @brief Write dimensions to list file
527 !<
528 subroutine log_griddata(this, found)
530 class(gwecndtype) :: this
531 type(gwecndparamfoundtype), intent(in) :: found
532 !
533 write (this%iout, '(1x,a)') 'Setting CND Griddata'
534 !
535 if (found%alh) then
536 write (this%iout, '(4x,a)') 'ALH set from input file'
537 end if
538 !
539 if (found%alv) then
540 write (this%iout, '(4x,a)') 'ALV set from input file'
541 end if
542 !
543 if (found%ath1) then
544 write (this%iout, '(4x,a)') 'ATH1 set from input file'
545 end if
546 !
547 if (found%ath2) then
548 write (this%iout, '(4x,a)') 'ATH2 set from input file'
549 end if
550 !
551 if (found%atv) then
552 write (this%iout, '(4x,a)') 'ATV set from input file'
553 end if
554 !
555 if (found%ktw) then
556 write (this%iout, '(4x,a)') 'KTW set from input file'
557 end if
558 !
559 if (found%kts) then
560 write (this%iout, '(4x,a)') 'KTS set from input file'
561 end if
562 !
563 write (this%iout, '(1x,a,/)') 'End Setting CND Griddata'
564 end subroutine log_griddata
565
566 !> @brief Update CND simulation data from input mempath
567 !<
568 subroutine source_griddata(this)
569 ! -- modules
575 ! -- dummy
576 class(gwecndtype) :: this
577 ! -- locals
578 character(len=LINELENGTH) :: errmsg
579 type(gwecndparamfoundtype) :: found
580 integer(I4B), dimension(:), pointer, contiguous :: map
581 ! -- formats
582 !
583 ! -- set map
584 map => null()
585 if (this%dis%nodes < this%dis%nodesuser) map => this%dis%nodeuser
586 !
587 ! -- update defaults with idm sourced values
588 call mem_set_value(this%alh, 'ALH', this%input_mempath, map, found%alh)
589 call mem_set_value(this%alv, 'ALV', this%input_mempath, map, found%alv)
590 call mem_set_value(this%ath1, 'ATH1', this%input_mempath, map, found%ath1)
591 call mem_set_value(this%ath2, 'ATH2', this%input_mempath, map, found%ath2)
592 call mem_set_value(this%atv, 'ATV', this%input_mempath, map, found%atv)
593 call mem_set_value(this%ktw, 'KTW', this%input_mempath, map, found%ktw)
594 call mem_set_value(this%kts, 'KTS', this%input_mempath, map, found%kts)
595 !
596 ! -- set active flags
597 if (found%alh) this%ialh = 1
598 if (found%alv) this%ialv = 1
599 if (found%ath1) this%iath1 = 1
600 if (found%ath2) this%iath2 = 1
601 if (found%atv) this%iatv = 1
602 if (found%ktw) this%iktw = 1
603 if (found%kts) this%ikts = 1
604 !
605 ! -- set this%idisp flag
606 if (found%alh) this%idisp = this%idisp + 1
607 if (found%alv) this%idisp = this%idisp + 1
608 if (found%ath1) this%idisp = this%idisp + 1
609 if (found%ath2) this%idisp = this%idisp + 1
610 !
611 ! -- manage dispersion arrays
612 if (this%idisp > 0) then
613 if (.not. (found%alh .and. found%ath1)) then
614 write (errmsg, '(1x,a)') &
615 'If dispersivities are specified then ALH and ATH1 are required.'
616 call store_error(errmsg)
617 end if
618 ! -- If alv not specified then point it to alh
619 if (.not. found%alv) &
620 call mem_reassignptr(this%alv, 'ALV', trim(this%memoryPath), &
621 'ALH', trim(this%memoryPath))
622 ! -- If ath2 not specified then point it to ath1
623 if (.not. found%ath2) &
624 call mem_reassignptr(this%ath2, 'ATH2', trim(this%memoryPath), &
625 'ATH1', trim(this%memoryPath))
626 ! -- If atv not specified then point it to ath2
627 if (.not. found%atv) &
628 call mem_reassignptr(this%atv, 'ATV', trim(this%memoryPath), &
629 'ATH2', trim(this%memoryPath))
630 else
631 call mem_reallocate(this%alh, 0, 'ALH', trim(this%memoryPath))
632 call mem_reallocate(this%alv, 0, 'ALV', trim(this%memoryPath))
633 call mem_reallocate(this%ath1, 0, 'ATH1', trim(this%memoryPath))
634 call mem_reallocate(this%ath2, 0, 'ATH2', trim(this%memoryPath))
635 call mem_reallocate(this%atv, 0, 'ATV', trim(this%memoryPath))
636 end if
637 !
638 ! -- log griddata
639 if (this%iout > 0) then
640 call this%log_griddata(found)
641 end if
642 end subroutine source_griddata
643
644 !> @brief Calculate dispersion coefficients
645 !<
646 subroutine calcdispellipse(this)
647 ! -- modules
648 ! -- dummy
649 class(gwecndtype) :: this
650 ! -- local
651 integer(I4B) :: nodes, n
652 real(DP) :: q, qx, qy, qz
653 real(DP) :: alh, alv, ath1, ath2, atv, a
654 real(DP) :: al, at1, at2
655 real(DP) :: qzoqsquared
656 real(DP) :: ktbulk ! TODO: Implement additional options for characterizing ktbulk (see Markle refs)
657 real(DP) :: dstar
658 real(DP) :: qsw
659 !
660 ! -- loop through and calculate dispersion coefficients and angles
661 nodes = size(this%d11)
662 do n = 1, nodes
663 !
664 ! -- initialize
665 this%d11(n) = dzero
666 this%d22(n) = dzero
667 this%d33(n) = dzero
668 this%angle1(n) = dzero
669 this%angle2(n) = dzero
670 this%angle3(n) = dzero
671 if (this%fmi%ibdgwfsat0(n) == 0) cycle
672 !
673 ! -- specific discharge
674 qx = dzero
675 qy = dzero
676 qz = dzero
677 q = dzero
678 qx = this%fmi%gwfspdis(1, n)
679 qy = this%fmi%gwfspdis(2, n)
680 qz = this%fmi%gwfspdis(3, n)
681 q = qx**2 + qy**2 + qz**2
682 if (q > dzero) q = sqrt(q)
683 !
684 ! -- dispersion coefficients
685 alh = dzero
686 alv = dzero
687 ath1 = dzero
688 ath2 = dzero
689 atv = dzero
690 if (this%idisp > 0) then
691 alh = this%alh(n)
692 alv = this%alv(n)
693 ath1 = this%ath1(n)
694 ath2 = this%ath2(n)
695 atv = this%atv(n)
696 end if
697 !
698 ! -- calculate
699 ktbulk = dzero
700 if (this%iktw > 0) ktbulk = ktbulk + this%porosity(n) * this%ktw(n) * &
701 this%fmi%gwfsat(n)
702 if (this%ikts > 0) ktbulk = ktbulk + (done - this%porosity(n)) * this%kts(n)
703 !
704 ! -- The division by rhow*cpw below is undertaken to render dstar in the
705 ! form of a thermal diffusivity, and not because the governing
706 ! equation is scaled by rhow*cpw. Because of this conceptual
707 ! distinction, ktbulk is divided by the explicitly calculated product
708 ! rhow*cpw, and not by the equivalent scale factor eqnsclfac, even
709 ! though it should make no practical difference in the result.
710 dstar = ktbulk / (this%gwecommon%gwecpw * this%gwecommon%gwerhow)
711 !
712 ! -- Calculate the longitudal and transverse dispersivities
713 al = dzero
714 at1 = dzero
715 at2 = dzero
716 if (q > dzero) then
717 qzoqsquared = (qz / q)**2
718 al = alh * (done - qzoqsquared) + alv * qzoqsquared
719 at1 = ath1 * (done - qzoqsquared) + atv * qzoqsquared
720 at2 = ath2 * (done - qzoqsquared) + atv * qzoqsquared
721 end if
722 !
723 ! -- Calculate and save the diagonal components of the dispersion tensor
724 qsw = q * this%fmi%gwfsat(n) * this%eqnsclfac
725 this%d11(n) = al * qsw + ktbulk
726 this%d22(n) = at1 * qsw + ktbulk
727 this%d33(n) = at2 * qsw + ktbulk
728 !
729 ! -- Angles of rotation if velocity based dispersion tensor
730 if (this%idisp > 0) then
731 !
732 ! -- angle3 is zero
733 this%angle3(n) = dzero
734
735 ! -- angle2: vertical inclination
736 if (q > dzero) then
737 a = max(-done, min(done, qz / q))
738 else
739 a = dzero
740 end if
741 this%angle2(n) = asin(a)
742
743 ! -- angle1: horizontal azimuth
744 if (qx /= dzero .or. qy /= dzero) then
745 this%angle1(n) = atan2(qy, qx)
746 else
747 this%angle1(n) = dzero
748 end if
749 end if
750 end do
751 end subroutine calcdispellipse
752
753 !> @brief Calculate dispersion coefficients
754 !<
755 subroutine calcdispcoef(this)
756 ! -- modules
757 use hgeoutilmodule, only: hyeff
759 ! -- dummy
760 class(gwecndtype) :: this
761 ! -- local
762 integer(I4B) :: nodes, n, m, idiag, ipos
763 real(DP) :: clnm, clmn, dn, dm
764 real(DP) :: vg1, vg2, vg3
765 integer(I4B) :: ihc, isympos
766 integer(I4B) :: iavgmeth
767 real(DP) :: satn, satm, topn, topm, botn, botm
768 real(DP) :: hwva, cond, cn, cm, denom
769 real(DP) :: anm, amn, thksatn, thksatm
770 !
771 ! -- set iavgmeth = 1 to use arithmetic averaging for effective dispersion
772 iavgmeth = 1
773 !
774 ! -- Process connections
775 nodes = size(this%d11)
776 do n = 1, nodes
777 if (this%fmi%ibdgwfsat0(n) == 0) cycle
778 idiag = this%dis%con%ia(n)
779 do ipos = this%dis%con%ia(n) + 1, this%dis%con%ia(n + 1) - 1
780 !
781 ! -- Set m to connected cell
782 m = this%dis%con%ja(ipos)
783 !
784 ! -- skip for lower triangle
785 if (m < n) cycle
786 isympos = this%dis%con%jas(ipos)
787 this%dispcoef(isympos) = dzero
788 if (this%fmi%ibdgwfsat0(m) == 0) cycle
789 !
790 ! -- cell dimensions
791 hwva = this%dis%con%hwva(isympos)
792 clnm = this%dis%con%cl1(isympos)
793 clmn = this%dis%con%cl2(isympos)
794 ihc = this%dis%con%ihc(isympos)
795 topn = this%dis%top(n)
796 topm = this%dis%top(m)
797 botn = this%dis%bot(n)
798 botm = this%dis%bot(m)
799 !
800 ! -- flow model information
801 satn = this%fmi%ibdgwfsat0(n)
802 satm = this%fmi%ibdgwfsat0(m)
803 !
804 ! -- Calculate dispersion coefficient for cell n in the direction
805 ! normal to the shared n-m face and for cell m in the direction
806 ! normal to the shared n-m face.
807 call this%dis%connection_normal(n, m, ihc, vg1, vg2, vg3, ipos)
808 dn = hyeff(this%d11(n), this%d22(n), this%d33(n), &
809 this%angle1(n), this%angle2(n), this%angle3(n), &
810 vg1, vg2, vg3, iavgmeth)
811 dm = hyeff(this%d11(m), this%d22(m), this%d33(m), &
812 this%angle1(m), this%angle2(m), this%angle3(m), &
813 vg1, vg2, vg3, iavgmeth)
814 !
815 ! -- Calculate dispersion conductance based on NPF subroutines and the
816 ! effective dispersion coefficients dn and dm.
817 if (ihc == 0) then
818 clnm = satn * (topn - botn) * dhalf
819 clmn = satm * (topm - botm) * dhalf
820 anm = hwva
821 !
822 ! -- n is convertible and unsaturated
823 if (satn == dzero) then
824 anm = dzero
825 else if (n > m .and. satn < done) then
826 anm = dzero
827 end if
828 !
829 ! -- m is convertible and unsaturated
830 if (satm == dzero) then
831 anm = dzero
832 else if (m > n .and. satm < done) then
833 anm = dzero
834 end if
835 !
836 ! -- amn is the same as anm for vertical flow
837 amn = anm
838 !
839 else
840 !
841 ! -- horizontal conductance
842 !
843 ! -- handle vertically staggered case
844 if (ihc == 2) then
845 thksatn = staggered_thkfrac(topn, botn, satn, topm, botm)
846 thksatm = staggered_thkfrac(topm, botm, satm, topn, botn)
847 else
848 thksatn = (topn - botn) * satn
849 thksatm = (topm - botm) * satm
850 end if
851 !
852 ! -- calculate the saturated area term
853 anm = thksatn * hwva
854 amn = thksatm * hwva
855 !
856 ! -- n or m is unsaturated, so no dispersion
857 if (satn == dzero .or. satm == dzero) then
858 anm = dzero
859 amn = dzero
860 end if
861 !
862 end if
863 !
864 ! -- calculate conductance using the two half cell conductances
865 cn = dzero
866 if (clnm > dzero) cn = dn * anm / clnm
867 cm = dzero
868 if (clmn > dzero) cm = dm * amn / clmn
869 denom = cn + cm
870 if (denom > dzero) then
871 cond = cn * cm / denom
872 else
873 cond = dzero
874 end if
875 !
876 ! -- Assign the calculated dispersion conductance
877 this%dispcoef(isympos) = cond
878 !
879 end do
880 end do
881 end subroutine calcdispcoef
882
883end module gwecndmodule
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 dhalf
real constant 1/2
Definition Constants.f90:68
real(dp), parameter dpi
real constant
real(dp), parameter dzero
real constant zero
Definition Constants.f90:65
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 cnd_ad(this)
Advance method for the package.
Definition gwe-cnd.f90:229
subroutine source_griddata(this)
Update CND simulation data from input mempath.
Definition gwe-cnd.f90:569
subroutine cnd_fc(this, kiter, nodes, nja, matrix_sln, idxglo, rhs, cnew)
Fill coefficient method for package.
Definition gwe-cnd.f90:264
subroutine, public cnd_cr(cndobj, name_model, input_mempath, inunit, iout, fmi, eqnsclfac, gwecommon)
Create a new CND object.
Definition gwe-cnd.f90:86
subroutine cnd_ar(this, ibound, porosity)
Allocate and read method for package.
Definition gwe-cnd.f90:210
subroutine calcdispellipse(this)
Calculate dispersion coefficients.
Definition gwe-cnd.f90:647
subroutine calcdispcoef(this)
Calculate dispersion coefficients.
Definition gwe-cnd.f90:756
subroutine cnd_ac(this, moffset, sparse)
Add connections to CND.
Definition gwe-cnd.f90:177
subroutine cnd_da(this)
@ brief Deallocate memory
Definition gwe-cnd.f90:430
subroutine allocate_arrays(this, nodes)
@ brief Allocate arrays for package
Definition gwe-cnd.f90:394
subroutine allocate_scalars(this)
@ brief Allocate scalar variables for package
Definition gwe-cnd.f90:343
subroutine source_options(this)
Update simulation mempath options.
Definition gwe-cnd.f90:502
subroutine cnd_df(this, dis, cndoptions)
Define CND object.
Definition gwe-cnd.f90:133
subroutine cnd_mc(this, moffset, matrix_sln)
Map CND connections.
Definition gwe-cnd.f90:194
subroutine log_griddata(this, found)
Write dimensions to list file.
Definition gwe-cnd.f90:529
subroutine cnd_cq(this, cnew, flowja)
@ brief Calculate flows for package
Definition gwe-cnd.f90:310
subroutine log_options(this, found)
Write user options to list file.
Definition gwe-cnd.f90:489
This module contains stateless conductance functions.
real(dp) function, public staggered_thkfrac(top, bot, sat, topc, botc)
Calculate the thickness fraction for staggered grids.
General-purpose hydrogeologic functions.
Definition HGeoUtil.f90:2
real(dp) function, public hyeff(k11, k22, k33, ang1, ang2, ang3, vg1, vg2, vg3, iavgmeth)
Calculate the effective horizontal hydraulic conductivity from an ellipse using a specified direction...
Definition HGeoUtil.f90:31
This module defines variable data types.
Definition kind.f90:8
subroutine, public memorystore_remove(component, subcomponent, context)
This module contains the base numerical package type.
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
This module contains simulation variables.
character(len=linelength) idm_context
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
subroutine, public xt3d_cr(xt3dobj, name_model, inunit, iout, ldispopt)
Create a new xt3d object.
data structure (and helpers) for passing cnd option data
Data for sharing among multiple packages. Originally read in from.