Skip to content

Commit ca387f4

Browse files
authored
refactor(prt): split TrackData into separate file and control modules (#2055)
Carved out of #1901 for tidiness. Split TrackDataModule into TrackFileModule and TrackControlModule. Also clean up some comments, and pass fmi down into cell/subcell tracking methods (not always needed, but best to be consistent).
1 parent 4e30455 commit ca387f4

18 files changed

Lines changed: 456 additions & 447 deletions

make/makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,8 @@ $(OBJDIR)/sort.o \
266266
$(OBJDIR)/FlowModelInterface.o \
267267
$(OBJDIR)/Cell.o \
268268
$(OBJDIR)/Subcell.o \
269-
$(OBJDIR)/TrackData.o \
269+
$(OBJDIR)/TrackFile.o \
270+
$(OBJDIR)/TrackControl.o \
270271
$(OBJDIR)/TimeSelect.o \
271272
$(OBJDIR)/prt-fmi.o \
272273
$(OBJDIR)/TimeStepSelect.o \

msvs/mf6core.vfproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,8 @@
328328
<File RelativePath="..\src\Model\ModelUtilities\SwfCxsUtils.f90"/>
329329
<File RelativePath="..\src\Model\ModelUtilities\TimeSelect.f90"/>
330330
<File RelativePath="..\src\Model\ModelUtilities\TimeStepSelect.f90"/>
331-
<File RelativePath="..\src\Model\ModelUtilities\TrackData.f90"/>
331+
<File RelativePath="..\src\Model\ModelUtilities\TrackFile.f90"/>
332+
<File RelativePath="..\src\Model\ModelUtilities\TrackControl.f90"/>
332333
<File RelativePath="..\src\Model\ModelUtilities\TspAdvOptions.f90"/>
333334
<File RelativePath="..\src\Model\ModelUtilities\UzfCellGroup.f90"/>
334335
<File RelativePath="..\src\Model\ModelUtilities\UzfEtUtil.f90"/>
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
module TrackControlModule
2+
3+
use KindModule, only: DP, I4B, LGP
4+
use ConstantsModule, only: DZERO, DONE, DPIO180
5+
use ParticleModule, only: ParticleType
6+
use BaseDisModule, only: DisBaseType
7+
use GeomUtilModule, only: transform
8+
use TrackFileModule, only: TrackFileType, save_record
9+
10+
implicit none
11+
public :: TrackControlType
12+
13+
!> @brief Manages particle track (i.e. pathline) files.
14+
!!
15+
!! Optionally filters events ("ireason" codes, selectable in the PRT-OC pkg):
16+
!!
17+
!! 0: RELEASE: particle is released
18+
!! 1: TRANSIT: particle moves from cell to cell
19+
!! 2: TIMESTEP: timestep ends
20+
!! 3: TERMINATE: tracking stops for a particle
21+
!! 4: WEAKSINK: particle exits a weak sink
22+
!! 5: USERTIME: user-specified tracking time
23+
!!
24+
!! An arbitrary number of files can be managed. Internal arrays
25+
!! are resized as needed.
26+
!<
27+
type :: TrackControlType
28+
private
29+
type(TrackFileType), public, allocatable :: trackfiles(:) !< output files
30+
integer(I4B), public :: ntrackfiles !< number of output files
31+
logical(LGP), public :: trackrelease !< track release events
32+
logical(LGP), public :: trackexit !< track cell-to-cell transitions
33+
logical(LGP), public :: tracktimestep !< track timestep ends
34+
logical(LGP), public :: trackterminate !< track termination events
35+
logical(LGP), public :: trackweaksink !< track weak sink exit events
36+
logical(LGP), public :: trackusertime !< track user-selected times
37+
contains
38+
procedure :: expand
39+
procedure, public :: init_track_file
40+
procedure, public :: save
41+
procedure, public :: set_track_events
42+
end type TrackControlType
43+
44+
contains
45+
46+
!> @brief Initialize a new track file
47+
subroutine init_track_file(this, iun, csv, iprp)
48+
! dummy
49+
class(TrackControlType) :: this
50+
integer(I4B), intent(in) :: iun
51+
logical(LGP), intent(in), optional :: csv
52+
integer(I4B), intent(in), optional :: iprp
53+
! local
54+
type(TrackFileType), pointer :: file
55+
56+
! Allocate or expand array
57+
if (.not. allocated(this%trackfiles)) then
58+
allocate (this%trackfiles(1))
59+
else
60+
call this%expand(increment=1)
61+
end if
62+
63+
! Setup new file
64+
allocate (file)
65+
file%iun = iun
66+
if (present(csv)) file%csv = csv
67+
if (present(iprp)) file%iprp = iprp
68+
69+
! Update array and counter
70+
this%ntrackfiles = size(this%trackfiles)
71+
this%trackfiles(this%ntrackfiles) = file
72+
73+
end subroutine init_track_file
74+
75+
!> @brief Expand the trackfile array, internal use only
76+
subroutine expand(this, increment)
77+
! dummy
78+
class(TrackControlType) :: this
79+
integer(I4B), optional, intent(in) :: increment
80+
! local
81+
integer(I4B) :: inclocal
82+
integer(I4B) :: isize
83+
integer(I4B) :: newsize
84+
type(TrackFileType), allocatable, dimension(:) :: temp
85+
86+
! Initialize optional args
87+
if (present(increment)) then
88+
inclocal = increment
89+
else
90+
inclocal = 1
91+
end if
92+
93+
! Increase size of array
94+
if (allocated(this%trackfiles)) then
95+
isize = size(this%trackfiles)
96+
newsize = isize + inclocal
97+
allocate (temp(newsize))
98+
temp(1:isize) = this%trackfiles
99+
deallocate (this%trackfiles)
100+
call move_alloc(temp, this%trackfiles)
101+
else
102+
allocate (this%trackfiles(inclocal))
103+
end if
104+
105+
end subroutine expand
106+
107+
!> @brief Save the particle's state to track output file(s).
108+
!!
109+
!! A record is saved to all enabled model-level files and to
110+
!! any PRP-level files with PRP index matching the particle's
111+
!! PRP index.
112+
!<
113+
subroutine save(this, particle, kper, kstp, reason, level)
114+
! dummy
115+
class(TrackControlType), intent(inout) :: this
116+
type(ParticleType), pointer, intent(in) :: particle
117+
integer(I4B), intent(in) :: kper
118+
integer(I4B), intent(in) :: kstp
119+
integer(I4B), intent(in) :: reason
120+
integer(I4B), intent(in), optional :: level
121+
! local
122+
integer(I4B) :: i
123+
type(TrackFileType) :: file
124+
125+
! Only save if reporting is enabled for specified event.
126+
if (.not. ((this%trackrelease .and. reason == 0) .or. &
127+
(this%trackexit .and. reason == 1) .or. &
128+
(this%tracktimestep .and. reason == 2) .or. &
129+
(this%trackterminate .and. reason == 3) .or. &
130+
(this%trackweaksink .and. reason == 4) .or. &
131+
(this%trackusertime .and. reason == 5))) &
132+
return
133+
134+
! For now, only allow reporting from outside the tracking
135+
! algorithm (e.g. release time), in which case level will
136+
! not be provided, or if within the tracking solution, in
137+
! subcells (level 3) only. This may change if the subcell
138+
! ever delegates tracking to even smaller subcomponents.
139+
if (present(level)) then
140+
if (level .ne. 3) return
141+
end if
142+
143+
! Save to any enabled model-scoped or PRP-scoped files
144+
do i = 1, this%ntrackfiles
145+
file = this%trackfiles(i)
146+
if (file%iun > 0 .and. &
147+
(file%iprp == -1 .or. &
148+
file%iprp == particle%iprp)) &
149+
call save_record(file%iun, particle, &
150+
kper, kstp, reason, csv=file%csv)
151+
end do
152+
end subroutine save
153+
154+
!> @brief Configure particle events to track.
155+
!!
156+
!! Each tracking event corresponds to an "ireason" code
157+
!! as appears in each row of track output.
158+
!<
159+
subroutine set_track_events(this, &
160+
release, &
161+
cellexit, &
162+
timestep, &
163+
terminate, &
164+
weaksink, &
165+
usertime)
166+
class(TrackControlType) :: this
167+
logical(LGP), intent(in) :: release
168+
logical(LGP), intent(in) :: cellexit
169+
logical(LGP), intent(in) :: timestep
170+
logical(LGP), intent(in) :: terminate
171+
logical(LGP), intent(in) :: weaksink
172+
logical(LGP), intent(in) :: usertime
173+
this%trackrelease = release
174+
this%trackexit = cellexit
175+
this%tracktimestep = timestep
176+
this%trackterminate = terminate
177+
this%trackweaksink = weaksink
178+
this%trackusertime = usertime
179+
end subroutine set_track_events
180+
181+
end module TrackControlModule

0 commit comments

Comments
 (0)