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

Functions/Subroutines

subroutine, public traverse_triangle (isolv, tol, step, texit, alpexit, betexit, itrifaceenter, itrifaceexit, rxx, rxy, ryx, ryy, alp0, bet0, alp1, bet1, alp2, bet2, alpi, beti, vziodz, az, bary)
 Traverse triangular cell. More...
 
subroutine, public canonical (x0, y0, x1, y1, x2, y2, v0x, v0y, v1x, v1y, v2x, v2y, xi, yi, rxx, rxy, ryx, ryy, sxx, sxy, syy, alp0, bet0, alp1, bet1, alp2, bet2, alpi, beti, bary)
 Set coordinates to "canonical" configuration. More...
 
subroutine, public get_w (alp1, bet1, alp2, bet2, waa, wab, wba, wbb, bary)
 Compute elements of W matrix. More...
 
subroutine, public solve_coefs (alpi, beti)
 Compute analytical solution coefficients depending on case. More...
 
subroutine, public step_analytical (t, alp, bet)
 Step (evaluate) analytically depending on case. More...
 
subroutine, public step_euler (nt, step, vziodz, az, alpi, beti, t, alp, bet)
 Step (evaluate) numerically depending in case. More...
 
subroutine, public find_exit_bary (isolv, itriface, itrifaceenter, alpi, beti, tol, step, vziodz, az, texit, alpexit, betexit)
 Find the exit time and location in barycentric coordinates. More...
 
real(dp) function fbary1 (bet)
 Brent's method applied to canonical face 1 (gamma = 0) More...
 
real(dp) function fbary2 (bet)
 Brent's method applied to canonical face 2 (alpha = 0) More...
 
subroutine, public get_t_alpt (bet, t, alp)
 Given beta evaluate t and alpha depending on case. More...
 
subroutine, public get_bet_outflow_bary (vn1, vn2, betoutlo, betouthi)
 Find outflow interval. More...
 
subroutine, public get_bet_soln_limits (beti, betsollo, betsolhi, ibettrend)
 Find trend of and limits on beta from beta{t} solution. More...
 
subroutine, public soln_brent (itriface, betlo, bethi, tol, texit, alpexit, betexit)
 Use Brent's method with initial bounds on beta of betlo and bethi. More...
 
subroutine, public soln_chand (itriface, betlo, bethi, tol, texit, alpexit, betexit)
 Use Chandrupatla's method with initial bounds on beta of betlo and bethi. More...
 
subroutine, public soln_test (itriface, betlo, bethi, tol, texit, alpexit, betexit)
 Use a test method with initial bounds on beta of betlo and bethi. More...
 
subroutine, public soln_euler (itriface, alpi, beti, step, vziodz, az, texit, alpexit, betexit)
 Use Euler integration to find exit. More...
 

Variables

real(dp) ca1
 
real(dp) ca2
 
real(dp) ca3
 
real(dp) cb1
 
real(dp) cb2
 Analytical solution coefficients. More...
 
real(dp) waa
 
real(dp) wab
 
real(dp) wba
 
real(dp) wbb
 Elements of the "velocity matrix," W. More...
 
real(dp), dimension(2) cv0
 
real(dp), dimension(2) cv1
 
real(dp), dimension(2) cv2
 "Canonical" velocity components at corners of triangular subcell More...
 
integer(i4b) icase
 Case index for analytical solution. More...
 

Function/Subroutine Documentation

◆ canonical()

subroutine, public ternarysolvetrack::canonical ( real(dp)  x0,
real(dp)  y0,
real(dp)  x1,
real(dp)  y1,
real(dp)  x2,
real(dp)  y2,
real(dp)  v0x,
real(dp)  v0y,
real(dp)  v1x,
real(dp)  v1y,
real(dp)  v2x,
real(dp)  v2y,
real(dp)  xi,
real(dp)  yi,
real(dp)  rxx,
real(dp)  rxy,
real(dp)  ryx,
real(dp)  ryy,
real(dp), intent(inout)  sxx,
real(dp), intent(inout)  sxy,
real(dp), intent(inout)  syy,
real(dp)  alp0,
real(dp)  bet0,
real(dp)  alp1,
real(dp)  bet1,
real(dp)  alp2,
real(dp)  bet2,
real(dp)  alpi,
real(dp)  beti,
logical(lgp), intent(in)  bary 
)
Parameters
ryyrotation matrix
[in,out]syyskew matrix entries (top left, top right, bottom right)
betialpha and beta coefficients
[in]barywhether to use barycentric coordinates

Definition at line 117 of file TernarySolveTrack.f90.

124  ! -- dummy
125  real(DP) :: x0
126  real(DP) :: y0
127  real(DP) :: x1
128  real(DP) :: y1
129  real(DP) :: x2
130  real(DP) :: y2
131  real(DP) :: v0x
132  real(DP) :: v0y
133  real(DP) :: v1x
134  real(DP) :: v1y
135  real(DP) :: v2x
136  real(DP) :: v2y
137  real(DP) :: xi
138  real(DP) :: yi
139  real(DP) :: rxx
140  real(DP) :: rxy
141  real(DP) :: ryx
142  real(DP) :: ryy !< rotation matrix
143  real(DP), intent(inout) :: sxx, sxy, syy !< skew matrix entries (top left, top right, bottom right)
144  real(DP) :: alp0
145  real(DP) :: bet0
146  real(DP) :: alp1
147  real(DP) :: bet1
148  real(DP) :: alp2
149  real(DP) :: bet2
150  real(DP) :: alpi
151  real(DP) :: beti !< alpha and beta coefficients
152  logical(LGP), intent(in) :: bary !< whether to use barycentric coordinates
153  ! -- local
154  real(DP) :: baselen
155  real(DP) :: oobaselen
156  real(DP) :: sinomega
157  real(DP) :: cosomega
158  real(DP) :: x1diff
159  real(DP) :: y1diff
160  real(DP) :: x2diff
161  real(DP) :: y2diff
162  real(DP) :: xidiff
163  real(DP) :: yidiff
164  real(DP) :: rot(2, 2), res(2)
165 
166  ! -- Translate and rotate coordinates to "canonical" configuration
167  x1diff = x1 - x0
168  y1diff = y1 - y0
169  x2diff = x2 - x0
170  y2diff = y2 - y0
171  baselen = dsqrt(x1diff * x1diff + y1diff * y1diff)
172  oobaselen = 1d0 / baselen
173  cosomega = x1diff * oobaselen
174  sinomega = y1diff * oobaselen
175  rxx = cosomega
176  rxy = sinomega
177  ryx = -sinomega
178  ryy = cosomega
179  alp0 = 0d0
180  bet0 = 0d0
181  alp1 = baselen
182  bet1 = 0d0
183 
184  rot = reshape((/rxx, ryx, rxy, ryy/), shape(rot))
185  res = matmul(rot, (/x2diff, y2diff/))
186  alp2 = res(1)
187  bet2 = res(2)
188 
189  cv0 = matmul(rot, (/v0x, v0y/))
190  cv1 = matmul(rot, (/v1x, v1y/))
191  cv2 = matmul(rot, (/v2x, v2y/))
192 
193  xidiff = xi - x0
194  yidiff = yi - y0
195  res = matmul(rot, (/xidiff, yidiff/))
196  alpi = res(1)
197  beti = res(2)
198 
199  if (bary) then
200  sxx = 1d0 / alp1
201  syy = 1d0 / bet2
202  sxy = -alp2 * sxx * syy
203  alp1 = 1d0
204  alp2 = 0d0
205  bet2 = 1d0
206  cv0 = skew(cv0, (/sxx, sxy, syy/))
207  cv1 = skew(cv1, (/sxx, sxy, syy/))
208  cv2 = skew(cv2, (/sxx, sxy, syy/))
209  res = (/alpi, beti/)
210  res = skew(res, (/sxx, sxy, syy/))
211  alpi = res(1)
212  beti = res(2)
213  end if
214 
Here is the call graph for this function:
Here is the caller graph for this function:

◆ fbary1()

real(dp) function ternarysolvetrack::fbary1 ( real(dp), intent(in)  bet)
private

Definition at line 634 of file TernarySolveTrack.f90.

635  ! -- dummy
636  real(DP), intent(in) :: bet
637  real(DP) :: fb
638  ! -- local
639  real(DP) :: t
640  real(DP) :: alpt
641 
642  ! -- Evaluate gamma{t{beta}} = 1. - alpha{t{beta}} - beta
643  call get_t_alpt(bet, t, alpt)
644  fb = 1d0 - alpt - bet
Here is the call graph for this function:
Here is the caller graph for this function:

◆ fbary2()

real(dp) function ternarysolvetrack::fbary2 ( real(dp), intent(in)  bet)
private

Definition at line 648 of file TernarySolveTrack.f90.

649  ! -- dummy
650  real(DP), intent(in) :: bet
651  real(DP) :: fb
652  ! -- local
653  real(DP) :: t
654  real(DP) :: alpt
655 
656  ! -- Evaluate alpha{t{beta}}
657  call get_t_alpt(bet, t, alpt)
658  fb = alpt
Here is the call graph for this function:
Here is the caller graph for this function:

◆ find_exit_bary()

subroutine, public ternarysolvetrack::find_exit_bary ( integer(i4b)  isolv,
integer(i4b)  itriface,
integer(i4b)  itrifaceenter,
real(dp)  alpi,
real(dp)  beti,
real(dp)  tol,
real(dp)  step,
real(dp)  vziodz,
real(dp)  az,
real(dp)  texit,
real(dp)  alpexit,
real(dp)  betexit 
)

Definition at line 443 of file TernarySolveTrack.f90.

447  ! -- dummy
448  integer(I4B) :: isolv
449  integer(I4B) :: itriface
450  integer(I4B) :: itrifaceenter
451  real(DP) :: alpi
452  real(DP) :: beti
453  real(DP) :: tol
454  real(DP) :: step
455  real(DP) :: vziodz
456  real(DP) :: az
457  real(DP) :: texit
458  real(DP) :: alpexit
459  real(DP) :: betexit
460  ! -- local
461  real(DP) :: alplo
462  real(DP) :: alphi
463  real(DP) :: alpt
464  real(DP) :: alplim
465  real(DP) :: fax
466  real(DP) :: fbx
467  real(DP) :: t
468  real(DP) :: tlo
469  real(DP) :: thi
470  real(DP) :: v0alpstar
471  real(DP) :: valpi
472  real(DP) :: v1n
473  real(DP) :: v2n
474  real(DP) :: vbeti
475  real(DP) :: zerotol
476  real(DP) :: betlo
477  real(DP) :: bethi
478  real(DP) :: betsollo
479  real(DP) :: betsolhi
480  real(DP) :: betoutlo
481  real(DP) :: betouthi
482  integer(I4B) :: ibettrend
483 
484  ! -- Use iterative scheme or numerical integration indicated by isolv.
485  zerotol = 1d-10 ! kluge
486  if (itriface .eq. 0) then
487  ! -- Checking for exit on canonical face 0 (beta = 0)
488  if (itrifaceenter .eq. 0) then
489  ! -- Entrance face, so no exit. (Normal velocity is uniform along face 0,
490  ! -- so it cannot be both an entrance and an exit.)
491  texit = huge(1d0)
492  else
493  ! -- Not the entrance face, so check for outflow
494  if (cv0(2) .ge. 0d0) then
495  ! -- Inflow or no flow, so no exit
496  texit = huge(1d0)
497  else
498  ! -- Outflow, so check beta-velocity at the initial location,
499  ! -- recognizing that it will never change sign along the
500  ! -- trajectory (and will not be blocked from zero by an asymptote)
501  vbeti = cv0(2) + wbb * beti
502  if (vbeti .ge. 0d0) then
503  ! -- Can't exit along beta = 0
504  texit = huge(1d0)
505  else
506  ! -- get alpt and check it
507  call get_t_alpt(0d0, t, alpt)
508  if ((alpt .ge. 0d0) .and. (alpt .le. 1d0)) then
509  ! -- alpt within the edge, so exit found
510  texit = t
511  alpexit = alpt
512  betexit = 0d0
513  else
514  ! -- alpt not within the edge, so not an exit
515  texit = huge(1d0)
516  end if
517  end if
518  end if
519  end if
520  ! -- End canonical face 0 (beta = 0)
521  else
522  ! -- Checking for exit on canonical face 1 (gamma = 0.) or 2 (alpha = 0.)
523  if (itriface .eq. 1) then
524  ! -- Normal velocities (gamma components) at ends of canonical face 1
525  v1n = -cv1(1) - cv1(2)
526  v2n = -cv2(1) - cv2(2)
527  else
528  ! -- Normal velocities (alpha components) at ends of canonical face 2
529  v1n = cv0(1)
530  v2n = cv2(1)
531  end if
532  if ((v1n .ge. 0d0) .and. (v2n .ge. 0d0)) then
533  ! -- No outflow at vn1 and vn2 corners; no outflow interval, so no exit.
534  texit = huge(1d0)
535  else
536  ! -- Find outflow interval
537  call get_bet_outflow_bary(v1n, v2n, betoutlo, betouthi)
538  ! -- Find trend of and limits on beta from beta{t} solution
539  call get_bet_soln_limits(beti, betsollo, betsolhi, ibettrend)
540  ! -- Look for exit
541  if (ibettrend .eq. 0) then
542  ! -- Beta is constant, so check if it's within the outflow interval;
543  ! -- if not, no exit; if so, solve for t and alpha
544  if ((beti .gt. betouthi) .or. (beti .lt. betoutlo)) then
545  texit = huge(1d0)
546  else
547  ! -- Check alpha-velocity at the initial location,
548  ! -- recognizing that it will never change sign along the
549  ! -- trajectory (and will not be blocked from zero by an asymptote)
550  ! -- in this special case
551  v0alpstar = cv0(1) + wab * beti
552  valpi = v0alpstar + waa * alpi
553  if ((itriface .eq. 1) .and. (valpi .le. 0d0)) then
554  ! -- Can't exit along gamma = 0.
555  texit = huge(1d0)
556  else if ((itriface .eq. 2) .and. (valpi .ge. 0d0)) then
557  ! -- Can't exit along alpha = 0.
558  texit = huge(1d0)
559  else
560  ! -- get exit
561  if (itriface .eq. 1) then
562  alpexit = 1d0 - beti
563  else
564  alpexit = 0d0
565  end if ! kluge note: seems like in this case (beta=const) this
566  betexit = beti ! must be the ONLY exit; no need to check other edges??
567  if (waa .ne. 0d0) then
568  alplim = -v0alpstar / waa
569  texit = dlog(alpexit - alplim / (alpi - alplim)) / waa
570  else
571  texit = (alpexit - alpi) / v0alpstar
572  end if
573  end if
574  end if
575  ! -- End constant-beta case
576  else
577  ! -- Beta varies along trajectory; combine outflow and soln limits on beta
578  bethi = min(betouthi, betsolhi)
579  betlo = max(betoutlo, betsollo)
580  if (betlo .ge. bethi) then
581  ! -- If bounds on bet leave no feasible interval, no exit
582  texit = huge(1d0)
583  else
584  ! -- Check sign of function value at beta bounds
585  call get_t_alpt(bethi, thi, alphi)
586  call get_t_alpt(betlo, tlo, alplo)
587  if (itriface .eq. 1) then
588  fax = 1d0 - betlo - alplo
589  fbx = 1d0 - bethi - alphi
590  else
591  fax = alplo
592  fbx = alphi
593  end if
594  if (fax * fbx .gt. 0d0) then
595  ! -- Root not bracketed; no exit
596  texit = huge(1d0)
597  else
598  if (isolv .eq. 0) then
599  ! -- Use Euler integration to find exit
600  call soln_euler(itriface, alpi, beti, step, vziodz, az, &
601  texit, alpexit, betexit)
602  else if (isolv .eq. 1) then
603  ! -- Use Brent's method with initial bounds on beta of betlo and bethi,
604  ! -- assuming they bound the root
605  call soln_brent(itriface, betlo, bethi, tol, texit, &
606  alpexit, betexit)
607  else if (isolv .eq. 2) then
608  ! -- Use Chandrupatla's method with initial bounds on beta of betlo and bethi,
609  ! -- assuming they bound the root
610  call soln_chand(itriface, betlo, bethi, tol, texit, &
611  alpexit, betexit)
612  else if (isolv .eq. 3) then
613  ! -- Use a test method with initial bounds on beta of betlo and bethi,
614  ! -- assuming they bound the root
615  call soln_test(itriface, betlo, bethi, tol, texit, &
616  alpexit, betexit)
617  else
618  call pstop(1, "Invalid isolv, expected 0, 1, 2, or 3")
619  end if
620  end if
621  end if
622  ! -- End variable-beta case
623  end if
624  end if
625  ! -- End canonical face 1 (gamma = 0.) or 2 (alpha = 0.)
626  end if
627 
628  if (texit .ne. huge(1d0) .and. texit .lt. 0d0) &
629  call pstop(1, "texit is negative (unexpected)") ! shouldn't get here
630 
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_bet_outflow_bary()

subroutine, public ternarysolvetrack::get_bet_outflow_bary ( real(dp)  vn1,
real(dp)  vn2,
real(dp)  betoutlo,
real(dp)  betouthi 
)

Definition at line 697 of file TernarySolveTrack.f90.

698  ! -- dummy
699  real(DP) :: vn1
700  real(DP) :: vn2
701  real(DP) :: betoutlo
702  real(DP) :: betouthi
703  ! -- local
704  real(DP) :: vndiff
705 
706  vndiff = vn2 - vn1
707  if (vn1 .lt. 0d0) then
708  ! -- Outflow at vn1 corner
709  betoutlo = 0d0
710  if (vn2 .le. 0d0) then
711  ! -- Outflow along entire edge (except possibly no-flow right at vn2 corner)
712  betouthi = 1d0
713  else
714  ! -- Outflow along part of edge
715  betouthi = -vn1 / vndiff
716  end if
717  else
718  ! -- Outflow at vn2 corner
719  betouthi = 1d0
720  if (vn1 .le. 0d0) then
721  ! -- Outflow along entire edge (except possibly no-flow right at vn1 corner)
722  betoutlo = 0d0
723  else
724  ! -- Outflow along part of edge
725  betoutlo = -vn1 / vndiff
726  end if
727  end if
728 
Here is the caller graph for this function:

◆ get_bet_soln_limits()

subroutine, public ternarysolvetrack::get_bet_soln_limits ( real(dp), intent(in)  beti,
real(dp)  betsollo,
real(dp)  betsolhi,
integer(i4b), intent(inout)  ibettrend 
)

Definition at line 732 of file TernarySolveTrack.f90.

733  ! -- dummy
734  real(DP), intent(in) :: beti
735  real(DP) :: betsollo
736  real(DP) :: betsolhi
737  integer(I4B), intent(inout) :: ibettrend
738  ! -- local
739  real(DP) :: betlim
740 
741  if (wbb .gt. 0d0) then
742  betlim = -cv0(2) / wbb
743  if (beti .gt. betlim) then
744  betsolhi = huge(1d0)
745  betsollo = beti
746  ibettrend = 1
747  else if (beti .lt. betlim) then
748  betsolhi = beti
749  betsollo = -huge(1d0)
750  ibettrend = -1
751  else
752  betsolhi = beti
753  betsollo = beti
754  ibettrend = 0
755  end if
756  else if (wbb .lt. 0d0) then
757  betlim = -cv0(2) / wbb
758  if (beti .gt. betlim) then
759  betsolhi = beti
760  betsollo = betlim
761  ibettrend = -1
762  else if (beti .lt. betlim) then
763  betsolhi = betlim
764  betsollo = beti
765  ibettrend = 1
766  else
767  betsolhi = beti
768  betsollo = beti
769  ibettrend = 0
770  end if
771  else ! kluge note: use zerotol and elsewhere?
772  if (cv0(2) .gt. 0d0) then
773  betsolhi = huge(1d0)
774  betsollo = beti
775  ibettrend = 1
776  else if (cv0(2) .lt. 0d0) then
777  betsolhi = beti
778  betsollo = -huge(1d0)
779  ibettrend = -1
780  else
781  betsolhi = beti
782  betsollo = beti
783  ibettrend = 0
784  end if
785  end if
786 
Here is the caller graph for this function:

◆ get_t_alpt()

subroutine, public ternarysolvetrack::get_t_alpt ( real(dp), intent(in)  bet,
real(dp)  t,
real(dp)  alp 
)

Definition at line 662 of file TernarySolveTrack.f90.

663  ! -- dummy
664  real(DP), intent(in) :: bet
665  real(DP) :: t
666  real(DP) :: alp
667  ! -- local
668  real(DP) :: term
669  real(DP) :: zerotol
670 
671  ! kluge note: assumes cb2<>0, wbb<>0 as appropriate
672  zerotol = 1d-10 ! kluge
673  term = (bet - cb1) / cb2
674  if (icase .eq. 1) then
675  term = max(term, zerotol)
676  t = dlog(term) / wbb
677  alp = ca1 + ca2 * dexp(waa * t) + ca3 * dexp(wbb * t)
678  else if (icase .eq. -1) then
679  term = max(term, zerotol)
680  t = dlog(term) / wbb
681  alp = ca1 + (ca2 + ca3 * t) * dexp(waa * t)
682  else if (icase .eq. 2) then
683  term = max(term, zerotol)
684  t = dlog(term) / wbb
685  alp = ca1 + ca2 * t + ca3 * dexp(wbb * t)
686  else if (icase .eq. 3) then
687  t = term
688  alp = ca1 + ca2 * t + ca3 * dexp(waa * t)
689  else if (icase .eq. 4) then
690  t = term
691  alp = ca1 + (ca2 + ca3 * t) * t
692  end if
693 
Here is the caller graph for this function:

◆ get_w()

subroutine, public ternarysolvetrack::get_w ( real(dp)  alp1,
real(dp)  bet1,
real(dp)  alp2,
real(dp)  bet2,
real(dp)  waa,
real(dp)  wab,
real(dp)  wba,
real(dp)  wbb,
logical(lgp), intent(in), optional  bary 
)
Parameters
bet2triangle face points
wbbw matrix
[in]barybarycentric coordinates

Definition at line 218 of file TernarySolveTrack.f90.

222  ! -- dummy
223  real(DP) :: alp1
224  real(DP) :: bet1
225  real(DP) :: alp2
226  real(DP) :: bet2 !< triangle face points
227  real(DP) :: waa
228  real(DP) :: wab
229  real(DP) :: wba
230  real(DP) :: wbb !< w matrix
231  logical(LGP), intent(in), optional :: bary !< barycentric coordinates
232  ! -- local
233  logical(LGP) :: lbary
234  real(DP) :: v1alpdiff
235  real(DP) :: v2alpdiff
236  real(DP) :: v2betdiff
237  real(DP) :: ooalp1
238  real(DP) :: oobet2
239  real(DP) :: vterm
240 
241  if (present(bary)) then
242  lbary = bary
243  else
244  lbary = .true.
245  end if
246 
247  ! -- Note: wab is the "alpha,beta" entry in matrix W
248  ! and the alpha component of the w^(beta) vector
249  v1alpdiff = cv1(1) - cv0(1)
250  v2alpdiff = cv2(1) - cv0(1)
251  v2betdiff = cv2(2) - cv0(2)
252  if (bary) then
253  waa = v1alpdiff
254  wab = v2alpdiff
255  wba = 0d0
256  wbb = v2betdiff
257  else
258  ooalp1 = 1d0 / alp1
259  oobet2 = 1d0 / bet2
260  vterm = v1alpdiff * ooalp1
261  waa = vterm
262  wab = (v2alpdiff - alp2 * vterm) * oobet2
263  wba = 0d0
264  wbb = v2betdiff * oobet2
265  end if
266 
Here is the caller graph for this function:

◆ soln_brent()

subroutine, public ternarysolvetrack::soln_brent ( integer(i4b), intent(in)  itriface,
real(dp)  betlo,
real(dp)  bethi,
real(dp), intent(in)  tol,
real(dp)  texit,
real(dp)  alpexit,
real(dp)  betexit 
)

Definition at line 790 of file TernarySolveTrack.f90.

792  ! -- dummy
793  integer(I4B), intent(in) :: itriface
794  real(DP) :: betlo
795  real(DP) :: bethi
796  real(DP), intent(in) :: tol
797  real(DP) :: texit
798  real(DP) :: alpexit
799  real(DP) :: betexit
800  ! -- local
801  real(DP) :: itmax
802  real(DP) :: itact
803  real(DP) :: blo
804  real(DP) :: bhi
805  procedure(f1d), pointer :: f
806 
807  ! -- assuming betlo and bethi bracket the root
808  ! --
809  ! tol = 1d-7 ! kluge
810  itmax = 50 ! kluge
811  itact = itmax + 1 ! kluge
812  blo = betlo
813  bhi = bethi
814  if (itriface .eq. 1) then
815  f => fbary1
816  betexit = zero_br(blo, bhi, f, tol)
817  else
818  f => fbary2
819  betexit = zero_br(blo, bhi, f, tol)
820  end if
821  call get_t_alpt(betexit, texit, alpexit)
822 
Here is the call graph for this function:
Here is the caller graph for this function:

◆ soln_chand()

subroutine, public ternarysolvetrack::soln_chand ( integer(i4b), intent(in)  itriface,
real(dp)  betlo,
real(dp)  bethi,
real(dp), intent(in)  tol,
real(dp)  texit,
real(dp)  alpexit,
real(dp)  betexit 
)

Definition at line 826 of file TernarySolveTrack.f90.

828  ! -- dummy
829  integer(I4B), intent(in) :: itriface
830  real(DP) :: betlo
831  real(DP) :: bethi
832  real(DP), intent(in) :: tol
833  real(DP) :: texit
834  real(DP) :: alpexit
835  real(DP) :: betexit
836  ! -- local
837  real(DP) :: itmax
838  real(DP) :: itact
839  real(DP) :: blo
840  real(DP) :: bhi
841  procedure(f1d), pointer :: f
842 
843  ! -- note: assuming betlo and bethi bracket the root
844  ! tol = 1d-7 ! kluge
845  itmax = 50 ! kluge
846  itact = itmax + 1 ! kluge
847  blo = betlo
848  bhi = bethi
849  if (itriface .eq. 1) then
850  f => fbary1
851  betexit = zero_ch(blo, bhi, f, tol)
852  else
853  f => fbary2
854  betexit = zero_ch(blo, bhi, f, tol)
855  end if
856  call get_t_alpt(betexit, texit, alpexit)
857 
Here is the call graph for this function:
Here is the caller graph for this function:

◆ soln_euler()

subroutine, public ternarysolvetrack::soln_euler ( integer(i4b), intent(in)  itriface,
real(dp)  alpi,
real(dp)  beti,
real(dp), intent(in)  step,
real(dp)  vziodz,
real(dp)  az,
real(dp)  texit,
real(dp)  alpexit,
real(dp)  betexit 
)

Definition at line 896 of file TernarySolveTrack.f90.

898  ! -- dummy
899  integer(I4B), intent(in) :: itriface
900  real(DP) :: alpi
901  real(DP) :: beti
902  real(DP), intent(in) :: step
903  real(DP) :: vziodz
904  real(DP) :: az
905  real(DP) :: texit
906  real(DP) :: alpexit
907  real(DP) :: betexit
908  ! -- local
909  real(DP) :: alp
910  real(DP) :: bet
911  real(DP) :: gam
912  real(DP) :: alpold
913  real(DP) :: betold
914  real(DP) :: gamold
915  real(DP) :: wt
916  real(DP) :: omwt
917  real(DP) :: t
918  real(DP) :: told
919 
920  t = 0d0
921  alp = alpi
922  bet = beti
923  if (itriface .eq. 1) gam = 1d0 - alpi - beti
924  do nt = 1, 1000000000 ! kluge hardwired
925  ! -- Save current time, alpha, and beta
926  told = t
927  alpold = alp
928  betold = bet
929  ! -- Step forward in time
930  ! t = dble(nt)*step
931  call step_euler(nt, step, vziodz, az, alpi, beti, t, alp, bet)
932  ! if (nt.eq.0) then
933  ! znum = zi
934  ! else
935  ! vz = vzbot + az*(znum - zbot)
936  ! znum = znum + vz*delt ! kluge note: can be smart about checking z
937  ! end if
938  if (itriface .eq. 1) then
939  ! -- If gamma has crossed zero, interpolate linearly
940  ! -- to find crossing (exit) point
941  gamold = gam
942  gam = 1d0 - alp - bet
943  if (gam .lt. 0d0) then
944  wt = gamold / (gamold - gam)
945  omwt = 1d0 - wt
946  texit = omwt * told + wt * t
947  alpexit = omwt * alpold + wt * alp
948  betexit = omwt * betold + wt * bet
949  exit
950  end if
951  else
952  ! -- If alpha has crossed zero, interpolate linearly
953  ! -- to find crossing (exit) point
954  if (alp .lt. 0d0) then
955  wt = alpold / (alpold - alp)
956  omwt = 1d0 - wt
957  texit = omwt * told + wt * t
958  alpexit = omwt * alpold + wt * alp
959  betexit = omwt * betold + wt * bet
960  exit
961  end if
962  end if
963  ! -- End time step loop
964  end do
965  if (nt .gt. 1000000000) then ! kluge hardwired
966  ! -- Exit not found after max number of time steps
967  call pstop(1, "Didn't find exit in soln_euler")
968  end if
969 
Here is the call graph for this function:
Here is the caller graph for this function:

◆ soln_test()

subroutine, public ternarysolvetrack::soln_test ( integer(i4b), intent(in)  itriface,
real(dp)  betlo,
real(dp)  bethi,
real(dp), intent(in)  tol,
real(dp)  texit,
real(dp)  alpexit,
real(dp)  betexit 
)

Definition at line 861 of file TernarySolveTrack.f90.

863  ! -- dummy
864  integer(I4B), intent(in) :: itriface
865  real(DP) :: betlo
866  real(DP) :: bethi
867  real(DP), intent(in) :: tol
868  real(DP) :: texit
869  real(DP) :: alpexit
870  real(DP) :: betexit
871  ! -- local
872  real(DP) :: itmax
873  real(DP) :: itact
874  real(DP) :: blo
875  real(DP) :: bhi
876  procedure(f1d), pointer :: f
877 
878  ! -- assuming betlo and bethi bracket the root
879  ! tol = 1d-7 ! kluge
880  itmax = 50 ! kluge
881  itact = itmax + 1 ! kluge
882  blo = betlo
883  bhi = bethi
884  if (itriface .eq. 1) then
885  f => fbary1
886  betexit = zero_test(blo, bhi, f, tol)
887  else
888  f => fbary2
889  betexit = zero_test(blo, bhi, f, tol)
890  end if
891  call get_t_alpt(betexit, texit, alpexit)
892 
Here is the call graph for this function:
Here is the caller graph for this function:

◆ solve_coefs()

subroutine, public ternarysolvetrack::solve_coefs ( real(dp)  alpi,
real(dp)  beti 
)

Definition at line 270 of file TernarySolveTrack.f90.

271  ! -- dummy
272  real(DP) :: alpi
273  real(DP) :: beti
274  ! -- local
275  real(DP) :: zerotol
276  real(DP) :: wratv
277  real(DP) :: acoef
278  real(DP) :: bcoef
279  real(DP) :: afact
280  real(DP) :: bfact
281  real(DP) :: vfact
282  real(DP) :: oowaa
283 
284  zerotol = 1d-10 ! kluge
285  if (dabs(wbb) .gt. zerotol) then
286  wratv = (wab / wbb) * cv0(2)
287  acoef = cv0(1) - wratv
288  bcoef = wratv + wab * beti
289  afact = acoef / waa
290  vfact = cv0(2) / wbb
291  ! -- Coefs for beta do not depend on whether waa = 0 or not
292  cb1 = -vfact ! const term in beta
293  cb2 = vfact + beti ! coef for e(wbb*t) term in beta
294  ! -- Coefs for alpha
295  if (dabs(waa) .gt. zerotol) then
296  ! -- Case waa <> 0, wbb <> 0
297  if (dabs(wbb - waa) .gt. zerotol) then
298  ! -- Subcase wbb <> waa
299  bfact = bcoef / (wbb - waa)
300  ca1 = -afact ! const term in alpha
301  ca2 = alpi + afact - bfact ! coef for exp(waa*t) term in alpha
302  ca3 = bfact ! coef for exp(wbb*t) term in alpha
303  icase = 1
304  else
305  ! -- Subcase wbb = waa
306  ca1 = -afact ! const term in alpha
307  ca2 = alpi + afact ! coef for exp(waa*t) term in alpha
308  ca3 = bcoef ! coef for t*exp(waa*t) term in alpha
309  icase = -1
310  end if
311  else
312  ! -- Case waa = 0, wbb <> 0
313  bfact = bcoef / wbb
314  ca1 = alpi - bfact ! const term in alpha
315  ca2 = acoef ! coef for t term in alpha
316  ca3 = bfact ! coef for exp(wbb*t) term in alpha
317  icase = 2
318  end if
319  else
320  ! -- Coefs for beta do not depend on whether waa = 0 or not
321  cb1 = beti ! const term in beta
322  cb2 = cv0(2) ! coef for t term in beta
323  if (dabs(waa) .gt. zerotol) then
324  ! -- Case waa <> 0, wbb = 0
325  oowaa = 1d0 / waa
326  vfact = (wab * oowaa) * cv0(2)
327  ca1 = -oowaa * (cv0(1) + wab * beti + vfact) ! const term in alpha
328  ca2 = -vfact ! coef for t term in alpha
329  ca3 = alpi - ca1 ! coef for exp(waa*t) term in alpha
330  icase = 3
331  else
332  ! -- Case waa = 0, wbb = 0
333  ca1 = alpi ! const term in alpha
334  ca2 = cv0(1) + wab * beti ! coef for t term in alpha
335  ca3 = 5d-1 * wab * cv0(2) ! coef for t^2 term in alpha
336  icase = 4
337  end if
338  end if
339 
Here is the caller graph for this function:

◆ step_analytical()

subroutine, public ternarysolvetrack::step_analytical ( real(dp), intent(in)  t,
real(dp)  alp,
real(dp)  bet 
)

Definition at line 343 of file TernarySolveTrack.f90.

344  ! -- dummy
345  real(DP), intent(in) :: t
346  real(DP) :: alp
347  real(DP) :: bet
348 
349  if (icase .eq. 1) then
350  alp = ca1 + ca2 * dexp(waa * t) + ca3 * dexp(wbb * t)
351  bet = cb1 + cb2 * dexp(wbb * t)
352  else if (icase .eq. -1) then
353  alp = ca1 + (ca2 + ca3 * t) * dexp(waa * t)
354  bet = cb1 + cb2 * dexp(wbb * t)
355  else if (icase .eq. 2) then
356  alp = ca1 + ca2 * t + ca3 * dexp(wbb * t)
357  bet = cb1 + cb2 * dexp(wbb * t)
358  else if (icase .eq. 3) then
359  alp = ca1 + ca2 * t + ca3 * dexp(waa * t)
360  bet = cb1 + cb2 * t
361  else if (icase .eq. 4) then
362  alp = ca1 + (ca2 + ca3 * t) * t
363  bet = cb1 + cb2 * t
364  end if
365 
Here is the caller graph for this function:

◆ step_euler()

subroutine, public ternarysolvetrack::step_euler ( integer(i4b)  nt,
real(dp), intent(in)  step,
real(dp)  vziodz,
real(dp)  az,
real(dp)  alpi,
real(dp)  beti,
real(dp), intent(inout)  t,
real(dp)  alp,
real(dp)  bet 
)

Definition at line 369 of file TernarySolveTrack.f90.

370  ! -- dummy
371  integer(I4B) :: nt
372  real(DP), intent(in) :: step
373  real(DP) :: vziodz
374  real(DP) :: az
375  real(DP) :: alpi
376  real(DP) :: beti
377  real(DP), intent(inout) :: t
378  real(DP) :: alp
379  real(DP) :: bet
380  ! -- local
381  real(DP) :: alpproj
382  real(DP) :: betproj
383  real(DP) :: valp
384  real(DP) :: vbet
385  real(DP) :: vz
386  real(DP) :: vmeasure
387  real(DP) :: delt
388  real(DP) :: thalf
389  real(DP) :: rkn1
390  real(DP) :: rln1
391  real(DP) :: rkn2
392  real(DP) :: rln2
393  real(DP) :: rkn3
394  real(DP) :: rln3
395  real(DP) :: rkn4
396  real(DP) :: rln4
397 
398  if (nt .eq. 0) then
399  ! -- Initial location
400  alp = alpi
401  bet = beti
402  t = 0d0
403  else
404  ! -- Step numerically
405  valp = cv0(1) + waa * alp + wab * bet
406  vbet = cv0(2) + wba * alp + wbb * bet
407  if (step .lt. 0d0) then
408  ! -- Compute time step based on abs value of step, interpreting the latter
409  ! -- as a distance in canonical coordinates (alpha, beta, and scaled z)
410  vz = vziodz * dexp(az * t)
411  vmeasure = dsqrt(valp * valp + vbet * vbet + vz * vz)
412  delt = -step / vmeasure
413  else
414  ! -- Set time step directly to step
415  delt = step
416  end if
417  ikluge = 2 ! kluge
418  if (ikluge .eq. 1) then
419  t = t + delt
420  alp = alp + valp * delt
421  bet = bet + vbet * delt
422  else
423  rkn1 = valp
424  rln1 = vbet
425  thalf = t + 5d-1 * delt
426  call step_analytical(thalf, alpproj, betproj)
427  rkn2 = cv0(1) + waa * alpproj + wab * betproj
428  rln2 = cv0(2) + wba * alpproj + wbb * betproj
429  rkn3 = rkn2
430  rln3 = rln2
431  t = t + delt
432  call step_analytical(t, alpproj, betproj)
433  rkn4 = cv0(1) + waa * alpproj + wab * betproj
434  rln4 = cv0(2) + wba * alpproj + wbb * betproj
435  alp = alp + delt * (rkn1 + 2d0 * rkn2 + 2d0 * rkn3 + rkn4) / 6d0
436  bet = bet + delt * (rln1 + 2d0 * rln2 + 2d0 * rln3 + rln4) / 6d0
437  end if
438  end if
439 
Here is the call graph for this function:
Here is the caller graph for this function:

◆ traverse_triangle()

subroutine, public ternarysolvetrack::traverse_triangle ( integer(i4b), intent(in)  isolv,
real(dp), intent(in)  tol,
real(dp), intent(in)  step,
real(dp), intent(out)  texit,
real(dp)  alpexit,
real(dp)  betexit,
integer(i4b)  itrifaceenter,
integer(i4b)  itrifaceexit,
real(dp)  rxx,
real(dp)  rxy,
real(dp)  ryx,
real(dp)  ryy,
real(dp)  alp0,
real(dp)  bet0,
real(dp)  alp1,
real(dp)  bet1,
real(dp)  alp2,
real(dp)  bet2,
real(dp)  alpi,
real(dp)  beti,
real(dp)  vziodz,
real(dp)  az,
logical(lgp), intent(in)  bary 
)
Parameters
[in]isolvsolution method
[in]tolsolution tolerance
[in]stepstepsize for numerical methods (e.g. euler)
[out]texittime particle exits the cell
betexitalpha and beta coefficients
itrifaceexitentry and exit faces
ryyrotation matrix
betialpha and beta coefficients
[in]barywhether to use barycentric coordinates

Definition at line 34 of file TernarySolveTrack.f90.

41  ! -- dummy
42  integer(I4B), intent(in) :: isolv !< solution method
43  real(DP), intent(in) :: tol !< solution tolerance
44  real(DP), intent(in) :: step !< stepsize for numerical methods (e.g. euler)
45  real(DP), intent(out) :: texit !< time particle exits the cell
46  real(DP) :: alpexit
47  real(DP) :: betexit !< alpha and beta coefficients
48  integer(I4B) :: itrifaceenter
49  integer(I4B) :: itrifaceexit !< entry and exit faces
50  real(DP) :: rxx
51  real(DP) :: rxy
52  real(DP) :: ryx
53  real(DP) :: ryy !< rotation matrix
54  real(DP) :: alp0
55  real(DP) :: bet0
56  real(DP) :: alp1
57  real(DP) :: bet1
58  real(DP) :: alp2
59  real(DP) :: bet2
60  real(DP) :: alpi
61  real(DP) :: beti !< alpha and beta coefficients
62  real(DP) :: vziodz
63  real(DP) :: az
64  logical(LGP), intent(in) :: bary !< whether to use barycentric coordinates
65  ! -- local
66  real(DP) :: texit0
67  real(DP) :: alpexit0
68  real(DP) :: betexit0
69  real(DP) :: texit1
70  real(DP) :: alpexit1
71  real(DP) :: betexit1
72  real(DP) :: texit2
73  real(DP) :: alpexit2
74  real(DP) :: betexit2
75 
76  ! -- Compute elements of matrix W
77  call get_w(alp1, bet1, alp2, bet2, waa, wab, wba, wbb, bary)
78 
79  ! -- Determine alpha and beta analytically as functions of time
80  call solve_coefs(alpi, beti)
81 
82  ! -- Compute exit time (travel time to exit) and exit location
83  call find_exit_bary(isolv, 0, itrifaceenter, &
84  alpi, beti, &
85  tol, step, vziodz, az, &
86  texit0, alpexit0, betexit0)
87  call find_exit_bary(isolv, 1, itrifaceenter, &
88  alpi, beti, &
89  tol, step, vziodz, az, &
90  texit1, alpexit1, betexit1)
91  call find_exit_bary(isolv, 2, itrifaceenter, &
92  alpi, beti, &
93  tol, step, vziodz, az, &
94  texit2, alpexit2, betexit2)
95  texit = min(texit0, texit1, texit2)
96 
97  ! -- Note that while the numbering of triangle faces is generally zero-based
98  ! -- (0, 1, 2), itrifaceexit, which gets passed out, is one-based (1, 2, 3).
99  if (texit .eq. texit0) then
100  alpexit = alpexit0
101  betexit = betexit0
102  itrifaceexit = 1
103  else if (texit .eq. texit1) then
104  alpexit = alpexit1
105  betexit = betexit1
106  itrifaceexit = 2
107  else if (texit .eq. texit2) then
108  alpexit = alpexit2
109  betexit = betexit2
110  itrifaceexit = 3
111  end if
112  if (texit .eq. huge(1d0)) itrifaceexit = 0
113 
Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ ca1

real(dp) ternarysolvetrack::ca1
private

Definition at line 26 of file TernarySolveTrack.f90.

26  real(DP) ca1, ca2, ca3, cb1, cb2 !< Analytical solution coefficients

◆ ca2

real(dp) ternarysolvetrack::ca2
private

Definition at line 26 of file TernarySolveTrack.f90.

◆ ca3

real(dp) ternarysolvetrack::ca3
private

Definition at line 26 of file TernarySolveTrack.f90.

◆ cb1

real(dp) ternarysolvetrack::cb1
private

Definition at line 26 of file TernarySolveTrack.f90.

◆ cb2

real(dp) ternarysolvetrack::cb2
private

Definition at line 26 of file TernarySolveTrack.f90.

◆ cv0

real(dp), dimension(2) ternarysolvetrack::cv0
private

Definition at line 28 of file TernarySolveTrack.f90.

28  real(DP) :: cv0(2), cv1(2), cv2(2) !< "Canonical" velocity components at corners of triangular subcell

◆ cv1

real(dp), dimension(2) ternarysolvetrack::cv1
private

Definition at line 28 of file TernarySolveTrack.f90.

◆ cv2

real(dp), dimension(2) ternarysolvetrack::cv2
private

Definition at line 28 of file TernarySolveTrack.f90.

◆ icase

integer(i4b) ternarysolvetrack::icase
private

Definition at line 29 of file TernarySolveTrack.f90.

29  integer(I4B) icase !< Case index for analytical solution

◆ waa

real(dp) ternarysolvetrack::waa
private

Definition at line 27 of file TernarySolveTrack.f90.

27  real(DP) waa, wab, wba, wbb !< Elements of the "velocity matrix," W

◆ wab

real(dp) ternarysolvetrack::wab
private

Definition at line 27 of file TernarySolveTrack.f90.

◆ wba

real(dp) ternarysolvetrack::wba
private

Definition at line 27 of file TernarySolveTrack.f90.

◆ wbb

real(dp) ternarysolvetrack::wbb
private

Definition at line 27 of file TernarySolveTrack.f90.