Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(PRT): localz option for particle release point package #1756

Merged
merged 2 commits into from
Apr 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 20 additions & 14 deletions autotest/test_prt_stop_zones.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,25 @@ def create_izone(nlay, nrow, ncol):
return izone


def build_gwf_sim(name, ws, mf6):
gwf_sim = FlopyReadmeCase.get_gwf_sim(
name, ws, mf6
)
gwf = gwf_sim.get_model()
dis = gwf.get_package("DIS")
nlay = int(name[-1])
botm = [FlopyReadmeCase.top - (k + 1) for k in range(nlay)]
botm_data = np.array(
[
list(repeat(b, FlopyReadmeCase.nrow * FlopyReadmeCase.ncol))
for b in botm
]
).reshape((nlay, FlopyReadmeCase.nrow, FlopyReadmeCase.ncol))
dis.nlay = nlay
dis.botm.set_data(botm_data)
return gwf_sim


def build_prt_sim(name, gwf_ws, prt_ws, mf6):
# create simulation
sim = flopy.mf6.MFSimulation(
Expand Down Expand Up @@ -193,21 +212,8 @@ def build_mp7_sim(name, ws, mp7, gwf):


def build_models(idx, test):
gwf_sim = FlopyReadmeCase.get_gwf_sim(
test.name, test.workspace, test.targets["mf6"]
)
gwf_sim = build_gwf_sim(test.name, test.workspace, test.targets["mf6"])
gwf = gwf_sim.get_model()
dis = gwf.get_package("DIS")
nlay = int(test.name[-1])
botm = [FlopyReadmeCase.top - (k + 1) for k in range(nlay)]
botm_data = np.array(
[
list(repeat(b, FlopyReadmeCase.nrow * FlopyReadmeCase.ncol))
for b in botm
]
).reshape((nlay, FlopyReadmeCase.nrow, FlopyReadmeCase.ncol))
dis.nlay = nlay
dis.botm.set_data(botm_data)
prt_sim = build_prt_sim(
test.name, test.workspace, test.workspace / "prt", test.targets["mf6"]
)
Expand Down
8 changes: 8 additions & 0 deletions doc/mf6io/mf6ivar/dfn/prt-prp.dfn
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ optional true
longname
description REPLACE boundnames {'{#1}': 'release-point'}

block options
name local_z
type keyword
reader urword
optional true
longname whether to use local z coordinates
description indicates that rptz defines the local z coordinate of the release point within the cell, with value between 0 and 1 (inclusive). If the cell is unsaturated at release time, the z coordinate is computed relative to the water table rather than the top of the cell.

block options
name track_filerecord
type record track fileout trackfile
Expand Down
25 changes: 23 additions & 2 deletions src/Model/ParticleTracking/prt-prp.f90
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ module PrtPrpModule
integer(I4B), pointer :: itrkhdr => null() !< track header file
integer(I4B), pointer :: itrkcsv => null() !< CSV track file
integer(I4B), pointer :: irlstls => null() !< release time file
logical(LGP), pointer :: localz => null() !< compute z coordinates local to the cell
logical(LGP), pointer :: rlsall => null() !< release in all time step
logical(LGP), pointer :: rlsfirst => null() !< release in first time step
logical(LGP), pointer :: rlstimelist => null() !< use global release time
Expand All @@ -58,6 +59,7 @@ module PrtPrpModule
real(DP), pointer, contiguous :: rptx(:) => null() !< release point x coordinates
real(DP), pointer, contiguous :: rpty(:) => null() !< release point y coordinates
real(DP), pointer, contiguous :: rptz(:) => null() !< release point z coordinates
real(DP), pointer, contiguous :: locz(:) => null() !< release point local z coordinates
real(DP), pointer, contiguous :: rptmass(:) => null() !< total mass released from point
character(len=LENBOUNDNAME), pointer, contiguous :: rptname(:) => null() !< release point names
type(TimeSelectType), pointer :: releasetimes
Expand Down Expand Up @@ -140,6 +142,7 @@ subroutine prp_da(this)
call mem_deallocate(this%rlsall)
call mem_deallocate(this%rlsfirst)
call mem_deallocate(this%rlstimelist)
call mem_deallocate(this%localz)
call mem_deallocate(this%offset)
call mem_deallocate(this%stoptime)
call mem_deallocate(this%stoptraveltime)
Expand All @@ -157,6 +160,7 @@ subroutine prp_da(this)
call mem_deallocate(this%rptx)
call mem_deallocate(this%rpty)
call mem_deallocate(this%rptz)
call mem_deallocate(this%locz)
call mem_deallocate(this%rptnode)
call mem_deallocate(this%rptmass)
call mem_deallocate(this%rlskstp)
Expand Down Expand Up @@ -201,6 +205,7 @@ subroutine prp_allocate_arrays(this, nodelist, auxvar)
call mem_allocate(this%rptx, this%nreleasepts, 'RPTX', this%memoryPath)
call mem_allocate(this%rpty, this%nreleasepts, 'RPTY', this%memoryPath)
call mem_allocate(this%rptz, this%nreleasepts, 'RPTZ', this%memoryPath)
call mem_allocate(this%locz, this%nreleasepts, 'LOCZ', this%memoryPath)
call mem_allocate(this%rptmass, this%nreleasepts, 'RPTMASS', this%memoryPath)
call mem_allocate(this%rptnode, this%nreleasepts, 'RPTNODER', &
this%memoryPath)
Expand Down Expand Up @@ -230,6 +235,7 @@ subroutine prp_allocate_scalars(this)
call mem_allocate(this%rlsall, 'RLSALL', this%memoryPath)
call mem_allocate(this%rlsfirst, 'RLSFIRST', this%memoryPath)
call mem_allocate(this%rlstimelist, 'RELEASETIME', this%memoryPath)
call mem_allocate(this%localz, 'LOCALZ', this%memoryPath)
call mem_allocate(this%offset, 'OFFSET', this%memoryPath)
call mem_allocate(this%stoptime, 'STOPTIME', this%memoryPath)
call mem_allocate(this%stoptraveltime, 'STOPTRAVELTIME', this%memoryPath)
Expand All @@ -247,6 +253,7 @@ subroutine prp_allocate_scalars(this)
this%rlsall = .false.
this%rlsfirst = .false.
this%rlstimelist = .false.
this%localz = .false.
this%offset = DZERO
this%stoptime = huge(1d0)
this%stoptraveltime = huge(1d0)
Expand Down Expand Up @@ -303,7 +310,7 @@ subroutine prp_ad(this)
character(len=LINELENGTH) :: errmsg
integer(I4B) :: ic, icu, nps, nts, nrel, &
nreleasets, np, irow, icol, ilay, icpl
real(DP) :: x, y, z, trelease, tend
real(DP) :: x, y, z, trelease, tend, top, bot, hds
real(DP), allocatable :: polyverts(:, :)
type(ParticleType), pointer :: particle

Expand Down Expand Up @@ -418,7 +425,14 @@ subroutine prp_ad(this)
end if
particle%x = x
particle%y = y
particle%z = this%rptz(nps)
if (this%localz) then
top = this%fmi%dis%top(ic)
bot = this%fmi%dis%bot(ic)
hds = this%fmi%gwfhead(ic)
particle%z = bot + this%rptz(nps) * (hds - bot)
else
particle%z = this%rptz(nps)
end if
particle%trelease = trelease
! Set stopping time to earlier of times specified by STOPTIME and STOPTRAVELTIME
if (this%stoptraveltime == huge(1d0)) then
Expand Down Expand Up @@ -794,6 +808,8 @@ subroutine prp_options(this, option, found)
&FOLLOWED BY FILEOUT')
end if
found = .true.
case ('LOCAL_Z')
this%localz = .true.
case default
found = .false.
end select
Expand Down Expand Up @@ -873,6 +889,11 @@ subroutine prp_read_packagedata(this)
y(n) = this%parser%GetDouble()
z(n) = this%parser%GetDouble()

if (this%localz .and. (z(n) < 0 .or. z(n) > 1)) then
call store_error('Local z coordinate must fall in the interval [0, 1]')
cycle
end if

! -- set default boundname
write (cno, '(i9.9)') n
bndName = 'PRP'//cno
Expand Down
Loading