15 character(len=LENMEMPATH) :: memorypath
16 integer(I4B),
pointer :: inunit => null()
17 integer(I4B),
pointer :: iout => null()
18 integer(I4B),
pointer :: inewton => null()
19 integer(I4B),
dimension(:),
pointer,
contiguous :: ibound => null()
20 integer(I4B),
dimension(:),
pointer,
contiguous :: iax => null()
21 integer(I4B),
dimension(:),
pointer,
contiguous :: jax => null()
22 integer(I4B),
dimension(:),
pointer,
contiguous :: idxglox => null()
23 integer(I4B),
dimension(:),
pointer,
contiguous :: ia_xt3d => null()
24 integer(I4B),
dimension(:),
pointer,
contiguous :: ja_xt3d => null()
25 integer(I4B),
pointer :: numextnbrs => null()
26 integer(I4B),
pointer :: ixt3d => null()
27 logical,
pointer :: nozee => null()
28 real(dp),
pointer :: vcthresh => null()
29 real(dp),
dimension(:, :),
pointer,
contiguous :: rmatck => null()
30 real(dp),
dimension(:),
pointer,
contiguous :: qsat => null()
31 integer(I4B),
pointer :: nbrmax => null()
32 real(dp),
dimension(:),
pointer,
contiguous :: amatpc => null()
33 real(dp),
dimension(:),
pointer,
contiguous :: amatpcx => null()
34 integer(I4B),
dimension(:),
pointer,
contiguous :: iallpc => null()
35 logical,
pointer :: lamatsaved => null()
38 real(dp),
dimension(:),
pointer,
contiguous :: k11 => null()
39 real(dp),
dimension(:),
pointer,
contiguous :: k22 => null()
40 real(dp),
dimension(:),
pointer,
contiguous :: k33 => null()
41 integer(I4B),
pointer :: ik22 => null()
42 integer(I4B),
pointer :: ik33 => null()
43 real(dp),
dimension(:),
pointer,
contiguous :: sat => null()
44 integer(I4B),
dimension(:),
pointer,
contiguous :: icelltype => null()
45 integer(I4B),
pointer :: iangle1 => null()
46 integer(I4B),
pointer :: iangle2 => null()
47 integer(I4B),
pointer :: iangle3 => null()
48 real(dp),
dimension(:),
pointer,
contiguous :: angle1 => null()
49 real(dp),
dimension(:),
pointer,
contiguous :: angle2 => null()
50 real(dp),
dimension(:),
pointer,
contiguous :: angle3 => null()
51 logical,
pointer :: ldispersion => null()
89 subroutine xt3d_cr(xt3dobj, name_model, inunit, iout, ldispopt)
92 character(len=*),
intent(in) :: name_model
93 integer(I4B),
intent(in) :: inunit
94 integer(I4B),
intent(in) :: iout
95 logical,
optional,
intent(in) :: ldispopt
104 call xt3dobj%allocate_scalars()
107 xt3dobj%inunit = inunit
109 if (
present(ldispopt)) xt3dobj%ldispersion = ldispopt
130 integer(I4B),
intent(in) :: moffset
134 integer(I4B) :: i, j, k, jj, kk, iglo, kglo, iadded
136 integer(I4B) :: ierror
139 if (this%ixt3d == 1)
then
143 call sparse_xt3d%init(this%dis%nodes, this%dis%nodes, nnz)
148 do i = 1, this%dis%nodes
151 do jj = this%dis%con%ia(i) + 1, this%dis%con%ia(i + 1) - 1
152 j = this%dis%con%ja(jj)
154 do kk = this%dis%con%ia(j) + 1, this%dis%con%ia(j + 1) - 1
155 k = this%dis%con%ja(kk)
157 call sparse_xt3d%addconnection(i, k, 1)
164 call mem_allocate(this%ia_xt3d, this%dis%nodes + 1,
'IA_XT3D', &
165 trim(this%memoryPath))
166 call mem_allocate(this%ja_xt3d, sparse_xt3d%nnz,
'JA_XT3D', &
167 trim(this%memoryPath))
168 call sparse_xt3d%filliaja(this%ia_xt3d, this%ja_xt3d, ierror)
169 call sparse_xt3d%destroy()
173 do i = 1, this%dis%nodes
175 do kk = this%ia_xt3d(i), this%ia_xt3d(i + 1) - 1
178 call sparse%addconnection(iglo, kglo, 1, iadded)
179 this%numextnbrs = this%numextnbrs + 1
184 call mem_allocate(this%ia_xt3d, 0,
'IA_XT3D', trim(this%memoryPath))
185 call mem_allocate(this%ja_xt3d, 0,
'JA_XT3D', trim(this%memoryPath))
196 integer(I4B),
intent(in) :: moffset
199 integer(I4B) :: i, j, iglo, jglo, niax, njax, ipos
200 integer(I4B) :: ipos_sln, icol_first, icol_last
201 integer(I4B) :: jj_xt3d
202 integer(I4B) :: igfirstnod, iglastnod
207 if (this%ixt3d == 1)
then
211 igfirstnod = moffset + 1
212 iglastnod = moffset + this%dis%nodes
215 niax = this%dis%nodes + 1
216 njax = this%numextnbrs
217 call mem_allocate(this%iax, niax,
'IAX', trim(this%memoryPath))
218 call mem_allocate(this%jax, njax,
'JAX', trim(this%memoryPath))
219 call mem_allocate(this%idxglox, njax,
'IDXGLOX', trim(this%memoryPath))
226 do i = 1, this%dis%nodes
230 icol_first = matrix_sln%get_first_col_pos(iglo)
231 icol_last = matrix_sln%get_last_col_pos(iglo)
232 do ipos_sln = icol_first, icol_last
236 jglo = matrix_sln%get_column(ipos_sln)
237 if (jglo < igfirstnod .or. jglo > iglastnod)
then
246 do jj_xt3d = this%ia_xt3d(i), this%ia_xt3d(i + 1) - 1
247 if (j == this%ja_xt3d(jj_xt3d))
then
255 this%jax(ipos) = matrix_sln%get_column(ipos_sln) - moffset
256 this%idxglox(ipos) = ipos_sln
261 this%iax(i + 1) = ipos
266 call mem_allocate(this%iax, 0,
'IAX', trim(this%memoryPath))
267 call mem_allocate(this%jax, 0,
'JAX', trim(this%memoryPath))
268 call mem_allocate(this%idxglox, 0,
'IDXGLOX', trim(this%memoryPath))
275 subroutine xt3d_ar(this, ibound, k11, ik33, k33, sat, ik22, k22, iangle1, &
276 iangle2, iangle3, angle1, angle2, angle3, inewton, icelltype)
281 integer(I4B),
dimension(:),
pointer,
contiguous,
intent(inout) :: ibound
282 real(DP),
dimension(:),
intent(in),
pointer,
contiguous :: k11
283 integer(I4B),
intent(in),
pointer :: ik33
284 real(DP),
dimension(:),
intent(in),
pointer,
contiguous :: k33
285 real(DP),
dimension(:),
intent(in),
pointer,
contiguous :: sat
286 integer(I4B),
intent(in),
pointer :: ik22
287 real(DP),
dimension(:),
intent(in),
pointer,
contiguous :: k22
288 integer(I4B),
intent(in),
pointer :: iangle1
289 integer(I4B),
intent(in),
pointer :: iangle2
290 integer(I4B),
intent(in),
pointer :: iangle3
291 real(DP),
dimension(:),
intent(in),
pointer,
contiguous :: angle1
292 real(DP),
dimension(:),
intent(in),
pointer,
contiguous :: angle2
293 real(DP),
dimension(:),
intent(in),
pointer,
contiguous :: angle3
294 integer(I4B),
intent(in),
pointer,
optional :: inewton
295 integer(I4B),
dimension(:),
intent(in),
pointer, &
296 contiguous,
optional :: icelltype
298 integer(I4B) :: n, nnbrs
300 character(len=*),
parameter :: fmtheader = &
301 "(1x, /1x, 'XT3D is active.'//)"
304 if (this%iout > 0)
then
305 write (this%iout, fmtheader)
309 this%ibound => ibound
316 this%iangle1 => iangle1
317 this%iangle2 => iangle2
318 this%iangle3 => iangle3
319 this%angle1 => angle1
320 this%angle2 => angle2
321 this%angle3 => angle3
323 if (
present(inewton))
then
325 this%inewton = inewton
327 if (
present(icelltype))
then
331 this%icelltype => icelltype
336 if (this%iangle2 == 0) this%nozee = .true.
340 do n = 1, this%dis%nodes
341 nnbrs = this%dis%con%ia(n + 1) - this%dis%con%ia(n) - 1
342 this%nbrmax = max(nnbrs, this%nbrmax)
346 if (this%dis%icondir == 0)
then
347 call store_error(
'Vertices not specified for discretization package, '// &
348 'but XT3D is active: '//trim(adjustl(this%memoryPath))// &
349 '. Vertices must be specified in discretization '// &
350 'package in order to use XT3D.', terminate=.true.)
354 if (this%dis%con%ianglex == 0)
then
355 call store_error(
'ANGLDEGX is not specified in the DIS package, '// &
356 'but XT3D is active: '//trim(adjustl(this%memoryPath))// &
357 '. ANGLDEGX must be provided in discretization '// &
358 'package in order to use XT3D.', terminate=.true.)
362 call this%allocate_arrays()
366 if (this%lamatsaved .and. .not. this%ldispersion) &
367 call this%xt3d_fcpc(this%dis%nodes, .true.)
371 subroutine xt3d_fc(this, kiter, matrix_sln, idxglo, rhs, hnew)
377 integer(I4B) :: kiter
379 integer(I4B),
intent(in),
dimension(:) :: idxglo
380 real(DP),
intent(inout),
dimension(:) :: rhs
381 real(DP),
intent(inout),
dimension(:) :: hnew
383 integer(I4B) :: nodes, nja
384 integer(I4B) :: n, m, ipos
385 logical :: allhc0, allhc1
386 integer(I4B) :: nnbr0, nnbr1
387 integer(I4B) :: il0, ii01, jjs01, il01, il10, ii00, ii11, ii10
389 integer(I4B),
dimension(this%nbrmax) :: inbr0, inbr1
390 real(DP) :: ar01, ar10
391 real(DP),
dimension(this%nbrmax, 3) :: vc0, vn0, vc1, vn1
392 real(DP),
dimension(this%nbrmax) :: dl0, dl0n, dl1, dl1n
393 real(DP),
dimension(3, 3) :: ck0, ck1
395 real(DP),
dimension(this%nbrmax) :: chati0, chat1j
396 real(DP) :: qnm, qnbrs
401 nodes = this%dis%nodes
402 nja = this%dis%con%nja
403 if (this%lamatsaved)
then
404 do i = 1, this%dis%con%nja
405 call matrix_sln%add_value_pos(idxglo(i), this%amatpc(i))
407 do i = 1, this%numextnbrs
408 call matrix_sln%add_value_pos(this%idxglox(i), this%amatpcx(i))
414 if (this%ibound(n) .eq. 0) cycle
416 if (this%lamatsaved)
then
417 if (this%iallpc(n) == 1) cycle
419 nnbr0 = this%dis%con%ia(n + 1) - this%dis%con%ia(n) - 1
421 call this%xt3d_load(nodes, n, nnbr0, inbr0, vc0, vn0, dl0, dl0n, &
426 ipos = this%dis%con%ia(n) + il0
427 if (this%dis%con%mask(ipos) == 0) cycle
431 if ((m .eq. 0) .or. (m .lt. n)) cycle
432 nnbr1 = this%dis%con%ia(m + 1) - this%dis%con%ia(m) - 1
434 call this%xt3d_load(nodes, m, nnbr1, inbr1, vc1, vn1, dl1, dl1n, &
437 call this%xt3d_indices(n, m, il0, ii01, jjs01, il01, il10, &
440 if (this%inewton /= 0)
then
444 call this%xt3d_areas(nodes, n, m, jjs01, .false., ar01, ar10, hnew)
448 call qconds(this%nbrmax, nnbr0, inbr0, il01, vc0, vn0, dl0, dl0n, ck0, &
449 nnbr1, inbr1, il10, vc1, vn1, dl1, dl1n, ck1, ar01, ar10, &
450 this%vcthresh, allhc0, allhc1, chat01, chati0, chat1j)
454 if (this%inewton /= 0)
then
456 qnm = chat01 * (hnew(m) - hnew(n))
458 call this%xt3d_qnbrs(nodes, n, m, nnbr0, inbr0, chati0, hnew, qnbrs)
461 call this%xt3d_qnbrs(nodes, m, n, nnbr1, inbr1, chat1j, hnew, qnbrs)
464 call this%xt3d_areas(nodes, n, m, jjs01, .true., ar01, ar10, hnew)
465 this%qsat(ii01) = qnm * ar01
467 call this%xt3d_areas(nodes, n, m, jjs01, .false., ar01, ar10, hnew, &
469 chat01 = chat01 * ar01
470 chati0 = chati0 * ar01
471 chat1j = chat1j * ar01
475 call matrix_sln%add_value_pos(idxglo(ii00), -chat01)
476 call matrix_sln%add_value_pos(idxglo(ii01), chat01)
477 call matrix_sln%add_value_pos(idxglo(ii11), -chat01)
478 call matrix_sln%add_value_pos(idxglo(ii10), chat01)
479 if (this%ixt3d == 1)
then
480 call this%xt3d_amat_nbrs(nodes, n, ii00, nnbr0, nja, matrix_sln, &
481 inbr0, idxglo, chati0)
482 call this%xt3d_amat_nbrnbrs(nodes, n, m, ii01, nnbr1, nja, matrix_sln, &
483 inbr1, idxglo, chat1j)
484 call this%xt3d_amat_nbrs(nodes, m, ii11, nnbr1, nja, matrix_sln, &
485 inbr1, idxglo, chat1j)
486 call this%xt3d_amat_nbrnbrs(nodes, m, n, ii10, nnbr0, nja, matrix_sln, &
487 inbr0, idxglo, chati0)
489 call this%xt3d_rhs(nodes, n, m, nnbr0, inbr0, chati0, hnew, rhs)
490 call this%xt3d_rhs(nodes, m, n, nnbr1, inbr1, chat1j, hnew, rhs)
505 integer(I4B),
intent(in) :: nodes
506 logical,
intent(in) :: lsat
508 integer(I4B) :: n, m, ipos
510 logical :: allhc0, allhc1
511 integer(I4B) :: nnbr0, nnbr1
512 integer(I4B) :: il0, ii01, jjs01, il01, il10, ii00, ii11, ii10
513 integer(I4B),
dimension(this%nbrmax) :: inbr0, inbr1
514 real(DP) :: ar01, ar10
515 real(DP),
dimension(this%nbrmax, 3) :: vc0, vn0, vc1, vn1
516 real(DP),
dimension(this%nbrmax) :: dl0, dl0n, dl1, dl1n
517 real(DP),
dimension(3, 3) :: ck0, ck1
519 real(DP),
dimension(this%nbrmax) :: chati0, chat1j
522 do n = 1,
size(this%amatpc)
523 this%amatpc(n) =
dzero
525 do n = 1,
size(this%amatpcx)
526 this%amatpcx(n) =
dzero
533 if (this%iallpc(n) == 0) cycle
534 if (this%ibound(n) == 0) cycle
535 nnbr0 = this%dis%con%ia(n + 1) - this%dis%con%ia(n) - 1
537 call this%xt3d_load(nodes, n, nnbr0, inbr0, vc0, vn0, dl0, dl0n, &
542 ipos = this%dis%con%ia(n) + il0
543 if (this%dis%con%mask(ipos) == 0) cycle
548 nnbr1 = this%dis%con%ia(m + 1) - this%dis%con%ia(m) - 1
550 call this%xt3d_load(nodes, m, nnbr1, inbr1, vc1, vn1, dl1, dl1n, &
553 call this%xt3d_indices(n, m, il0, ii01, jjs01, il01, il10, &
556 call this%xt3d_areas(nodes, n, m, jjs01, lsat, ar01, ar10)
559 call qconds(this%nbrmax, nnbr0, inbr0, il01, vc0, vn0, dl0, dl0n, ck0, &
560 nnbr1, inbr1, il10, vc1, vn1, dl1, dl1n, ck1, ar01, ar10, &
561 this%vcthresh, allhc0, allhc1, chat01, chati0, chat1j)
563 this%amatpc(ii00) = this%amatpc(ii00) - chat01
564 this%amatpc(ii01) = this%amatpc(ii01) + chat01
565 this%amatpc(ii11) = this%amatpc(ii11) - chat01
566 this%amatpc(ii10) = this%amatpc(ii10) + chat01
567 call this%xt3d_amatpc_nbrs(nodes, n, ii00, nnbr0, inbr0, chati0)
568 call this%xt3d_amatpcx_nbrnbrs(nodes, n, m, ii01, nnbr1, inbr1, chat1j)
569 call this%xt3d_amatpc_nbrs(nodes, m, ii11, nnbr1, inbr1, chat1j)
570 call this%xt3d_amatpcx_nbrnbrs(nodes, m, n, ii10, nnbr0, inbr0, chati0)
577 subroutine xt3d_fhfb(this, kiter, nodes, nja, matrix_sln, idxglo, rhs, hnew, &
584 integer(I4B) :: kiter
585 integer(I4B),
intent(in) :: nodes
586 integer(I4B),
intent(in) :: nja
589 integer(I4B),
intent(in),
dimension(nja) :: idxglo
590 real(DP),
intent(inout),
dimension(nodes) :: rhs
591 real(DP),
intent(inout),
dimension(nodes) :: hnew
594 logical :: allhc0, allhc1
595 integer(I4B) :: nnbr0, nnbr1
596 integer(I4B) :: il0, ii01, jjs01, il01, il10, ii00, ii11, ii10, il
597 integer(I4B),
dimension(this%nbrmax) :: inbr0, inbr1
598 real(DP) :: ar01, ar10
599 real(DP),
dimension(this%nbrmax, 3) :: vc0, vn0, vc1, vn1
600 real(DP),
dimension(this%nbrmax) :: dl0, dl0n, dl1, dl1n
601 real(DP),
dimension(3, 3) :: ck0, ck1
603 real(DP),
dimension(this%nbrmax) :: chati0, chat1j
604 real(DP) :: qnm, qnbrs
610 nnbr0 = this%dis%con%ia(n + 1) - this%dis%con%ia(n) - 1
612 call this%xt3d_load(nodes, n, nnbr0, inbr0, vc0, vn0, dl0, dl0n, &
616 if (inbr0(il) .eq. m)
then
621 nnbr1 = this%dis%con%ia(m + 1) - this%dis%con%ia(m) - 1
623 call this%xt3d_load(nodes, m, nnbr1, inbr1, vc1, vn1, dl1, dl1n, &
626 call this%xt3d_indices(n, m, il0, ii01, jjs01, il01, il10, &
629 if (this%inewton /= 0)
then
633 call this%xt3d_areas(nodes, n, m, jjs01, .false., ar01, ar10, hnew)
638 call qconds(this%nbrmax, nnbr0, inbr0, il01, vc0, vn0, dl0, dl0n, &
639 ck0, nnbr1, inbr1, il10, vc1, vn1, dl1, dl1n, ck1, ar01, ar10, &
640 this%vcthresh, allhc0, allhc1, chat01, chati0, chat1j)
643 if (condhfb > dzero)
then
644 term = chat01 / (chat01 + condhfb)
648 chat01 = -chat01 * term
649 chati0 = -chati0 * term
650 chat1j = -chat1j * term
654 if (this%inewton /= 0)
then
656 qnm = chat01 * (hnew(m) - hnew(n))
658 call this%xt3d_qnbrs(nodes, n, m, nnbr0, inbr0, chati0, hnew, qnbrs)
661 call this%xt3d_qnbrs(nodes, m, n, nnbr1, inbr1, chat1j, hnew, qnbrs)
670 call this%xt3d_areas(nodes, n, m, jjs01, .true., ar01, ar10, hnew)
671 this%qsat(ii01) = this%qsat(ii01) + qnm * ar01
673 call this%xt3d_areas(nodes, n, m, jjs01, .false., ar01, ar10, hnew, &
675 chat01 = chat01 * ar01
676 chati0 = chati0 * ar01
677 chat1j = chat1j * ar01
681 call matrix_sln%add_value_pos(idxglo(ii00), -chat01)
682 call matrix_sln%add_value_pos(idxglo(ii01), chat01)
683 call matrix_sln%add_value_pos(idxglo(ii11), -chat01)
684 call matrix_sln%add_value_pos(idxglo(ii10), chat01)
685 if (this%ixt3d == 1)
then
686 call this%xt3d_amat_nbrs(nodes, n, ii00, nnbr0, nja, matrix_sln, &
687 inbr0, idxglo, chati0)
688 call this%xt3d_amat_nbrnbrs(nodes, n, m, ii01, nnbr1, nja, matrix_sln, &
689 inbr1, idxglo, chat1j)
690 call this%xt3d_amat_nbrs(nodes, m, ii11, nnbr1, nja, matrix_sln, &
691 inbr1, idxglo, chat1j)
692 call this%xt3d_amat_nbrnbrs(nodes, m, n, ii10, nnbr0, nja, matrix_sln, &
693 inbr0, idxglo, chati0)
695 call this%xt3d_rhs(nodes, n, m, nnbr0, inbr0, chati0, hnew, rhs)
696 call this%xt3d_rhs(nodes, m, n, nnbr1, inbr1, chat1j, hnew, rhs)
701 subroutine xt3d_fn(this, kiter, nodes, nja, matrix_sln, idxglo, rhs, hnew)
707 integer(I4B) :: kiter
708 integer(I4B),
intent(in) :: nodes
709 integer(I4B),
intent(in) :: nja
711 integer(I4B),
intent(in),
dimension(nja) :: idxglo
712 real(DP),
intent(inout),
dimension(nodes) :: rhs
713 real(DP),
intent(inout),
dimension(nodes) :: hnew
715 integer(I4B) :: n, m, ipos
716 integer(I4B) :: nnbr0
717 integer(I4B) :: il0, ii01, jjs01, il01, il10, ii00, ii11, ii10
718 integer(I4B),
dimension(this%nbrmax) :: inbr0
719 integer(I4B) :: iups, idn
720 real(DP) :: topup, botup, derv, term
726 if (this%ibound(n) .eq. 0) cycle
730 if (this%lamatsaved)
then
731 if (this%iallpc(n) == 1) cycle
733 nnbr0 = this%dis%con%ia(n + 1) - this%dis%con%ia(n) - 1
737 call this%xt3d_load_inbr(n, nnbr0, inbr0)
742 ipos = this%dis%con%ia(n) + il0
743 if (this%dis%con%mask(ipos) == 0) cycle
748 if ((inbr0(il0) .eq. 0) .or. (m .lt. n)) cycle
751 call this%xt3d_indices(n, m, il0, ii01, jjs01, il01, il10, &
758 if (this%qsat(ii01) < dzero) iups = n
760 if (iups == n) idn = m
763 if ((this%icelltype(iups) == 0) .and. (this%ixt3d .eq. 1)) cycle
767 topup = this%dis%top(iups)
768 botup = this%dis%bot(iups)
769 if (this%dis%con%ihc(jjs01) == 2)
then
770 topup = min(this%dis%top(n), this%dis%top(m))
771 botup = max(this%dis%bot(n), this%dis%bot(m))
776 term = this%qsat(ii01) * derv
782 call matrix_sln%add_value_pos(idxglo(ii00), term)
783 rhs(n) = rhs(n) + term * hnew(n)
786 call matrix_sln%add_value_pos(idxglo(ii10), -term)
787 rhs(m) = rhs(m) - term * hnew(n)
793 call matrix_sln%add_value_pos(idxglo(ii01), term)
794 rhs(n) = rhs(n) + term * hnew(m)
797 call matrix_sln%add_value_pos(idxglo(ii11), -term)
798 rhs(m) = rhs(m) - term * hnew(m)
812 real(DP),
intent(inout),
dimension(:) :: hnew
813 real(DP),
intent(inout),
dimension(:) :: flowja
815 integer(I4B) :: n, ipos, m, nodes
816 real(DP) :: qnm, qnbrs
817 logical :: allhc0, allhc1
818 integer(I4B) :: nnbr0, nnbr1
819 integer(I4B) :: il0, ii01, jjs01, il01, il10, ii00, ii11, ii10
820 integer(I4B),
dimension(this%nbrmax) :: inbr0, inbr1
821 real(DP) :: ar01, ar10
822 real(DP),
dimension(this%nbrmax, 3) :: vc0, vn0, vc1, vn1
823 real(DP),
dimension(this%nbrmax) :: dl0, dl0n, dl1, dl1n
824 real(DP),
dimension(3, 3) :: ck0, ck1
826 real(DP),
dimension(this%nbrmax) :: chati0, chat1j
829 nodes = this%dis%nodes
833 if (this%ibound(n) .eq. 0) cycle
834 nnbr0 = this%dis%con%ia(n + 1) - this%dis%con%ia(n) - 1
837 call this%xt3d_load(nodes, n, nnbr0, inbr0, vc0, vn0, dl0, dl0n, &
846 if ((inbr0(il0) .eq. 0) .or. (m .lt. n)) cycle
847 nnbr1 = this%dis%con%ia(m + 1) - this%dis%con%ia(m) - 1
850 call this%xt3d_load(nodes, m, nnbr1, inbr1, vc1, vn1, dl1, dl1n, &
854 call this%xt3d_indices(n, m, il0, ii01, jjs01, il01, il10, &
858 if (this%inewton /= 0)
then
859 call this%xt3d_areas(nodes, n, m, jjs01, .true., ar01, ar10, hnew)
860 call this%xt3d_areas(nodes, n, m, jjs01, .false., ar01, ar10, hnew, &
863 call this%xt3d_areas(nodes, n, m, jjs01, .false., ar01, ar10, hnew)
868 call qconds(this%nbrmax, nnbr0, inbr0, il01, vc0, vn0, dl0, dl0n, ck0, &
869 nnbr1, inbr1, il10, vc1, vn1, dl1, dl1n, ck1, ar01, ar10, &
870 this%vcthresh, allhc0, allhc1, chat01, chati0, chat1j)
873 qnm = chat01 * (hnew(m) - hnew(n))
876 call this%xt3d_qnbrs(nodes, n, m, nnbr0, inbr0, chati0, hnew, qnbrs)
880 call this%xt3d_qnbrs(nodes, m, n, nnbr1, inbr1, chat1j, hnew, qnbrs)
883 flowja(ipos) = flowja(ipos) + qnm
884 flowja(this%dis%con%isym(ipos)) = flowja(this%dis%con%isym(ipos)) - qnm
898 real(DP),
intent(inout),
dimension(:) :: hnew
899 real(DP),
intent(inout),
dimension(:) :: flowja
902 integer(I4B) :: nodes
903 logical :: allhc0, allhc1
905 integer(I4B) :: nnbr0, nnbr1
906 integer(I4B) :: il0, ii01, jjs01, il01, il10, ii00, ii11, ii10, il
907 integer(I4B),
dimension(this%nbrmax) :: inbr0, inbr1
909 real(DP) :: ar01, ar10
910 real(DP),
dimension(this%nbrmax, 3) :: vc0, vn0, vc1, vn1
911 real(DP),
dimension(this%nbrmax) :: dl0, dl0n, dl1, dl1n
912 real(DP),
dimension(3, 3) :: ck0, ck1
914 real(DP),
dimension(this%nbrmax) :: chati0, chat1j
915 real(DP) :: qnm, qnbrs
920 nodes = this%dis%nodes
921 nnbr0 = this%dis%con%ia(n + 1) - this%dis%con%ia(n) - 1
924 call this%xt3d_load(nodes, n, nnbr0, inbr0, vc0, vn0, dl0, dl0n, &
929 if (inbr0(il) .eq. m)
then
935 nnbr1 = this%dis%con%ia(m + 1) - this%dis%con%ia(m) - 1
938 call this%xt3d_load(nodes, m, nnbr1, inbr1, vc1, vn1, dl1, dl1n, &
942 call this%xt3d_indices(n, m, il0, ii01, jjs01, il01, il10, &
946 if (this%inewton /= 0)
then
950 call this%xt3d_areas(nodes, n, m, jjs01, .false., ar01, ar10, hnew)
955 call qconds(this%nbrmax, nnbr0, inbr0, il01, vc0, vn0, dl0, dl0n, &
956 ck0, nnbr1, inbr1, il10, vc1, vn1, dl1, dl1n, ck1, ar01, ar10, &
957 this%vcthresh, allhc0, allhc1, chat01, chati0, chat1j)
960 if (condhfb > dzero)
then
961 term = chat01 / (chat01 + condhfb)
965 chat01 = -chat01 * term
966 chati0 = -chati0 * term
967 chat1j = -chat1j * term
970 qnm = chat01 * (hnew(m) - hnew(n))
973 call this%xt3d_qnbrs(nodes, n, m, nnbr0, inbr0, chati0, hnew, qnbrs)
977 call this%xt3d_qnbrs(nodes, m, n, nnbr1, inbr1, chat1j, hnew, qnbrs)
982 if (this%inewton /= 0)
then
983 call this%xt3d_areas(nodes, n, m, jjs01, .true., ar01, ar10, hnew)
984 call this%xt3d_areas(nodes, n, m, jjs01, .false., ar01, ar10, hnew, &
990 flowja(ipos) = flowja(ipos) + qnm
991 flowja(this%dis%con%isym(ipos)) = flowja(this%dis%con%isym(ipos)) - qnm
1003 if (this%ixt3d /= 0)
then
1038 call mem_allocate(this%ixt3d,
'IXT3D', this%memoryPath)
1039 call mem_allocate(this%nbrmax,
'NBRMAX', this%memoryPath)
1040 call mem_allocate(this%inunit,
'INUNIT', this%memoryPath)
1042 call mem_allocate(this%inewton,
'INEWTON', this%memoryPath)
1043 call mem_allocate(this%numextnbrs,
'NUMEXTNBRS', this%memoryPath)
1044 call mem_allocate(this%nozee,
'NOZEE', this%memoryPath)
1045 call mem_allocate(this%vcthresh,
'VCTHRESH', this%memoryPath)
1046 call mem_allocate(this%lamatsaved,
'LAMATSAVED', this%memoryPath)
1047 call mem_allocate(this%ldispersion,
'LDISPERSION', this%memoryPath)
1056 this%nozee = .false.
1057 this%vcthresh = 1.d-10
1058 this%lamatsaved = .false.
1059 this%ldispersion = .false.
1070 integer(I4B) :: njax
1074 if (this%inewton /= 0)
then
1075 call mem_allocate(this%qsat, this%dis%nja,
'QSAT', this%memoryPath)
1077 call mem_allocate(this%qsat, 0,
'QSAT', this%memoryPath)
1083 if (this%ldispersion)
then
1087 this%lamatsaved = .true.
1088 call mem_allocate(this%iallpc, this%dis%nodes,
'IALLPC', this%memoryPath)
1089 do n = 1, this%dis%nodes
1097 call this%xt3d_iallpc()
1101 if (this%lamatsaved)
then
1102 call mem_allocate(this%amatpc, this%dis%nja,
'AMATPC', this%memoryPath)
1103 njax = this%numextnbrs
1104 call mem_allocate(this%amatpcx, njax,
'AMATPCX', this%memoryPath)
1106 call mem_allocate(this%amatpc, 0,
'AMATPC', this%memoryPath)
1107 call mem_allocate(this%amatpcx, 0,
'AMATPCX', this%memoryPath)
1111 call mem_allocate(this%rmatck, 3, 3,
'RMATCK', this%memoryPath)
1115 if (this%inewton /= 0)
then
1117 else if (this%lamatsaved)
then
1119 this%amatpcx =
dzero
1130 integer(I4B) :: n, m, mm, il0, il1
1131 integer(I4B) :: nnbr0, nnbr1
1132 integer(I4B),
dimension(this%nbrmax) :: inbr0, inbr1
1134 if (this%ixt3d == 2)
then
1135 this%lamatsaved = .false.
1136 call mem_allocate(this%iallpc, 0,
'IALLPC', this%memoryPath)
1140 call mem_allocate(this%iallpc, this%dis%nodes,
'IALLPC', this%memoryPath)
1141 do n = 1, this%dis%nodes
1147 do n = 1, this%dis%nodes
1148 if (this%icelltype(n) /= 0)
then
1152 nnbr0 = this%dis%con%ia(n + 1) - this%dis%con%ia(n) - 1
1153 call this%xt3d_load_inbr(n, nnbr0, inbr0)
1157 if (this%icelltype(m) /= 0)
then
1162 nnbr1 = this%dis%con%ia(m + 1) - this%dis%con%ia(m) - 1
1163 call this%xt3d_load_inbr(m, nnbr1, inbr1)
1166 if (this%icelltype(mm) /= 0)
then
1178 this%lamatsaved = .false.
1179 do n = 1, this%dis%nodes
1180 if (this%iallpc(n) == 1)
then
1181 this%lamatsaved = .true.
1187 if (.not. this%lamatsaved)
then
1200 integer(I4B) :: n, m, il0, ii01, jjs01, il01, il10, ii00, ii11, ii10
1202 integer(I4B) :: iinm
1209 call this%xt3d_get_iinm(m, n, iinm)
1210 il10 = iinm - this%dis%con%ia(m)
1212 ii00 = this%dis%con%ia(n)
1216 jjs01 = this%dis%con%jas(ii01)
1218 ii11 = this%dis%con%ia(m)
1226 subroutine xt3d_load(this, nodes, n, nnbr, inbr, vc, vn, dl, dln, ck, allhc)
1232 integer(I4B),
intent(in) :: nodes
1233 integer(I4B) :: n, nnbr
1234 integer(I4B),
dimension(this%nbrmax) :: inbr
1235 real(DP),
dimension(this%nbrmax, 3) :: vc, vn
1236 real(DP),
dimension(this%nbrmax) :: dl, dln
1237 real(DP),
dimension(3, 3) :: ck
1239 integer(I4B) :: il, ii, jj, jjs
1240 integer(I4B) :: ihcnjj
1241 real(DP) :: satn, satjj
1242 real(DP) :: cl1njj, cl2njj, dltot, ooclsum
1246 ck(1, 1) = this%k11(n)
1247 ck(2, 2) = this%k22(n)
1248 ck(3, 3) = this%k33(n)
1249 call this%xt3d_fillrmatck(n)
1250 ck = matmul(this%rmatck, ck)
1251 ck = matmul(ck, transpose(this%rmatck))
1259 ii = il + this%dis%con%ia(n)
1260 jj = this%dis%con%ja(ii)
1261 jjs = this%dis%con%jas(ii)
1262 if (this%ibound(jj) .ne. 0)
then
1265 satjj = this%sat(jj)
1268 ihcnjj = this%dis%con%ihc(jjs)
1269 call this%dis%connection_normal(n, jj, ihcnjj, vn(il, 1), vn(il, 2), &
1271 call this%dis%connection_vector(n, jj, this%nozee, satn, satjj, ihcnjj, &
1272 vc(il, 1), vc(il, 2), vc(il, 3), dltot)
1274 cl1njj = this%dis%con%cl1(jjs)
1275 cl2njj = this%dis%con%cl2(jjs)
1277 cl1njj = this%dis%con%cl2(jjs)
1278 cl2njj = this%dis%con%cl1(jjs)
1280 ooclsum = 1d0 / (cl1njj + cl2njj)
1281 dl(il) = dltot * cl1njj * ooclsum
1282 dln(il) = dltot * cl2njj * ooclsum
1283 if (this%dis%con%ihc(jjs) .eq. 0) allhc = .false.
1295 integer(I4B) :: n, nnbr
1296 integer(I4B),
dimension(this%nbrmax) :: inbr
1298 integer(I4B) :: il, ii, jj
1303 ii = il + this%dis%con%ia(n)
1304 jj = this%dis%con%ja(ii)
1305 if (this%ibound(jj) .ne. 0)
then
1315 subroutine xt3d_areas(this, nodes, n, m, jjs01, lsat, ar01, ar10, hnew, qsat)
1321 integer(I4B) :: nodes, n, m, jjs01
1322 real(DP) :: ar01, ar10
1323 real(DP),
intent(inout),
dimension(:),
optional :: hnew
1324 real(DP),
intent(in),
optional :: qsat
1326 real(DP) :: topn, botn, topm, botm, thksatn, thksatm
1327 real(DP) :: sill_top, sill_bot, tpn, tpm
1331 if (this%dis%con%ihc(jjs01) == 0)
then
1334 ar01 = this%dis%con%hwva(jjs01)
1336 else if (this%inewton /= 0)
then
1342 topn = this%dis%top(n)
1343 botn = this%dis%bot(n)
1344 topm = this%dis%top(m)
1345 botm = this%dis%bot(m)
1346 thksatn = topn - botn
1347 thksatm = topm - botm
1348 if (this%dis%con%ihc(jjs01) .eq. 2)
then
1350 sill_top = min(topn, topm)
1351 sill_bot = max(botn, botm)
1352 tpn = botn + thksatn
1353 tpm = botm + thksatm
1354 thksatn = max(min(tpn, sill_top) - sill_bot,
dzero)
1355 thksatm = max(min(tpm, sill_top) - sill_bot,
dzero)
1357 ar01 = this%dis%con%hwva(jjs01) *
dhalf * (thksatn + thksatm)
1363 if (
present(qsat))
then
1370 if (qsat <
dzero)
then
1371 satups = this%sat(n)
1373 satups = this%sat(m)
1380 call store_error(
'Program error: xt3d_areas called for a Newton &
1381 &horizontal connection without the saturated &
1382 &flow qsat.', terminate=.true.)
1385 ar01 = ar01 * satups
1391 topn = this%dis%top(n)
1392 botn = this%dis%bot(n)
1393 topm = this%dis%top(m)
1394 botm = this%dis%bot(m)
1395 thksatn = topn - botn
1396 thksatm = topm - botm
1397 if (.not. lsat)
then
1398 thksatn = this%sat(n) * thksatn
1399 thksatm = this%sat(m) * thksatm
1401 if (this%dis%con%ihc(jjs01) == 2)
then
1403 sill_top = min(topn, topm)
1404 sill_bot = max(botn, botm)
1405 tpn = botn + thksatn
1406 tpm = botm + thksatm
1407 thksatn = max(min(tpn, sill_top) - sill_bot,
dzero)
1408 thksatm = max(min(tpm, sill_top) - sill_bot,
dzero)
1410 ar01 = this%dis%con%hwva(jjs01) * thksatn
1411 ar10 = this%dis%con%hwva(jjs01) * thksatm
1418 matrix_sln, inbr, idxglo, chat)
1421 integer(I4B),
intent(in) :: nodes
1422 integer(I4B) :: n, idiag, nnbr, nja
1424 integer(I4B),
dimension(this%nbrmax) :: inbr
1425 integer(I4B),
intent(in),
dimension(nja) :: idxglo
1426 real(DP),
dimension(this%nbrmax) :: chat
1428 integer(I4B) :: iil, iii
1431 if (inbr(iil) .ne. 0)
then
1432 iii = this%dis%con%ia(n) + iil
1433 call matrix_sln%add_value_pos(idxglo(idiag), -chat(iil))
1434 call matrix_sln%add_value_pos(idxglo(iii), chat(iil))
1442 matrix_sln, inbr, idxglo, chat)
1445 integer(I4B),
intent(in) :: nodes
1446 integer(I4B) :: n, m, ii01, nnbr, nja
1448 integer(I4B),
dimension(this%nbrmax) :: inbr
1449 integer(I4B),
intent(in),
dimension(nja) :: idxglo
1450 real(DP),
dimension(this%nbrmax) :: chat
1452 integer(I4B) :: iil, iii, jjj, iixjjj, iijjj
1455 if (inbr(iil) .ne. 0)
then
1456 call matrix_sln%add_value_pos(idxglo(ii01), chat(iil))
1457 iii = this%dis%con%ia(m) + iil
1458 jjj = this%dis%con%ja(iii)
1459 call this%xt3d_get_iinmx(n, jjj, iixjjj)
1460 if (iixjjj .ne. 0)
then
1461 call matrix_sln%add_value_pos(this%idxglox(iixjjj), -chat(iil))
1463 call this%xt3d_get_iinm(n, jjj, iijjj)
1464 call matrix_sln%add_value_pos(idxglo(iijjj), -chat(iil))
1475 integer(I4B),
intent(in) :: nodes
1476 integer(I4B) :: n, idiag, nnbr
1477 integer(I4B),
dimension(this%nbrmax) :: inbr
1478 real(DP),
dimension(this%nbrmax) :: chat
1480 integer(I4B) :: iil, iii
1483 iii = this%dis%con%ia(n) + iil
1484 this%amatpc(idiag) = this%amatpc(idiag) - chat(iil)
1485 this%amatpc(iii) = this%amatpc(iii) + chat(iil)
1494 integer(I4B),
intent(in) :: nodes
1495 integer(I4B) :: n, m, ii01, nnbr
1496 integer(I4B),
dimension(this%nbrmax) :: inbr
1497 real(DP),
dimension(this%nbrmax) :: chat
1499 integer(I4B) :: iil, iii, jjj, iixjjj, iijjj
1502 this%amatpc(ii01) = this%amatpc(ii01) + chat(iil)
1503 iii = this%dis%con%ia(m) + iil
1504 jjj = this%dis%con%ja(iii)
1505 call this%xt3d_get_iinmx(n, jjj, iixjjj)
1506 if (iixjjj .ne. 0)
then
1507 this%amatpcx(iixjjj) = this%amatpcx(iixjjj) - chat(iil)
1509 call this%xt3d_get_iinm(n, jjj, iijjj)
1510 this%amatpc(iijjj) = this%amatpc(iijjj) - chat(iil)
1521 integer(I4B) :: n, m, iinm
1523 integer(I4B) :: ii, jj
1526 do ii = this%dis%con%ia(n), this%dis%con%ia(n + 1) - 1
1527 jj = this%dis%con%ja(ii)
1541 integer(I4B) :: n, m, iinmx
1543 integer(I4B) :: iix, jjx
1546 do iix = this%iax(n), this%iax(n + 1) - 1
1548 if (jjx .eq. m)
then
1557 subroutine xt3d_rhs(this, nodes, n, m, nnbr, inbr, chat, hnew, &
1561 integer(I4B),
intent(in) :: nodes
1562 integer(I4B) :: n, m, nnbr
1563 integer(I4B),
dimension(this%nbrmax) :: inbr
1564 real(DP),
dimension(this%nbrmax) :: chat
1565 real(DP),
intent(inout),
dimension(nodes) :: hnew, rhs
1567 integer(I4B) :: iil, iii, jjj
1571 if (inbr(iil) .ne. 0)
then
1572 iii = iil + this%dis%con%ia(n)
1573 jjj = this%dis%con%ja(iii)
1574 term = chat(iil) * (hnew(jjj) - hnew(n))
1575 rhs(n) = rhs(n) - term
1576 rhs(m) = rhs(m) + term
1583 subroutine xt3d_qnbrs(this, nodes, n, m, nnbr, inbr, chat, hnew, &
1587 integer(I4B),
intent(in) :: nodes
1588 integer(I4B) :: n, m, nnbr
1589 integer(I4B),
dimension(this%nbrmax) :: inbr
1591 real(DP),
dimension(this%nbrmax) :: chat
1592 real(DP),
intent(inout),
dimension(nodes) :: hnew
1594 integer(I4B) :: iil, iii, jjj
1599 if (inbr(iil) .ne. 0)
then
1600 iii = iil + this%dis%con%ia(n)
1601 jjj = this%dis%con%ja(iii)
1602 term = chat(iil) * (hnew(jjj) - hnew(n))
1603 qnbrs = qnbrs + term
1615 integer(I4B),
intent(in) :: n
1617 real(DP) :: ang1, ang2, ang3, ang2d, ang3d
1618 real(DP) :: s1, c1, s2, c2, s3, c3
1620 if (this%nozee)
then
1623 ang1 = this%angle1(n)
1627 ang1 = this%angle1(n)
1628 ang2 = this%angle2(n)
1629 ang3 = this%angle3(n)
1637 this%rmatck(1, 1) = c1 * c2
1638 this%rmatck(1, 2) = c1 * s2 * s3 - s1 * c3
1639 this%rmatck(1, 3) = -c1 * s2 * c3 - s1 * s3
1640 this%rmatck(2, 1) = s1 * c2
1641 this%rmatck(2, 2) = s1 * s2 * s3 + c1 * c3
1642 this%rmatck(2, 3) = -s1 * s2 * c3 + c1 * s3
1643 this%rmatck(3, 1) = s2
1644 this%rmatck(3, 2) = -c2 * s3
1645 this%rmatck(3, 3) = c2 * c3
This module contains simulation constants.
real(dp), parameter dhalf
real constant 1/2
real(dp), parameter dzero
real constant zero
integer(i4b), parameter lenmempath
maximum length of the memory path
real(dp), parameter done
real constant 1
This module defines variable data types.
character(len=lenmempath) function create_mem_path(component, subcomponent, context)
returns the path to the memory object
This module contains simulation methods.
subroutine, public store_error(msg, terminate)
Store an error message.
real(dp) function squadraticsaturationderivative(top, bot, x, eps)
@ brief Derivative of the quadratic saturation function
subroutine qconds(nnbrmx, nnbr0, inbr0, il01, vc0, vn0, dl0, dl0n, ck0, nnbr1, inbr1, il10, vc1, vn1, dl1, dl1n, ck1, ar01, ar10, vcthresh, allhc0, allhc1, chat01, chati0, chat1j)
Compute the "conductances" in the normal-flux expression for an interface (modflow-usg version)....
subroutine xt3d_load(this, nodes, n, nnbr, inbr, vc, vn, dl, dln, ck, allhc)
Load conductivity and connection info for a cell into arrays used by XT3D.
subroutine xt3d_ac(this, moffset, sparse)
Add connections for extended neighbors to the sparse matrix.
subroutine xt3d_get_iinmx(this, n, m, iinmx)
Get position of n-m "extended connection" in jax array (return 0 if not connected)
subroutine xt3d_amatpcx_nbrnbrs(this, nodes, n, m, ii01, nnbr, inbr, chat)
Add contributions from neighbors of neighbor to amatpc and amatpcx.
subroutine allocate_arrays(this)
Allocate xt3d arrays.
subroutine xt3d_amat_nbrnbrs(this, nodes, n, m, ii01, nnbr, nja, matrix_sln, inbr, idxglo, chat)
Add contributions from neighbors of neighbor to amat.
subroutine xt3d_da(this)
Deallocate variables.
subroutine allocate_scalars(this)
Allocate scalar pointer variables.
subroutine xt3d_amat_nbrs(this, nodes, n, idiag, nnbr, nja, matrix_sln, inbr, idxglo, chat)
Add contributions from neighbors to amat.
subroutine xt3d_flowja(this, hnew, flowja)
Budget.
subroutine xt3d_get_iinm(this, n, m, iinm)
Get position of n-m connection in ja array (return 0 if not connected)
subroutine xt3d_areas(this, nodes, n, m, jjs01, lsat, ar01, ar10, hnew, qsat)
Compute interfacial areas.
subroutine xt3d_fhfb(this, kiter, nodes, nja, matrix_sln, idxglo, rhs, hnew, n, m, condhfb)
Formulate HFB correction.
subroutine xt3d_flowjahfb(this, n, m, hnew, flowja, condhfb)
hfb contribution to flowja when xt3d is used
subroutine xt3d_indices(this, n, m, il0, ii01, jjs01, il01, il10, ii00, ii11, ii10)
Set various indices for XT3D.
subroutine xt3d_load_inbr(this, n, nnbr, inbr)
Load neighbor list for a cell.
subroutine xt3d_fcpc(this, nodes, lsat)
Formulate for permanently confined connections and save in amatpc and amatpcx.
subroutine xt3d_fn(this, kiter, nodes, nja, matrix_sln, idxglo, rhs, hnew)
Fill Newton terms for xt3d.
subroutine xt3d_fillrmatck(this, n)
Fill rmat array for cell n.
subroutine xt3d_mc(this, moffset, matrix_sln)
Map connections and construct iax, jax, and idxglox.
subroutine, public xt3d_cr(xt3dobj, name_model, inunit, iout, ldispopt)
Create a new xt3d object.
subroutine xt3d_qnbrs(this, nodes, n, m, nnbr, inbr, chat, hnew, qnbrs)
Add contributions to flow from neighbors.
subroutine xt3d_fc(this, kiter, matrix_sln, idxglo, rhs, hnew)
Formulate.
subroutine xt3d_rhs(this, nodes, n, m, nnbr, inbr, chat, hnew, rhs)
Add contributions to rhs.
subroutine xt3d_df(this, dis)
Define the xt3d object.
subroutine xt3d_iallpc(this)
Allocate and populate iallpc array. Set lamatsaved.
subroutine xt3d_ar(this, ibound, k11, ik33, k33, sat, ik22, k22, iangle1, iangle2, iangle3, angle1, angle2, angle3, inewton, icelltype)
Allocate and Read.
subroutine xt3d_amatpc_nbrs(this, nodes, n, idiag, nnbr, inbr, chat)
Add contributions from neighbors to amatpc.