subroutine aptqhyp (ax, ay, az, bx, by, bz, cx, cy, cz,
     &                    dx, dy, dz, tol, qc, qx, qy, qz,
     &                    qxy, qyz, qzx, qxx, qyy, qzz, nerr)

ccbeg.
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
c
c                             SUBROUTINE APTQHYP
c
c     call aptqhyp (ax, ay, az, bx, by, bz, cx, cy, cz,
c    &              dx, dy, dz, tol, qc, qx, qy, qz,
c    &              qxy, qyz, qzx, qxx, qyy, qzz, nerr)
c
c     Version:  aptqhyp  Updated    1999 March 3 18:00.
c               aptqhyp  Originated 1999 February 22 18:00.
c
c     Author:   Arthur L. Edwards, LLNL, L-298, Telephone (925) 422-4123.
c
c
c     Purpose:  To find the quadric surface (a plane or hyperbolic paraboloid)
c               that passes through the four vertices a = (ax, ay, az),
c               b = (bx, by, bz), c = (cx, cy, cz) and d = (dx, dy, dz) of a
c               quadrangle, and also contains the four edges of the quadrangle
c               and its center point (at the intersection of the two lines
c               joining the midpoints of opposite sides).
c               The equation of the quadric surface is:
c
c                 f(x, y, z) = qc + qx * x + qy * y + qz * z +
c                              qxy * x * y + qyz * y * z + qzx * z * x +
c                              qxx * x**2 + qyy * y**2 + qzz * z**2 = 0.
c
c               If fewer than three of the vertex points are distinct, the
c               method fails, and nerr = 1 is returned.
c
c     Input:    ax, ay, az, bx, by, bz, cx, cy, cz, dx, dy, dz, tol.
c
c     Output:   qc, qx, qy, qz, qxy, qyz, qzx, qxx, qyy, qzz, nerr.
c
c     Calls: aptpfit, aptsolv, apttris, aptvdis 
c               
c
c     Glossary:
c
c     ax,ay,az  Input    The x, y and z coordinates of a point at vertex a of
c                          a quadrangle.
c
c     bx,by,bz  Input    The x, y and z coordinates of a point at vertex b of
c                          a quadrangle.
c
c     cx,cy,cz  Input    The x, y and z coordinates of a point at vertex c of
c                          a quadrangle.
c
c     dx,dy,dz  Input    The x, y and z coordinates of a point at vertex d of
c                          a quadrangle.
c
c     nerr      Output   Error indicator.  0 if a good solution was obtained.
c                          1 if the matrix of coefficients "abc" is singular.
c                            The determinant of the matrix "abc" is zero.
c                          2 if any right-hand side residual "dr" exceeds 1.e-6
c                            times the maximum d value.  Results may be usable.
c                          3 if any solution residual "xyzr" exceeds 1.e-6 times
c                            the maximum xyz value.  Results may be usable.
c                          4 if three or more vertex points coincide.
c
c     qc        In/Out   Constant term in the implicit surface equation.
c                          Zero only if the surface passes through the origin.
c
c     qx,qy,qz  In/Out   Coefficients of x, y, z in implicit surface equation.
c                          For a plane, the x, y z components of the normal
c                          vector.
c
c     q..       In/Out   Coefficients of the second-order terms in the implicit
c                          surface equation:  qxy, qyz, qzx, qxx, qyy, qzz.
c                          Coefficients of x*y, y*z, z*x, x**2, y**2, z**2,
c                          respectively.  Zero for a plane.
c
c     tol       Input    Numerical tolerance limit.
c                          On computers with 48-bit floating-point numbers,
c                          recommend 1.e-5 to 1.e-11.
c
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
ccend.

c.... Local variables.

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

cbugc***DEBUG begins.
cbug 9901 format (/ 'aptqhyp finding hyperboloid.  tol=',1pe13.5)
cbug 9902 format (/ 'ax, ay, az=   ',1p3e22.14 /
cbug     &          'bx, by, bz=   ',1p3e22.14 /
cbug     &          'cx, cy, cz=   ',1p3e22.14 /
cbug     &          'dx, dy, dz=   ',1p3e22.14 )
cbug      write ( 3, 9901) tol
cbug      write ( 3, 9902) ax, ay, az, bx, by, bz, cx, cy, cz, dx, dy, dz
cbugc***DEBUG ends.

c.... Initialize.

      nerr = 0

      qc   = -1.e99
      qx   = -1.e99
      qy   = -1.e99
      qz   = -1.e99
      qxy  = -1.e99
      qyz  = -1.e99
      qzx  = -1.e99
      qxx  = -1.e99
      qyy  = -1.e99
      qzz  = -1.e99

c.... Find the coordinates of the nine points to be fit.
c....   Points 1-4 are the original vertices.
c....   Points 5-8 are the midpoints of the edges.
c....   Point 9 is the center of the quadrangle.
c....   Add a random vector to insure that coefficient qc is not zero.

      avgx = 0.25 * (abs (ax) + abs (bx) + abs (cx) + abs (dx))
      avgy = 0.25 * (abs (ay) + abs (by) + abs (cy) + abs (dy))
      avgz = 0.25 * (abs (az) + abs (bz) + abs (cz) + abs (dz))

      ntry = 0

  110 ntry = ntry + 1

      xran = ranf () * avgx
      yran = ranf () * avgy
      zran = ranf () * avgz

      x1 = ax + xran
      y1 = ay + yran
      z1 = az + zran

      x2 = bx + xran
      y2 = by + yran
      z2 = bz + zran

      x3 = cx + xran
      y3 = cy + yran
      z3 = cz + zran

      x4 = dx + xran
      y4 = dy + yran
      z4 = dz + zran

      x5 = 0.5 * (x1 + x2)
      y5 = 0.5 * (y1 + y2)
      z5 = 0.5 * (z1 + z2)

      x6 = 0.5 * (x2 + x3)
      y6 = 0.5 * (y2 + y3)
      z6 = 0.5 * (z2 + z3)

      x7 = 0.5 * (x3 + x4)
      y7 = 0.5 * (y3 + y4)
      z7 = 0.5 * (z3 + z4)

      x8 = 0.5 * (x4 + x1)
      y8 = 0.5 * (y4 + y1)
      z8 = 0.5 * (z4 + z1)

      x9 = 0.25 * (x1 + x2 + x3 + x4)
      y9 = 0.25 * (y1 + y2 + y3 + y4)
      z9 = 0.25 * (z1 + z2 + z3 + z4)
cbugcbugc***DEBUG begins.
cbugcbug 9110 format ('aptqhyp DEBUG      ',1p3e20.12)
cbugcbug      write ( 3, 9110) x1, y1, z1, x2, y2, z2, x3, y3, z3,
cbugcbug     &                   x4, y4, z4, x5, y5, z5, x6, y6, z6,
cbugcbug     &                   x7, y7, z7, x8, y8, z8, x9, y9, z9
cbugcbugc***DEBUG ends.

c.... Find the coefficients of qx.

      abc(1,1) = x1
      abc(2,1) = x2
      abc(3,1) = x3
      abc(4,1) = x4
      abc(5,1) = x5
      abc(6,1) = x6
      abc(7,1) = x7
      abc(8,1) = x8
      abc(9,1) = x9

c.... Find the coefficients of qy.

      abc(1,2) = y1
      abc(2,2) = y2
      abc(3,2) = y3
      abc(4,2) = y4
      abc(5,2) = y5
      abc(6,2) = y6
      abc(7,2) = y7
      abc(8,2) = y8
      abc(9,2) = y9

c.... Find the coefficients of qz.

      abc(1,3) = z1
      abc(2,3) = z2
      abc(3,3) = z3
      abc(4,3) = z4
      abc(5,3) = z5
      abc(6,3) = z6
      abc(7,3) = z7
      abc(8,3) = z8
      abc(9,3) = z9

c.... Find the coefficients of qxy.

      abc(1,4) = x1 * y1
      abc(2,4) = x2 * y2
      abc(3,4) = x3 * y3
      abc(4,4) = x4 * y4
      abc(5,4) = x5 * y5
      abc(6,4) = x6 * y6
      abc(7,4) = x7 * y7
      abc(8,4) = x8 * y8
      abc(9,4) = x9 * y9

c.... Find the coefficients of qyz.

      abc(1,5) = y1 * z1
      abc(2,5) = y2 * z2
      abc(3,5) = y3 * z3
      abc(4,5) = y4 * z4
      abc(5,5) = y5 * z5
      abc(6,5) = y6 * z6
      abc(7,5) = y7 * z7
      abc(8,5) = y8 * z8
      abc(9,5) = y9 * z9

c.... Find the coefficients of qzx.

      abc(1,6) = z1 * x1
      abc(2,6) = z2 * x2
      abc(3,6) = z3 * x3
      abc(4,6) = z4 * x4
      abc(5,6) = z5 * x5
      abc(6,6) = z6 * x6
      abc(7,6) = z7 * x7
      abc(8,6) = z8 * x8
      abc(9,6) = z9 * x9

c.... Find the coefficients of qxx.

      abc(1,7) = x1 * x1
      abc(2,7) = x2 * x2
      abc(3,7) = x3 * x3
      abc(4,7) = x4 * x4
      abc(5,7) = x5 * x5
      abc(6,7) = x6 * x6
      abc(7,7) = x7 * x7
      abc(8,7) = x8 * x8
      abc(9,7) = x9 * x9

c.... Find the coefficients of qyy.

      abc(1,8) = y1 * y1
      abc(2,8) = y2 * y2
      abc(3,8) = y3 * y3
      abc(4,8) = y4 * y4
      abc(5,8) = y5 * y5
      abc(6,8) = y6 * y6
      abc(7,8) = y7 * y7
      abc(8,8) = y8 * y8
      abc(9,8) = y9 * y9

c.... Find the coefficients of qyy.

      abc(1,9) = z1 * z1
      abc(2,9) = z2 * z2
      abc(3,9) = z3 * z3
      abc(4,9) = z4 * z4
      abc(5,9) = z5 * z5
      abc(6,9) = z6 * z6
      abc(7,9) = z7 * z7
      abc(8,9) = z8 * z8
      abc(9,9) = z9 * z9

c.... Find the right-side constants.  Assume qc = -1.

      d(1) = 1.0
      d(2) = 1.0
      d(3) = 1.0
      d(4) = 1.0
      d(5) = 1.0
      d(6) = 1.0
      d(7) = 1.0
      d(8) = 1.0
      d(9) = 1.0

c.... Solve the nine simultaneous equations.

      call aptsolv (abc, d, 9, work, 9, tol, xyz, cba, xyzm, xyzr,
     &              dm, dr, nerr)

c.... See if a good fit was obtained.

      if (nerr .ne. 0) then           ! No good solution.
        if (ntry .ge. 10) then        ! Did 10 tries.

c....     See if any three of the vertex points are unique.

c....     Find the edge lengths.

          call aptvdis (ax, ay, az, bx, by, bz, 1, tol,
     &                  abx, aby, abz, ablen, nerra)

          call aptvdis (bx, by, bz, cx, cy, cz, 1, tol,
     &                  bcx, bcy, bcz, bclen, nerra)

          call aptvdis (cx, cy, cz, dx, dy, dz, 1, tol,
     &                  cdx, cdy, cdz, cdlen, nerra)

          call aptvdis (dx, dy, dz, ax, ay, az, 1, tol,
     &                  dax, day, daz, dalen, nerra)

          call aptvdis (ax, ay, az, cx, cy, cz, 1, tol,
     &                  acx, acy, acz, aclen, nerra)

          call aptvdis (bx, by, bz, dx, dy, dz, 1, tol,
     &                  bdx, bdy, bdz, bdlen, nerra)

          nver = 1                    ! Point "a".
          x1 = ax
          y1 = ay
          z1 = az
          if (ablen .ne. 0.0) then
            nver = 2                  ! Points "a" and "b".
            x2 = bx
            y2 = by
            z2 = bz
            if ((aclen .ne. 0.0)  .and.
     &          (bclen .ne. 0.0)) then
              nver = 3                ! Points "a", "b" and "c".
              x3 = cx
              y3 = cy
              z3 = cz
            elseif ((dalen .ne. 0.0)  .and.
     &              (bdlen .ne. 0.0)) then
              nver = 3                ! Points "a", "b" and "d".
              x3 = dx
              y3 = dy
              z3 = dz
            endif
          elseif (aclen .ne. 0.0) then
            nver = 2                  ! Points "a" and "c".
            x2 = cx
            y2 = cy
            z2 = cz
            if ((dalen .ne. 0.0)  .and.
     &          (cdlen .ne. 0.0)) then
              nver = 3                ! Points "a", "c" and "d".
              x3 = dx
              y3 = dy
              z3 = dz
            endif
          endif

          if (nver .eq. 3) then       ! Three distinct points exist.

            nerr = 0

c....       Find the coefficients of the equation of the plane.

            call aptpfit (x1, y1, z1, x2, y2, z2, x3, y3, z3, tol,
     &                    sc, sx, sy, sz, nerra)

            if (nerra .ne. 0) then    ! Still no good solution.
              nerr = 4
              go to 210
            endif

            qc  = sc
            qx  = sx
            qy  = sy
            qz  = sz
            qxy = 0.0
            qyz = 0.0
            qzx = 0.0
            qxx = 0.0
            qyy = 0.0
            qzz = 0.0

          endif                       ! Three distinct points exist.

          go to 210
        endif
        nerr = 0
        go to 110
      endif

c.... Store data for the quadric surface.

      qc  = -1.0
      qx  = xyz(1)
      qy  = xyz(2)
      qz  = xyz(3)
      qxy = xyz(4)
      qyz = xyz(5)
      qzx = xyz(6)
      qxx = xyz(7)
      qyy = xyz(8)
      qzz = xyz(9)

c.... Remove the random vector.

      rx = -xran
      ry = -yran
      rz = -zran

      call apttris (1, rx, ry, rz, qc, qx, qy, qz,
     &              qxy, qyz, qzx, qxx, qyy, qzz, tol, nerr)

c.... Normalize the coefficients.

      fact = 1.0
      if     (qc  .ne. 0.0) then
        fact = -1.0 / qc
      elseif (qx  .ne. 0.0) then
        fact =  1.0 / qx
      elseif (qy  .ne. 0.0) then
        fact =  1.0 / qy
      elseif (qz  .ne. 0.0) then
        fact =  1.0 / qz
      elseif (qxy .ne. 0.0) then
        fact =  1.0 / qxy
      elseif (qyz .ne. 0.0) then
        fact =  1.0 / qyz
      elseif (qzx .ne. 0.0) then
        fact =  1.0 / qzx
      elseif (qxx .ne. 0.0) then
        fact =  1.0 / qxx
      elseif (qyy .ne. 0.0) then
        fact =  1.0 / qyy
      elseif (qzz .ne. 0.0) then
        fact =  1.0 / qzz
      endif

      qc  = qc  * fact
      qx  = qx  * fact
      qy  = qy  * fact
      qz  = qz  * fact
      qxy = qxy * fact
      qyz = qyz * fact
      qzx = qzx * fact
      qxx = qxx * fact
      qyy = qyy * fact
      qzz = qzz * fact

  210 continue                        ! End of loop over rows.
cbugc***DEBUG begins.
cbug 9910 format (/ 'aptqhyp results.  nerr = ',i2)
cbug 9911 format (/ 'nerr =',i2,'.  1 = singular matrix.',
cbug     &  '  2 = large q residuals.  3 = large s residuals.')
cbug 9912 format (/ 'unknowns  qc =',1pe22.14 /
cbug     &          'qx,  qy,  qz =',1p3e22.14 /
cbug     &          'qxy, qyz, qzx=',1p3e22.14 /
cbug     &          'qxx, qyy, qzz=',1p3e22.14 )
cbug      write ( 3, 9910) nerr
cbug      if (nerr .ne. 0) then
cbug        write ( 3, 9911) nerr
cbug      endif
cbug      write ( 3, 9912) qc, qx, qy, qz, qxy, qyz, qzx, qxx, qyy, qzz
cbugc***DEBUG ends.

      return

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

UCRL-WEB-209832