subroutine aptripq (px, py, pz,
     &                    ac, ax, ay, az, axy, ayz, azx, axx, ayy, azz,
     &                    bc, bx, by, bz, bxy, byz, bzx, bxx, byy, bzz,
     &                    cc, cx, cy, cz, cxy, cyz, czx, cxx, cyy, czz,
     &                    tol, tx, ty, tz, nerr)

ccbeg.
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
c
c                             SUBROUTINE APTRIPQ
c
c     call aptripq (px, py, pz,
c    &              ac, ax, ay, az, axy, ayz, azx, axx, ayy, azz,
c    &              bc, bx, by, bz, bxy, byz, bzx, bxx, byy, bzz,
c    &              cc, cx, cy, cz, cxy, cyz, czx, cxx, cyy, czz,
c    &              tol, tx, ty, tz, nerr)
c
c     Version:  aptripq  Updated    1999 August 11 14:00.
c               aptripq  Originated 1997 December 10 15:40.
c
c     Author:   Arthur L. Edwards, LLNL, L-298, Telephone (925) 422-4123.
c
c
c     Purpose:  To find, near point p = (px, py, pz), one of the 8 possible
c               triple points of intersection t = (tx, ty, tz) of the three
c               quadric surfaces with the implicit equations:
c
c                 A = ac + ax  * x     + ay  * y     + az  * z
c                        + axy * x * y + ayz * y * z + azx * z * x
c                        + axx * x**2  + ayy * y**2  + azz * z**2 = 0
c                 B = bc + bx  * x     + by  * y     + bz  * z
c                        + bxy * x * y + byz * y * z + bzx * z * x
c                        + bxx * x**2  + byy * y**2  + bzz * z**2 = 0
c                 C = cc + cx  * x     + cy  * y     + cz  * z
c                        + cxy * x * y + cyz * y * z + czx * z * x
c                        + cxx * x**2  + cyy * y**2  + czz * z**2 = 0
c
c               The three quadric surfaces have the normal vectors:
c
c                 AN  = (ANx, ANy, ANz) = grad (A)
c                 ANx = ax + 2 * axx * x +     axy * y +     azx * z
c                 ANy = ay +     axy * x + 2 * ayy * y +     ayz * z
c                 ANz = az +     azx * x +     ayz * y + 2 * azz * z
c
c                 BN  = (BNx, BNy, BNz) = grad (B)
c                 BNx = bx + 2 * bxx * x +     bxy * y +     bzx * z
c                 BNy = by +     bxy * x + 2 * byy * y +     byz * z
c                 BNz = bz +     bzx * x +     byz * y + 2 * bzz * z
c
c                 CN  = (CNx, CNy, CNz) = grad (C)
c                 CNx = cx + 2 * cxx * x +     cxy * y +     czx * z
c                 CNy = cy +     cxy * x + 2 * cyy * y +     cyz * z
c                 CNz = cz +     czx * x +     cyz * y + 2 * czz * z
c
c               The method is iterative, starting with the initial guess
c               (x, y, z) = (px, py, pz).  Each step of the iteration, the
c               estimated triple point is successively replaced by its proximal
c               point on each of the three surfaces (which works well for
c               surfaces that are highly curved or meet nearly orthogonally),
c               then improved by solving the three simultaneous equations:
c
c                 A + ANx * (x' - x) + ANy * (y' - y) + ANz * (z' - z) = 0
c                 B + BNx * (x' - x) + BNy * (y' - y) + BNz * (z' - z) = 0
c                 C + CNx * (x' - x) + CNy * (y' - y) + CNz * (z' - z) = 0
c
c               (which works well for surfaces that are flat or meet at a small
c               angle).  Iterating is continued to convergence (nerr = 0) or
c               failure (nerr > 0).
c
c               Convergence is determined by the precision limit tol, which
c               should be in the range from 1.e-5 to 1.e-15 for 64-bit
c               floating point arithmetic.
c
c     Input:    px, py, pz,
c               ac, ax, ay, az, axy, ayz, azx, axx, ayy, azz,
c               bc, bx, by, bz, bxy, byz, bzx, bxx, byy, bzz,
c               cc, cx, cy, cz, cxy, cyz, czx, cxx, cyy, czz, tol.
c
c     Output:   tx, ty, tz, nerr.
c
c     Calls: aptsolv, aptwhis 
c
c     Glossary:
c
c     ac, ...   Input    Coefficients of the implicit equation for the first
c                          quadric surface:
c                          ac + ax  * x     + ay  * y     + az  * z +
c                               axy * x * y + ayz * y * z + azx * z * x +
c                               axx * x**2  + ayy * y**2  + azz * z**2 = 0
c
c     bc, ...   Input    Coefficients of the implicit equation for the second
c                          quadric surface:
c                          bc + bx  * x     + by  * y     + bz  * z +
c                               bxy * x * y + byz * y * z + bzx * z * x +
c                               bxx * x**2  + byy * y**2  + bzz * z**2 = 0
c
c     cc, ...   Input    Coefficients of the implicit equation for the third
c                          quadric surface:
c                          cc + cx  * x     + cy  * y     + cz  * z +
c                               cxy * x * y + cyz * y * z + czx * z * x +
c                               cxx * x**2  + cyy * y**2  + czz * z**2 = 0
c
c     nerr      Output   Indicates an input error, if not zero:
c                          1 if there is no solution, such as when there is no
c                            triple point.
c                          2 if the method fails to converge in 1000 iterations,
c                            which may indicate too small a value of tol.
c                          3 if the the method diverges.
c
c     px,py,pz  Input    The x, y, z coordinates of point "p", the initial guess
c                          for the triple point.
c
c     tol       Input    Numerical tolerance limit.  With 64-bit floating point
c                          numbers, 1.e-5 to 1.e-11 is recommended.
c                          Used both as an absolute and relative convergence
c                          criterion.  Changes in triple point coordinates less
c                          than 10 * tol are treated as insignificant.
c
c     tx,ty,tz  Output   Coordinates x, y and z at one of the triple point
c                          intersections (usually the one nearest point "p")
c                          of the three quadric surfaces, if nerr = 0.
c                          If no solution is found, point "t" is returned as
c                          (-1.e99, -1.e99, -1.e99).
c
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
ccend.

c.... Local variables.

      common /ltripq/ abc(3,3)        ! Coefficients of equations (row, column).
      common /ltripq/ cba(3,3)        ! Inverse of matrix abc     (row, column).
      common /ltripq/ d(3)            ! Right-hand side constants.
      common /ltripq/ dm(3)           ! Right-hand side constants check.
      common /ltripq/ dr(3)           ! Right-hand side constants residuals.
      common /ltripq/ work(3,4)       ! Working matrix.
      common /ltripq/ xyz(3)          ! Solution.
      common /ltripq/ xyzm(3)         ! Solution check.
      common /ltripq/ xyzr(3)         ! Solution residuals.

      common /ltripq/ dist(4)         ! Distance to a proximal point.
      common /ltripq/ xx(4)           ! Coordinate x of a proximal point.
      common /ltripq/ yy(4)           ! Coordinate x of a proximal point.
      common /ltripq/ zz(4)           ! Coordinate x of a proximal point.

c.... Initialize.

      nerr = 0

      tx   = -1.e99
      ty   = -1.e99
      tz   = -1.e99

c=======================================================================********
cbugc***DEBUG begins.
cbug 9901 format (/ 'aptripq finding a triple point of three',
cbug     &  ' quadric surfaces.',
cbug     &  '  tol=',1pe13.5)
cbug 9902 format ('Initial guess:' /
cbug     &        '  px, py, pz =',1p3e22.14 )
cbug 9903 format ('Quadric ac   =',1pe22.14 /
cbug     &        '  ax,ay,az   =',1p3e22.14 /
cbug     &        '  axy,ayz,azx=',1p3e22.14 /
cbug     &        '  axx,ayy,azz=',1p3e22.14 )
cbug 9904 format ('Quadric bc   =',1pe22.14 /
cbug     &        '  bx,by,bz   =',1p3e22.14 /
cbug     &        '  bxy,byz,bzx=',1p3e22.14 /
cbug     &        '  bxx,byy,bzz=',1p3e22.14 )
cbug 9905 format ('Quadric cc   =',1pe22.14 /
cbug     &        '  cx,cy,cz   =',1p3e22.14 /
cbug     &        '  cxy,cyz,czx=',1p3e22.14 /
cbug     &        '  cxx,cyy,czz=',1p3e22.14 )
cbug      write ( 3, 9901) tol
cbug      write ( 3, 9902) px, py, pz
cbug      write ( 3, 9903) ac, ax, ay, az, axy, ayz, azx, axx, ayy, azz
cbug      write ( 3, 9904) bc, bx, by, bz, bxy, byz, bzx, bxx, byy, bzz
cbug      write ( 3, 9905) cc, cx, cy, cz, cxy, cyz, czx, cxx, cyy, czz
cbugc***DEBUG ends.

c.... Initialize for the iteration.

      x = px
      y = py
      z = pz

      xold3 = x
      yold3 = y
      zold3 = z

      aside = -1.e99
      bside = -1.e99
      cside = -1.e99

      xcyc1 = -1.e99
      ycyc1 = -1.e99
      zcyc1 = -1.e99

      xcyc2 = -1.e99
      ycyc2 = -1.e99
      zcyc2 = -1.e99

      xcyc3 = -1.e99
      ycyc3 = -1.e99
      zcyc3 = -1.e99

c=======================================================================********

c.... Iterate to find the solution.

      do 380 nit = 1, 1000            ! Iterate to find solution.
cbugcbugc***DEBUG begins.
cbugcbug 9910 format (/ i3,1x,'x,y,z    =',1p3e22.14 )
cbugcbug      write ( 3, 9910) nit, x, y, z
cbugcbugc***DEBUG ends.

c....   Try three successive proximal points.

        ncon = 0                      ! Number of sequential unchanged points.
        ncyc = 0                      ! Number of cycling points.

c....   Move to proximal point on first surface.

        xold1 = x
        yold1 = y
        zold1 = z

        tolx = 1.e-15

        call aptwhis (x, y, z,
     &                ac, ax, ay, az, axy, ayz, azx, axx, ayy, azz,
     &                tolx,
     &                dside, anx, any, anz,
     &                nprox, xx, yy, zz, dist, nerra)

        if ((nerra .ne. 0)  .or.
     &      (nprox .le. 0)) then
          nerr = 1
          go to 999
        endif

        nr = 1.0 + ranf () * nprox

        x = xx(nr)
        y = yy(nr)
        z = zz(nr)
cbugcbugc***DEBUG begins.
cbugcbug 9911 format (i3,1x,'x,y,z  1 =',1p3e22.14 )
cbugcbug      write ( 3, 9911) nit, x, y, z
cbugcbugc***DEBUG ends.

        if ((abs (x - xold3) .le. tol * (10.0 + abs (xold3)))  .and.
     &      (abs (y - yold3) .le. tol * (10.0 + abs (yold3)))  .and.
     &      (abs (z - zold3) .le. tol * (10.0 + abs (zold3)))) then
          ncon = ncon + 1
        endif

        if ((abs (x - xcyc1) .le. tol * abs (xcyc1))  .and.
     &      (abs (y - ycyc1) .le. tol * abs (ycyc1))  .and.
     &      (abs (z - zcyc1) .le. tol * abs (zcyc1))) then
          ncyc = ncyc + 1
        endif

        xcyc1 = x
        ycyc1 = y
        zcyc1 = z

c....   Move to proximal point on second surface.

        xold2 = x
        yold2 = y
        zold2 = z

        call aptwhis (x, y, z,
     &                bc, bx, by, bz, bxy, byz, bzx, bxx, byy, bzz,
     &                tolx,
     &                dside, bnx, bny, bnz,
     &                nprox, xx, yy, zz, dist, nerra)

        if ((nerra .ne. 0)  .or.
     &      (nprox .le. 0)) then
          nerr = 1
          go to 999
        endif

        nr = 1.0 + ranf () * nprox

        x = xx(nr)
        y = yy(nr)
        z = zz(nr)
cbugcbugc***DEBUG begins.
cbugcbug 9912 format (i3,1x,'x,y,z  2 =',1p3e22.14 )
cbugcbug      write ( 3, 9912) nit, x, y, z
cbugcbugc***DEBUG ends.

        if ((abs (x - xold1) .le. tol * (10.0 + abs (xold1)))  .and.
     &      (abs (y - yold1) .le. tol * (10.0 + abs (yold1)))  .and.
     &      (abs (z - zold1) .le. tol * (10.0 + abs (zold1)))) then
          ncon = ncon + 1
        endif

        if ((abs (x - xcyc2) .le. tol * abs (xcyc2))  .and.
     &      (abs (y - ycyc2) .le. tol * abs (ycyc2))  .and.
     &      (abs (z - zcyc2) .le. tol * abs (zcyc2))) then
          ncyc = ncyc + 1
        endif

        xcyc2 = x
        ycyc2 = y
        zcyc2 = z

c....   Move to proximal point on third surface.

        xold3 = x
        yold3 = y
        zold3 = z

        call aptwhis (x, y, z,
     &                cc, cx, cy, cz, cxy, cyz, czx, cxx, cyy, czz,
     &                tolx,
     &                dside, cnx, cny, cnz,
     &                nprox, xx, yy, zz, dist, nerra)

        if ((nerra .ne. 0)  .or.
     &      (nprox .le. 0)) then
          nerr = 1
          go to 999
        endif

        nr = 1.0 + ranf () * nprox

        x = xx(nr)
        y = yy(nr)
        z = zz(nr)
cbugcbugc***DEBUG begins.
cbugcbug 9913 format (i3,1x,'x,y,z  3 =',1p3e22.14 )
cbugcbug      write ( 3, 9913) nit, x, y, z
cbugcbugc***DEBUG ends.

        if ((abs (x - xold2) .le. tol * (10.0 + abs (xold2)))  .and.
     &      (abs (y - yold2) .le. tol * (10.0 + abs (yold2)))  .and.
     &      (abs (z - zold2) .le. tol * (10.0 + abs (zold2)))) then
          ncon = ncon + 1
        endif

        if ((abs (x - xcyc3) .le. tol * abs (xcyc3))  .and.
     &      (abs (y - ycyc3) .le. tol * abs (ycyc3))  .and.
     &      (abs (z - zcyc3) .le. tol * abs (zcyc3))) then
          ncyc = ncyc + 1
        endif

        xcyc3 = x
        ycyc3 = y
        zcyc3 = z

        if (ncon .eq. 3) then
cbugcbugc***DEBUG begins.
cbugcbug 9914 format ('Converged in',i3,' iterations.')
cbugcbug      write ( 3, 9914) nit
cbugcbugc***DEBUG ends.
          go to 410
        endif

        if (ncyc .eq. 3) then
cbugcbugc***DEBUG begins.
cbugcbug 9915 format ('Detected cycling in',i3,' iterations.')
cbugcbug      write ( 3, 9915) nit
cbugcbugc***DEBUG ends.
          nerr = 3
          go to 999
        endif

c....   Find the new values of the implicit equations.

        asideold = aside
        bsideold = bside
        csideold = cside

        aside = ac + ax  * x     + ay  * y     + az  * z
     &             + axy * x * y + ayz * y * z + azx * z * x
     &             + axx * x**2  + ayy * y**2  + azz * z**2

        bside = bc + bx  * x     + by  * y     + bz  * z
     &             + bxy * x * y + byz * y * z + bzx * z * x
     &             + bxx * x**2  + byy * y**2  + bzz * z**2

        cside = cc + cx  * x     + cy  * y     + cz  * z
     &             + cxy * x * y + cyz * y * z + czx * z * x
     &             + cxx * x**2  + cyy * y**2  + czz * z**2
cbugcbugc***DEBUG begins.
cbugcbug 9921 format ('side(a,b,c)  =',1p3e22.14)
cbugcbug      write ( 3, 9921) aside, bside, cside
cbugcbugc***DEBUG ends.

c....  Truncate meaningless residuals to zero.

        aserr = tol * (abs(ac)  +
     &          2*abs(ax*x)     + 2*abs(ay*y)     + 2*abs(az*z)    +
     &          3*abs(axy*x*y)  + 3*abs(ayz*y*z)  + 3*abs(azx*z*x) +
     &          3*abs(axx*x**2) + 3*abs(ayy*y**2) + 3*abs(azz*z**2))

        if (abs (aside) .le. aserr) aside = 0.0

        bserr = tol * (abs(bc)  +
     &          2*abs(bx*x)     + 2*abs(by*y)     + 2*abs(bz*z)    +
     &          3*abs(bxy*x*y)  + 3*abs(byz*y*z)  + 3*abs(bzx*z*x) +
     &          3*abs(axx*x**2) + 3*abs(ayy*y**2) + 3*abs(azz*z**2))

        if (abs (bside) .le. bserr) bside = 0.0

        cserr = tol * (abs(cc)  +
     &          2*abs(cx*x)     + 2*abs(cy*y)     + 2*abs(cz*z)    +
     &          3*abs(cxy*x*y)  + 3*abs(cyz*y*z)  + 3*abs(czx*z*x) +
     &          3*abs(cxx*x**2) + 3*abs(cyy*y**2) + 3*abs(czz*z**2))

        if (abs (cside) .le. cserr) cside = 0.0
cbugcbugc***DEBUG begins.
cbugcbug 9922 format ('serr(a,b,c)  =',1p3e22.14)
cbugcbug 9923 format ('side(a,b,c)tr=',1p3e22.14)
cbugcbug      write ( 3, 9922) aserr, bserr, cserr
cbugcbug      write ( 3, 9923) aside, bside, cside
cbugcbugc***DEBUG ends.

c....   See if the test point is at a triple intersection point.

        if ((aside .eq. 0.0)  .and.
     &      (bside .eq. 0.0)  .and.
     &      (cside .eq. 0.0)) then
cbugcbugc***DEBUG begins.
cbugcbug      write ( 3, 9914) nit
cbugcbugc***DEBUG ends.
          go to 410
        endif

c....   See if the method is not converging.

        if ((abs (aside) .ge. abs (asideold))  .and.
     &      (abs (bside) .ge. abs (bsideold))  .and.
     &      (abs (cside) .ge. abs (csideold))) then
cbugcbugc***DEBUG begins.
cbugcbug 9931 format ('aptripq not converging.')
cbugcbug      write ( 3, 9931)
cbugcbugc***DEBUG ends.
          nerr = 3
          go to 999
        endif

c....   Find the components of the normal vectors.

        anx = ax + 2 * axx * x +     axy * y +     azx * z
        any = ay +     axy * x + 2 * ayy * y +     ayz * z
        anz = az +     azx * x +     ayz * y + 2 * azz * z

        bnx = bx + 2 * bxx * x +     bxy * y +     bzx * z
        bny = by +     bxy * x + 2 * byy * y +     byz * z
        bnz = bz +     bzx * x +     byz * y + 2 * bzz * z

        cnx = cx + 2 * cxx * x +     cxy * y +     czx * z
        cny = cy +     cxy * x + 2 * cyy * y +     cyz * z
        cnz = cz +     czx * x +     cyz * y + 2 * czz * z
cbugcbugc***DEBUG begins.
cbugcbug 9941 format ('anx,y,z      =',1p3e22.14)
cbugcbug 9942 format ('bnx,y,z      =',1p3e22.14)
cbugcbug 9943 format ('cnx,y,z      =',1p3e22.14)
cbugcbug      write ( 3, 9941) anx, any, anz
cbugcbug      write ( 3, 9942) bnx, bny, bnz
cbugcbug      write ( 3, 9943) cnx, cny, cnz
cbugcbugc***DEBUG ends.

c....   Find the coefficients of the three equations to be solved.

        abc(1,1) = anx
        abc(2,1) = any
        abc(3,1) = anz
        d(1)     = -aside

        abc(1,2) = bnx
        abc(2,2) = bny
        abc(3,2) = bnz
        d(2)     = -bside

        abc(1,3) = cnx
        abc(2,3) = cny
        abc(3,3) = cnz
        d(3)     = -cside

c....   Solve the three simultaneous equations.

        call aptsolv (abc, d, 3, work, 3, 0., xyz, cba, xyzm, xyzr,
     &                dm, dr, nerra)

        if (nerra .eq. 0) then
          dx = xyz(1)
          dy = xyz(2)
          dz = xyz(3)
cbugcbugc***DEBUG begins.
cbugcbug 9951 format ('dx,dy,dz     =',1p3e22.14)
cbugcbug      write ( 3, 9951) dx, dy, dz
cbugcbugc***DEBUG ends.
          x  = x + dx
          y  = y + dy
          z  = z + dz
cbugcbugc***DEBUG begins.
cbugcbug 9955 format (i3,1x,'x,y,z new=',1p3e22.14 )
cbugcbug      write ( 3, 9955) nit, x, y, z
cbugcbugc***DEBUG ends.
          if ((abs (dx) .lt. tol * (10.0 + abs (x)))  .and.
     &        (abs (dy) .lt. tol * (10.0 + abs (y)))  .and.
     &        (abs (dz) .lt. tol * (10.0 + abs (z)))) then
cbugcbugc***DEBUG begins.
cbugcbug      write ( 3, 9914) nit
cbugcbugc***DEBUG ends.
            go to 410
          endif
        else
cbugcbugc***DEBUG begins.
cbugcbug 9958 format ('aptsolv says singular equations.')
cbugcbug      write ( 3, 9958)
cbugcbugc***DEBUG ends.
          nerr = 1
          go to 999
        endif

  380 continue                        ! End of each iteration.

cbugcbugc***DEBUG begins.
cbugcbug 9961 format ('aptripq failed to converge in',i4,' iterations.')
cbugcbug      write ( 3, 9961) nit
cbugcbugc***DEBUG ends.
      nerr = 2                        ! Failed to converge.
      go to 999

c.... Converged to triple point.

  410 if (nerr .eq. 0) then
        tx = x
        ty = y
        tz = z
      endif

c=======================================================================********

  999 continue
cbugc***DEBUG begins.
cbug 9991 format (/ 'aptripq results.  nerr=',i2,', nit=',i3.'.')
cbug 9992 format ('Triple  (xyz)=',1p3e22.14 )
cbug      write ( 3, 9991) nerr, nit
cbug      write ( 3, 9992) tx, ty, tz
cbugc***DEBUG ends.

      return

c.... End of subroutine aptripq.      (+1 line)
      end

UCRL-WEB-209832