MODFLOW 6  version 6.6.0.dev0
USGS Modular Hydrologic Model
MethodCellPollockQuad.f90
Go to the documentation of this file.
2 
3  use kindmodule, only: dp, i4b
4  use errorutilmodule, only: pstop
5  use constantsmodule, only: done, dzero
6  use methodmodule, only: methodtype
11  use particlemodule, only: particletype
13  implicit none
14 
15  private
17  public :: create_method_cell_quad
18 
20  contains
21  procedure, public :: apply => apply_mcpq
22  procedure, public :: deallocate
23  procedure, public :: load => load_mcpq
24  procedure, public :: load_subcell
25  procedure, public :: pass => pass_mcpq
27 
28 contains
29 
30  !> @brief Create a new Pollock quad-refined cell method
31  subroutine create_method_cell_quad(method)
32  ! -- dummy
33  type(methodcellpollockquadtype), pointer :: method
34  ! -- local
35  type(cellrectquadtype), pointer :: cell
36  type(subcellrecttype), pointer :: subcell
37 
38  allocate (method)
39  call create_cell_rect_quad(cell)
40  method%cell => cell
41  method%type => method%cell%type
42  method%delegates = .true.
43  call create_subcell_rect(subcell)
44  method%subcell => subcell
45  end subroutine create_method_cell_quad
46 
47  !> @brief Deallocate the Pollock quad-refined cell method
48  subroutine deallocate (this)
49  class(methodcellpollockquadtype), intent(inout) :: this
50  deallocate (this%type)
51  end subroutine deallocate
52 
53  !> @brief Load subcell into tracking method
54  subroutine load_mcpq(this, particle, next_level, submethod)
55  class(methodcellpollockquadtype), intent(inout) :: this
56  type(particletype), pointer, intent(inout) :: particle
57  integer, intent(in) :: next_level
58  class(methodtype), pointer, intent(inout) :: submethod
59 
60  select type (subcell => this%subcell)
61  type is (subcellrecttype)
62  call this%load_subcell(particle, subcell)
63  end select
64  call method_subcell_plck%init( &
65  cell=this%cell, &
66  subcell=this%subcell, &
67  trackfilectl=this%trackfilectl, &
68  tracktimes=this%tracktimes)
69  submethod => method_subcell_plck
70  end subroutine load_mcpq
71 
72  !> @brief Pass particle to next subcell if there is one, or to the cell face
73  subroutine pass_mcpq(this, particle)
74  ! -- dummy
75  class(methodcellpollockquadtype), intent(inout) :: this
76  type(particletype), pointer, intent(inout) :: particle
77  ! -- local
78  integer(I4B) :: isc, exitFace, npolyverts, inface, infaceoff
79 
80  select type (cell => this%cell)
81  type is (cellrectquadtype)
82  exitface = particle%iboundary(3)
83  isc = particle%idomain(3)
84  npolyverts = cell%defn%npolyverts
85 
86  ! exitFace uses MODPATH 7 iface convention here
87  select case (exitface)
88  case (0)
89  ! -- Subcell interior (cell interior)
90  inface = -1
91  case (1)
92  select case (isc)
93  case (1)
94  ! -- W face, subcell 1 --> E face, subcell 4 (cell interior)
95  particle%idomain(3) = 4
96  particle%iboundary(3) = 2
97  inface = 0 ! want Domain(2) unchanged; Boundary(2) = 0
98  case (2)
99  ! -- W face, subcell 2 --> E face, subcell 3 (cell interior)
100  particle%idomain(3) = 3
101  particle%iboundary(3) = 2
102  inface = 0 ! want Domain(2) unchanged; Boundary(2) = 0
103  case (3)
104  ! -- W face, subcell 3 (cell face)
105  inface = 1 ! want Domain(2) = -Domain(2); Boundary(2) = inface
106  infaceoff = 0
107  case (4)
108  ! -- W face, subcell 4 (cell face)
109  inface = 2 ! want Domain(2) = -Domain(2); Boundary(2) = inface
110  infaceoff = -1
111  end select
112  case (2)
113  select case (isc)
114  case (1)
115  ! -- E face, subcell 1 (cell face)
116  inface = 3 ! want Domain(2) = -Domain(2); Boundary(2) = inface
117  infaceoff = 0
118  case (2)
119  ! -- E face, subcell 2 (cell face)
120  inface = 4 ! want Domain(2) = -Domain(2); Boundary(2) = inface
121  infaceoff = -1
122  case (3)
123  ! -- E face, subcell 3 --> W face, subcell 2 (cell interior)
124  particle%idomain(3) = 2
125  particle%iboundary(3) = 1
126  inface = 0 ! want Domain(2) unchanged; Boundary(2) = 0
127  case (4)
128  ! -- E face, subcell 4 --> W face subcell 1 (cell interior)
129  particle%idomain(3) = 1
130  particle%iboundary(3) = 1
131  inface = 0 ! want Domain(2) unchanged; Boundary(2) = 0
132  end select
133  case (3)
134  select case (isc)
135  case (1)
136  ! -- S face, subcell 1 --> N face, subcell 2 (cell interior)
137  particle%idomain(3) = 2
138  particle%iboundary(3) = 4
139  inface = 0 ! want Domain(2) unchanged; Boundary(2) = 0
140  case (2)
141  ! -- S face, subcell 2 (cell face)
142  inface = 4 ! want Domain(2) = -Domain(2); Boundary(2) = inface
143  infaceoff = 0
144  case (3)
145  ! -- S face, subcell 3 (cell face)
146  inface = 1 ! want Domain(2) = -Domain(2); Boundary(2) = inface
147  infaceoff = -1
148  case (4)
149  ! -- S face, subcell 4 --> N face, subcell 3 (cell interior)
150  particle%idomain(3) = 3
151  particle%iboundary(3) = 4
152  inface = 0 ! want Domain(2) unchanged; Boundary(2) = 0
153  end select
154  case (4)
155  select case (isc)
156  case (1)
157  ! -- N face, subcell 1 (cell face)
158  inface = 3 ! want Domain(2) = -Domain(2); Boundary(2) = inface
159  infaceoff = -1
160  case (2)
161  ! -- N face, subcell 2 --> S face, subcell 1 (cell interior)
162  particle%idomain(3) = 1
163  particle%iboundary(3) = 3
164  inface = 0 ! want Domain(2) unchanged; Boundary(2) = 0
165  case (3)
166  ! -- N face, subcell 3 --> S face, subcell 4 (cell interior)
167  particle%idomain(3) = 4
168  particle%iboundary(3) = 3
169  inface = 0 ! want Domain(2) unchanged; Boundary(2) = 0
170  case (4)
171  ! -- N face, subcell 4 (cell face)
172  inface = 2 ! want Domain(2) = -Domain(2); Boundary(2) = inface
173  infaceoff = 0
174  end select
175  case (5)
176  ! -- Subcell bottom (cell bottom)
177  inface = npolyverts + 2 ! want Domain(2) = -Domain(2); Boundary(2) = inface
178  case (6)
179  ! -- Subcell top (cell top)
180  inface = npolyverts + 3 ! want Domain(2) = -Domain(2); Boundary(2) = inface
181  end select
182 
183  if (inface .eq. -1) then
184  particle%iboundary(2) = 0
185  else if (inface .eq. 0) then
186  particle%iboundary(2) = 0
187  else
188  if ((inface .ge. 1) .and. (inface .le. 4)) then
189  ! -- Account for local cell rotation
190  inface = inface + cell%irvOrigin - 1
191  if (inface .gt. 4) inface = inface - 4
192  inface = cell%irectvert(inface) + infaceoff
193  if (inface .lt. 1) inface = inface + npolyverts
194  end if
195  particle%iboundary(2) = inface
196  end if
197  end select
198  end subroutine pass_mcpq
199 
200  !> @brief Solve the quad-rectangular cell via Pollock's method
201  subroutine apply_mcpq(this, particle, tmax)
202  ! -- dummy
203  class(methodcellpollockquadtype), intent(inout) :: this
204  type(particletype), pointer, intent(inout) :: particle
205  real(DP), intent(in) :: tmax
206  ! -- local
207  double precision :: xOrigin, yOrigin, zOrigin, sinrot, cosrot
208 
209  select type (cell => this%cell)
210  type is (cellrectquadtype)
211  ! -- Update particle state, terminate early if done advancing
212  call this%update(particle, cell%defn)
213  if (.not. particle%advancing) return
214 
215  ! -- If the particle is above the top of the cell (which is presumed to
216  ! -- represent a water table above the cell bottom), pass the particle
217  ! -- vertically and instantaneously to the cell top elevation and save
218  ! -- the particle state to output file(s).
219  if (particle%z > cell%defn%top) then
220  particle%z = cell%defn%top
221  call this%save(particle, reason=1) ! reason=1: cell transition
222  end if
223 
224  ! -- Transform particle location into local cell coordinates,
225  ! translated and rotated but not scaled relative to model.
226  ! Then track particle, transform back to model coordinates,
227  ! and reset transformation (drop accumulated roundoff error)
228  xorigin = cell%xOrigin
229  yorigin = cell%yOrigin
230  zorigin = cell%zOrigin
231  sinrot = cell%sinrot
232  cosrot = cell%cosrot
233  call particle%transform(xorigin, yorigin, zorigin, &
234  sinrot, cosrot)
235  call this%track(particle, 2, tmax)
236  call particle%transform(xorigin, yorigin, zorigin, &
237  sinrot, cosrot, invert=.true.)
238  call particle%transform(reset=.true.)
239  end select
240  end subroutine apply_mcpq
241 
242  !> @brief Load the rectangular subcell from the rectangular cell
243  subroutine load_subcell(this, particle, subcell)
244  ! -- dummy
245  class(methodcellpollockquadtype), intent(inout) :: this
246  type(particletype), pointer, intent(inout) :: particle
247  class(subcellrecttype), intent(inout) :: subcell
248  ! -- local
249  real(DP) :: dx, dy, dz, areax, areay, areaz
250  real(DP) :: dxprel, dyprel
251  integer(I4B) :: isc, npolyverts, m1, m2
252  real(DP) :: qextl1, qextl2, qintl1, qintl2
253  real(DP) :: factor, term
254 
255  select type (cell => this%cell)
256  type is (cellrectquadtype)
257  factor = done / cell%defn%retfactor
258  factor = factor / cell%defn%porosity
259  npolyverts = cell%defn%npolyverts
260 
261  isc = particle%idomain(3)
262  ! -- Subcells 1, 2, 3, and 4 are Pollock's subcells A, B, C, and D,
263  ! -- respectively
264 
265  dx = cell%dx
266  dy = cell%dy
267  ! -- If not already known, determine subcell number
268  if (isc .le. 0) then
269  dxprel = particle%x / dx
270  dyprel = particle%y / dy
271 
272  if (dyprel .ge. 5d-1) then
273  if (dxprel .le. 5d-1) then
274  isc = 4
275  else
276  isc = 1
277  end if
278  else
279  if (dxprel .le. 5d-1) then
280  isc = 3
281  else
282  isc = 2
283  end if
284  end if
285 
286  subcell%isubcell = isc
287  particle%idomain(3) = isc
288  end if
289  dx = 5d-1 * dx
290  dy = 5d-1 * dy
291  dz = cell%defn%top - &
292  cell%defn%bot
293  areax = dy * dz
294  areay = dx * dz
295  areaz = dx * dy
296  qintl1 = cell%qintl(isc)
297  ! qintl list wraps around, so isc+1=5 is ok
298  qintl2 = cell%qintl(isc + 1)
299  qextl1 = cell%qextl1(isc)
300  qextl2 = cell%qextl2(isc)
301  !
302  subcell%dx = dx
303  subcell%dy = dy
304  subcell%dz = dz
305  subcell%sinrot = dzero
306  subcell%cosrot = done
307  subcell%zOrigin = dzero
308  select case (isc)
309  case (1)
310  subcell%xOrigin = dx
311  subcell%yOrigin = dy
312  term = factor / areax
313  subcell%vx1 = qintl1 * term
314  subcell%vx2 = -qextl2 * term
315  term = factor / areay
316  subcell%vy1 = -qintl2 * term
317  subcell%vy2 = -qextl1 * term
318  case (2)
319  subcell%xOrigin = dx
320  subcell%yOrigin = dzero
321  term = factor / areax
322  subcell%vx1 = -qintl2 * term
323  subcell%vx2 = -qextl1 * term
324  term = factor / areay
325  subcell%vy1 = qextl2 * term
326  subcell%vy2 = -qintl1 * term
327  case (3)
328  subcell%xOrigin = dzero
329  subcell%yOrigin = dzero
330  term = factor / areax
331  subcell%vx1 = qextl2 * term
332  subcell%vx2 = -qintl1 * term
333  term = factor / areay
334  subcell%vy1 = qextl1 * term
335  subcell%vy2 = qintl2 * term
336  case (4)
337  subcell%xOrigin = dzero
338  subcell%yOrigin = dy
339  term = factor / areax
340  subcell%vx1 = qextl1 * term
341  subcell%vx2 = qintl2 * term
342  term = factor / areay
343  subcell%vy1 = qintl1 * term
344  subcell%vy2 = -qextl2 * term
345  end select
346  m1 = npolyverts + 2
347  m2 = m1 + 1
348  term = factor / areaz
349  subcell%vz1 = 2.5d-1 * cell%defn%faceflow(m1) * term
350  subcell%vz2 = -2.5d-1 * cell%defn%faceflow(m2) * term
351  end select
352  end subroutine load_subcell
353 
subroutine, public create_cell_rect_quad(cell)
Create a new rectangular-quad cell.
This module contains simulation constants.
Definition: Constants.f90:9
real(dp), parameter dzero
real constant zero
Definition: Constants.f90:65
real(dp), parameter done
real constant 1
Definition: Constants.f90:76
subroutine pstop(status, message)
Stop the program, optionally specifying an error status code.
Definition: ErrorUtil.f90:24
This module defines variable data types.
Definition: kind.f90:8
procedure subroutine, public create_method_cell_quad(method)
Create a new Pollock quad-refined cell method.
subroutine load_mcpq(this, particle, next_level, submethod)
Load subcell into tracking method.
subroutine pass_mcpq(this, particle)
Pass particle to next subcell if there is one, or to the cell face.
subroutine load_subcell(this, particle, subcell)
Load the rectangular subcell from the rectangular cell.
subroutine apply_mcpq(this, particle, tmax)
Solve the quad-rectangular cell via Pollock's method.
Particle tracking strategies.
Definition: Method.f90:2
Subcell-level tracking methods.
type(methodsubcellpollocktype), pointer, public method_subcell_plck
subroutine, public create_subcell_rect(subcell)
Create a new rectangular subcell.
Definition: SubcellRect.f90:28
Base grid cell definition.
Definition: CellDefn.f90:10
Base type for particle tracking methods.
Definition: Method.f90:29
Particle tracked by the PRT model.
Definition: Particle.f90:32
Manages particle track (i.e. pathline) files.
Definition: TrackData.f90:38