21 integer(I4B) :: nverts
22 real(dp),
allocatable,
dimension(:) :: xvert
23 real(dp),
allocatable,
dimension(:) :: yvert
24 real(dp),
allocatable,
dimension(:) :: vne
25 real(dp),
allocatable,
dimension(:) :: vv0x
26 real(dp),
allocatable,
dimension(:) :: vv0y
27 real(dp),
allocatable,
dimension(:) :: vv1x
28 real(dp),
allocatable,
dimension(:) :: vv1y
38 integer(I4B),
allocatable,
dimension(:) :: iprev
39 real(dp),
allocatable,
dimension(:) :: xvertnext
40 real(dp),
allocatable,
dimension(:) :: yvertnext
41 integer(I4B),
public,
pointer :: zeromethod
65 method%name => method%cell%type
66 method%delegates = .true.
68 method%subcell => subcell
74 deallocate (this%name)
78 subroutine load_mct(this, particle, next_level, submethod)
82 integer(I4B),
intent(in) :: next_level
83 class(
methodtype),
pointer,
intent(inout) :: submethod
85 select type (subcell => this%subcell)
87 call this%load_subcell(particle, subcell)
92 subcell=this%subcell, &
93 trackctl=this%trackctl, &
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
160 select type (cell => this%cell)
163 call this%check(particle, this%cell%defn)
164 if (.not. particle%advancing)
return
167 this%nverts = cell%defn%npolyverts
170 if (
allocated(this%xvert))
then
171 deallocate (this%xvert)
172 deallocate (this%yvert)
173 deallocate (this%vne)
174 deallocate (this%vv0x)
175 deallocate (this%vv0y)
176 deallocate (this%vv1x)
177 deallocate (this%vv1y)
178 deallocate (this%iprev)
179 deallocate (this%xvertnext)
180 deallocate (this%yvertnext)
183 allocate (this%xvert(this%nverts))
184 allocate (this%yvert(this%nverts))
185 allocate (this%vne(this%nverts))
186 allocate (this%vv0x(this%nverts))
187 allocate (this%vv0y(this%nverts))
188 allocate (this%vv1x(this%nverts))
189 allocate (this%vv1y(this%nverts))
190 allocate (this%iprev(this%nverts))
191 allocate (this%xvertnext(this%nverts))
192 allocate (this%yvertnext(this%nverts))
195 do i = 1, this%nverts
196 this%xvert(i) = cell%defn%polyvert(1, i)
197 this%yvert(i) = cell%defn%polyvert(2, i)
201 this%ztop = cell%defn%top
202 this%zbot = cell%defn%bot
203 this%dz = this%ztop - this%zbot
206 do i = 1, this%nverts
209 this%iprev = cshift(this%iprev, -1)
210 this%xvertnext = cshift(this%xvert, 1)
211 this%yvertnext = cshift(this%yvert, 1)
218 call this%track(particle, 2, tmax)
252 select type (cell => this%cell)
256 isc = particle%idomain(3)
260 do iv0 = 1, this%nverts
263 x1 = this%xvertnext(iv0)
264 y1 = this%yvertnext(iv0)
271 di2 = xi * y2rel - yi * x2rel
272 d02 = x0 * y2rel - y0 * x2rel
273 d12 = x1rel * y2rel - y1rel * x2rel
274 di1 = xi * y1rel - yi * x1rel
275 d01 = x0 * y1rel - y0 * x1rel
276 alphai = (di2 - d02) / d12
277 betai = -(di1 - d01) / d12
279 if ((alphai .ge.
dzero) .and. &
280 (alphai + betai .le.
done))
then
286 print *,
"error -- initial triangle not found in cell ", ic, &
287 " for particle at ", particle%x, particle%y, particle%z
291 particle%idomain(3) = isc
294 subcell%isubcell = isc
298 subcell%x0 = this%xvert(iv0)
299 subcell%y0 = this%yvert(iv0)
300 subcell%x1 = this%xvertnext(iv0)
301 subcell%y1 = this%yvertnext(iv0)
302 subcell%x2 = this%xctr
303 subcell%y2 = this%yctr
304 subcell%v0x = this%vv0x(iv0)
305 subcell%v0y = this%vv0y(iv0)
306 subcell%v1x = this%vv1x(iv0)
307 subcell%v1y = this%vv1y(iv0)
308 subcell%v2x = this%vctrx
309 subcell%v2y = this%vctry
310 subcell%ztop = this%ztop
311 subcell%zbot = this%zbot
313 subcell%vzbot = this%vzbot
314 subcell%vztop = this%vztop
327 real(DP),
allocatable,
dimension(:) :: xvals
328 real(DP),
allocatable,
dimension(:) :: yvals
335 real(DP),
allocatable,
dimension(:) :: wk1
336 real(DP),
allocatable,
dimension(:) :: wk2
337 real(DP),
allocatable,
dimension(:) :: unextxnext
338 real(DP),
allocatable,
dimension(:) :: unextynext
339 real(DP),
allocatable,
dimension(:) :: le
340 real(DP),
allocatable,
dimension(:) :: unextx
341 real(DP),
allocatable,
dimension(:) :: unexty
343 real(DP),
allocatable,
dimension(:) :: areasub
345 real(DP),
allocatable,
dimension(:) :: li
346 real(DP),
allocatable,
dimension(:) :: unintx
347 real(DP),
allocatable,
dimension(:) :: uninty
348 real(DP),
allocatable,
dimension(:) :: xmid
349 real(DP),
allocatable,
dimension(:) :: ymid
350 real(DP),
allocatable,
dimension(:) :: lm
351 real(DP),
allocatable,
dimension(:) :: umx
352 real(DP),
allocatable,
dimension(:) :: umy
353 real(DP),
allocatable,
dimension(:) :: kappax
354 real(DP),
allocatable,
dimension(:) :: kappay
355 real(DP),
allocatable,
dimension(:) :: vm0x
356 real(DP),
allocatable,
dimension(:) :: vm0y
357 real(DP),
allocatable,
dimension(:) :: vm1x
358 real(DP),
allocatable,
dimension(:) :: vm1y
360 select type (cell => this%cell)
364 allocate (le(this%nverts))
365 allocate (unextx(this%nverts))
366 allocate (unexty(this%nverts))
367 allocate (areasub(this%nverts))
368 allocate (li(this%nverts))
369 allocate (unintx(this%nverts))
370 allocate (uninty(this%nverts))
371 allocate (xmid(this%nverts))
372 allocate (ymid(this%nverts))
373 allocate (lm(this%nverts))
374 allocate (umx(this%nverts))
375 allocate (umy(this%nverts))
376 allocate (kappax(this%nverts))
377 allocate (kappay(this%nverts))
378 allocate (vm0x(this%nverts))
379 allocate (vm0y(this%nverts))
380 allocate (vm1x(this%nverts))
381 allocate (vm1y(this%nverts))
382 allocate (unextxnext(this%nverts))
383 allocate (unextynext(this%nverts))
384 allocate (wk1(this%nverts))
385 allocate (wk2(this%nverts))
390 wk1 = this%xvertnext - this%xvert
391 wk2 = this%yvertnext - this%yvert
392 le = dsqrt(wk1 * wk1 + wk2 * wk2)
397 areacell =
area(this%xvert, this%yvert)
400 sixa = areacell * 6.d0
401 wk1 = -(this%xvert * this%yvertnext - this%xvertnext * this%yvert)
402 this%xctr = sum((this%xvert + this%xvertnext) * wk1) / sixa
403 this%yctr = sum((this%yvert + this%yvertnext) * wk1) / sixa
406 do i = 1, this%nverts
407 xvals(1) = this%xvert(i)
408 xvals(2) = this%xvertnext(i)
410 yvals(1) = this%yvert(i)
411 yvals(2) = this%yvertnext(i)
413 areasub(i) =
area(xvals, yvals)
417 term =
done / (cell%defn%porosity * cell%defn%retfactor * this%dz)
418 do i = 1, this%nverts
419 this%vne(i) = -cell%defn%faceflow(i) * term / le(i)
423 divcell = sum(le * this%vne) / areacell
426 wk1 = this%xvert - this%xctr
427 wk2 = this%yvert - this%yctr
428 li = dsqrt(wk1 * wk1 + wk2 * wk2)
432 unextxnext = cshift(unintx, 1)
433 unextynext = cshift(uninty, 1)
436 xmid = 5.d-1 * (this%xvert + this%xctr)
437 ymid = 5.d-1 * (this%yvert + this%yctr)
440 wk1 = cshift(xmid, 1) - xmid
441 wk2 = cshift(ymid, 1) - ymid
442 lm = dsqrt(wk1 * wk1 + wk2 * wk2)
459 call this%calc_thru_hcsum(vm0i0, divcell, le, li, lm, areasub, areacell, &
460 unintx, uninty, unextx, unexty, &
461 unextxnext, unextynext, &
462 kappax, kappay, vm0x, vm0y, vm1x, vm1y, hcsum0)
464 vm0ival = vm0i0 + perturb
465 call this%calc_thru_hcsum(vm0ival, divcell, le, li, lm, areasub, areacell, &
466 unintx, uninty, unextx, unexty, &
467 unextxnext, unextynext, &
468 kappax, kappay, vm0x, vm0y, vm1x, vm1y, hcsum)
470 jac = (hcsum - hcsum0) / perturb
471 vm0ival = vm0i0 - hcsum0 / jac
472 call this%calc_thru_hcsum(vm0ival, divcell, le, li, lm, areasub, areacell, &
473 unintx, uninty, unextx, unexty, &
474 unextxnext, unextynext, &
475 kappax, kappay, vm0x, vm0y, vm1x, vm1y, hcsum)
480 this%vv0x = 2.d0 * vm0x - this%vctrx
481 this%vv0y = 2.d0 * vm0y - this%vctry
482 this%vv1x = 2.d0 * vm1x - this%vctrx
483 this%vv1y = 2.d0 * vm1y - this%vctry
486 term =
done / (cell%defn%retfactor * cell%defn%porosity * areacell)
487 this%vzbot = cell%defn%faceflow(this%nverts + 2) * term
488 this%vztop = -cell%defn%faceflow(this%nverts + 3) * term
509 deallocate (unextxnext)
510 deallocate (unextynext)
520 le, li, lm, areasub, areacell, &
521 unintx, uninty, unextx, unexty, &
522 unintxnext, unintynext, &
523 kappax, kappay, vm0x, vm0y, vm1x, vm1y, hcsum)
529 real(DP),
dimension(:) :: le
530 real(DP),
dimension(:) :: li
531 real(DP),
dimension(:) :: lm
532 real(DP),
dimension(:) :: areasub
534 real(DP),
dimension(:) :: unintx
535 real(DP),
dimension(:) :: uninty
536 real(DP),
dimension(:) :: unextx
537 real(DP),
dimension(:) :: unexty
538 real(DP),
dimension(:) :: unintxnext
539 real(DP),
dimension(:) :: unintynext
540 real(DP),
dimension(:) :: kappax
541 real(DP),
dimension(:) :: kappay
542 real(DP),
dimension(:) :: vm0x
543 real(DP),
dimension(:) :: vm0y
544 real(DP),
dimension(:) :: vm1x
545 real(DP),
dimension(:) :: vm1y
547 real(DP),
allocatable,
dimension(:) :: vm0i
548 real(DP),
allocatable,
dimension(:) :: vm0e
549 real(DP),
allocatable,
dimension(:) :: vm1i
550 real(DP),
allocatable,
dimension(:) :: vm1e
551 real(DP),
allocatable,
dimension(:) :: uprod
552 real(DP),
allocatable,
dimension(:) :: det
553 real(DP),
allocatable,
dimension(:) :: wt
554 real(DP),
allocatable,
dimension(:) :: bi0x
555 real(DP),
allocatable,
dimension(:) :: be0x
556 real(DP),
allocatable,
dimension(:) :: bi0y
557 real(DP),
allocatable,
dimension(:) :: be0y
558 real(DP),
allocatable,
dimension(:) :: bi1x
559 real(DP),
allocatable,
dimension(:) :: be1x
560 real(DP),
allocatable,
dimension(:) :: bi1y
561 real(DP),
allocatable,
dimension(:) :: be1y
562 real(DP),
allocatable,
dimension(:) :: be01x
563 real(DP),
allocatable,
dimension(:) :: be01y
575 allocate (vm0i(this%nverts))
576 allocate (vm0e(this%nverts))
577 allocate (vm1i(this%nverts))
578 allocate (vm1e(this%nverts))
579 allocate (uprod(this%nverts))
580 allocate (det(this%nverts))
581 allocate (wt(this%nverts))
582 allocate (bi0x(this%nverts))
583 allocate (be0x(this%nverts))
584 allocate (bi0y(this%nverts))
585 allocate (be0y(this%nverts))
586 allocate (bi1x(this%nverts))
587 allocate (be1x(this%nverts))
588 allocate (bi1y(this%nverts))
589 allocate (be1y(this%nverts))
590 allocate (be01x(this%nverts))
591 allocate (be01y(this%nverts))
597 do i = 2, this%nverts
599 vm0i(i) = (li(ip) * vm0i(ip) - le(ip) * this%vne(ip) &
600 + areasub(ip) * divcell) / li(i)
604 vm1i = cshift(vm0i, 1)
607 uprod = unintx * unextx + uninty * unexty
608 det =
done - uprod * uprod
609 bi0x = (unintx - unextx * uprod) / det
610 be0x = (unextx - unintx * uprod) / det
611 bi0y = (uninty - unexty * uprod) / det
612 be0y = (unexty - uninty * uprod) / det
613 uprod = unintxnext * unextx + unintynext * unexty
614 det =
done - uprod * uprod
615 bi1x = (unintxnext - unextx * uprod) / det
616 be1x = (unextx - unintxnext * uprod) / det
617 bi1y = (unintynext - unexty * uprod) / det
618 be1y = (unexty - unintynext * uprod) / det
619 be01x = 5.d-1 * (be0x + be1x)
620 be01y = 5.d-1 * (be0y + be1y)
621 wt = areasub / areacell
622 emxx =
dtwo - sum(wt * be01x * unextx)
623 emxy = -sum(wt * be01x * unexty)
624 emyx = -sum(wt * be01y * unextx)
625 emyy =
dtwo - sum(wt * be01y * unexty)
626 rx = sum(wt * (bi0x * vm0i + bi1x * vm1i + be01x * this%vne))
627 ry = sum(wt * (bi0y * vm0i + bi1y * vm1i + be01y * this%vne))
628 emdet = emxx * emyy - emxy * emyx
629 this%vctrx = (emyy * rx - emxy * ry) / emdet
630 this%vctry = (emxx * ry - emyx * rx) / emdet
633 vm0e = 5.d-1 * (this%vne + unextx * this%vctrx + unexty * this%vctry)
639 vm0x = bi0x * vm0i + be0x * vm0e
640 vm0y = bi0y * vm0i + be0y * vm0e
641 vm1x = bi1x * vm1i + be1x * vm0e
642 vm1y = bi1y * vm1i + be1y * vm0e
646 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 the subdomain tracking method (submethod).
subroutine pass(this, particle)
Pass the particle to the next subdomain.
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.