22 integer(I4B) :: nverts
23 real(dp),
allocatable,
dimension(:) :: xvert
24 real(dp),
allocatable,
dimension(:) :: yvert
25 real(dp),
allocatable,
dimension(:) :: vne
26 real(dp),
allocatable,
dimension(:) :: vv0x
27 real(dp),
allocatable,
dimension(:) :: vv0y
28 real(dp),
allocatable,
dimension(:) :: vv1x
29 real(dp),
allocatable,
dimension(:) :: vv1y
39 integer(I4B),
allocatable,
dimension(:) :: iprev
40 real(dp),
allocatable,
dimension(:) :: xvertnext
41 real(dp),
allocatable,
dimension(:) :: yvertnext
42 integer(I4B),
public,
pointer :: zeromethod
66 method%type => method%cell%type
67 method%delegates = .true.
69 method%subcell => subcell
75 deallocate (this%type)
79 subroutine load_mct(this, particle, next_level, submethod)
83 integer(I4B),
intent(in) :: next_level
84 class(
methodtype),
pointer,
intent(inout) :: submethod
86 select type (subcell => this%subcell)
88 call this%load_subcell(particle, subcell)
92 subcell=this%subcell, &
93 trackfilectl=this%trackfilectl, &
94 tracktimes=this%tracktimes)
105 integer(I4B) :: exitFace
106 integer(I4B) :: inface
108 exitface = particle%iboundary(3)
109 isc = particle%idomain(3)
111 select case (exitface)
118 if (inface .eq. 0) inface = this%nverts
122 if (isc .gt. this%nverts) isc = 1
123 particle%idomain(3) = isc
124 particle%iboundary(3) = 3
129 if (isc .lt. 1) isc = this%nverts
130 particle%idomain(3) = isc
131 particle%iboundary(3) = 2
135 inface = this%nverts + 2
138 inface = this%nverts + 3
140 if (inface .eq. -1)
then
141 particle%iboundary(2) = 0
142 else if (inface .eq. 0)
then
143 particle%iboundary(2) = 0
145 particle%iboundary(2) = inface
155 real(DP),
intent(in) :: tmax
161 call this%update(particle, this%cell%defn)
164 if (.not. particle%advancing)
return
169 if (particle%z > this%cell%defn%top)
then
170 particle%z = this%cell%defn%top
171 call this%save(particle, reason=1)
174 select type (cell => this%cell)
177 this%nverts = cell%defn%npolyverts
179 if (
allocated(this%xvert))
then
180 deallocate (this%xvert)
181 deallocate (this%yvert)
182 deallocate (this%vne)
183 deallocate (this%vv0x)
184 deallocate (this%vv0y)
185 deallocate (this%vv1x)
186 deallocate (this%vv1y)
187 deallocate (this%iprev)
188 deallocate (this%xvertnext)
189 deallocate (this%yvertnext)
191 allocate (this%xvert(this%nverts))
192 allocate (this%yvert(this%nverts))
193 allocate (this%vne(this%nverts))
194 allocate (this%vv0x(this%nverts))
195 allocate (this%vv0y(this%nverts))
196 allocate (this%vv1x(this%nverts))
197 allocate (this%vv1y(this%nverts))
198 allocate (this%iprev(this%nverts))
199 allocate (this%xvertnext(this%nverts))
200 allocate (this%yvertnext(this%nverts))
202 do i = 1, this%nverts
203 this%xvert(i) = cell%defn%polyvert(1, i)
204 this%yvert(i) = cell%defn%polyvert(2, i)
207 this%ztop = cell%defn%top
208 this%zbot = cell%defn%bot
209 this%dz = this%ztop - this%zbot
211 do i = 1, this%nverts
214 this%iprev = cshift(this%iprev, -1)
215 this%xvertnext = cshift(this%xvert, 1)
216 this%yvertnext = cshift(this%yvert, 1)
223 call this%track(particle, 2, tmax)
257 select type (cell => this%cell)
261 isc = particle%idomain(3)
265 do iv0 = 1, this%nverts
268 x1 = this%xvertnext(iv0)
269 y1 = this%yvertnext(iv0)
276 di2 = xi * y2rel - yi * x2rel
277 d02 = x0 * y2rel - y0 * x2rel
278 d12 = x1rel * y2rel - y1rel * x2rel
279 di1 = xi * y1rel - yi * x1rel
280 d01 = x0 * y1rel - y0 * x1rel
281 alphai = (di2 - d02) / d12
282 betai = -(di1 - d01) / d12
284 if ((alphai .ge.
dzero) .and. &
285 (alphai + betai .le.
done))
then
291 print *,
"error -- initial triangle not found in cell ", ic, &
292 " for particle at ", particle%x, particle%y, particle%z
296 particle%idomain(3) = isc
299 subcell%isubcell = isc
303 subcell%x0 = this%xvert(iv0)
304 subcell%y0 = this%yvert(iv0)
305 subcell%x1 = this%xvertnext(iv0)
306 subcell%y1 = this%yvertnext(iv0)
307 subcell%x2 = this%xctr
308 subcell%y2 = this%yctr
309 subcell%v0x = this%vv0x(iv0)
310 subcell%v0y = this%vv0y(iv0)
311 subcell%v1x = this%vv1x(iv0)
312 subcell%v1y = this%vv1y(iv0)
313 subcell%v2x = this%vctrx
314 subcell%v2y = this%vctry
315 subcell%ztop = this%ztop
316 subcell%zbot = this%zbot
318 subcell%vzbot = this%vzbot
319 subcell%vztop = this%vztop
332 real(DP),
allocatable,
dimension(:) :: xvals
333 real(DP),
allocatable,
dimension(:) :: yvals
340 real(DP),
allocatable,
dimension(:) :: wk1
341 real(DP),
allocatable,
dimension(:) :: wk2
342 real(DP),
allocatable,
dimension(:) :: unextxnext
343 real(DP),
allocatable,
dimension(:) :: unextynext
344 real(DP),
allocatable,
dimension(:) :: le
345 real(DP),
allocatable,
dimension(:) :: unextx
346 real(DP),
allocatable,
dimension(:) :: unexty
348 real(DP),
allocatable,
dimension(:) :: areasub
350 real(DP),
allocatable,
dimension(:) :: li
351 real(DP),
allocatable,
dimension(:) :: unintx
352 real(DP),
allocatable,
dimension(:) :: uninty
353 real(DP),
allocatable,
dimension(:) :: xmid
354 real(DP),
allocatable,
dimension(:) :: ymid
355 real(DP),
allocatable,
dimension(:) :: lm
356 real(DP),
allocatable,
dimension(:) :: umx
357 real(DP),
allocatable,
dimension(:) :: umy
358 real(DP),
allocatable,
dimension(:) :: kappax
359 real(DP),
allocatable,
dimension(:) :: kappay
360 real(DP),
allocatable,
dimension(:) :: vm0x
361 real(DP),
allocatable,
dimension(:) :: vm0y
362 real(DP),
allocatable,
dimension(:) :: vm1x
363 real(DP),
allocatable,
dimension(:) :: vm1y
365 select type (cell => this%cell)
369 allocate (le(this%nverts))
370 allocate (unextx(this%nverts))
371 allocate (unexty(this%nverts))
372 allocate (areasub(this%nverts))
373 allocate (li(this%nverts))
374 allocate (unintx(this%nverts))
375 allocate (uninty(this%nverts))
376 allocate (xmid(this%nverts))
377 allocate (ymid(this%nverts))
378 allocate (lm(this%nverts))
379 allocate (umx(this%nverts))
380 allocate (umy(this%nverts))
381 allocate (kappax(this%nverts))
382 allocate (kappay(this%nverts))
383 allocate (vm0x(this%nverts))
384 allocate (vm0y(this%nverts))
385 allocate (vm1x(this%nverts))
386 allocate (vm1y(this%nverts))
387 allocate (unextxnext(this%nverts))
388 allocate (unextynext(this%nverts))
389 allocate (wk1(this%nverts))
390 allocate (wk2(this%nverts))
395 wk1 = this%xvertnext - this%xvert
396 wk2 = this%yvertnext - this%yvert
397 le = dsqrt(wk1 * wk1 + wk2 * wk2)
402 areacell =
area(this%xvert, this%yvert)
405 sixa = areacell * 6.d0
406 wk1 = -(this%xvert * this%yvertnext - this%xvertnext * this%yvert)
407 this%xctr = sum((this%xvert + this%xvertnext) * wk1) / sixa
408 this%yctr = sum((this%yvert + this%yvertnext) * wk1) / sixa
411 do i = 1, this%nverts
412 xvals(1) = this%xvert(i)
413 xvals(2) = this%xvertnext(i)
415 yvals(1) = this%yvert(i)
416 yvals(2) = this%yvertnext(i)
418 areasub(i) =
area(xvals, yvals)
422 term =
done / (cell%defn%porosity * cell%defn%retfactor * this%dz)
423 do i = 1, this%nverts
424 this%vne(i) = -cell%defn%faceflow(i) * term / le(i)
428 divcell = sum(le * this%vne) / areacell
431 wk1 = this%xvert - this%xctr
432 wk2 = this%yvert - this%yctr
433 li = dsqrt(wk1 * wk1 + wk2 * wk2)
437 unextxnext = cshift(unintx, 1)
438 unextynext = cshift(uninty, 1)
441 xmid = 5.d-1 * (this%xvert + this%xctr)
442 ymid = 5.d-1 * (this%yvert + this%yctr)
445 wk1 = cshift(xmid, 1) - xmid
446 wk2 = cshift(ymid, 1) - ymid
447 lm = dsqrt(wk1 * wk1 + wk2 * wk2)
464 call this%calc_thru_hcsum(vm0i0, divcell, le, li, lm, areasub, areacell, &
465 unintx, uninty, unextx, unexty, &
466 unextxnext, unextynext, &
467 kappax, kappay, vm0x, vm0y, vm1x, vm1y, hcsum0)
469 vm0ival = vm0i0 + perturb
470 call this%calc_thru_hcsum(vm0ival, divcell, le, li, lm, areasub, areacell, &
471 unintx, uninty, unextx, unexty, &
472 unextxnext, unextynext, &
473 kappax, kappay, vm0x, vm0y, vm1x, vm1y, hcsum)
475 jac = (hcsum - hcsum0) / perturb
476 vm0ival = vm0i0 - hcsum0 / jac
477 call this%calc_thru_hcsum(vm0ival, divcell, le, li, lm, areasub, areacell, &
478 unintx, uninty, unextx, unexty, &
479 unextxnext, unextynext, &
480 kappax, kappay, vm0x, vm0y, vm1x, vm1y, hcsum)
485 this%vv0x = 2.d0 * vm0x - this%vctrx
486 this%vv0y = 2.d0 * vm0y - this%vctry
487 this%vv1x = 2.d0 * vm1x - this%vctrx
488 this%vv1y = 2.d0 * vm1y - this%vctry
491 term =
done / (cell%defn%retfactor * cell%defn%porosity * areacell)
492 this%vzbot = cell%defn%faceflow(this%nverts + 2) * term
493 this%vztop = -cell%defn%faceflow(this%nverts + 3) * term
514 deallocate (unextxnext)
515 deallocate (unextynext)
525 le, li, lm, areasub, areacell, &
526 unintx, uninty, unextx, unexty, &
527 unintxnext, unintynext, &
528 kappax, kappay, vm0x, vm0y, vm1x, vm1y, hcsum)
534 real(DP),
dimension(:) :: le
535 real(DP),
dimension(:) :: li
536 real(DP),
dimension(:) :: lm
537 real(DP),
dimension(:) :: areasub
539 real(DP),
dimension(:) :: unintx
540 real(DP),
dimension(:) :: uninty
541 real(DP),
dimension(:) :: unextx
542 real(DP),
dimension(:) :: unexty
543 real(DP),
dimension(:) :: unintxnext
544 real(DP),
dimension(:) :: unintynext
545 real(DP),
dimension(:) :: kappax
546 real(DP),
dimension(:) :: kappay
547 real(DP),
dimension(:) :: vm0x
548 real(DP),
dimension(:) :: vm0y
549 real(DP),
dimension(:) :: vm1x
550 real(DP),
dimension(:) :: vm1y
552 real(DP),
allocatable,
dimension(:) :: vm0i
553 real(DP),
allocatable,
dimension(:) :: vm0e
554 real(DP),
allocatable,
dimension(:) :: vm1i
555 real(DP),
allocatable,
dimension(:) :: vm1e
556 real(DP),
allocatable,
dimension(:) :: uprod
557 real(DP),
allocatable,
dimension(:) :: det
558 real(DP),
allocatable,
dimension(:) :: wt
559 real(DP),
allocatable,
dimension(:) :: bi0x
560 real(DP),
allocatable,
dimension(:) :: be0x
561 real(DP),
allocatable,
dimension(:) :: bi0y
562 real(DP),
allocatable,
dimension(:) :: be0y
563 real(DP),
allocatable,
dimension(:) :: bi1x
564 real(DP),
allocatable,
dimension(:) :: be1x
565 real(DP),
allocatable,
dimension(:) :: bi1y
566 real(DP),
allocatable,
dimension(:) :: be1y
567 real(DP),
allocatable,
dimension(:) :: be01x
568 real(DP),
allocatable,
dimension(:) :: be01y
580 allocate (vm0i(this%nverts))
581 allocate (vm0e(this%nverts))
582 allocate (vm1i(this%nverts))
583 allocate (vm1e(this%nverts))
584 allocate (uprod(this%nverts))
585 allocate (det(this%nverts))
586 allocate (wt(this%nverts))
587 allocate (bi0x(this%nverts))
588 allocate (be0x(this%nverts))
589 allocate (bi0y(this%nverts))
590 allocate (be0y(this%nverts))
591 allocate (bi1x(this%nverts))
592 allocate (be1x(this%nverts))
593 allocate (bi1y(this%nverts))
594 allocate (be1y(this%nverts))
595 allocate (be01x(this%nverts))
596 allocate (be01y(this%nverts))
602 do i = 2, this%nverts
604 vm0i(i) = (li(ip) * vm0i(ip) - le(ip) * this%vne(ip) &
605 + areasub(ip) * divcell) / li(i)
609 vm1i = cshift(vm0i, 1)
612 uprod = unintx * unextx + uninty * unexty
613 det =
done - uprod * uprod
614 bi0x = (unintx - unextx * uprod) / det
615 be0x = (unextx - unintx * uprod) / det
616 bi0y = (uninty - unexty * uprod) / det
617 be0y = (unexty - uninty * uprod) / det
618 uprod = unintxnext * unextx + unintynext * unexty
619 det =
done - uprod * uprod
620 bi1x = (unintxnext - unextx * uprod) / det
621 be1x = (unextx - unintxnext * uprod) / det
622 bi1y = (unintynext - unexty * uprod) / det
623 be1y = (unexty - unintynext * uprod) / det
624 be01x = 5.d-1 * (be0x + be1x)
625 be01y = 5.d-1 * (be0y + be1y)
626 wt = areasub / areacell
627 emxx =
dtwo - sum(wt * be01x * unextx)
628 emxy = -sum(wt * be01x * unexty)
629 emyx = -sum(wt * be01y * unextx)
630 emyy =
dtwo - sum(wt * be01y * unexty)
631 rx = sum(wt * (bi0x * vm0i + bi1x * vm1i + be01x * this%vne))
632 ry = sum(wt * (bi0y * vm0i + bi1y * vm1i + be01y * this%vne))
633 emdet = emxx * emyy - emxy * emyx
634 this%vctrx = (emyy * rx - emxy * ry) / emdet
635 this%vctry = (emxx * ry - emyx * rx) / emdet
638 vm0e = 5.d-1 * (this%vne + unextx * this%vctrx + unexty * this%vctry)
644 vm0x = bi0x * vm0i + be0x * vm0e
645 vm0y = bi0y * vm0i + be0y * vm0e
646 vm1x = bi1x * vm1i + be1x * vm0e
647 vm1y = bi1y * vm1i + be1y * vm0e
651 hcsum = sum(lm * (kappax * (vm0x + vm1x) + kappay * (vm0y + vm1y)))
subroutine, public create_cell_poly(cell)
Create a new polygonal cell.
This module contains simulation constants.
real(dp), parameter dhalf
real constant 1/2
real(dp), parameter dzero
real constant zero
real(dp), parameter dtwo
real constant 2
real(dp), parameter done
real constant 1
subroutine pstop(status, message)
Stop the program, optionally specifying an error status code.
real(dp) function, public area(xv, yv, cw)
Calculate polygon area, with vertices given in CW or CCW order.
This module defines variable data types.
subroutine apply_mct(this, particle, tmax)
Apply the ternary method to a polygonal cell.
subroutine load_mct(this, particle, next_level, submethod)
Load subcell into tracking method.
subroutine destroy_mct(this)
Destroy the tracking method.
subroutine, public create_method_cell_ternary(method)
Create a tracking method.
subroutine load_subcell(this, particle, subcell)
Loads a triangular subcell from the polygonal cell.
subroutine calc_thru_hcsum(this, vm0ival, divcell, le, li, lm, areasub, areacell, unintx, uninty, unextx, unexty, unintxnext, unintynext, kappax, kappay, vm0x, vm0y, vm1x, vm1y, hcsum)
subroutine vertvelo(this)
Calculate vertex velocities.
subroutine pass_mct(this, particle)
Pass particle to next subcell if there is one, or to the cell face.
Particle tracking strategies.
subroutine load(this, particle, next_level, submethod)
Load subdomain tracking method (submethod)
subroutine pass(this, particle)
Pass a particle to the next subdomain, internal use only.
Subcell-level tracking methods.
type(methodsubcellternarytype), pointer, public method_subcell_tern
subroutine, public create_subcell_tri(subcell)
Create a new triangular subcell.
Base type for particle tracking methods.
Particle tracked by the PRT model.
Manages particle track (i.e. pathline) files.