34 integer(I4B) :: itopbotexit = -1, itrifaceexit = -1
47 integer(I4B),
public,
pointer :: zeromethod
68 method%subcell => subcell
69 method%name => method%subcell%type
70 method%delegates = .false.
76 deallocate (this%name)
83 real(DP),
intent(in) :: tmax
85 select type (subcell => this%subcell)
87 call this%track_subcell(subcell, particle, tmax)
99 real(DP),
intent(in) :: tmax
101 real(DP) :: dt, dtexit, texit
102 real(DP) :: t0, t, x, y, z0, z
103 integer(I4B) :: exit_face, exit_soln, event_code, i, isolv
107 if (particle%iexmeth == 0)
then
110 isolv = particle%iexmeth
116 call this%find_exits(particle, subcell)
118 exit_z = this%exit_solutions(1)
119 exit_lateral = this%exit_solutions(2)
123 if (exit_z%itopbotexit == 0 .and. &
124 exit_lateral%itrifaceexit == 0)
then
130 exit_soln = this%pick_exit(particle)
131 exit_face = this%exit_solutions(exit_soln)%iboundary
132 dtexit = this%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)
214 integer(I4B) :: exit_soln
216 if (this%exit_solutions(1)%itopbotexit == 0)
then
218 else if (this%exit_solutions(2)%itrifaceexit == 0 .or. &
219 this%exit_solutions(1)%dt < this%exit_solutions(2)%dt)
then
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)
295 zirel = (particle%z - subcell%zbot) / subcell%dz
296 if (zirel >
done)
then
298 else if (zirel <
dzero)
then
306 if (itrifaceenter == -1) itrifaceenter = 999
311 this%exit_solutions(2)%rxx = rxx
312 this%exit_solutions(2)%rxy = rxy
313 this%exit_solutions(2)%ryx = ryx
314 this%exit_solutions(2)%ryy = ryy
315 this%exit_solutions(2)%sxx = sxx
316 this%exit_solutions(2)%sxy = sxy
317 this%exit_solutions(2)%syy = syy
320 if (this%exit_solutions(1)%itopbotexit /= 0)
then
321 if (this%exit_solutions(1)%itopbotexit == -1)
then
322 this%exit_solutions(1)%iboundary = 4
324 this%exit_solutions(1)%iboundary = 5
329 if (this%exit_solutions(2)%itrifaceexit /= 0) &
330 this%exit_solutions(2)%iboundary = this%exit_solutions(2)%itrifaceexit
336 alp1, bet1, alp2, bet2, alpi, beti) &
338 integer(I4B) :: isolv
340 integer(I4B) :: itrifaceenter
351 solution%dt, solution%alpexit, solution%betexit, &
352 itrifaceenter, solution%itrifaceexit, &
353 alp1, bet1, alp2, bet2, alpi, beti)
354 if (solution%itrifaceexit > 0) solution%status =
ok_exit
358 real(dp),
intent(in) :: v1
359 real(dp),
intent(in) :: v2
360 real(dp),
intent(in) :: dx
361 real(dp),
intent(in) :: xl
365 call calculate_dt(v1, v2, dx, xl, solution%v, solution%dvdx, &
366 solution%dt, solution%status, solution%itopbotexit)
377 dt, status, itopbotexit)
399 integer(I4B) :: status
400 integer(I4B) :: itopbotexit
401 logical(LGP) :: noOutflow
407 if (v2a .lt.
dzero) v2a = -v2a
409 if (v1a .lt.
dzero) v1a = -v1a
412 if (dva .lt.
dzero) dva = -dva
417 if ((v2a .lt. tol) .and. (v1a .lt. tol))
then
429 if (v2a .gt. vv) vv = v2a
431 if (vvv .lt. 1.0d-4)
then
436 if (v1 .gt. zro)
then
440 if (v1 .lt. zrom)
then
452 v = (
done - xl) * v1 + xl * v2
457 if (v1 .lt.
dzero) nooutflow = .false.
458 if (v2 .gt.
dzero) nooutflow = .false.
469 if ((v1 .le.
dzero) .and. (v2 .ge.
dzero))
then
470 if (abs(v) .le.
dzero)
then
472 if (v2 .le.
dzero) v = -v
482 if (vr .le.
dzero)
then
491 if (v1v2 .gt.
dzero)
then
492 if (v .gt.
dzero)
then
496 if (v .lt.
dzero)
then
503 dt = log(abs(vr)) / dvdx
509 izstatus, x0, y0, az, vzi, vzbot, &
510 ztop, zbot, zi, x, y, z, exitface)
520 integer(I4B) :: izstatus
532 integer(I4B),
optional :: exitface
534 integer(I4B) :: lexitface
535 real(DP) :: rot(2, 2), res(2), loc(2)
540 if (
present(exitface))
then
551 if (lexitface .eq. 1)
then
553 else if (lexitface .eq. 2)
then
555 else if (lexitface .eq. 3)
then
560 if (lexitface .eq. 4)
then
562 else if (lexitface .eq. 5)
then
566 if (izstatus .eq. 2)
then
569 else if (izstatus .eq. 1)
then
574 z = zbot + (vzi * dexp(az * dt) - vzbot) / az
580 loc =
skew(loc, (/sxx, sxy, syy/), invert=.true.)
581 rot = reshape((/rxx, rxy, ryx, ryy/), shape(rot))
582 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)
subroutine find_exits(this, particle, domain)
Calculate exit solutions for each coordinate direction.
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.
integer(i4b) function pick_exit(this, particle)
Determine earliest exit face.
@, 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.