Skip to content

Commit 19295a9

Browse files
authored
refactor(prt-fmi): add boundary face awareness (#2477)
Store IFLOWFACE assigned boundary faces in PRT FMI. Revision of #2446 following review. No functional changes. Factored out of #2475, as this will be useful to fix the top face exit issue described in #2468 too.
1 parent 5faa2c6 commit 19295a9

File tree

1 file changed

+60
-11
lines changed

1 file changed

+60
-11
lines changed

src/Model/ParticleTracking/prt-fmi.f90

Lines changed: 60 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
module PrtFmiModule
22

3-
use KindModule, only: DP, I4B
4-
use ConstantsModule, only: DZERO, LENAUXNAME, LENPACKAGENAME
3+
use KindModule, only: DP, I4B, LGP
4+
use ErrorUtilModule, only: pstop
5+
use ConstantsModule, only: DZERO, LENAUXNAME, LENPACKAGENAME, LENVARNAME
56
use SimModule, only: store_error
67
use SimVariablesModule, only: errmsg
78
use FlowModelInterfaceModule, only: FlowModelInterfaceType
@@ -22,12 +23,15 @@ module PrtFmiModule
2223
double precision, allocatable, public :: SinkFlows(:) ! cell sink flows array
2324
double precision, allocatable, public :: StorageFlows(:) ! cell storage flows array
2425
double precision, allocatable, public :: BoundaryFlows(:) ! cell boundary flows array
26+
integer(I4B), allocatable, public :: BoundaryFaces(:) ! bitmask of assigned boundary faces
2527

2628
contains
2729

2830
procedure :: fmi_ad
2931
procedure :: fmi_df => prtfmi_df
3032
procedure, private :: accumulate_flows
33+
procedure :: mark_boundary_face
34+
procedure :: is_boundary_face
3135

3236
end type PrtFmiType
3337

@@ -76,8 +80,8 @@ subroutine fmi_ad(this)
7680
&"(/1X,'DRY CELL REACTIVATED AT ', a)"
7781
!
7882
! Set flag to indicated that flows are being updated. For the case where
79-
! flows may be reused (only when flows are read from a file) then set
80-
! the flag to zero to indicated that flows were not updated
83+
! flows may be reused (only when flows are read from a file) then set
84+
! the flag to zero to indicated that flows were not updated
8185
this%iflowsupdated = 1
8286
!
8387
! If reading flows from a budget file, read the next set of records
@@ -102,7 +106,7 @@ subroutine fmi_ad(this)
102106
do n = 1, this%dis%nodes
103107
!
104108
! Calculate the ibound-like array that has 0 if saturation
105-
! is zero and 1 otherwise
109+
! is zero and 1 otherwise
106110
if (this%gwfsat(n) > DZERO) then
107111
this%ibdgwfsat0(n) = 1
108112
else
@@ -150,6 +154,7 @@ subroutine prtfmi_df(this, dis, idryinactive)
150154
allocate (this%SourceFlows(this%dis%nodes))
151155
allocate (this%SinkFlows(this%dis%nodes))
152156
allocate (this%BoundaryFlows(this%dis%nodes * this%max_faces))
157+
allocate (this%BoundaryFaces(this%dis%nodes))
153158

154159
end subroutine prtfmi_df
155160

@@ -160,7 +165,7 @@ subroutine accumulate_flows(this)
160165
class(PrtFmiType) :: this
161166
! local
162167
integer(I4B) :: j, i, ip, ib
163-
integer(I4B) :: ioffset, iflowface, iauxiflowface
168+
integer(I4B) :: ioffset, iflowface, iauxiflowface, iface
164169
real(DP) :: qbnd
165170
character(len=LENAUXNAME) :: auxname
166171
integer(I4B) :: naux
@@ -176,6 +181,7 @@ subroutine accumulate_flows(this)
176181
this%SourceFlows = DZERO
177182
this%SinkFlows = DZERO
178183
this%BoundaryFlows = DZERO
184+
this%BoundaryFaces = 0
179185
do ip = 1, this%nflowpack
180186
iauxiflowface = 0
181187
naux = this%gwfpackages(ip)%naux
@@ -194,16 +200,19 @@ subroutine accumulate_flows(this)
194200
if (this%ibound(i) <= 0) cycle
195201
qbnd = this%gwfpackages(ip)%get_flow(ib)
196202
! todo, after initial release: default iflowface values for different packages
197-
iflowface = 0
203+
iflowface = 0 ! iflowface number
204+
iface = 0 ! internal face number
198205
if (iauxiflowface > 0) then
199206
iflowface = NINT(this%gwfpackages(ip)%auxvar(iauxiflowface, ib))
207+
iface = iflowface
200208
! maps bot -2 -> max_faces - 1, top -1 -> max_faces
201-
if (iflowface < 0) iflowface = iflowface + this%max_faces + 1
209+
if (iface < 0) iface = iface + this%max_faces + 1
202210
end if
203-
if (iflowface .gt. 0) then
211+
if (iface > 0) then
212+
call this%mark_boundary_face(i, iface)
204213
ioffset = (i - 1) * this%max_faces
205-
this%BoundaryFlows(ioffset + iflowface) = &
206-
this%BoundaryFlows(ioffset + iflowface) + qbnd
214+
this%BoundaryFlows(ioffset + iface) = &
215+
this%BoundaryFlows(ioffset + iface) + qbnd
207216
else if (qbnd .gt. DZERO) then
208217
this%SourceFlows(i) = this%SourceFlows(i) + qbnd
209218
else if (qbnd .lt. DZERO) then
@@ -214,4 +223,44 @@ subroutine accumulate_flows(this)
214223

215224
end subroutine accumulate_flows
216225

226+
!> @brief Mark a face as a boundary face.
227+
subroutine mark_boundary_face(this, ic, iface)
228+
class(PrtFmiType) :: this
229+
integer(I4B), intent(in) :: ic !< node number (reduced)
230+
integer(I4B), intent(in) :: iface !< face number
231+
! local
232+
integer(I4B) :: bit_pos
233+
234+
if (ic <= 0 .or. ic > size(this%BoundaryFaces)) return
235+
if (iface == 0) return
236+
bit_pos = iface - 1 ! bit position 0-based
237+
if (bit_pos < 0 .or. bit_pos > 31) then
238+
print *, 'Invalid bitmask position: ', iface
239+
print *, 'Expected a value in range [0, 31]'
240+
call pstop(1)
241+
end if
242+
this%BoundaryFaces(ic) = ibset(this%BoundaryFaces(ic), bit_pos)
243+
end subroutine mark_boundary_face
244+
245+
!> @brief Check if a face is assigned to a boundary package.
246+
function is_boundary_face(this, ic, iface) result(is_boundary)
247+
class(PrtFmiType) :: this
248+
integer(I4B), intent(in) :: ic !< node number (reduced)
249+
integer(I4B), intent(in) :: iface !< face number
250+
logical(LGP) :: is_boundary
251+
! local
252+
integer(I4B) :: bit_pos
253+
254+
is_boundary = .false.
255+
if (ic <= 0 .or. ic > size(this%BoundaryFaces)) return
256+
if (iface == 0) return
257+
bit_pos = iface - 1 ! bit position 0-based
258+
if (bit_pos < 0 .or. bit_pos > 31) then
259+
print *, 'Invalid bitmask position: ', iface
260+
print *, 'Expected a value in range [0, 31]'
261+
call pstop(1)
262+
end if
263+
is_boundary = btest(this%BoundaryFaces(ic), bit_pos)
264+
end function is_boundary_face
265+
217266
end module PrtFmiModule

0 commit comments

Comments
 (0)