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

ccbeg.
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
c
c                             SUBROUTINE APTQPER
c
c     call aptqper (ac, ax, ay, az, axy, ayz, azx, axx, ayy, azz,
c    &              bc, bx, by, bz, bxy, byz, bzx, bxx, byy, bzz, tol,
c    &              cc, cx, cy, cz, cxy, cyz, czx, cxx, cyy, czz, nerr)
c
c     Version:  aptqper  Updated    2000 May 24 14:00.
c               aptqper  Originated 2000 May 24 14:00.
c
c     Author:   Arthur L. Edwards, LLNL, L-298, Telephone (925) 422-4123.
c
c
c     Purpose:  For the two families of quadric surfaces represented by
c               quadric surfaces A(x,y,z) and B(x,y,z), with arbitrary values
c               of the constant terms ac and bc:
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               to find the quadric surface C(x,y,z) representing the locus
c               of points where the families A and B are perpendicular to
c               each other:
c
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               Method:  the two 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               Then C(x,y,z) = AN dot BN = 0, where the normal vectors are
c               perpendicular.
c
c     Input:    ac, ax, ay, az, axy, ayz, azx, axx, ayy, azz,
c               bc, bx, by, bz, bxy, byz, bzx, bxx, byy, bzz, tol.
c
c     Output:   cc, cx, cy, cz, cxy, cyz, czx, cxx, cyy, czz, nerr.
c
c     Calls: aptaxis (source, binary in aptaxis (source, binary in Compass 
c               Cluster East machine, ~edwards/work/apt/src) 
c
c     Glossary:
c
c     ac, ...   Input    Coefficients of the implicit equation for
c                          quadric surface A:
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
c                          quadric surface B:
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, ...   Output   Coefficients of the implicit equation for
c                          quadric surface 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     nerr      Output   Indicates an input error, if not zero:
c                          1 if the equation of quadric surface C is bad.
c
c     tol       Input    Numerical tolerance limit.  With 64-bit floating point
c                          numbers, 1.e-5 to 1.e-11 is recommended.
c
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
ccend.

c.... Local variables.

      dimension rotm    (3,3)         ! Coordinate transformation matrix.

cbugc***DEBUG begins.
cbug 9901 format (/ 'aptqper finding quadric surface where two',
cbug     &  ' quadric surface families' /
cbug     &  ' are perpendicular.','  tol=',1pe13.5)
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      write ( 3, 9901) tolx
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
cbugc***DEBUG ends.

c.... Initialize.

      nerr  = 0

c.... Find the coefficients of quadric surface C.

      cc  = ax * bx + ay * by + az * bz
      cx  = 2.0 * axx * bx + 2.0 * ax * bxx +
     &      ay * bxy + axy * by + az * bzx + azx * bz
      cy  = 2.0 * ayy * by + 2.0 * ay * byy +
     &      az * byz + ayz * bz + ax * bxy + axy * bx
      cz  = 2.0 * azz * bz + 2.0 * az * bzz +
     &      ax * bzx + azx * bx + ay * byz + ayz * by
      cxy = 2.0 * axx * bxy + 2.0 * axy * bxx +
     &      2.0 * ayy * bxy + 2.0 * axy * byy +
     &      azx * byz + ayz * bzx
      cyz = 2.0 * ayy * byz + 2.0 * ayz * byy +
     &      2.0 * azz * byz + 2.0 * ayz * bzz +
     &      axy * bzx + azx * bxy
      czx = 2.0 * azz * bzx + 2.0 * azx * bzz +
     &      2.0 * axx * bzx + 2.0 * azx * bxx +
     &      ayz * bxy + axy * byz
      cxx = 4.0 * axx * bxx + axy * bxy + azx * bzx
      cyy = 4.0 * ayy * byy + ayz * byz + axy * bxy
      czz = 4.0 * azz * bzz + azx * bzx + ayz * byz

cbugcbugc***DEBUG begins.
cbugcbug      write ( 3, 9992) cc, cx, cy, cz, cxy, cyz, czx, cxx, cyy, czz
cbugcbugc***DEBUG ends.

c.... Replace coefficients with zero, if within truncation limits.

      if (tol .gt. 0.0) then          ! Truncate small coefficients to zero.

      ccerr  = abs (ax * bx) + abs (ay * by) + abs (az * bz)
      cxerr  = 2.0 * abs (axx * bx) + 2.0 * abs (ax * bxx) +
     &         abs (ay * bxy) + abs (axy * by) +
     &         abs (az * bzx) + abs (azx * bz)
      cyerr  = 2.0 * abs (ayy * by) + 2.0 * abs (ay * byy) +
     &         abs (az * byz) + abs (ayz * bz) +
     &         abs (ax * bxy) + abs (axy * bx)
      czerr  = 2.0 * abs (azz * bz) + 2.0 * abs (az * bzz) +
     &         abs (ax * bzx) + abs (azx * bx) +
     &         abs (ay * byz) + abs (ayz * by)
      cxyerr = 2.0 * abs (axx * bxy) + 2.0 * abs (axy * bxx) +
     &         2.0 * abs (ayy * bxy) + 2.0 * abs (axy * byy) +
     &         abs (azx * byz) + abs (ayz * bzx)
      cyzerr = 2.0 * abs (ayy * byz) + 2.0 * abs (ayz * byy) +
     &         2.0 * abs (azz * byz) + 2.0 * abs (ayz * bzz) +
     &         abs (axy * bzx) + abs (azx * bxy)
      czxerr = 2.0 * abs (azz * bzx) + 2.0 * abs (azx * bzz) +
     &         2.0 * abs (axx * bzx) + 2.0 * abs (azx * bxx) +
     &         abs (ayz * bxy) + abs (axy * byz)
      cxxerr = 4.0 * abs (axx * bxx) + abs (axy * bxy) + abs (azx * bzx)
      cyyerr = 4.0 * abs (ayy * byy) + abs (ayz * byz) + abs (axy * bxy)
      czzerr = 4.0 * abs (azz * bzz) + abs (azx * bzx) + abs (ayz * byz)

      if (abs (cc)  .le. tol * ccerr ) cc  = 0.0
      if (abs (cx)  .le. tol * cxerr ) cx  = 0.0
      if (abs (cy)  .le. tol * cyerr ) cy  = 0.0
      if (abs (cz)  .le. tol * czerr ) cz  = 0.0
      if (abs (cxy) .le. tol * cxyerr) cxy = 0.0
      if (abs (cyz) .le. tol * cyzerr) cyz = 0.0
      if (abs (czx) .le. tol * czxerr) czx = 0.0
      if (abs (cxx) .le. tol * cxxerr) cxx = 0.0
      if (abs (cyy) .le. tol * cyyerr) cyy = 0.0
      if (abs (czz) .le. tol * czzerr) czz = 0.0

cbugcbugc***DEBUG begins.
cbugcbug      write ( 3, 9992) cc, cx, cy, cz, cxy, cyz, czx, cxx, cyy, czz
cbugcbugc***DEBUG ends.


      endif                           ! Truncated small coefficients to zero.

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

c.... See if quadric surface C is real, not imaginary or impossible.

      dc   = cc
      dx   = cx
      dy   = cy
      dz   = cz
      dxy  = cxy
      dyz  = cyz
      dzx  = czx
      dxx  = cxx
      dyy  = cyy
      dzz  = czz

      call aptaxis (dc, dx, dy, dz, dxy, dyz, dzx, dxx, dyy, dzz,
     &              tol, cenx, ceny, cenz, rotm, ntype, nerra)

cbugcbugc***DEBUG begins.
cbugcbug 9998 format ('DEBUG ntype=',i3,' nerra=',i3)
cbugcbug      write ( 3, 9998) ntype, nerra
cbugcbugc***DEBUG ends.

      if ((nerra .ne. 0)   .or.
     &    (ntype .lt. 0)   .or.
     &    (ntype .gt. 16)) then
        nerr = 1                      ! Imaginary or impossible surface.
      endif

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

  999 continue
cbugc***DEBUG begins.
cbug 9991 format (/ 'aptqper results.  nerr=',i2)
cbug 9992 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, 9991) nerr
cbug      write ( 3, 9992) cc, cx, cy, cz, cxy, cyz, czx, cxx, cyy, czz
cbugc***DEBUG ends.

      return

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

UCRL-WEB-209832