11module 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+
217266end module PrtFmiModule
0 commit comments