34 integer(I4B) :: itopbotexit = -1, itrifaceexit = -1
47 integer(I4B),
public,
pointer :: zeromethod
65 method%subcell => subcell
66 method%name => method%subcell%type
67 method%delegates = .false.
73 deallocate (this%name)
80 real(DP),
intent(in) :: tmax
82 select type (subcell => this%subcell)
84 call this%track_subcell(subcell, particle, tmax)
96 real(DP),
intent(in) :: tmax
98 real(DP) :: dt, dtexit, texit
99 real(DP) :: t0, t, x, y, z0, z
100 integer(I4B) :: exit_face, exit_soln, event_code, i, isolv
105 if (particle%iexmeth == 0)
then
108 isolv = particle%iexmeth
116 call find_exits(particle, subcell, exit_solutions, z0)
118 exit_z = exit_solutions(1)
119 exit_lateral = exit_solutions(2)
123 if (exit_z%itopbotexit == 0 .and. &
124 exit_lateral%itrifaceexit == 0)
then
131 exit_face = exit_solutions(exit_soln)%iboundary
132 dtexit = exit_solutions(exit_soln)%dt
133 if (dtexit <
dzero)
then
143 call this%tracktimes%advance()
144 if (this%tracktimes%any())
then
145 do i = this%tracktimes%selection(1), this%tracktimes%selection(2)
146 t = this%tracktimes%times(i)
148 if (t > texit .or. t > tmax)
exit
151 exit_lateral%rxx, exit_lateral%rxy, &
152 exit_lateral%ryx, exit_lateral%ryy, &
153 exit_lateral%sxx, exit_lateral%sxy, &
154 exit_lateral%syy, exit_z%status, &
155 subcell%x0, subcell%y0, &
156 exit_z%dvdx, exit_z%v, &
157 subcell%vzbot, subcell%ztop, subcell%zbot, &
164 call this%usertime(particle)
171 if (texit .gt. tmax)
then
178 particle%advancing = .false.
188 exit_lateral%rxx, exit_lateral%rxy, &
189 exit_lateral%ryx, exit_lateral%ryy, &
190 exit_lateral%sxx, exit_lateral%sxy, &
191 exit_lateral%syy, exit_z%status, &
192 subcell%x0, subcell%y0, &
193 exit_z%dvdx, exit_z%v, &
194 subcell%vzbot, subcell%ztop, subcell%zbot, &
195 z0, x, y, z, exit_face)
203 call this%timestep(particle)
204 else if (event_code ==
featexit)
then
205 call this%subcellexit(particle)
213 integer(I4B) :: exit_soln
215 if (exit_solutions(1)%itopbotexit == 0)
then
217 else if (exit_solutions(2)%itrifaceexit == 0 .or. &
218 exit_solutions(1)%dt < exit_solutions(2)%dt)
then
231 real(DP),
intent(out) :: z0
233 integer(I4B) :: ntmax
252 integer(I4B) :: isolv
253 integer(I4B) :: itrifaceenter
259 if (particle%iexmeth == 0)
then
262 isolv = particle%iexmeth
265 select type (subcell => domain)
278 subcell%x1, subcell%y1, &
279 subcell%x2, subcell%y2, &
280 subcell%v0x, subcell%v0y, &
281 subcell%v1x, subcell%v1y, &
282 subcell%v2x, subcell%v2y, &
283 particle%x, particle%y, &
284 rxx, rxy, ryx, ryy, &
286 alp0, bet0, alp1, bet1, alp2, bet2, alpi, beti)
297 zirel = (particle%z - subcell%zbot) / subcell%dz
298 if (zirel >
done)
then
300 else if (zirel <
dzero)
then
303 z0 = subcell%zbot + zirel * subcell%dz
309 if (itrifaceenter == -1) itrifaceenter = 999
314 exit_solutions(2)%rxx = rxx
315 exit_solutions(2)%rxy = rxy
316 exit_solutions(2)%ryx = ryx
317 exit_solutions(2)%ryy = ryy
318 exit_solutions(2)%sxx = sxx
319 exit_solutions(2)%sxy = sxy
320 exit_solutions(2)%syy = syy
323 if (exit_solutions(1)%itopbotexit /= 0)
then
324 if (exit_solutions(1)%itopbotexit == -1)
then
325 exit_solutions(1)%iboundary = 4
327 exit_solutions(1)%iboundary = 5
332 if (exit_solutions(2)%itrifaceexit /= 0) &
333 exit_solutions(2)%iboundary = exit_solutions(2)%itrifaceexit
339 alp1, bet1, alp2, bet2, alpi, beti) &
341 integer(I4B) :: isolv
343 integer(I4B) :: itrifaceenter
354 solution%dt, solution%alpexit, solution%betexit, &
355 itrifaceenter, solution%itrifaceexit, &
356 alp1, bet1, alp2, bet2, alpi, beti)
357 if (solution%itrifaceexit > 0) solution%status =
ok_exit
361 real(dp),
intent(in) :: v1
362 real(dp),
intent(in) :: v2
363 real(dp),
intent(in) :: dx
364 real(dp),
intent(in) :: xl
368 call calculate_dt(v1, v2, dx, xl, solution%v, solution%dvdx, &
369 solution%dt, solution%status, solution%itopbotexit)
380 dt, status, itopbotexit)
402 integer(I4B) :: status
403 integer(I4B) :: itopbotexit
404 logical(LGP) :: noOutflow
410 if (v2a .lt.
dzero) v2a = -v2a
412 if (v1a .lt.
dzero) v1a = -v1a
415 if (dva .lt.
dzero) dva = -dva
420 if ((v2a .lt. tol) .and. (v1a .lt. tol))
then
432 if (v2a .gt. vv) vv = v2a
434 if (vvv .lt. 1.0d-4)
then
439 if (v1 .gt. zro)
then
443 if (v1 .lt. zrom)
then
455 v = (
done - xl) * v1 + xl * v2
460 if (v1 .lt.
dzero) nooutflow = .false.
461 if (v2 .gt.
dzero) nooutflow = .false.
472 if ((v1 .le.
dzero) .and. (v2 .ge.
dzero))
then
473 if (abs(v) .le.
dzero)
then
475 if (v2 .le.
dzero) v = -v
485 if (vr .le.
dzero)
then
494 if (v1v2 .gt.
dzero)
then
495 if (v .gt.
dzero)
then
499 if (v .lt.
dzero)
then
506 dt = log(abs(vr)) / dvdx
512 izstatus, x0, y0, az, vzi, vzbot, &
513 ztop, zbot, zi, x, y, z, exitface)
523 integer(I4B) :: izstatus
535 integer(I4B),
optional :: exitface
537 integer(I4B) :: lexitface
538 real(DP) :: rot(2, 2), res(2), loc(2)
543 if (
present(exitface))
then
554 if (lexitface .eq. 1)
then
556 else if (lexitface .eq. 2)
then
558 else if (lexitface .eq. 3)
then
563 if (lexitface .eq. 4)
then
565 else if (lexitface .eq. 5)
then
569 if (izstatus .eq. 2)
then
572 else if (izstatus .eq. 1)
then
577 z = zbot + (vzi * dexp(az * dt) - vzbot) / az
583 loc =
skew(loc, (/sxx, sxy, syy/), invert=.true.)
584 rot = reshape((/rxx, rxy, ryx, ryy/), shape(rot))
585 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.
@ ok_exit_constant
exit found, constant velocity
@ ok_exit
exit found using velocity interpolation
@ no_exit_stationary
no exit, zero velocity
@ no_exit_no_outflow
no exit, no outflow
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
type(barycentricexitsolutiontype) function find_lateral_exit(isolv, tol, itrifaceenter, alp1, bet1, alp2, bet2, alpi, beti)
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 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.
type(barycentricexitsolutiontype) function find_vertical_exit(v1, v2, dx, xL)
integer(i4b) function pick_exit(exit_solutions)
Determine earliest exit face.
subroutine, public create_method_subcell_ternary(method)
Create a new ternary subcell tracking method.
subroutine calculate_dt(v1, v2, dx, xL, v, dvdx, dt, status, itopbotexit)
Do calculations related to analytical z solution.
subroutine find_exits(particle, domain, exit_solutions, z0)
Calculate exit solutions for each coordinate direction.
@, 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...
Base type for exit solutions.
Linear velocity interpolation exit solution.
A generic heterogeneous doubly-linked list.
Abstract base type for subcell tracking methods.
Barycentric velocity interpolation exit solution. Inherit from LinearExitSolutionType to get around a...
Ternary triangular subcell tracking method.
Particle tracked by the PRT model.