23 integer(I4B),
pointer :: zeromethod
51 allocate (method%type)
52 allocate (method%zeromethod)
56 method%delegates = .true.
63 deallocate (this%type)
67 subroutine load_disv(this, particle, next_level, submethod)
75 integer(I4B),
intent(in) :: next_level
76 class(
methodtype),
pointer,
intent(inout) :: submethod
83 select type (cell => this%cell)
86 ic = particle%idomain(next_level)
87 call this%load_cell_defn(ic, cell%defn)
88 if (this%fmi%ibdgwfsat0(ic) == 0)
then
93 trackfilectl=this%trackfilectl, &
94 tracktimes=this%tracktimes)
98 if (cell%defn%can_be_rect)
then
103 trackfilectl=this%trackfilectl, &
104 tracktimes=this%tracktimes)
106 else if (cell%defn%can_be_quad)
then
111 trackfilectl=this%trackfilectl, &
112 tracktimes=this%tracktimes)
117 trackfilectl=this%trackfilectl, &
118 tracktimes=this%tracktimes)
134 integer(I4B) :: inface
139 integer(I4B) :: idiag
144 inface = particle%iboundary(2)
147 select type (cell => this%cell)
149 select type (dis => this%fmi%dis)
151 inbr = cell%defn%facenbr(inface)
152 if (inbr .eq. 0)
then
159 particle%advancing = .false.
160 call this%save(particle, reason=3)
163 idiag = dis%con%ia(cell%defn%icell)
165 ic = dis%con%ja(ipos)
166 particle%idomain(2) = ic
169 icu = dis%get_nodeuser(ic)
170 call get_jk(icu, dis%ncpl, dis%nlay, icpl, ilay)
174 call this%map_neighbor(cell%defn, inface, z)
175 particle%iboundary(2) = inface
176 particle%idomain(3:) = 0
177 particle%iboundary(3:) = 0
182 this%flowja(ipos) = this%flowja(ipos) -
done
184 this%flowja(dis%con%isym(ipos)) &
185 = this%flowja(dis%con%isym(ipos)) +
done
196 integer(I4B),
intent(inout) :: inface
197 double precision,
intent(inout) :: z
200 integer(I4B) :: npolyvertsin
202 integer(I4B) :: npolyverts
204 integer(I4B) :: inbrnbr
216 inbr = defn%facenbr(inface)
217 if (inbr .eq. 0)
then
223 j = this%fmi%dis%con%ia(icin)
224 ic = this%fmi%dis%con%ja(j + inbr)
227 call this%load_cell_defn(ic, cd)
228 npolyvertsin = defn%npolyverts
229 npolyverts = cd%npolyverts
230 if (inface .eq. npolyvertsin + 2)
then
232 inface = npolyverts + 3
233 else if (inface .eq. npolyvertsin + 3)
then
235 inface = npolyverts + 2
238 j = this%fmi%dis%con%ia(ic)
240 do m = 1, npolyverts + 3
241 inbrnbr = cd%facenbr(m)
242 if (this%fmi%dis%con%ja(j + inbrnbr) .eq. icin)
then
250 zrel = (z - botfrom) / (topfrom - botfrom)
252 top = this%fmi%dis%top(ic)
253 bot = this%fmi%dis%bot(ic)
254 sat = this%fmi%gwfsat(ic)
255 z = bot + zrel * sat * (top - bot)
265 real(DP),
intent(in) :: tmax
266 call this%track(particle, 1, tmax)
273 integer(I4B),
intent(in) :: ic
276 integer(I4B) :: icu2d
279 integer(I4B) :: npolyverts
281 select type (dis => this%fmi%dis)
283 ncpl = dis%get_ncpl()
284 icu = dis%get_nodeuser(ic)
285 icu2d = icu - ((icu - 1) / ncpl) * ncpl
286 npolyverts = dis%iavert(icu2d + 1) - dis%iavert(icu2d) - 1
287 if (npolyverts .le. 0) npolyverts = npolyverts +
size(dis%javert)
296 integer(I4B),
intent(in) :: iatop
300 if (iatop .lt. 0)
then
301 top = this%fmi%dis%top(-iatop)
303 top = this%fmi%dis%bot(iatop)
311 integer(I4B),
intent(in) :: ic
320 defn%npolyverts = this%get_npolyverts(ic)
321 defn%iatop =
get_iatop(this%fmi%dis%get_ncpl(), &
322 this%fmi%dis%get_nodeuser(ic))
323 top = this%fmi%dis%top(ic)
324 bot = this%fmi%dis%bot(ic)
325 sat = this%fmi%gwfsat(ic)
326 top = bot + sat * (top - bot)
330 defn%porosity = this%porosity(ic)
331 defn%retfactor = this%retfactor(ic)
332 defn%izone = this%izone(ic)
335 call this%fmi%dis%get_polyverts( &
341 call this%load_nbrs_to_defn(defn)
344 call this%load_flags_to_defn(defn)
347 call this%load_flows_to_defn(defn)
358 integer(I4B) :: npolyverts
369 integer(I4B) :: istart1
370 integer(I4B) :: istart2
371 integer(I4B) :: istop1
372 integer(I4B) :: istop2
373 integer(I4B) :: iedgeface
377 npolyverts = defn%npolyverts
380 if (
size(defn%facenbr) < npolyverts + 3) &
383 select type (dis => this%fmi%dis)
388 icu1 = dis%get_nodeuser(ic1)
389 ncpl = dis%get_ncpl()
390 call get_jk(icu1, ncpl, dis%nlay, j1, k1)
391 istart1 = dis%iavert(j1)
392 istop1 = dis%iavert(j1 + 1) - 1
393 do iloc = 1, dis%con%ia(ic1 + 1) - dis%con%ia(ic1) - 1
394 ipos = dis%con%ia(ic1) + iloc
395 if (dis%con%mask(ipos) == 0) cycle
396 ic2 = dis%con%ja(ipos)
397 icu2 = dis%get_nodeuser(ic2)
398 call get_jk(icu2, ncpl, dis%nlay, j2, k2)
399 istart2 = dis%iavert(j2)
400 istop2 = dis%iavert(j2 + 1) - 1
402 dis%javert(istart2:istop2), &
404 if (iedgeface /= 0)
then
407 defn%facenbr(iedgeface) = int(iloc, 1)
411 defn%facenbr(npolyverts + 2) = int(iloc, 1)
412 else if (k2 < k1)
then
414 defn%facenbr(npolyverts + 3) = int(iloc, 1)
416 call pstop(1,
"k2 should be <> k1, since no shared edge face")
422 defn%facenbr(npolyverts + 1) = defn%facenbr(1)
437 integer(I4B),
dimension(:) :: ivlist1
438 integer(I4B),
dimension(:) :: ivlist2
439 integer(I4B),
intent(out) :: iedgeface
444 logical(LGP) :: found
450 outerloop:
do il1 = 1, nv1 - 1
452 if (ivlist1(il1) == ivlist2(il2) .and. &
453 ivlist1(il1 + 1) == ivlist2(il2 - 1))
then
472 integer(I4B) :: npolyverts
477 npolyverts = defn%npolyverts
480 if (
size(defn%faceflow) < npolyverts + 3) &
491 do m = 1, npolyverts + 3
494 defn%faceflow(m) = this%fmi%gwfflowja(this%fmi%dis%con%ia(ic) + n)
496 call this%load_boundary_flows_to_defn_poly(defn)
499 do m = 1, npolyverts + 3
500 if (defn%faceflow(m) < 0d0) defn%inoexitface = 0
504 defn%distflow = this%fmi%SourceFlows(ic) + this%fmi%SinkFlows(ic) + &
505 this%fmi%StorageFlows(ic)
508 if (this%fmi%SinkFlows(ic) .ne. 0d0)
then
524 integer(I4B) :: npolyverts
525 integer(I4B) :: ioffset
528 npolyverts = defn%npolyverts
533 ioffset = (ic - 1) * 10
535 defn%faceflow(1) = defn%faceflow(1) + &
536 this%fmi%BoundaryFlows(ioffset + 4)
537 defn%faceflow(2) = defn%faceflow(2) + &
538 this%fmi%BoundaryFlows(ioffset + 2)
539 defn%faceflow(3) = defn%faceflow(3) + &
540 this%fmi%BoundaryFlows(ioffset + 3)
541 defn%faceflow(4) = defn%faceflow(4) + &
542 this%fmi%BoundaryFlows(ioffset + 1)
543 defn%faceflow(5) = defn%faceflow(1)
544 defn%faceflow(6) = defn%faceflow(6) + &
545 this%fmi%BoundaryFlows(ioffset + 9)
546 defn%faceflow(7) = defn%faceflow(7) + &
547 this%fmi%BoundaryFlows(ioffset + 10)
559 integer(I4B) :: npolyverts
563 integer(I4B) :: ioffset
567 integer(I4B) :: mdiff
569 integer(I4B) :: irectvert(5)
572 npolyverts = defn%npolyverts
577 ioffset = (ic - 1) * 10
582 else if (n .eq. 4)
then
587 qbf = this%fmi%BoundaryFlows(ioffset + nbf)
590 if (.not. defn%ispv180(m))
then
595 irectvert(5) = irectvert(1)
597 m2 = irectvert(n + 1)
598 if (m2 .lt. m1) m2 = m2 + npolyverts
600 if (mdiff .eq. 1)
then
602 defn%faceflow(m1) = defn%faceflow(m1) + qbf
606 defn%faceflow(m1) = defn%faceflow(m1) + qbf
607 defn%faceflow(m1 + 1) = defn%faceflow(m1 + 1) + qbf
612 defn%faceflow(m) = defn%faceflow(1)
615 defn%faceflow(m) = defn%faceflow(m) + &
616 this%fmi%BoundaryFlows(ioffset + 9)
619 defn%faceflow(m) = defn%faceflow(m) + &
620 this%fmi%BoundaryFlows(ioffset + 10)
632 integer(I4B) :: npolyverts
633 integer(I4B) :: ioffset
637 npolyverts = defn%npolyverts
640 ioffset = (ic - 1) * 10
641 do iv = 1, npolyverts
643 defn%faceflow(iv) = &
644 defn%faceflow(iv) + &
645 this%fmi%BoundaryFlows(ioffset + iv)
647 defn%faceflow(npolyverts + 1) = defn%faceflow(1)
648 defn%faceflow(npolyverts + 2) = &
649 defn%faceflow(npolyverts + 2) + &
650 this%fmi%BoundaryFlows(ioffset + 9)
651 defn%faceflow(npolyverts + 3) = &
652 defn%faceflow(npolyverts + 3) + &
653 this%fmi%BoundaryFlows(ioffset + 10)
665 integer(I4B) :: npolyverts
671 integer(I4B) :: num90
672 integer(I4B) :: num180
673 integer(I4B) :: numacute
685 s0mag, s2x, s2y, s2mag, sinang, dotprod
689 npolyverts = defn%npolyverts
692 if (
size(defn%ispv180) < npolyverts + 3) &
697 defn%ispv180(1:npolyverts + 1) = .false.
698 defn%can_be_rect = .false.
699 defn%can_be_quad = .false.
713 else if (m1 .eq. npolyverts)
then
720 x0 = defn%polyvert(1, m0)
721 y0 = defn%polyvert(2, m0)
722 x1 = defn%polyvert(1, m1)
723 y1 = defn%polyvert(2, m1)
724 x2 = defn%polyvert(1, m2)
725 y2 = defn%polyvert(2, m2)
728 s0mag = dsqrt(s0x * s0x + s0y * s0y)
731 s2mag = dsqrt(s2x * s2x + s2y * s2y)
732 sinang = (s0x * s2y - s0y * s2x) / (s0mag * s2mag)
734 if (dabs(sinang) .lt. epsang)
then
735 dotprod = s0x * s2x + s0y * s2y
736 if (dotprod .gt. 0d0)
then
737 print *,
"Cell ", ic,
" has a zero angle"
738 print *,
" (tolerance epsang = ", epsang,
")"
742 print *,
"Cell ", ic, &
743 " has consecutive 180-deg angles - not supported"
744 print *,
" (tolerance epsang = ", epsang,
")"
746 else if (dabs((s2mag - s0mag) / max(s2mag, s0mag)) .gt. epslen)
then
747 print *,
"Cell ", ic, &
748 " has a non-bisecting 180-deg vertex - not supported"
749 print *,
" (tolerance epslen = ", epslen,
")"
756 defn%ispv180(m) = .true.
758 else if (sinang .gt. 0d0)
then
759 numacute = numacute + 1
760 if (dabs(1d0 - sinang) .lt. epsang) num90 = num90 + 1
763 print *,
"Cell ", ic, &
764 " has an obtuse angle and so is nonconvex"
765 print *,
" (tolerance epsang = ", epsang,
")"
769 if ((num90 .ne. 4) .and. (num180 .ne. 0))
then
770 print *,
"Cell ", ic, &
771 " is a non-rectangle with a 180-deg angle - not supported"
772 print *,
" (tolerance epsang = ", epsang,
")"
776 defn%ispv180(npolyverts + 1) = defn%ispv180(1)
778 if (num90 .eq. 4)
then
779 if (num180 .eq. 0)
then
780 defn%can_be_rect = .true.
782 defn%can_be_quad = .true.
subroutine, public create_defn(cellDefn)
Create a new cell definition object.
integer function get_npolyverts(this)
Return the number of polygon vertices.
subroutine, public create_cell_poly(cell)
Create a new polygonal cell.
subroutine, public cell_poly_to_rect(poly, rect)
Convert CellPoly representation to CellRect if possible.
subroutine, public cell_poly_to_quad(poly, quad)
Convert CellPoly representation to CellRectQuad if possible.
This module contains simulation constants.
real(dp), parameter done
real constant 1
subroutine pstop(status, message)
Stop the program, optionally specifying an error status code.
subroutine, public get_jk(nodenumber, ncpl, nlay, icpl, ilay)
Get layer index and within-layer node index from node number and grid dimensions. If nodenumber is in...
This module defines variable data types.
Cell-level tracking methods.
type(methodcellpollocktype), pointer, public method_cell_plck
type(methodcellpasstobottype), pointer, public method_cell_ptb
type(methodcellpollockquadtype), pointer, public method_cell_quad
type(methodcellternarytype), pointer, public method_cell_tern
subroutine, public create_method_disv(method)
Create a new vertex grid (DISV) tracking method.
subroutine load_boundary_flows_to_defn_rect(this, defn)
Load boundary flows from the grid into a rectangular cell. Assumes cell index and number of vertices ...
subroutine load_nbrs_to_defn(this, defn)
Loads face neighbors to cell definition from the grid Assumes cell index and number of vertices are a...
subroutine shared_edgeface(ivlist1, ivlist2, iedgeface)
Find the edge face shared by two cells.
subroutine map_neighbor(this, defn, inface, z)
Map location on cell face to shared cell face of neighbor.
subroutine load_boundary_flows_to_defn_rect_quad(this, defn)
Load boundary flows from the grid into rectangular quadcell. Assumes cell index and number of vertice...
subroutine load_flags_to_defn(this, defn)
Load 180-degree vertex indicator array and set flags indicating how cell can be represented (kluge: l...
subroutine load_disv(this, particle, next_level, submethod)
Load the cell and the tracking method.
subroutine load_boundary_flows_to_defn_poly(this, defn)
Load boundary flows from the grid into a polygonal cell. Assumes cell index and number of vertices ar...
real(dp) function get_top(this, iatop)
Get top elevation based on index iatop kluge note: not needed???
subroutine load_flows_to_defn(this, defn)
Load flows into the cell definition. These include face flows and net distributed flows....
subroutine load_cell_defn(this, ic, defn)
Load cell definition from the grid.
subroutine apply_disv(this, particle, tmax)
Apply the DISV-grid method.
subroutine pass_disv(this, particle)
Pass a particle to the next cell, if there is one.
Particle tracking strategies.
integer(i4b) function, public get_iatop(ncpl, icu)
Get the index corresponding to top elevation of a cell in the grid. This is -1 if the cell is in the ...
Base grid cell definition.
Base type for grid cells of a concrete type. Contains a cell-definition which is information shared b...
Vertex grid discretization.
Base type for particle tracking methods.
A particle tracked by the PRT model.
Manages particle track (i.e. pathline) files.