MODFLOW 6  version 6.5.0.dev2
MODFLOW 6 Code Documentation
methodcellternarymodule Module Reference

Data Types

type  methodcellternarytype
 

Functions/Subroutines

procedure subroutine, public create_method_cell_ternary (method)
 Create a tracking method. More...
 
subroutine destroy_mct (this)
 Destroy the tracking method. More...
 
subroutine load_mct (this, particle, next_level, submethod)
 Load subcell into tracking method. More...
 
subroutine pass_mct (this, particle)
 Pass particle to next subcell if there is one, or to the cell face. More...
 
subroutine apply_mct (this, particle, tmax)
 Apply the ternary method to a polygonal cell. More...
 
subroutine load_subcell (this, particle, subcell)
 Loads a triangular subcell from the polygonal cell. More...
 

Function/Subroutine Documentation

◆ apply_mct()

subroutine methodcellternarymodule::apply_mct ( class(methodcellternarytype), intent(inout)  this,
type(particletype), intent(inout), pointer  particle,
real(dp), intent(in)  tmax 
)
private

Definition at line 147 of file MethodCellTernary.f90.

148  use constantsmodule, only: dzero, done, dhalf
149  ! dummy
150  class(MethodCellTernaryType), intent(inout) :: this
151  type(ParticleType), pointer, intent(inout) :: particle
152  real(DP), intent(in) :: tmax
153  ! local
154  integer(I4B) :: npolyverts
155  integer(I4B) :: iv
156  integer(I4B) :: ivp1
157  integer(I4B) :: ivm1
158  real(DP) :: retfactor
159  real(DP) :: x0
160  real(DP) :: y0
161  real(DP) :: x1
162  real(DP) :: y1
163  real(DP) :: x2
164  real(DP) :: y2
165  real(DP) :: xsum
166  real(DP) :: ysum
167  real(DP) :: vxsum
168  real(DP) :: vysum
169  real(DP) :: flow0
170  real(DP) :: flow1
171  real(DP) :: v0x
172  real(DP) :: v0y
173  real(DP) :: d01x
174  real(DP) :: d01y
175  real(DP) :: d02x
176  real(DP) :: d02y
177  real(DP) :: det
178  real(DP) :: area
179  real(DP) :: term
180 
181  select type (cell => this%cell)
182  type is (cellpolytype)
183  ! -- Update particle state, checking whether any reporting or
184  ! -- termination conditions apply
185  call this%update(particle, cell%defn)
186 
187  ! -- Return early if particle is done advancing
188  if (.not. particle%advancing) return
189 
190  ! -- If the particle is above the top of the cell (presumed water table)
191  ! -- pass it vertically and instantaneously to the cell top and save the
192  ! -- particle state to file
193  if (particle%z > cell%defn%top) then
194  particle%z = cell%defn%top
195  call this%save(particle, reason=1) ! reason=1: cell transition
196  end if
197 
198  npolyverts = cell%defn%npolyverts
199  if (allocated(this%x_vert)) then
200  deallocate (this%x_vert)
201  deallocate (this%y_vert)
202  deallocate (this%vx_vert_polygon)
203  deallocate (this%vy_vert_polygon)
204  end if
205  allocate (this%x_vert(npolyverts))
206  allocate (this%y_vert(npolyverts))
207  allocate (this%vx_vert_polygon(npolyverts))
208  allocate (this%vy_vert_polygon(npolyverts))
209 
210  xsum = dzero
211  ysum = dzero
212  vxsum = dzero
213  vysum = dzero
214  area = dzero
215  this%ztop = cell%defn%top
216  this%zbot = cell%defn%bot
217  this%dz = this%ztop - this%zbot
218  do iv = 1, npolyverts
219  ivp1 = iv + 1
220  if (ivp1 .gt. npolyverts) ivp1 = 1
221  ivm1 = iv - 1
222  if (ivm1 .lt. 1) ivm1 = npolyverts
223  x0 = cell%defn%polyvert(1, iv)
224  y0 = cell%defn%polyvert(2, iv)
225  x2 = cell%defn%polyvert(1, ivp1)
226  y2 = cell%defn%polyvert(2, ivp1)
227  x1 = cell%defn%polyvert(1, ivm1)
228  y1 = cell%defn%polyvert(2, ivm1)
229  term = done / (cell%defn%porosity * this%dz)
230  flow0 = cell%defn%faceflow(iv) * term
231  flow1 = cell%defn%faceflow(ivm1) * term
232  d01x = x1 - x0 ! kluge note: do this more efficiently, not recomputing things so much???
233  d01y = y1 - y0
234  d02x = x2 - x0
235  d02y = y2 - y0
236  ! kluge note: can det ever be zero, like maybe for a 180-deg vertex???
237  ! oodet = DONE/(d01y*d02x - d02y*d01x)
238  ! velmult = particle%velmult
239  ! kluge note: "flow" is volumetric (face) flow rate per unit thickness, divided by porosity
240  ! v0x = -velmult*oodet*(d02x*flow1 + d01x*flow0)
241  ! v0y = -velmult*oodet*(d02y*flow1 + d01y*flow0) !
242  det = d01y * d02x - d02y * d01x
243  retfactor = cell%defn%retfactor
244  ! kluge note: can det ever be zero, like maybe for a 180-deg vertex???
245  ! term = velfactor/det
246  ! kluge note: can det ever be zero, like maybe for a 180-deg vertex???
247  term = done / (retfactor * det)
248  ! kluge note: "flow" here is volumetric flow rate (MODFLOW face flow)
249  v0x = -term * (d02x * flow1 + d01x * flow0)
250  ! per unit thickness, divided by porosity
251  v0y = -term * (d02y * flow1 + d01y * flow0)
252  this%vx_vert_polygon(iv) = v0x
253  this%vy_vert_polygon(iv) = v0y
254  xsum = xsum + x0
255  ysum = ysum + y0
256  vxsum = vxsum + v0x
257  vysum = vysum + v0y
258  this%x_vert(iv) = x0
259  this%y_vert(iv) = y0
260  area = area + x0 * y1 - x1 * y0
261  end do
262  area = area * dhalf
263  term = done / (retfactor * cell%defn%porosity * area)
264  this%vzbot = cell%defn%faceflow(npolyverts + 2) * term
265  this%vztop = -cell%defn%faceflow(npolyverts + 3) * term
266  this%xctr = xsum / dble(npolyverts)
267  this%yctr = ysum / dble(npolyverts)
268  this%vxctr = vxsum / dble(npolyverts)
269  this%vyctr = vysum / dble(npolyverts)
270 
271  ! -- Track across subcells
272  call this%track(particle, 2, tmax) ! kluge, hardwired to level 2
273  end select
This module contains simulation constants.
Definition: Constants.f90:9
real(dp), parameter dhalf
real constant 1/2
Definition: Constants.f90:67
real(dp), parameter dzero
real constant zero
Definition: Constants.f90:64
real(dp), parameter done
real constant 1
Definition: Constants.f90:75

◆ create_method_cell_ternary()

procedure subroutine, public methodcellternarymodule::create_method_cell_ternary ( type(methodcellternarytype), pointer  method)

Definition at line 45 of file MethodCellTernary.f90.

46  ! -- dummy
47  type(MethodCellTernaryType), pointer :: method
48  ! -- local
49  type(CellPolyType), pointer :: cell
50  type(SubcellTriType), pointer :: subcell
51 
52  allocate (method)
53  allocate (method%zeromethod)
54  call create_cell_poly(cell)
55  method%cell => cell
56  method%type => method%cell%type
57  method%delegates = .true.
58  call create_subcell_tri(subcell)
59  method%subcell => subcell
60  method%zeromethod = 0
Here is the call graph for this function:
Here is the caller graph for this function:

◆ destroy_mct()

subroutine methodcellternarymodule::destroy_mct ( class(methodcellternarytype), intent(inout)  this)
private

Definition at line 64 of file MethodCellTernary.f90.

65  class(MethodCellTernaryType), intent(inout) :: this
66  deallocate (this%type)

◆ load_mct()

subroutine methodcellternarymodule::load_mct ( class(methodcellternarytype), intent(inout)  this,
type(particletype), intent(inout), pointer  particle,
integer(i4b), intent(in)  next_level,
class(methodtype), intent(inout), pointer  submethod 
)
private

Definition at line 70 of file MethodCellTernary.f90.

71  ! -- dummy
72  class(MethodCellTernaryType), intent(inout) :: this
73  type(ParticleType), pointer, intent(inout) :: particle
74  integer(I4B), intent(in) :: next_level
75  class(MethodType), pointer, intent(inout) :: submethod
76 
77  select type (subcell => this%subcell)
78  type is (subcelltritype)
79  call this%load_subcell(particle, subcell)
80  end select
81  call method_subcell_tern%init( &
82  cell=this%cell, &
83  subcell=this%subcell, &
84  trackfilectl=this%trackfilectl, &
85  tracktimes=this%tracktimes)
86  submethod => method_subcell_tern
87  method_subcell_tern%zeromethod = this%zeromethod

◆ load_subcell()

subroutine methodcellternarymodule::load_subcell ( class(methodcellternarytype), intent(inout)  this,
type(particletype), intent(inout), pointer  particle,
class(subcelltritype), intent(inout)  subcell 
)

Definition at line 277 of file MethodCellTernary.f90.

278  ! -- modules
280  ! -- dummy
281  class(MethodCellTernaryType), intent(inout) :: this
282  type(ParticleType), pointer, intent(inout) :: particle
283  class(SubcellTriType), intent(inout) :: subcell
284  ! -- local
285  integer(I4B) :: ic
286  integer(I4B) :: isc
287  integer(I4B) :: npolyverts
288  integer(I4B) :: iv0
289  integer(I4B) :: iv1
290  integer(I4B) :: ipv0
291  integer(I4B) :: ipv1
292  integer(I4B) :: iv
293  real(DP) :: x0
294  real(DP) :: y0
295  real(DP) :: x1
296  real(DP) :: y1
297  real(DP) :: x2
298  real(DP) :: y2
299  real(DP) :: x1rel
300  real(DP) :: y1rel
301  real(DP) :: x2rel
302  real(DP) :: y2rel
303  real(DP) :: xi
304  real(DP) :: yi
305  real(DP) :: di2
306  real(DP) :: d02
307  real(DP) :: d12
308  real(DP) :: di1
309  real(DP) :: d01
310  real(DP) :: alphai
311  real(DP) :: betai
312  real(DP) :: betatol
313 
314  select type (cell => this%cell)
315  type is (cellpolytype)
316  ic = cell%defn%icell
317  subcell%icell = ic
318  isc = particle%idomain(3)
319  npolyverts = cell%defn%npolyverts
320  if (isc .le. 0) then
321  xi = particle%x
322  yi = particle%y
323  do iv = 1, npolyverts
324  iv0 = iv
325  iv1 = iv + 1
326  if (iv1 .gt. npolyverts) iv1 = 1
327  ipv0 = iv0
328  ipv1 = iv1
329  x0 = this%x_vert(ipv0)
330  y0 = this%y_vert(ipv0)
331  x1 = this%x_vert(ipv1)
332  y1 = this%y_vert(ipv1)
333  x2 = this%xctr
334  y2 = this%yctr
335  x1rel = x1 - x0
336  y1rel = y1 - y0
337  x2rel = x2 - x0
338  y2rel = y2 - y0
339  di2 = xi * y2rel - yi * x2rel
340  d02 = x0 * y2rel - y0 * x2rel
341  d12 = x1rel * y2rel - y1rel * x2rel
342  di1 = xi * y1rel - yi * x1rel
343  d01 = x0 * y1rel - y0 * x1rel
344  alphai = (di2 - d02) / d12
345  betai = -(di1 - d01) / d12
346  ! kluge note: can iboundary(2) be used to identify the subcell?
347  betatol = -1e-7 ! kluge
348  ! kluge note: think this handles points on triangle boundaries ok
349  if ((alphai .ge. 0d0) .and. &
350  (betai .ge. betatol) .and. &
351  (alphai + betai .le. 1d0)) then
352  isc = iv ! but maybe not!!!!!!!!!!!!
353  exit ! kluge note: doesn't handle particle smack on cell center
354  end if
355  end do
356  if (isc .le. 0) then
357  print *, "error -- initial triangle not found for particle ", &
358  get_particle_id(particle), " in cell ", ic
359  call pstop(1)
360  else
361  ! subcellTri%isubcell = isc
362  ! kluge note: as a matter of form, do we want to allow
363  ! this subroutine to modify the particle???
364  particle%idomain(3) = isc
365  end if
366  end if
367  subcell%isubcell = isc
368 
369  ! -- Set coordinates and velocities at vertices of triangular subcell
370  iv0 = isc
371  iv1 = isc + 1
372  if (iv1 .gt. npolyverts) iv1 = 1
373  ipv0 = iv0
374  ipv1 = iv1
375  subcell%x0 = this%x_vert(ipv0)
376  subcell%y0 = this%y_vert(ipv0)
377  subcell%x1 = this%x_vert(ipv1)
378  subcell%y1 = this%y_vert(ipv1)
379  subcell%x2 = this%xctr
380  subcell%y2 = this%yctr
381  subcell%v0x = this%vx_vert_polygon(iv0)
382  subcell%v0y = this%vy_vert_polygon(iv0)
383  subcell%v1x = this%vx_vert_polygon(iv1)
384  subcell%v1y = this%vy_vert_polygon(iv1)
385  subcell%v2x = this%vxctr
386  subcell%v2y = this%vyctr
387  subcell%ztop = this%ztop
388  subcell%zbot = this%zbot
389  subcell%dz = this%dz
390  subcell%vzbot = this%vzbot
391  subcell%vztop = this%vztop
392  end select
pure character(len=lenmempath) function, public get_particle_id(particle)
Return the particle's composite ID.
Definition: Particle.f90:354
Here is the call graph for this function:

◆ pass_mct()

subroutine methodcellternarymodule::pass_mct ( class(methodcellternarytype), intent(inout)  this,
type(particletype), intent(inout), pointer  particle 
)
private

Definition at line 91 of file MethodCellTernary.f90.

92  ! -- dummy
93  class(MethodCellTernaryType), intent(inout) :: this
94  type(ParticleType), pointer, intent(inout) :: particle
95  ! local
96  integer(I4B) :: isc
97  integer(I4B) :: exitFace
98  integer(I4B) :: inface
99  integer(I4B) :: npolyverts
100 
101  exitface = particle%iboundary(3)
102  isc = particle%idomain(3)
103  select type (cell => this%cell)
104  type is (cellpolytype)
105  npolyverts = cell%defn%npolyverts
106  end select
107 
108  select case (exitface)
109  case (0)
110  ! -- Subcell interior (cell interior)
111  inface = -1
112  case (1)
113  ! -- Subcell face 1 (cell face)
114  inface = isc
115  if (inface .eq. 0) inface = npolyverts
116  case (2)
117  ! -- Subcell face --> next subcell in "cycle" (cell interior)
118  isc = isc + 1
119  if (isc .gt. npolyverts) isc = 1
120  particle%idomain(3) = isc
121  particle%iboundary(3) = 3
122  inface = 0
123  case (3)
124  ! -- Subcell face --> preceding subcell in "cycle" (cell interior)
125  isc = isc - 1
126  if (isc .lt. 1) isc = npolyverts
127  particle%idomain(3) = isc
128  particle%iboundary(3) = 2
129  inface = 0
130  case (4)
131  ! -- Subcell bottom (cell bottom)
132  inface = npolyverts + 2
133  case (5)
134  ! -- Subcell top (cell top)
135  inface = npolyverts + 3
136  end select
137  if (inface .eq. -1) then
138  particle%iboundary(2) = 0
139  else if (inface .eq. 0) then
140  particle%iboundary(2) = 0
141  else
142  particle%iboundary(2) = inface
143  end if