MODFLOW 6  version 6.7.0.dev3
USGS Modular Hydrologic Model
Particle.f90
Go to the documentation of this file.
2 
3  use kindmodule, only: dp, i4b, lgp
4  use listmodule, only: listtype
9  implicit none
10  public
11 
12  !> Tracking "levels" defined in method modules. Currently only 3 used.
13  integer, parameter :: max_level = 4
14 
15  !> @brief Particle status enumeration.
16  !!
17  !! Particles begin in status 1 (active) at release time. Status may only
18  !! increase over time. Status values greater than one imply termination.
19  !! A particle may terminate for several reasons, all mutually exclusive.
20  !! A particle's final tracking status will always be greater than one.
21  !!
22  !! Status codes 0-3 and 5-8 correspond directly to MODPATH 7 status codes.
23  !! Code 4 does not apply to PRT because PRT does not distinguish forwards
24  !! from backwards tracking. Status code 9 provides more specific, subcell-
25  !! level information about a particle which terminates due to no outflow.
26  !! Code 10 distinguishes particles which have "timed out" upon reaching a
27  !! user-specified stop time or the end of the simulation.
28  !<
29  enum, bind(C)
30  enumerator :: active = 1
31  enumerator :: term_boundary = 2 !< terminated at a boundary face
32  enumerator :: term_weaksink = 3 !< terminated in a weak sink cell
33  enumerator :: term_no_exits = 5 !< terminated in a cell with no exit face
34  enumerator :: term_stopzone = 6 !< terminated in a cell with a stop zone number
35  enumerator :: term_inactive = 7 !< terminated in an inactive cell
36  enumerator :: term_unreleased = 8 !< terminated permanently unreleased
37  enumerator :: term_no_exits_sub = 9 !< terminated in a subcell with no exit face
38  enumerator :: term_timeout = 10 !< terminated at stop time or end of simulation
39  end enum
40 
41  !> @brief Particle tracked by the PRT model.
42  !!
43  !! Record-type to conveniently shuffle a particle's
44  !! state to/from storage before/after its trajectory
45  !! is solved for each time step.
46  !!
47  !! Particle coordinates may be local to the cell or
48  !! global/model. Routines are provided to convert a
49  !! particle's global coordinates to/from cell-local
50  !! coordinates for tracking through cell subdomains.
51  !!
52  !! Particles are identified by composite key, i.e.,
53  !! combinations of properties imdl, iprp, irpt, and
54  !! trelease. An optional label may be provided, but
55  !! need not be unique
56  !<
58  private
59  ! identity
60  character(len=LENBOUNDNAME), public :: name = '' !< optional particle name
61  integer(I4B), public :: imdl !< index of model the particle originated in
62  integer(I4B), public :: iprp !< index of release package the particle is from
63  integer(I4B), public :: irpt !< index of release point the particle is from
64  integer(I4B), public :: ip !< index of particle in the particle list
65  ! options
66  logical(LGP), public :: extend !< whether to extend tracking beyond the end of the simulation
67  logical(LGP), public :: frctrn !< whether to force solving the particle with the ternary method
68  integer(I4B), public :: istopweaksink !< weak sink option (0: do not stop, 1: stop)
69  integer(I4B), public :: istopzone !< stop zone number
70  integer(I4B), public :: idrymeth !< dry tracking method
71  integer(I4B), public :: iexmeth !< method for iterative solution of particle exit location and time in generalized Pollock's method
72  integer(I4B), public :: icycwin !< cycle detection window size
73  real(dp), public :: extol !< tolerance for iterative solution of particle exit location and time in generalized Pollock's method
74  ! state
75  integer(I4B), public :: itrdomain(max_level) !< tracking domain indices
76  integer(I4B), public :: iboundary(max_level) !< tracking domain boundary indices
77  integer(I4B), public :: icu !< user cell number
78  integer(I4B), public :: ilay !< grid layer
79  integer(I4B), public :: izone !< current zone number
80  integer(I4B), public :: istatus !< tracking status
81  real(dp), public :: x !< x coordinate
82  real(dp), public :: y !< y coordinate
83  real(dp), public :: z !< z coordinate
84  real(dp), public :: trelease !< release time
85  real(dp), public :: tstop !< stop time
86  real(dp), public :: ttrack !< time tracked so far
87  real(dp), public :: xorigin !< x origin for coordinate transformation from model to local
88  real(dp), public :: yorigin !< y origin for coordinate transformation from model to local
89  real(dp), public :: zorigin !< z origin for coordinate transformation from model to local
90  real(dp), public :: sinrot !< sine of rotation angle for coordinate transformation from model to local
91  real(dp), public :: cosrot !< cosine of rotation angle for coordinate transformation from model to local
92  logical(LGP), public :: transformed !< whether coordinates have been transformed from model to local
93  logical(LGP), public :: advancing !< whether particle is still being tracked for current time step
94  type(listtype), public, pointer :: history !< history of particle positions (for cycle detection)
95  contains
96  procedure, public :: destroy => destroy_particle
97  procedure, public :: get_model_coords
98  procedure, public :: transform => transform_coords
99  procedure, public :: reset_transform
100  procedure, public :: get_id
101  end type particletype
102 
103  !> @brief Structure of arrays to store particles.
105  private
106  ! identity
107  character(len=LENBOUNDNAME), dimension(:), pointer, public, contiguous :: name !< optional particle label
108  integer(I4B), dimension(:), pointer, public, contiguous :: imdl !< index of model particle originated in
109  integer(I4B), dimension(:), pointer, public, contiguous :: iprp !< index of release package the particle originated in
110  integer(I4B), dimension(:), pointer, public, contiguous :: irpt !< index of release point in the particle release package the particle originated in
111  ! options
112  logical(LGP), dimension(:), pointer, public, contiguous :: extend !< whether to extend tracking beyond the end of the simulation
113  logical(LGP), dimension(:), pointer, public, contiguous :: frctrn !< force ternary method
114  integer(I4B), dimension(:), pointer, public, contiguous :: istopweaksink !< weak sink option: 0 = do not stop, 1 = stop
115  integer(I4B), dimension(:), pointer, public, contiguous :: istopzone !< stop zone number
116  integer(I4B), dimension(:), pointer, public, contiguous :: idrymeth !< stop in dry cells
117  integer(I4B), dimension(:), pointer, public, contiguous :: iexmeth !< method for iterative solution of particle exit location and time in generalized Pollock's method
118  integer(I4B), dimension(:), pointer, public, contiguous :: icycwin !< cycle detection window size
119  real(dp), dimension(:), pointer, public, contiguous :: extol !< tolerance for iterative solution of particle exit location and time in generalized Pollock's method
120  ! state
121  integer(I4B), dimension(:, :), pointer, public, contiguous :: itrdomain !< array of indices for domains in the tracking domain hierarchy
122  integer(I4B), dimension(:, :), pointer, public, contiguous :: iboundary !< array of indices for tracking domain boundaries
123  integer(I4B), dimension(:), pointer, public, contiguous :: icu !< cell number (user)
124  integer(I4B), dimension(:), pointer, public, contiguous :: ilay !< layer
125  integer(I4B), dimension(:), pointer, public, contiguous :: izone !< current zone number
126  integer(I4B), dimension(:), pointer, public, contiguous :: istatus !< particle status
127  real(dp), dimension(:), pointer, public, contiguous :: x !< model x coord of particle
128  real(dp), dimension(:), pointer, public, contiguous :: y !< model y coord of particle
129  real(dp), dimension(:), pointer, public, contiguous :: z !< model z coord of particle
130  real(dp), dimension(:), pointer, public, contiguous :: trelease !< particle release time
131  real(dp), dimension(:), pointer, public, contiguous :: tstop !< particle stop time
132  real(dp), dimension(:), pointer, public, contiguous :: ttrack !< current tracking time
133  contains
134  procedure, public :: destroy
135  procedure, public :: num_stored
136  procedure, public :: resize
137  procedure, public :: get
138  procedure, public :: put
139  end type particlestoretype
140 
141 contains
142 
143  !> @brief Create a new particle
144  subroutine create_particle(particle)
145  type(particletype), pointer :: particle !< particle
146  allocate (particle)
147  allocate (particle%history)
148  end subroutine create_particle
149 
150  !> @brief Allocate particle store
151  subroutine create_particle_store(store, np, mempath)
152  type(particlestoretype), pointer :: store !< store
153  integer(I4B), intent(in) :: np !< number of particles
154  character(*), intent(in) :: mempath !< path to memory
155 
156  allocate (store)
157  call mem_allocate(store%imdl, np, 'PLIMDL', mempath)
158  call mem_allocate(store%irpt, np, 'PLIRPT', mempath)
159  call mem_allocate(store%iprp, np, 'PLIPRP', mempath)
160  call mem_allocate(store%name, lenboundname, np, 'PLNAME', mempath)
161  call mem_allocate(store%icu, np, 'PLICU', mempath)
162  call mem_allocate(store%ilay, np, 'PLILAY', mempath)
163  call mem_allocate(store%izone, np, 'PLIZONE', mempath)
164  call mem_allocate(store%istatus, np, 'PLISTATUS', mempath)
165  call mem_allocate(store%x, np, 'PLX', mempath)
166  call mem_allocate(store%y, np, 'PLY', mempath)
167  call mem_allocate(store%z, np, 'PLZ', mempath)
168  call mem_allocate(store%trelease, np, 'PLTRELEASE', mempath)
169  call mem_allocate(store%tstop, np, 'PLTSTOP', mempath)
170  call mem_allocate(store%ttrack, np, 'PLTTRACK', mempath)
171  call mem_allocate(store%istopweaksink, np, 'PLISTOPWEAKSINK', mempath)
172  call mem_allocate(store%istopzone, np, 'PLISTOPZONE', mempath)
173  call mem_allocate(store%idrymeth, np, 'PLIDRYMETH', mempath)
174  call mem_allocate(store%frctrn, np, 'PLFRCTRN', mempath)
175  call mem_allocate(store%iexmeth, np, 'PLIEXMETH', mempath)
176  call mem_allocate(store%extol, np, 'PLEXTOL', mempath)
177  call mem_allocate(store%extend, np, 'PLEXTEND', mempath)
178  call mem_allocate(store%icycwin, np, 'PLICYCWIN', mempath)
179  call mem_allocate(store%itrdomain, np, max_level, 'PLIDOMAIN', mempath)
180  call mem_allocate(store%iboundary, np, max_level, 'PLIBOUNDARY', mempath)
181  end subroutine create_particle_store
182 
183  !> @brief Destroy particle store after use.
184  subroutine destroy(this, mempath)
185  class(particlestoretype), intent(inout) :: this !< store
186  character(*), intent(in) :: mempath !< path to memory
187 
188  call mem_deallocate(this%imdl, 'PLIMDL', mempath)
189  call mem_deallocate(this%iprp, 'PLIPRP', mempath)
190  call mem_deallocate(this%irpt, 'PLIRPT', mempath)
191  call mem_deallocate(this%name, 'PLNAME', mempath)
192  call mem_deallocate(this%icu, 'PLICU', mempath)
193  call mem_deallocate(this%ilay, 'PLILAY', mempath)
194  call mem_deallocate(this%izone, 'PLIZONE', mempath)
195  call mem_deallocate(this%istatus, 'PLISTATUS', mempath)
196  call mem_deallocate(this%x, 'PLX', mempath)
197  call mem_deallocate(this%y, 'PLY', mempath)
198  call mem_deallocate(this%z, 'PLZ', mempath)
199  call mem_deallocate(this%trelease, 'PLTRELEASE', mempath)
200  call mem_deallocate(this%tstop, 'PLTSTOP', mempath)
201  call mem_deallocate(this%ttrack, 'PLTTRACK', mempath)
202  call mem_deallocate(this%istopweaksink, 'PLISTOPWEAKSINK', mempath)
203  call mem_deallocate(this%istopzone, 'PLISTOPZONE', mempath)
204  call mem_deallocate(this%idrymeth, 'PLIDRYMETH', mempath)
205  call mem_deallocate(this%frctrn, 'PLFRCTRN', mempath)
206  call mem_deallocate(this%iexmeth, 'PLIEXMETH', mempath)
207  call mem_deallocate(this%extol, 'PLEXTOL', mempath)
208  call mem_deallocate(this%extend, 'PLEXTEND', mempath)
209  call mem_deallocate(this%icycwin, 'PLICYCWIN', mempath)
210  call mem_deallocate(this%itrdomain, 'PLIDOMAIN', mempath)
211  call mem_deallocate(this%iboundary, 'PLIBOUNDARY', mempath)
212  end subroutine destroy
213 
214  !> @brief Destroy a particle after use.
215  subroutine destroy_particle(particle)
216  class(particletype), intent(inout) :: particle !< particle
217  deallocate (particle%history)
218  end subroutine destroy_particle
219 
220  !> @brief Reallocate particle storage to the given size.
221  subroutine resize(this, np, mempath)
222  ! dummy
223  class(particlestoretype), intent(inout) :: this !< particle store
224  integer(I4B), intent(in) :: np !< number of particles
225  character(*), intent(in) :: mempath !< path to memory
226 
227  ! resize arrays
228  call mem_reallocate(this%imdl, np, 'PLIMDL', mempath)
229  call mem_reallocate(this%iprp, np, 'PLIPRP', mempath)
230  call mem_reallocate(this%irpt, np, 'PLIRPT', mempath)
231  call mem_reallocate(this%name, lenboundname, np, 'PLNAME', mempath)
232  call mem_reallocate(this%icu, np, 'PLICU', mempath)
233  call mem_reallocate(this%ilay, np, 'PLILAY', mempath)
234  call mem_reallocate(this%izone, np, 'PLIZONE', mempath)
235  call mem_reallocate(this%istatus, np, 'PLISTATUS', mempath)
236  call mem_reallocate(this%x, np, 'PLX', mempath)
237  call mem_reallocate(this%y, np, 'PLY', mempath)
238  call mem_reallocate(this%z, np, 'PLZ', mempath)
239  call mem_reallocate(this%trelease, np, 'PLTRELEASE', mempath)
240  call mem_reallocate(this%tstop, np, 'PLTSTOP', mempath)
241  call mem_reallocate(this%ttrack, np, 'PLTTRACK', mempath)
242  call mem_reallocate(this%istopweaksink, np, 'PLISTOPWEAKSINK', mempath)
243  call mem_reallocate(this%istopzone, np, 'PLISTOPZONE', mempath)
244  call mem_reallocate(this%idrymeth, np, 'PLIDRYMETH', mempath)
245  call mem_reallocate(this%frctrn, np, 'PLFRCTRN', mempath)
246  call mem_reallocate(this%iexmeth, np, 'PLIEXMETH', mempath)
247  call mem_reallocate(this%extol, np, 'PLEXTOL', mempath)
248  call mem_reallocate(this%extend, np, 'PLEXTEND', mempath)
249  call mem_reallocate(this%icycwin, np, 'PLICYCWIN', mempath)
250  call mem_reallocate(this%itrdomain, np, max_level, 'PLIDOMAIN', mempath)
251  call mem_reallocate(this%iboundary, np, max_level, 'PLIBOUNDARY', mempath)
252  end subroutine resize
253 
254  !> @brief Load a particle from the particle store.
255  !!
256  !! This routine is used to initialize a particle for tracking.
257  !! The advancing flag and coordinate transformation are reset.
258  !<
259  subroutine get(this, particle, imdl, iprp, ip)
260  class(particlestoretype), intent(inout) :: this !< particle store
261  class(particletype), intent(inout) :: particle !< particle
262  integer(I4B), intent(in) :: imdl !< index of model particle originated in
263  integer(I4B), intent(in) :: iprp !< index of particle release package particle originated in
264  integer(I4B), intent(in) :: ip !< index into the particle list
265 
266  call particle%reset_transform()
267  call particle%history%Clear()
268  particle%imdl = imdl
269  particle%iprp = iprp
270  particle%irpt = this%irpt(ip)
271  particle%ip = ip
272  particle%name = this%name(ip)
273  particle%istopweaksink = this%istopweaksink(ip)
274  particle%istopzone = this%istopzone(ip)
275  particle%idrymeth = this%idrymeth(ip)
276  particle%icu = this%icu(ip)
277  particle%ilay = this%ilay(ip)
278  particle%izone = this%izone(ip)
279  particle%istatus = this%istatus(ip)
280  particle%x = this%x(ip)
281  particle%y = this%y(ip)
282  particle%z = this%z(ip)
283  particle%trelease = this%trelease(ip)
284  particle%tstop = this%tstop(ip)
285  particle%ttrack = this%ttrack(ip)
286  particle%advancing = .true.
287  particle%itrdomain(1:max_level) = &
288  this%itrdomain(ip, 1:max_level)
289  particle%itrdomain(1) = imdl
290  particle%iboundary(1:max_level) = &
291  this%iboundary(ip, 1:max_level)
292  particle%frctrn = this%frctrn(ip)
293  particle%iexmeth = this%iexmeth(ip)
294  particle%extol = this%extol(ip)
295  particle%extend = this%extend(ip)
296  particle%icycwin = this%icycwin(ip)
297  end subroutine get
298 
299  !> @brief Save a particle's state to the particle store.
300  subroutine put(this, particle, ip)
301  class(particlestoretype), intent(inout) :: this !< particle storage
302  class(particletype), intent(in) :: particle !< particle
303  integer(I4B), intent(in) :: ip !< particle index
304 
305  this%imdl(ip) = particle%imdl
306  this%iprp(ip) = particle%iprp
307  this%irpt(ip) = particle%irpt
308  this%name(ip) = particle%name
309  this%istopweaksink(ip) = particle%istopweaksink
310  this%istopzone(ip) = particle%istopzone
311  this%idrymeth(ip) = particle%idrymeth
312  this%icu(ip) = particle%icu
313  this%ilay(ip) = particle%ilay
314  this%izone(ip) = particle%izone
315  this%istatus(ip) = particle%istatus
316  this%x(ip) = particle%x
317  this%y(ip) = particle%y
318  this%z(ip) = particle%z
319  this%trelease(ip) = particle%trelease
320  this%tstop(ip) = particle%tstop
321  this%ttrack(ip) = particle%ttrack
322  this%itrdomain( &
323  ip, &
324  1:max_level) = &
325  particle%itrdomain(1:max_level)
326  this%iboundary( &
327  ip, &
328  1:max_level) = &
329  particle%iboundary(1:max_level)
330  this%frctrn(ip) = particle%frctrn
331  this%iexmeth(ip) = particle%iexmeth
332  this%extol(ip) = particle%extol
333  this%extend(ip) = particle%extend
334  this%icycwin(ip) = particle%icycwin
335  end subroutine put
336 
337  !> @brief Transform particle coordinates.
338  !!
339  !! Apply a translation and/or rotation to particle coordinates.
340  !! No rescaling. It's also possible to invert a transformation.
341  !! Be sure to reset the transformation after using it.
342  !<
343  subroutine transform_coords(this, xorigin, yorigin, zorigin, &
344  sinrot, cosrot, invert)
345  use geomutilmodule, only: transform, compose
346  class(particletype), intent(inout) :: this !< particle
347  real(DP), intent(in), optional :: xorigin !< x coordinate of origin
348  real(DP), intent(in), optional :: yorigin !< y coordinate of origin
349  real(DP), intent(in), optional :: zorigin !< z coordinate of origin
350  real(DP), intent(in), optional :: sinrot !< sine of rotation angle
351  real(DP), intent(in), optional :: cosrot !< cosine of rotation angle
352  logical(LGP), intent(in), optional :: invert !< whether to invert
353 
354  call transform(this%x, this%y, this%z, &
355  this%x, this%y, this%z, &
356  xorigin, yorigin, zorigin, &
357  sinrot, cosrot, invert)
358 
359  call compose(this%xorigin, this%yorigin, this%zorigin, &
360  this%sinrot, this%cosrot, &
361  xorigin, yorigin, zorigin, &
362  sinrot, cosrot, invert)
363 
364  this%transformed = .true.
365  end subroutine transform_coords
366 
367  !> @brief Reset particle coordinate transformation properties.
368  subroutine reset_transform(this)
369  class(particletype), intent(inout) :: this !< particle
370 
371  this%xorigin = dzero
372  this%yorigin = dzero
373  this%zorigin = dzero
374  this%sinrot = dzero
375  this%cosrot = done
376  this%cosrot = done
377  this%transformed = .false.
378  end subroutine reset_transform
379 
380  !> @brief Return the particle's model coordinates,
381  !! inverting any applied transformation if needed.
382  !! The particle's state is not altered.
383  subroutine get_model_coords(this, x, y, z)
384  use geomutilmodule, only: transform, compose
385  class(particletype), intent(in) :: this !< particle
386  real(DP), intent(out) :: x !< x coordinate
387  real(DP), intent(out) :: y !< y coordinate
388  real(DP), intent(out) :: z !< z coordinate
389 
390  if (this%transformed) then
391  call transform(this%x, this%y, this%z, x, y, z, &
392  this%xorigin, this%yorigin, this%zorigin, &
393  this%sinrot, this%cosrot, invert=.true.)
394  else
395  x = this%x
396  y = this%y
397  z = this%z
398  end if
399  end subroutine get_model_coords
400 
401  !> @brief Return the number of particles.
402  integer function num_stored(this) result(n)
403  class(particlestoretype) :: this
404  n = size(this%imdl)
405  end function num_stored
406 
407  !> @brief Get a string identifier for the particle.
408  function get_id(this) result(str)
409  class(particletype), intent(in) :: this
410  character(len=:), allocatable :: str
411  ! local
412  character(len=LINELENGTH) :: temp
413 
414  write (temp, '(I0,1a,I0,1a,I0,1a,G0)') &
415  this%imdl, this%iprp, this%irpt, this%trelease
416  str = trim(adjustl(temp))
417  end function get_id
418 
419 end module particlemodule
This module contains simulation constants.
Definition: Constants.f90:9
integer(i4b), parameter linelength
maximum length of a standard line
Definition: Constants.f90:45
integer(i4b), parameter lenboundname
maximum length of a bound name
Definition: Constants.f90:36
real(dp), parameter dzero
real constant zero
Definition: Constants.f90:65
integer(i4b), parameter lenmempath
maximum length of the memory path
Definition: Constants.f90:27
real(dp), parameter done
real constant 1
Definition: Constants.f90:76
subroutine, public transform(xin, yin, zin, xout, yout, zout, xorigin, yorigin, zorigin, sinrot, cosrot, invert)
Apply a 3D translation and optional 2D rotation to coordinates.
Definition: GeomUtil.f90:183
subroutine, public compose(xorigin, yorigin, zorigin, sinrot, cosrot, xorigin_new, yorigin_new, zorigin_new, sinrot_new, cosrot_new, invert)
Apply a 3D translation and 2D rotation to an existing transformation.
Definition: GeomUtil.f90:243
This module defines variable data types.
Definition: kind.f90:8
subroutine get(this, particle, imdl, iprp, ip)
Load a particle from the particle store.
Definition: Particle.f90:260
subroutine resize(this, np, mempath)
Reallocate particle storage to the given size.
Definition: Particle.f90:222
subroutine create_particle_store(store, np, mempath)
Allocate particle store.
Definition: Particle.f90:152
character(len=:) function, allocatable get_id(this)
Get a string identifier for the particle.
Definition: Particle.f90:409
subroutine get_model_coords(this, x, y, z)
Return the particle's model coordinates, inverting any applied transformation if needed....
Definition: Particle.f90:384
integer function num_stored(this)
Return the number of particles.
Definition: Particle.f90:403
subroutine reset_transform(this)
Reset particle coordinate transformation properties.
Definition: Particle.f90:369
@ term_weaksink
terminated in a weak sink cell
Definition: Particle.f90:32
@ term_timeout
terminated at stop time or end of simulation
Definition: Particle.f90:38
@ term_inactive
terminated in an inactive cell
Definition: Particle.f90:35
@ term_no_exits
terminated in a cell with no exit face
Definition: Particle.f90:33
@ term_stopzone
terminated in a cell with a stop zone number
Definition: Particle.f90:34
@ term_no_exits_sub
terminated in a subcell with no exit face
Definition: Particle.f90:37
@ term_unreleased
terminated permanently unreleased
Definition: Particle.f90:36
@ term_boundary
terminated at a boundary face
Definition: Particle.f90:31
subroutine transform_coords(this, xorigin, yorigin, zorigin, sinrot, cosrot, invert)
Transform particle coordinates.
Definition: Particle.f90:345
subroutine destroy(this, mempath)
Destroy particle store after use.
Definition: Particle.f90:185
subroutine create_particle(particle)
Create a new particle.
Definition: Particle.f90:145
subroutine put(this, particle, ip)
Save a particle's state to the particle store.
Definition: Particle.f90:301
integer, parameter max_level
Tracking "levels" defined in method modules. Currently only 3 used.
Definition: Particle.f90:13
subroutine destroy_particle(particle)
Destroy a particle after use.
Definition: Particle.f90:216
A generic heterogeneous doubly-linked list.
Definition: List.f90:14
Structure of arrays to store particles.
Definition: Particle.f90:104
Particle tracked by the PRT model.
Definition: Particle.f90:57