28 real(dp),
allocatable,
public :: qextl1(:), qextl2(:), qintl(:)
46 method%subcell => subcell
47 method%name => method%subcell%type
48 method%delegates = .false.
54 deallocate (this%name)
62 real(DP),
intent(in) :: tmax
69 select type (subcell => this%subcell)
77 x_origin = subcell%xOrigin
78 y_origin = subcell%yOrigin
79 sinrot = subcell%sinrot
80 cosrot = subcell%cosrot
81 call particle%transform(x_origin, y_origin)
87 particle%x = min(max(particle%x,
dzero), subcell%dx)
88 particle%y = min(max(particle%y,
dzero), subcell%dy)
89 particle%z = min(max(particle%z,
dzero), subcell%dz)
91 call this%track_subcell(subcell, particle, tmax)
92 call particle%transform(x_origin, y_origin, invert=.true.)
110 real(DP),
intent(in) :: tmax
112 real(DP) :: dt, dtexit, texit
113 real(DP) :: t, x, y, z
114 real(DP) :: t0, x0, y0, z0
115 integer(I4B) :: i, exit_face, exit_soln
123 call find_exits(particle, subcell, exit_solutions, x0, y0, z0)
124 exit_x = exit_solutions(1)
125 exit_y = exit_solutions(2)
126 exit_z = exit_solutions(3)
130 if (exit_soln == 0)
then
134 exit_face = exit_solutions(exit_soln)%iboundary
135 dtexit = exit_solutions(exit_soln)%dt
137 texit = particle%ttrack + dtexit
159 call this%tracktimes%advance()
160 if (this%tracktimes%any())
then
161 do i = this%tracktimes%selection(1), this%tracktimes%selection(2)
162 t = this%tracktimes%times(i)
163 if (t < particle%ttrack) cycle
164 if (t > texit .or. t > tmax)
exit
166 x =
new_x(exit_x%v, exit_x%dvdx, subcell%vx1, subcell%vx2, &
167 dt, x0, subcell%dx, exit_x%status == 1)
168 y =
new_x(exit_y%v, exit_y%dvdx, subcell%vy1, subcell%vy2, &
169 dt, y0, subcell%dy, exit_y%status == 1)
170 z =
new_x(exit_z%v, exit_z%dvdx, subcell%vz1, subcell%vz2, &
171 dt, z0, subcell%dz, exit_z%status == 1)
172 particle%x = x * subcell%dx
173 particle%y = y * subcell%dy
174 particle%z = z * subcell%dz
177 call this%usertime(particle)
183 if (texit .gt. tmax)
then
186 x =
new_x(exit_x%v, exit_x%dvdx, subcell%vx1, subcell%vx2, &
187 dt, x0, subcell%dx, exit_x%status == 1)
188 y =
new_x(exit_y%v, exit_y%dvdx, subcell%vy1, subcell%vy2, &
189 dt, y0, subcell%dy, exit_y%status == 1)
190 z =
new_x(exit_z%v, exit_z%dvdx, subcell%vz1, subcell%vz2, &
191 dt, z0, subcell%dz, exit_z%status == 1)
194 particle%advancing = .false.
195 particle%x = x * subcell%dx
196 particle%y = y * subcell%dy
197 particle%z = z * subcell%dz
200 call this%timestep(particle)
209 if ((exit_face .eq. 1) .or. (exit_face .eq. 2))
then
211 y =
new_x(exit_y%v, exit_y%dvdx, subcell%vy1, subcell%vy2, &
212 dt, y0, subcell%dy, exit_y%status == 1)
213 z =
new_x(exit_z%v, exit_z%dvdx, subcell%vz1, subcell%vz2, &
214 dt, z0, subcell%dz, exit_z%status == 1)
215 if (exit_face .eq. 2) x =
done
216 else if ((exit_face .eq. 3) .or. (exit_face .eq. 4))
then
217 x =
new_x(exit_x%v, exit_x%dvdx, subcell%vx1, subcell%vx2, dt, &
218 x0, subcell%dx, exit_x%status == 1)
220 z =
new_x(exit_z%v, exit_z%dvdx, subcell%vz1, subcell%vz2, dt, &
221 z0, subcell%dz, exit_z%status == 1)
222 if (exit_face .eq. 4) y =
done
223 else if ((exit_face .eq. 5) .or. (exit_face .eq. 6))
then
224 x =
new_x(exit_x%v, exit_x%dvdx, subcell%vx1, subcell%vx2, &
225 dt, x0, subcell%dx, exit_x%status == 1)
226 y =
new_x(exit_y%v, exit_y%dvdx, subcell%vy1, subcell%vy2, &
227 dt, y0, subcell%dy, exit_y%status == 1)
229 if (exit_face .eq. 6) z =
done
231 print *,
"programmer error, invalid exit face", exit_face
234 particle%x = x * subcell%dx
235 particle%y = y * subcell%dy
236 particle%z = z * subcell%dz
239 call this%subcellexit(particle)
246 integer(I4B) :: exit_soln
253 if (exit_solutions(1)%status < 2)
then
255 dtmin = exit_solutions(1)%dt
257 if (exit_solutions(2)%status < 2 .and. &
258 exit_solutions(2)%dt < dtmin)
then
260 dtmin = exit_solutions(2)%dt
262 if (exit_solutions(3)%status < 2 .and. &
263 exit_solutions(3)%dt < dtmin)
then
275 subroutine find_exits(particle, domain, exit_solutions, x0, y0, z0)
279 real(DP),
intent(out) :: x0, y0, z0
284 x0 = particle%x / domain%dx
285 y0 = particle%y / domain%dy
286 z0 = particle%z / domain%dz
290 find_exit(domain%vx1, domain%vx2, domain%dx, x0), &
291 find_exit(domain%vy1, domain%vy2, domain%dy, y0), &
292 find_exit(domain%vz1, domain%vz2, domain%dz, z0) &
296 if (exit_solutions(1)%v <
dzero)
then
297 exit_solutions(1)%iboundary = 1
298 else if (exit_solutions(1)%v >
dzero)
then
299 exit_solutions(1)%iboundary = 2
301 if (exit_solutions(2)%v <
dzero)
then
302 exit_solutions(2)%iboundary = 3
303 else if (exit_solutions(2)%v >
dzero)
then
304 exit_solutions(2)%iboundary = 4
306 if (exit_solutions(3)%v <
dzero)
then
307 exit_solutions(3)%iboundary = 5
308 else if (exit_solutions(3)%v >
dzero)
then
309 exit_solutions(3)%iboundary = 6
317 real(dp),
intent(in) :: v1
318 real(dp),
intent(in) :: v2
319 real(dp),
intent(in) :: dx
320 real(dp),
intent(in) :: xl
325 solution%v, solution%dvdx, solution%dt)
345 integer(I4B) :: status
361 logical(LGP) :: nooutflow
367 if (v2a .lt.
dzero) v2a = -v2a
369 if (v1a .lt.
dzero) v1a = -v1a
372 if (dva .lt.
dzero) dva = -dva
377 if ((v2a .lt. tol) .and. (v1a .lt. tol))
then
388 if (v2a .gt. vv) vv = v2a
390 if (vvv .lt. 1.0d-4)
then
395 if (v1 .gt. zro) dt = (dx - x) / v1
396 if (v1 .lt. zrom) dt = -x / v1
405 v = (
done - xl) * v1 + xl * v2
410 if (v1 .lt.
dzero) nooutflow = .false.
411 if (v2 .gt.
dzero) nooutflow = .false.
421 if ((v1 .le.
dzero) .and. (v2 .ge.
dzero))
then
422 if (abs(v) .le.
dzero)
then
424 if (v2 .le.
dzero) v = -v
434 if (vr .le.
dzero)
then
442 if (v1v2 .gt.
dzero)
then
443 if (v .gt.
dzero) vr = vr2
444 if (v .lt.
dzero) vr = vr1
449 if (dabs(vr) .lt. 1.0d-10)
then
469 pure function new_x(v, dvdx, v1, v2, dt, x, dx, velocity_profile)
result(newx)
471 real(dp),
intent(in) :: v
472 real(dp),
intent(in) :: dvdx
473 real(dp),
intent(in) :: v1
474 real(dp),
intent(in) :: v2
475 real(dp),
intent(in) :: dt
476 real(dp),
intent(in) :: x
477 real(dp),
intent(in) :: dx
478 logical(LGP),
intent(in),
optional :: velocity_profile
481 logical(LGP) :: lprofile
484 if (
present(velocity_profile))
then
485 lprofile = velocity_profile
493 newx = newx + (v1 * dt / dx)
494 else if (v .ne.
dzero)
then
495 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
subroutine find_exits(particle, domain, exit_solutions, x0, y0, z0)
Compute candidate exit solutions.
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, 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.
integer(i4b) function pick_exit(exit_solutions)
Pick the exit solution with the shortest travel time.
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 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.