28 real(dp),
allocatable,
public :: qextl1(:), qextl2(:), qintl(:)
49 method%subcell => subcell
50 method%name => method%subcell%type
51 method%delegates = .false.
57 deallocate (this%name)
65 real(DP),
intent(in) :: tmax
73 select type (subcell => this%subcell)
79 x_origin = subcell%xOrigin
80 y_origin = subcell%yOrigin
81 z_origin = subcell%zOrigin
82 sinrot = subcell%sinrot
83 cosrot = subcell%cosrot
84 call particle%transform(x_origin, y_origin)
85 call this%track_subcell(subcell, particle, tmax)
86 call particle%transform(x_origin, y_origin, invert=.true.)
104 real(DP),
intent(in) :: tmax
106 real(DP) :: dt, dtexit, texit
107 real(DP) :: t, x, y, z
108 real(DP) :: t0, x0, y0, z0
109 integer(I4B) :: i, exit_face, exit_soln
113 x0 = particle%x / subcell%dx
114 y0 = particle%y / subcell%dy
115 z0 = particle%z / subcell%dz
118 call this%find_exits(particle, subcell)
119 exit_x = this%exit_solutions(1)
120 exit_y = this%exit_solutions(2)
121 exit_z = this%exit_solutions(3)
124 exit_soln = this%pick_exit(particle)
125 if (exit_soln == 0)
then
129 exit_face = this%exit_solutions(exit_soln)%iboundary
130 dtexit = this%exit_solutions(exit_soln)%dt
132 texit = particle%ttrack + dtexit
154 call this%tracktimes%advance()
155 if (this%tracktimes%any())
then
156 do i = this%tracktimes%selection(1), this%tracktimes%selection(2)
157 t = this%tracktimes%times(i)
158 if (t < particle%ttrack) cycle
159 if (t > texit .or. t > tmax)
exit
161 x =
new_x(exit_x%v, exit_x%dvdx, subcell%vx1, subcell%vx2, &
162 dt, x0, subcell%dx, exit_x%status == 1)
163 y =
new_x(exit_y%v, exit_y%dvdx, subcell%vy1, subcell%vy2, &
164 dt, y0, subcell%dy, exit_y%status == 1)
165 z =
new_x(exit_z%v, exit_z%dvdx, subcell%vz1, subcell%vz2, &
166 dt, z0, subcell%dz, exit_z%status == 1)
167 particle%x = x * subcell%dx
168 particle%y = y * subcell%dy
169 particle%z = z * subcell%dz
172 call this%usertime(particle)
178 if (texit .gt. tmax)
then
181 x =
new_x(exit_x%v, exit_x%dvdx, subcell%vx1, subcell%vx2, &
182 dt, x0, subcell%dx, exit_x%status == 1)
183 y =
new_x(exit_y%v, exit_y%dvdx, subcell%vy1, subcell%vy2, &
184 dt, y0, subcell%dy, exit_y%status == 1)
185 z =
new_x(exit_z%v, exit_z%dvdx, subcell%vz1, subcell%vz2, &
186 dt, z0, subcell%dz, exit_z%status == 1)
189 particle%advancing = .false.
190 particle%x = x * subcell%dx
191 particle%y = y * subcell%dy
192 particle%z = z * subcell%dz
195 call this%timestep(particle)
204 if ((exit_face .eq. 1) .or. (exit_face .eq. 2))
then
206 y =
new_x(exit_y%v, exit_y%dvdx, subcell%vy1, subcell%vy2, &
207 dt, y0, subcell%dy, exit_y%status == 1)
208 z =
new_x(exit_z%v, exit_z%dvdx, subcell%vz1, subcell%vz2, &
209 dt, z0, subcell%dz, exit_z%status == 1)
210 if (exit_face .eq. 2) x =
done
211 else if ((exit_face .eq. 3) .or. (exit_face .eq. 4))
then
212 x =
new_x(exit_x%v, exit_x%dvdx, subcell%vx1, subcell%vx2, dt, &
213 x0, subcell%dx, exit_x%status == 1)
215 z =
new_x(exit_z%v, exit_z%dvdx, subcell%vz1, subcell%vz2, dt, &
216 z0, subcell%dz, exit_z%status == 1)
217 if (exit_face .eq. 4) y =
done
218 else if ((exit_face .eq. 5) .or. (exit_face .eq. 6))
then
219 x =
new_x(exit_x%v, exit_x%dvdx, subcell%vx1, subcell%vx2, &
220 dt, x0, subcell%dx, exit_x%status == 1)
221 y =
new_x(exit_y%v, exit_y%dvdx, subcell%vy1, subcell%vy2, &
222 dt, y0, subcell%dy, exit_y%status == 1)
224 if (exit_face .eq. 6) z =
done
226 print *,
"programmer error, invalid exit face", exit_face
229 particle%x = x * subcell%dx
230 particle%y = y * subcell%dy
231 particle%z = z * subcell%dz
234 call this%subcellexit(particle)
242 integer(I4B) :: exit_soln
249 if (this%exit_solutions(1)%status < 2)
then
251 dtmin = this%exit_solutions(1)%dt
253 if (this%exit_solutions(2)%status < 2 .and. &
254 this%exit_solutions(2)%dt < dtmin)
then
256 dtmin = this%exit_solutions(2)%dt
258 if (this%exit_solutions(3)%status < 2 .and. &
259 this%exit_solutions(3)%dt < dtmin)
then
271 real(DP) :: x0, y0, z0
276 x0 = particle%x / domain%dx
277 y0 = particle%y / domain%dy
278 z0 = particle%z / domain%dz
281 this%exit_solutions = [ &
282 find_exit(domain%vx1, domain%vx2, domain%dx, x0), &
283 find_exit(domain%vy1, domain%vy2, domain%dy, y0), &
284 find_exit(domain%vz1, domain%vz2, domain%dz, z0) &
288 if (this%exit_solutions(1)%v <
dzero)
then
289 this%exit_solutions(1)%iboundary = 1
290 else if (this%exit_solutions(1)%v >
dzero)
then
291 this%exit_solutions(1)%iboundary = 2
293 if (this%exit_solutions(2)%v <
dzero)
then
294 this%exit_solutions(2)%iboundary = 3
295 else if (this%exit_solutions(2)%v >
dzero)
then
296 this%exit_solutions(2)%iboundary = 4
298 if (this%exit_solutions(3)%v <
dzero)
then
299 this%exit_solutions(3)%iboundary = 5
300 else if (this%exit_solutions(3)%v >
dzero)
then
301 this%exit_solutions(3)%iboundary = 6
309 real(dp),
intent(in) :: v1
310 real(dp),
intent(in) :: v2
311 real(dp),
intent(in) :: dx
312 real(dp),
intent(in) :: xl
317 solution%v, solution%dvdx, solution%dt)
337 integer(I4B) :: status
353 logical(LGP) :: nooutflow
359 if (v2a .lt.
dzero) v2a = -v2a
361 if (v1a .lt.
dzero) v1a = -v1a
364 if (dva .lt.
dzero) dva = -dva
369 if ((v2a .lt. tol) .and. (v1a .lt. tol))
then
380 if (v2a .gt. vv) vv = v2a
382 if (vvv .lt. 1.0d-4)
then
387 if (v1 .gt. zro) dt = (dx - x) / v1
388 if (v1 .lt. zrom) dt = -x / v1
397 v = (
done - xl) * v1 + xl * v2
402 if (v1 .lt.
dzero) nooutflow = .false.
403 if (v2 .gt.
dzero) nooutflow = .false.
413 if ((v1 .le.
dzero) .and. (v2 .ge.
dzero))
then
414 if (abs(v) .le.
dzero)
then
416 if (v2 .le.
dzero) v = -v
426 if (vr .le.
dzero)
then
434 if (v1v2 .gt.
dzero)
then
435 if (v .gt.
dzero) vr = vr2
436 if (v .lt.
dzero) vr = vr1
441 if (dabs(vr) .lt. 1.0d-10)
then
461 pure function new_x(v, dvdx, v1, v2, dt, x, dx, velocity_profile)
result(newx)
463 real(dp),
intent(in) :: v
464 real(dp),
intent(in) :: dvdx
465 real(dp),
intent(in) :: v1
466 real(dp),
intent(in) :: v2
467 real(dp),
intent(in) :: dt
468 real(dp),
intent(in) :: x
469 real(dp),
intent(in) :: dx
470 logical(LGP),
intent(in),
optional :: velocity_profile
473 logical(LGP) :: lprofile
476 if (
present(velocity_profile))
then
477 lprofile = velocity_profile
485 newx = newx + (v1 * dt / dx)
486 else if (v .ne.
dzero)
then
487 newx = newx + (v * (exp(dvdx * dt) -
done) / dvdx / dx)
This module contains simulation constants.
real(dp), parameter dzero
real constant zero
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
This module defines variable data types.
Particle tracking strategies.
@, public level_subfeature
pure real(dp) function new_x(v, dvdx, v1, v2, dt, x, dx, velocity_profile)
Update a cell-local coordinate based on a time increment.
integer(i4b) function pick_exit(this, particle)
Pick the exit solution with the shortest travel time.
integer(i4b) function, public calculate_dt(v1, v2, dx, xL, v, dvdx, dt)
Calculate particle travel time to exit and exit status.
type(linearexitsolutiontype) function find_exit(v1, v2, dx, xL)
Find an exit solution for one dimension.
subroutine track_subcell(this, subcell, particle, tmax)
Track a particle across a rectangular subcell using Pollock's method.
subroutine, public create_method_subcell_pollock(method)
Create a new Pollock's subcell method.
subroutine find_exits(this, particle, domain)
Compute candidate exit solutions.
subroutine apply_msp(this, particle, tmax)
Apply Pollock's method to a rectangular subcell.
@, public featexit
particle exited a grid feature
@, public timestep
time step ended
@ term_timeout
terminated at stop time or end of simulation
@ term_no_exits_sub
terminated in a subcell with no exit face
subroutine, public create_subcell_rect(subcell)
Create a new rectangular subcell.
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.
Rectangular subcell tracking method.
Particle tracked by the PRT model.