25 integer(I4B) :: nverts
26 real(dp),
allocatable,
dimension(:) :: xvert
27 real(dp),
allocatable,
dimension(:) :: yvert
28 real(dp),
allocatable,
dimension(:) :: vne
29 real(dp),
allocatable,
dimension(:) :: vv0x
30 real(dp),
allocatable,
dimension(:) :: vv0y
31 real(dp),
allocatable,
dimension(:) :: vv1x
32 real(dp),
allocatable,
dimension(:) :: vv1y
42 integer(I4B),
allocatable,
dimension(:) :: iprev
43 real(dp),
allocatable,
dimension(:) :: xvertnext
44 real(dp),
allocatable,
dimension(:) :: yvertnext
45 integer(I4B),
public,
pointer :: zeromethod
51 procedure,
public :: pass =>
pass_mct
69 method%name => method%cell%type
70 method%delegates = .true.
72 method%subcell => subcell
81 deallocate (this%name)
84 call this%method_subcell_tern%deallocate()
85 deallocate (this%method_subcell_tern)
89 subroutine load_mct(this, particle, next_level, submethod)
93 integer(I4B),
intent(in) :: next_level
94 class(
methodtype),
pointer,
intent(inout) :: submethod
96 select type (subcell => this%subcell)
98 call this%load_subcell(particle, subcell)
101 call this%method_subcell_tern%init( &
104 subcell=this%subcell, &
105 events=this%events, &
106 tracktimes=this%tracktimes)
107 submethod => this%method_subcell_tern
117 integer(I4B) :: exitFace
118 integer(I4B) :: inface
123 select case (exitface)
130 if (inface .eq. 0) inface = this%nverts
134 if (isc .gt. this%nverts) isc = 1
141 if (isc .lt. 1) isc = this%nverts
147 inface = this%nverts + 2
150 inface = this%nverts + 3
153 if (inface .eq. -1)
then
155 else if (inface .eq. 0)
then
168 real(DP),
intent(in) :: tmax
171 real(DP) :: x, y, z, xO, yO
172 real(DP),
allocatable :: xs(:), ys(:)
175 select type (cell => this%cell)
177 call this%assess(particle, this%cell%defn, tmax)
178 if (.not. particle%advancing)
return
181 this%nverts = cell%defn%npolyverts
184 if (
allocated(this%xvert))
then
185 deallocate (this%xvert)
186 deallocate (this%yvert)
187 deallocate (this%vne)
188 deallocate (this%vv0x)
189 deallocate (this%vv0y)
190 deallocate (this%vv1x)
191 deallocate (this%vv1y)
192 deallocate (this%iprev)
193 deallocate (this%xvertnext)
194 deallocate (this%yvertnext)
197 allocate (this%xvert(this%nverts))
198 allocate (this%yvert(this%nverts))
199 allocate (this%vne(this%nverts))
200 allocate (this%vv0x(this%nverts))
201 allocate (this%vv0y(this%nverts))
202 allocate (this%vv1x(this%nverts))
203 allocate (this%vv1y(this%nverts))
204 allocate (this%iprev(this%nverts))
205 allocate (this%xvertnext(this%nverts))
206 allocate (this%yvertnext(this%nverts))
210 allocate (xs(this%nverts))
211 allocate (ys(this%nverts))
212 xs = cell%defn%polyvert(1, :)
213 ys = cell%defn%polyvert(2, :)
214 xo = xs(minloc(abs(xs), dim=1))
215 yo = ys(minloc(abs(ys), dim=1))
220 do i = 1, this%nverts
221 x = cell%defn%polyvert(1, i)
222 y = cell%defn%polyvert(2, i)
223 call transform(x, y,
dzero, x, y, z, xo, yo)
229 this%ztop = cell%defn%top
230 this%zbot = cell%defn%bot
231 this%dz = this%ztop - this%zbot
234 do i = 1, this%nverts
237 this%iprev = cshift(this%iprev, -1)
238 this%xvertnext = cshift(this%xvert, 1)
239 this%yvertnext = cshift(this%yvert, 1)
247 call particle%transform(xo, yo)
248 call this%track(particle, 2, tmax)
249 call particle%transform(xo, yo, invert=.true.)
250 call particle%reset_transform()
261 integer(I4B) :: ic, isc, iv0
262 real(DP) :: x0, y0, x1, y1, x2, y2, xi, yi
263 real(DP) :: x1rel, y1rel, x2rel, y2rel
264 real(DP) :: di2, d02, d12, di1, d01
265 real(DP) :: alphai, betai
267 select type (cell => this%cell)
275 do iv0 = 1, this%nverts
278 x1 = this%xvertnext(iv0)
279 y1 = this%yvertnext(iv0)
286 di2 = xi * y2rel - yi * x2rel
287 d02 = x0 * y2rel - y0 * x2rel
288 d12 = x1rel * y2rel - y1rel * x2rel
289 di1 = xi * y1rel - yi * x1rel
290 d01 = x0 * y1rel - y0 * x1rel
291 alphai = (di2 - d02) / d12
292 betai = -(di1 - d01) / d12
294 if ((alphai .ge.
dzero) .and. &
295 (alphai + betai .le.
done))
then
301 print *,
"error -- initial triangle not found in cell ", ic, &
302 " for particle at ", particle%x, particle%y, particle%z
309 subcell%isubcell = isc
313 subcell%x0 = this%xvert(iv0)
314 subcell%y0 = this%yvert(iv0)
315 subcell%x1 = this%xvertnext(iv0)
316 subcell%y1 = this%yvertnext(iv0)
317 subcell%x2 = this%xctr
318 subcell%y2 = this%yctr
319 subcell%v0x = this%vv0x(iv0)
320 subcell%v0y = this%vv0y(iv0)
321 subcell%v1x = this%vv1x(iv0)
322 subcell%v1y = this%vv1y(iv0)
323 subcell%v2x = this%vctrx
324 subcell%v2y = this%vctry
325 subcell%ztop = this%ztop
326 subcell%zbot = this%zbot
328 subcell%vzbot = this%vzbot
329 subcell%vztop = this%vztop
342 real(DP),
allocatable,
dimension(:) :: xvals
343 real(DP),
allocatable,
dimension(:) :: yvals
350 real(DP),
allocatable,
dimension(:) :: wk1
351 real(DP),
allocatable,
dimension(:) :: wk2
352 real(DP),
allocatable,
dimension(:) :: unextxnext
353 real(DP),
allocatable,
dimension(:) :: unextynext
354 real(DP),
allocatable,
dimension(:) :: le
355 real(DP),
allocatable,
dimension(:) :: unextx
356 real(DP),
allocatable,
dimension(:) :: unexty
358 real(DP),
allocatable,
dimension(:) :: areasub
360 real(DP),
allocatable,
dimension(:) :: li
361 real(DP),
allocatable,
dimension(:) :: unintx
362 real(DP),
allocatable,
dimension(:) :: uninty
363 real(DP),
allocatable,
dimension(:) :: xmid
364 real(DP),
allocatable,
dimension(:) :: ymid
365 real(DP),
allocatable,
dimension(:) :: lm
366 real(DP),
allocatable,
dimension(:) :: umx
367 real(DP),
allocatable,
dimension(:) :: umy
368 real(DP),
allocatable,
dimension(:) :: kappax
369 real(DP),
allocatable,
dimension(:) :: kappay
370 real(DP),
allocatable,
dimension(:) :: vm0x
371 real(DP),
allocatable,
dimension(:) :: vm0y
372 real(DP),
allocatable,
dimension(:) :: vm1x
373 real(DP),
allocatable,
dimension(:) :: vm1y
375 integer(I4B) :: nvert
377 select type (cell => this%cell)
381 allocate (le(this%nverts))
382 allocate (unextx(this%nverts))
383 allocate (unexty(this%nverts))
384 allocate (areasub(this%nverts))
385 allocate (li(this%nverts))
386 allocate (unintx(this%nverts))
387 allocate (uninty(this%nverts))
388 allocate (xmid(this%nverts))
389 allocate (ymid(this%nverts))
390 allocate (lm(this%nverts))
391 allocate (umx(this%nverts))
392 allocate (umy(this%nverts))
393 allocate (kappax(this%nverts))
394 allocate (kappay(this%nverts))
395 allocate (vm0x(this%nverts))
396 allocate (vm0y(this%nverts))
397 allocate (vm1x(this%nverts))
398 allocate (vm1y(this%nverts))
399 allocate (unextxnext(this%nverts))
400 allocate (unextynext(this%nverts))
401 allocate (wk1(this%nverts))
402 allocate (wk2(this%nverts))
407 wk1 = this%xvertnext - this%xvert
408 wk2 = this%yvertnext - this%yvert
409 le = dsqrt(wk1 * wk1 + wk2 * wk2)
414 areacell = area(this%xvert, this%yvert)
415 sixa = areacell * dsix
416 wk1 = -(this%xvert * this%yvertnext - this%xvertnext * this%yvert)
417 nvert =
size(this%xvert)
418 this%xctr = sum((this%xvert + this%xvertnext) * wk1) / sixa
419 this%yctr = sum((this%yvert + this%yvertnext) * wk1) / sixa
425 do i = 1, this%nverts
426 xvals(1) = this%xvert(i)
427 xvals(2) = this%xvertnext(i)
429 yvals(1) = this%yvert(i)
430 yvals(2) = this%yvertnext(i)
432 areasub(i) = area(xvals, yvals)
436 term =
done / (cell%defn%porosity * cell%defn%retfactor * this%dz)
437 do i = 1, this%nverts
438 this%vne(i) = -cell%defn%faceflow(i) * term / le(i)
442 divcell = sum(le * this%vne) / areacell
445 wk1 = this%xvert - this%xctr
446 wk2 = this%yvert - this%yctr
447 li = dsqrt(wk1 * wk1 + wk2 * wk2)
451 unextxnext = cshift(unintx, 1)
452 unextynext = cshift(uninty, 1)
455 xmid = 5.d-1 * (this%xvert + this%xctr)
456 ymid = 5.d-1 * (this%yvert + this%yctr)
459 wk1 = cshift(xmid, 1) - xmid
460 wk2 = cshift(ymid, 1) - ymid
461 lm = dsqrt(wk1 * wk1 + wk2 * wk2)
478 call this%calc_thru_hcsum(vm0i0, divcell, le, li, lm, areasub, areacell, &
479 unintx, uninty, unextx, unexty, &
480 unextxnext, unextynext, &
481 kappax, kappay, vm0x, vm0y, vm1x, vm1y, hcsum0)
483 vm0ival = vm0i0 + perturb
484 call this%calc_thru_hcsum(vm0ival, divcell, le, li, lm, areasub, areacell, &
485 unintx, uninty, unextx, unexty, &
486 unextxnext, unextynext, &
487 kappax, kappay, vm0x, vm0y, vm1x, vm1y, hcsum)
489 jac = (hcsum - hcsum0) / perturb
490 vm0ival = vm0i0 - hcsum0 / jac
491 call this%calc_thru_hcsum(vm0ival, divcell, le, li, lm, areasub, areacell, &
492 unintx, uninty, unextx, unexty, &
493 unextxnext, unextynext, &
494 kappax, kappay, vm0x, vm0y, vm1x, vm1y, hcsum)
499 this%vv0x = 2.d0 * vm0x - this%vctrx
500 this%vv0y = 2.d0 * vm0y - this%vctry
501 this%vv1x = 2.d0 * vm1x - this%vctrx
502 this%vv1y = 2.d0 * vm1y - this%vctry
505 term =
done / (cell%defn%retfactor * cell%defn%porosity * areacell)
506 this%vzbot = cell%defn%faceflow(this%nverts + 2) * term
507 this%vztop = -cell%defn%faceflow(this%nverts + 3) * term
528 deallocate (unextxnext)
529 deallocate (unextynext)
539 le, li, lm, areasub, areacell, &
540 unintx, uninty, unextx, unexty, &
541 unintxnext, unintynext, &
542 kappax, kappay, vm0x, vm0y, vm1x, vm1y, hcsum)
548 real(DP),
dimension(:) :: le
549 real(DP),
dimension(:) :: li
550 real(DP),
dimension(:) :: lm
551 real(DP),
dimension(:) :: areasub
553 real(DP),
dimension(:) :: unintx
554 real(DP),
dimension(:) :: uninty
555 real(DP),
dimension(:) :: unextx
556 real(DP),
dimension(:) :: unexty
557 real(DP),
dimension(:) :: unintxnext
558 real(DP),
dimension(:) :: unintynext
559 real(DP),
dimension(:) :: kappax
560 real(DP),
dimension(:) :: kappay
561 real(DP),
dimension(:) :: vm0x
562 real(DP),
dimension(:) :: vm0y
563 real(DP),
dimension(:) :: vm1x
564 real(DP),
dimension(:) :: vm1y
566 real(DP),
allocatable,
dimension(:) :: vm0i
567 real(DP),
allocatable,
dimension(:) :: vm0e
568 real(DP),
allocatable,
dimension(:) :: vm1i
569 real(DP),
allocatable,
dimension(:) :: vm1e
570 real(DP),
allocatable,
dimension(:) :: uprod
571 real(DP),
allocatable,
dimension(:) :: det
572 real(DP),
allocatable,
dimension(:) :: wt
573 real(DP),
allocatable,
dimension(:) :: bi0x
574 real(DP),
allocatable,
dimension(:) :: be0x
575 real(DP),
allocatable,
dimension(:) :: bi0y
576 real(DP),
allocatable,
dimension(:) :: be0y
577 real(DP),
allocatable,
dimension(:) :: bi1x
578 real(DP),
allocatable,
dimension(:) :: be1x
579 real(DP),
allocatable,
dimension(:) :: bi1y
580 real(DP),
allocatable,
dimension(:) :: be1y
581 real(DP),
allocatable,
dimension(:) :: be01x
582 real(DP),
allocatable,
dimension(:) :: be01y
594 allocate (vm0i(this%nverts))
595 allocate (vm0e(this%nverts))
596 allocate (vm1i(this%nverts))
597 allocate (vm1e(this%nverts))
598 allocate (uprod(this%nverts))
599 allocate (det(this%nverts))
600 allocate (wt(this%nverts))
601 allocate (bi0x(this%nverts))
602 allocate (be0x(this%nverts))
603 allocate (bi0y(this%nverts))
604 allocate (be0y(this%nverts))
605 allocate (bi1x(this%nverts))
606 allocate (be1x(this%nverts))
607 allocate (bi1y(this%nverts))
608 allocate (be1y(this%nverts))
609 allocate (be01x(this%nverts))
610 allocate (be01y(this%nverts))
616 do i = 2, this%nverts
618 vm0i(i) = (li(ip) * vm0i(ip) - le(ip) * this%vne(ip) &
619 + areasub(ip) * divcell) / li(i)
623 vm1i = cshift(vm0i, 1)
626 uprod = unintx * unextx + uninty * unexty
627 det =
done - uprod * uprod
628 bi0x = (unintx - unextx * uprod) / det
629 be0x = (unextx - unintx * uprod) / det
630 bi0y = (uninty - unexty * uprod) / det
631 be0y = (unexty - uninty * uprod) / det
632 uprod = unintxnext * unextx + unintynext * unexty
633 det =
done - uprod * uprod
634 bi1x = (unintxnext - unextx * uprod) / det
635 be1x = (unextx - unintxnext * uprod) / det
636 bi1y = (unintynext - unexty * uprod) / det
637 be1y = (unexty - unintynext * uprod) / det
638 be01x = 5.d-1 * (be0x + be1x)
639 be01y = 5.d-1 * (be0y + be1y)
640 wt = areasub / areacell
641 emxx =
dtwo - sum(wt * be01x * unextx)
642 emxy = -sum(wt * be01x * unexty)
643 emyx = -sum(wt * be01y * unextx)
644 emyy =
dtwo - sum(wt * be01y * unexty)
645 rx = sum(wt * (bi0x * vm0i + bi1x * vm1i + be01x * this%vne))
646 ry = sum(wt * (bi0y * vm0i + bi1y * vm1i + be01y * this%vne))
647 emdet = emxx * emyy - emxy * emyx
648 this%vctrx = (emyy * rx - emxy * ry) / emdet
649 this%vctry = (emxx * ry - emyx * rx) / emdet
652 vm0e = 5.d-1 * (this%vne + unextx * this%vctrx + unexty * this%vctry)
658 vm0x = bi0x * vm0i + be0x * vm0e
659 vm0y = bi0y * vm0i + be0y * vm0e
660 vm1x = bi1x * vm1i + be1x * vm0e
661 vm1y = bi1y * vm1i + be1y * vm0e
665 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 dsix
real constant 6
real(dp), parameter done
real constant 1
subroutine pstop(status, message)
Stop the program, optionally specifying an error status code.
subroutine, public transform(xin, yin, zin, xout, yout, zout, xorigin, yorigin, zorigin, sinrot, cosrot, invert)
Apply a 3D translation and optional 2D rotation to coordinates.
real(dp) function, public area(xv, yv, cw)
Calculate polygon area, with vertices given in CW or CCW order.
logical function, public point_in_polygon(x, y, poly)
Check if a point is within a polygon.
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.
@, public level_subfeature
subroutine, public create_method_subcell_ternary(method)
Create a new ternary subcell tracking method.
subroutine, public create_subcell_tri(subcell)
Create a new triangular subcell.
Base type for particle tracking methods.
Ternary triangular subcell tracking method.
Particle tracked by the PRT model.