33 itrifaceenter, itrifaceexit, &
35 alp0, bet0, alp1, bet1, alp2, bet2, alpi, beti, &
39 integer(I4B),
intent(in) :: isolv
40 real(dp),
intent(in) :: tol
41 real(dp),
intent(in) :: step
42 real(dp),
intent(out) :: texit
45 integer(I4B) :: itrifaceenter
46 integer(I4B) :: itrifaceexit
61 logical(LGP),
intent(in) :: bary
82 tol, step, vziodz, az, &
83 texit0, alpexit0, betexit0)
86 tol, step, vziodz, az, &
87 texit1, alpexit1, betexit1)
90 tol, step, vziodz, az, &
91 texit2, alpexit2, betexit2)
92 texit = min(texit0, texit1, texit2)
96 if (texit .eq. texit0)
then
100 else if (texit .eq. texit1)
then
104 else if (texit .eq. texit2)
then
109 if (texit .eq. huge(1d0)) itrifaceexit = 0
115 v0x, v0y, v1x, v1y, v2x, v2y, &
117 rxx, rxy, ryx, ryy, &
119 alp0, bet0, alp1, bet1, alp2, bet2, alpi, beti, &
140 real(dp),
intent(inout) :: sxx, sxy, syy
149 logical(LGP),
intent(in) :: bary
152 real(dp) :: oobaselen
161 real(dp) :: rot(2, 2), res(2)
168 baselen = dsqrt(x1diff * x1diff + y1diff * y1diff)
169 oobaselen = 1d0 / baselen
170 cosomega = x1diff * oobaselen
171 sinomega = y1diff * oobaselen
181 rot = reshape((/rxx, ryx, rxy, ryy/), shape(rot))
182 res = matmul(rot, (/x2diff, y2diff/))
186 cv0 = matmul(rot, (/v0x, v0y/))
187 cv1 = matmul(rot, (/v1x, v1y/))
188 cv2 = matmul(rot, (/v2x, v2y/))
192 res = matmul(rot, (/xidiff, yidiff/))
199 sxy = -alp2 * sxx * syy
207 res =
skew(res, (/sxx, sxy, syy/))
216 alp1, bet1, alp2, bet2, &
217 waa, wab, wba, wbb, &
228 logical(LGP),
intent(in),
optional :: bary
230 logical(LGP) :: lbary
231 real(dp) :: v1alpdiff
232 real(dp) :: v2alpdiff
233 real(dp) :: v2betdiff
238 if (
present(bary))
then
246 v1alpdiff =
cv1(1) -
cv0(1)
247 v2alpdiff =
cv2(1) -
cv0(1)
248 v2betdiff =
cv2(2) -
cv0(2)
257 vterm = v1alpdiff * ooalp1
259 wab = (v2alpdiff - alp2 * vterm) * oobet2
261 wbb = v2betdiff * oobet2
282 if (dabs(
wbb) .gt. zerotol)
then
284 acoef =
cv0(1) - wratv
285 bcoef = wratv +
wab * beti
292 if (dabs(
waa) .gt. zerotol)
then
294 if (dabs(
wbb -
waa) .gt. zerotol)
then
296 bfact = bcoef / (
wbb -
waa)
298 ca2 = alpi + afact - bfact
320 if (dabs(
waa) .gt. zerotol)
then
323 vfact = (
wab * oowaa) *
cv0(2)
324 ca1 = -oowaa * (
cv0(1) +
wab * beti + vfact)
342 real(dp),
intent(in) :: t
346 if (
icase .eq. 1)
then
349 else if (
icase .eq. -1)
then
352 else if (
icase .eq. 2)
then
355 else if (
icase .eq. 3)
then
358 else if (
icase .eq. 4)
then
368 tol, step, vziodz, az, &
369 texit, alpexit, betexit)
371 integer(I4B) :: isolv
372 integer(I4B) :: itriface
373 integer(I4B) :: itrifaceenter
393 real(dp) :: v0alpstar
405 integer(I4B) :: ibettrend
409 if (itriface .eq. 0)
then
411 if (itrifaceenter .eq. 0)
then
417 if (
cv0(2) .ge. 0d0)
then
424 vbeti =
cv0(2) +
wbb * beti
425 if (vbeti .ge. 0d0)
then
431 if ((alpt .ge. 0d0) .and. (alpt .le. 1d0))
then
446 if (itriface .eq. 1)
then
455 if ((v1n .ge. 0d0) .and. (v2n .ge. 0d0))
then
464 if (ibettrend .eq. 0)
then
467 if ((beti .gt. betouthi) .or. (beti .lt. betoutlo))
then
474 v0alpstar =
cv0(1) +
wab * beti
475 valpi = v0alpstar +
waa * alpi
476 if ((itriface .eq. 1) .and. (valpi .le. 0d0))
then
479 else if ((itriface .eq. 2) .and. (valpi .ge. 0d0))
then
484 if (itriface .eq. 1)
then
490 if (
waa .ne. 0d0)
then
491 alplim = -v0alpstar /
waa
492 texit = dlog(alpexit - alplim / (alpi - alplim)) /
waa
494 texit = (alpexit - alpi) / v0alpstar
501 bethi = min(betouthi, betsolhi)
502 betlo = max(betoutlo, betsollo)
503 if (betlo .ge. bethi)
then
510 if (itriface .eq. 1)
then
511 fax = 1d0 - betlo - alplo
512 fbx = 1d0 - bethi - alphi
517 if (fax * fbx .gt. 0d0)
then
521 if (isolv .eq. 1)
then
524 call soln_brent(itriface, betlo, bethi, tol, texit, &
526 else if (isolv .eq. 2)
then
529 call soln_chand(itriface, betlo, bethi, tol, texit, &
532 call pstop(1,
"Invalid isolv, expected one of: 1, 2")
542 if (texit .ne. huge(1d0) .and. texit .lt. 0d0) &
543 call pstop(1,
"texit is negative (unexpected)")
550 real(dp),
intent(in) :: bet
558 fb = 1d0 - alpt - bet
564 real(dp),
intent(in) :: bet
578 real(dp),
intent(in) :: bet
588 if (
icase .eq. 1)
then
589 term = max(term, zerotol)
592 else if (
icase .eq. -1)
then
593 term = max(term, zerotol)
596 else if (
icase .eq. 2)
then
597 term = max(term, zerotol)
600 else if (
icase .eq. 3)
then
603 else if (
icase .eq. 4)
then
621 if (vn1 .lt. 0d0)
then
624 if (vn2 .le. 0d0)
then
629 betouthi = -vn1 / vndiff
634 if (vn1 .le. 0d0)
then
639 betoutlo = -vn1 / vndiff
648 real(dp),
intent(in) :: beti
651 integer(I4B),
intent(inout) :: ibettrend
655 if (
wbb .gt. 0d0)
then
657 if (beti .gt. betlim)
then
661 else if (beti .lt. betlim)
then
663 betsollo = -huge(1d0)
670 else if (
wbb .lt. 0d0)
then
672 if (beti .gt. betlim)
then
676 else if (beti .lt. betlim)
then
686 if (
cv0(2) .gt. 0d0)
then
690 else if (
cv0(2) .lt. 0d0)
then
692 betsollo = -huge(1d0)
705 texit, alpexit, betexit)
707 integer(I4B),
intent(in) :: itriface
710 real(dp),
intent(in) :: tol
719 procedure(
f1d),
pointer :: f
728 if (itriface .eq. 1)
then
730 betexit =
zero_br(blo, bhi, f, tol)
733 betexit =
zero_br(blo, bhi, f, tol)
741 texit, alpexit, betexit)
743 integer(I4B),
intent(in) :: itriface
746 real(dp),
intent(in) :: tol
755 procedure(
f1d),
pointer :: f
763 if (itriface .eq. 1)
then
765 betexit =
zero_ch(blo, bhi, f, tol)
768 betexit =
zero_ch(blo, bhi, f, tol)
subroutine pstop(status, message)
Stop the program, optionally specifying an error status code.
pure real(dp) function, dimension(2), public skew(v, s, invert)
Skew a 2D vector along the x-axis.
This module defines variable data types.
real(dp) function, public zero_ch(x0, x1, f, epsa)
Compute zeros on an interval using Chadrupatla's method.
real(dp) function, public zero_br(ax, bx, f, tol)
Compute a zero of the function f(x) in the interval (x0, x1).
real(dp) function fbary1(bet)
Brent's method applied to canonical face 1 (gamma = 0)
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.
real(dp), dimension(2) cv2
"Canonical" velocity components at corners of triangular subcell
integer(i4b) icase
Case index for analytical solution.
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.
real(dp) wbb
Elements of the "velocity matrix," W.
subroutine, public get_w(alp1, bet1, alp2, bet2, waa, wab, wba, wbb, bary)
Compute elements of W matrix.
real(dp), dimension(2) cv1
subroutine, public get_bet_outflow_bary(vn1, vn2, betoutlo, betouthi)
Find outflow interval.
subroutine, public get_t_alpt(bet, t, alp)
Given beta evaluate t and alpha depending on case.
subroutine, public get_bet_soln_limits(beti, betsollo, betsolhi, ibettrend)
Find trend of and limits on beta from beta{t} solution.
subroutine, public solve_coefs(alpi, beti)
Compute analytical solution coefficients depending on case.
subroutine, public soln_brent(itriface, betlo, bethi, tol, texit, alpexit, betexit)
Use Brent's method with initial bounds on beta of betlo and bethi.
real(dp) cb2
Analytical solution coefficients.
real(dp), dimension(2) cv0
real(dp) function fbary2(bet)
Brent's method applied to canonical face 2 (alpha = 0)
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.
subroutine, public soln_chand(itriface, betlo, bethi, tol, texit, alpexit, betexit)
Use Chandrupatla's method with initial bounds on beta of betlo and bethi.
subroutine, public step_analytical(t, alp, bet)
Step (evaluate) analytically depending on case.