24 integer(I4B),
public,
pointer :: zeromethod
42 method%subcell => subcell
43 method%name => method%subcell%type
44 method%delegates = .false.
50 deallocate (this%name)
57 real(DP),
intent(in) :: tmax
59 select type (subcell => this%subcell)
61 call this%track_subcell(subcell, particle, tmax)
73 real(DP),
intent(in) :: tmax
75 integer(I4B) :: exitFace
125 integer(I4B) :: izstatus
126 integer(I4B) :: itopbotexit
127 integer(I4B) :: ntmax
128 integer(I4B) :: isolv
129 integer(I4B) :: itrifaceenter
130 integer(I4B) :: itrifaceexit
135 integer(I4B) :: event_code
139 if (particle%iexmeth == 0)
then
142 isolv = particle%iexmeth
168 vzbot = subcell%vzbot
169 vztop = subcell%vztop
182 v0x, v0y, v1x, v1y, v2x, v2y, &
184 rxx, rxy, ryx, ryy, &
186 alp0, bet0, alp1, bet1, alp2, bet2, alpi, beti)
195 zirel = (zi - zbot) / dz
196 if (zirel >
done)
then
198 else if (zirel <
dzero)
then
202 az, dtexitz, izstatus, &
208 if (itrifaceenter == -1) itrifaceenter = 999
210 dtexitxy, alpexit, betexit, &
211 itrifaceenter, itrifaceexit, &
212 alp1, bet1, alp2, bet2, alpi, beti)
216 if (itopbotexit == 0 .and. itrifaceexit == 0)
then
217 call this%terminate(particle, &
223 if (itopbotexit == 0)
then
225 exitface = itrifaceexit
227 else if (itrifaceexit == 0 .or. dtexitz < dtexitxy)
then
233 exitface = itrifaceexit
236 if (exitface == 45)
then
237 if (itopbotexit == -1)
then
245 if (dtexit <
dzero)
then
246 call this%terminate(particle, &
251 texit = particle%ttrack + dtexit
258 call this%tracktimes%advance()
259 if (this%tracktimes%any())
then
260 do i = this%tracktimes%selection(1), this%tracktimes%selection(2)
261 t = this%tracktimes%times(i)
262 if (t < particle%ttrack) cycle
263 if (t >= texit .or. t >= tmax)
exit
266 izstatus, x0, y0, az, vzi, vzbot, &
267 ztop, zbot, zi, x, y, z)
273 call this%usertime(particle)
280 if (texit .gt. tmax)
then
287 particle%advancing = .false.
297 izstatus, x0, y0, az, vzi, vzbot, &
298 ztop, zbot, zi, x, y, z, exitface)
306 call this%timestep(particle)
307 else if (event_code ==
featexit)
then
308 call this%subcellexit(particle)
320 dt, status, itopbotexit)
342 integer(I4B) :: status
343 integer(I4B) :: itopbotexit
344 logical(LGP) :: noOutflow
350 if (v2a .lt.
dzero) v2a = -v2a
352 if (v1a .lt.
dzero) v1a = -v1a
355 if (dva .lt.
dzero) dva = -dva
360 if ((v2a .lt. tol) .and. (v1a .lt. tol))
then
372 if (v2a .gt. vv) vv = v2a
374 if (vvv .lt. 1.0d-4)
then
379 if (v1 .gt. zro)
then
383 if (v1 .lt. zrom)
then
395 v = (
done - xl) * v1 + xl * v2
400 if (v1 .lt.
dzero) nooutflow = .false.
401 if (v2 .gt.
dzero) nooutflow = .false.
412 if ((v1 .le.
dzero) .and. (v2 .ge.
dzero))
then
413 if (abs(v) .le.
dzero)
then
415 if (v2 .le.
dzero) v = -v
425 if (vr .le.
dzero)
then
434 if (v1v2 .gt.
dzero)
then
435 if (v .gt.
dzero)
then
439 if (v .lt.
dzero)
then
446 dt = log(abs(vr)) / dvdx
452 izstatus, x0, y0, az, vzi, vzbot, &
453 ztop, zbot, zi, x, y, z, exitFace)
463 integer(I4B) :: izstatus
475 integer(I4B),
optional :: exitFace
477 integer(I4B) :: lexitface
478 real(DP) :: rot(2, 2), res(2), loc(2)
483 if (
present(exitface))
then
494 if (lexitface .eq. 1)
then
496 else if (lexitface .eq. 2)
then
498 else if (lexitface .eq. 3)
then
503 if (lexitface .eq. 4)
then
505 else if (lexitface .eq. 5)
then
509 if (izstatus .eq. 2)
then
512 else if (izstatus .eq. 1)
then
517 z = zbot + (vzi * dexp(az * dt) - vzbot) / az
523 loc =
skew(loc, (/sxx, sxy, syy/), invert=.true.)
524 rot = reshape((/rxx, rxy, ryx, ryy/), shape(rot))
525 res = matmul(rot, loc)
This module contains simulation constants.
real(dp), parameter dsame
real constant for values that are considered the same based on machine precision
real(dp), parameter dep3
real constant 1000
real(dp), parameter donethird
real constant 1/3
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.
subroutine, public clamp_bary(alpha, beta, gamma, pad)
Clamp barycentric coordinates to the interior of a triangle, with optional padding some minimum dista...
pure real(dp) function, dimension(2), public skew(v, s, invert)
Skew a 2D vector along the x-axis.
This module defines variable data types.
pure logical function, public is_close(a, b, rtol, atol, symmetric)
Check if a real value is approximately equal to another.
Particle tracking strategies.
@, public level_subfeature
subroutine track_subcell(this, subcell, particle, tmax)
Track a particle across a triangular subcell.
subroutine apply_mst(this, particle, tmax)
Apply the ternary subcell tracking method.
subroutine, public create_method_subcell_ternary(method)
Create a new ternary subcell tracking method.
subroutine calculate_xyz_position(dt, rxx, rxy, ryx, ryy, sxx, sxy, syy, izstatus, x0, y0, az, vzi, vzbot, ztop, zbot, zi, x, y, z, exitFace)
Calculate the particle's local unscaled xyz coordinates after dt.
subroutine calculate_dt(v1, v2, dx, xL, v, dvdx, dt, status, itopbotexit)
Do calculations related to analytical z solution.
@, public featexit
particle exited a grid feature
@, public usertime
user-specified tracking time
@, public terminate
particle terminated
@, public timestep
time step ended
@ term_no_exits_sub
terminated in a subcell with no exit face
subroutine, public create_subcell_tri(subcell)
Create a new triangular subcell.
subroutine, public traverse_triangle(isolv, tol, texit, alpexit, betexit, itrifaceenter, itrifaceexit, alp1, bet1, alp2, bet2, alpi, beti)
Traverse triangular cell.
subroutine, public step_analytical(t, alp, bet)
Step (evaluate) analytically depending on case.
subroutine, public canonical(x0, y0, x1, y1, x2, y2, v0x, v0y, v1x, v1y, v2x, v2y, xi, yi, rxx, rxy, ryx, ryy, sxx, sxy, syy, alp0, bet0, alp1, bet1, alp2, bet2, alpi, beti)
Set coordinates to "canonical" configuration.
Base type for grid cells of a concrete type. Contains a cell-definition which is information shared b...
Ternary triangular subcell tracking method.
Particle tracked by the PRT model.