subroutine aptrois (smat, inv, ax, ay, az, qc, qx, qy, qz,
     &                    qxy, qyz, qzx, qxx, qyy, qzz, tol, nerr)

ccbeg.
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
c
c                             SUBROUTINE APTROIS
c
c     call aptrois (smat, inv, ax, ay, az, qc, qx, qy, qz,
c    &              qxy, qyz, qzx, qxx, qyy, qzz, tol, nerr)
c
c     Version:  aptrois  Updated    1999 March 15 11:30.
c               aptrois  Originated 1990 October 16 15:00.
c
c     Author:   Arthur L. Edwards, LLNL, L-298, Telephone (925) 422-4123.
c
c
c     Purpose:  To find the new coefficients of the equation for a general
c               second-order surface in xyz space, resulting from a general
c               coordinate transformation (rotation, reflection, and/or
c               inversion) around the invariant point a = (ax, ay, az),
c               based on the transformation matrix smat (inv = 0) or its
c               inverse (inv = 1).
c
c               The equation for the surface is initially as follows:
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               After the transformation, replace x, y, z with
c
c                 x' = smat(1,1) * x + smat(1,2) * y + smat(1,3) * z
c                 y' = smat(2,1) * x + smat(2,2) * y + smat(2,3) * z
c                 z' = smat(3,1) * x + smat(3,2) * y + smat(3,3) * z  (inv = 0)
c
c                 x' = smat(1,1) * x + smat(2,1) * y + smat(3,1) * z
c                 y' = smat(1,2) * x + smat(2,2) * y + smat(3,2) * z
c                 z' = smat(1,3) * x + smat(2,3) * y + smat(3,3) * z  (inv = 1)
c
c               Note:  use subroutine aptmopv to transform points and vectors
c               with matrix smat.
c
c     Input:    smat, inv, ax, ay, az, qc, qx, qy, qz, qxy, qyz, qzx,
c               qxx, qyy, qzz, tol.
c
c     Output:   qc, qx, qy, qz, qxy, qyz, qzx, qxx, qyy, qzz, nerr.
c
c     Calls: apttris 
c
c     Glossary:
c
c     ax,ay,az  Input    The x, y, z coordinates of an invariant point "a".
c
c     inv       Input    The transformation option:
c                          0 to use the transformation matrix smat.
c                          1 to use the inverse of the transformation matrix
c                            smat (exchange rows and columns).
c
c     nerr      Output   Indicates an input error, if not zero:
c                          1 if inv is not 0 or 1.
c
c     qc        In/Out   Constant term in implicit surface equation.
c                          Zero only if surface passes through origin.
c                          Invariant to a general symmetry transformation.
c
c     qx,qy,qz  In/Out   Coefficients of x, y, z in implicit surface equation.
c                          All zero only if the center of symmetry of the
c                          surface is at the origin.
c
c     q..       In/Out   Coefficients of the second-order terms in 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.  All zero for a planar surface.
c                          The coefficients qxy, qyz, qzx are all zero only if
c                          the symmetry axes of the surface are aligned with the
c                          x, y and z axes, or the surface is a plane.
c                          The sum qxx + qyy + qzz is invariant to a general
c                          symmetry transformation.
c
c     smat      Input    The coordinate transformation matrix operator.
c                          It transforms a point (x, y, z) to the point
c                          (x', y', z') as follows:
c                            x' = smat(1,1) * x + smat(1,2) * y + smat(1,3) * z
c                            y' = smat(2,1) * x + smat(2,2) * y + smat(2,3) * z
c                            z' = smat(3,1) * x + smat(3,2) * y + smat(3,3) * z.
c                          The rows and columns of smat must be unit vectors,
c                          with each row orthogonal to the other rows, and each
c                          column orthogonal to the other columns.  For the
c                          inverse operation, the rows and columns of smat
c                          are interchanged.  See the APT subroutines with
c                          names beginning with aptinv, aptref, aptrot.
c
c     tol       Input    Numerical tolerance limit.
c                          On Cray computers, recommend 1.e-5 to 1.e-11.
c
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
ccend.

c.... Dimensioned arguments.

c---- Coordinate transformation matrix.
      dimension smat    (3,3)

c.... Local variables.

c---- Coefficient of x in equation for x.
      common /laptrois/ cxx
c---- Coefficient of y in equation for x.
      common /laptrois/ cxy
c---- Coefficient of z in equation for x.
      common /laptrois/ cxz
c---- Coefficient of x in equation for y.
      common /laptrois/ cyx
c---- Coefficient of y in equation for y.
      common /laptrois/ cyy
c---- Coefficient of z in equation for y.
      common /laptrois/ cyz
c---- Coefficient of x in equation for z.
      common /laptrois/ czx
c---- Coefficient of y in equation for z.
      common /laptrois/ czy
c---- Coefficient of z in equation for z.
      common /laptrois/ czz
c---- Distance of point "a" from origin.
      common /laptrois/ da
c---- Temporary value of qc.
      common /laptrois/ qcp
c---- Estimated error in qc.
      common /laptrois/ qcperr
c---- Temporary value of qx.
      common /laptrois/ qxp
c---- Estimated error in qx.
      common /laptrois/ qxperr
c---- Temporary value of qxx.
      common /laptrois/ qxxp
c---- Estimated error in qxx.
      common /laptrois/ qxxperr
c---- Temporary value of qxy.
      common /laptrois/ qxyp
c---- Estimated error in qxy.
      common /laptrois/ qxyperr
c---- Temporary value of qy.
      common /laptrois/ qyp
c---- Estimated error in qy.
      common /laptrois/ qyperr
c---- Temporary value of qyy.
      common /laptrois/ qyyp
c---- Estimated error in qyy.
      common /laptrois/ qyyperr
c---- Temporary value of qyz.
      common /laptrois/ qyzp
c---- Estimated error in qyz.
      common /laptrois/ qyzperr
c---- Temporary value of qz.
      common /laptrois/ qzp
c---- Estimated error in qz.
      common /laptrois/ qzperr
c---- Temporary value of qzx.
      common /laptrois/ qzxp
c---- Estimated error in qzx.
      common /laptrois/ qzxperr
c---- Temporary value of qzz.
      common /laptrois/ qzzp
c---- Estimated error in qzz.
      common /laptrois/ qzzperr
cbugc***DEBUG begins.
cbugc---- Index in smat.
cbug      common /laptrois/ i
cbugc---- Index in smat.
cbug      common /laptrois/ j
cbug 9901 format (/ 'aptrois transforming an implicit surface.  inv=',i2,
cbug     &  '  tol=',1pe13.5)
cbug 9902 format ('  smat=',3(/ 14x,1p3e22.14))
cbug 9903 format (/
cbug     &  '  ax,ay,az=   ',1p3e22.14 //
cbug     &  '  qc=         ',1pe22.14 /
cbug     &  '  qx,qy,qz=   ',1p3e22.14 /
cbug     &  '  qxy,qyz,qzx=',1p3e22.14 /
cbug     &  '  qxx,qyy,qzz=',1p3e22.14)
cbug      write ( 3, 9901) inv, tol
cbug      write ( 3, 9902) ((smat(i,j), j = 1, 3), i = 1, 3)
cbug      write ( 3, 9903) ax, ay, az, qc, qx, qy, qz,
cbug     &  qxy, qyz, qzx, qxx, qyy, qzz
cbugc***DEBUG ends.

c.... Initialize.

      nerr = 0

c.... Test for input errors.

      if ((inv .lt. 0) .or. (inv .gt. 1)) then
        nerr = 1
cbugcbugc***DEBUG begins.
cbugcbug 9904   format (/ "inv is not 0 or 1")
cbugcbug        write ( 3, 9904)
cbugcbugc***DEBUG ends.
        go to 210
      endif

c.... Find the distance of point "a" from the origin.

      da = sqrt (ax**2 + ay**2 + az**2)

c.... Translate the invariant point "a" to the origin.

c---- Translate point "a" to origin.
      if (da .gt. tol) then

        call apttris (0, ax, ay, az, qc, qx, qy, qz, qxy, qyz, qzx,
     &                qxx, qyy, qzz, tol, nerr)
cbugcbugc***DEBUG begins.
cbugcbug 9801 format (/ 'aptrois DEBUG 1:' /
cbugcbug     &  '  qc=         ',1pe22.14 /
cbugcbug     &  '  qx,qy,qz=   ',1p3e22.14 /
cbugcbug     &  '  qxy,qyz,qzx=',1p3e22.14 /
cbugcbug     &  '  qxx,qyy,qzz=',1p3e22.14)
cbugcbug      write ( 3, 9801) qc, qx, qy, qz,
cbugcbug     &  qxy, qyz, qzx, qxx, qyy, qzz
cbugcbugc***DEBUG ends.

c---- Tested da.
      endif

c.... Find the transformation coefficients.

c---- Operate with matrix smat.
      if (inv .eq. 0) then

        cxx = smat(1,1)
        cxy = smat(1,2)
        cxz = smat(1,3)
        cyx = smat(2,1)
        cyy = smat(2,2)
        cyz = smat(2,3)
        czx = smat(3,1)
        czy = smat(3,2)
        czz = smat(3,3)

c---- Operate with the inverse of smat.
      elseif (inv .eq. 1) then

        cxx = smat(1,1)
        cxy = smat(2,1)
        cxz = smat(3,1)
        cyx = smat(1,2)
        cyy = smat(2,2)
        cyz = smat(3,2)
        czx = smat(1,3)
        czy = smat(2,3)
        czz = smat(3,3)

c---- Tested inv.
      endif

c.... Find the new implicit equation coefficients.

      qcp  = qc
      qxp  = cxx * qx + cxy * qy + cxz * qz
      qyp  = cyy * qy + cyz * qz + cyx * qx
      qzp  = czz * qz + czx * qx + czy * qy
      qxyp = (cxx * cyy + cxy * cyx) * qxy +
     &       (cxy * cyz + cxz * cyy) * qyz +
     &       (cxz * cyx + cxx * cyz) * qzx +
     &       2.0 * (cxx * cyx * qxx + cxy * cyy * qyy + cxz * cyz * qzz)
      qyzp = (cyy * czz + cyz * czy) * qyz +
     &       (cyz * czx + cyx * czz) * qzx +
     &       (cyx * czy + cyy * czx) * qxy +
     &       2.0 * (cyy * czy * qyy + cyz * czz * qzz + cyx * czx * qxx)
      qzxp = (czz * cxx + czx * cxz) * qzx +
     &       (czx * cxy + czy * cxx) * qxy +
     &       (czy * cxz + czz * cxy) * qyz +
     &       2.0 * (czz * cxz * qzz + czx * cxx * qxx + czy * cxy * qyy)
      qxxp = cxx * cxy * qxy + cxy * cxz * qyz + cxz * cxx * qzx +
     &       cxx**2 * qxx + cxy**2 * qyy + cxz**2 * qzz
      qyyp = cyy * cyz * qyz + cyz * cyx * qzx + cyx * cyy * qxy +
     &       cyy**2 * qyy + cyz**2 * qzz + cyx**2 * qxx
      qzzp = czz * czx * qzx + czx * czy * qxy + czy * czz * qyz +
     &       czz**2 * qzz + czx**2 * qxx + czy**2 * qyy

cbugcbugc***DEBUG begins.
cbugcbug 9802 format (/ 'aptrois DEBUG 2:' /
cbugcbug     &  '  qc= (all p) ',1pe22.14 /
cbugcbug     &  '  qx,qy,qz=   ',1p3e22.14 /
cbugcbug     &  '  qxy,qyz,qzx=',1p3e22.14 /
cbugcbug     &  '  qxx,qyy,qzz=',1p3e22.14)
cbugcbug      write ( 3, 9802) qcp, qxp, qyp, qzp,
cbugcbug     &  qxyp, qyzp, qzxp, qxxp, qyyp, qzzp
cbugcbugc***DEBUG ends.
c.... See if small values are to be truncated to zero.

c---- Test for truncation to zero.
      if (tol .gt. 0.0) then

        qcperr  = (abs (qc)) * tol
        qxperr  = (abs (cxx * qx) + abs (cxy * qy) + abs (cxz * qz)) *
     &            2.0 * tol
        qyperr  = (abs (cyy * qy) + abs (cyz * qz) + abs (cyx * qx)) *
     &            2.0 * tol
        qzperr  = (abs (czz * qz) + abs (czx * qx) + abs (czy * qy)) *
     &            2.0 * tol
        qxyperr = (abs (cxx * cyy * qxy) + abs (cxy * cyx * qxy) +
     &             abs (cxy * cyz * qyz) + abs (cxz * cyy * qyz) +
     &             abs (cxz * cyx * qzx) + abs (cxx * cyz * qzx) +
     &             2.0 * (abs (cxx * cyx * qxx) +
     &                    abs (cxy * cyy * qyy) +
     &                    abs (cxz * cyz * qzz))) * 3.0 * tol
        qyzperr = (abs (cyy * czz * qyz) + abs (cyz * czy * qyz) +
     &             abs (cyz * czx * qzx) + abs (cyx * czz * qzx) +
     &             abs (cyx * czy * qxy) + abs (cyy * czx * qxy) +
     &             2.0 * (abs (cyy * czy * qyy) +
     &                    abs (cyz * czz * qzz) +
     &                    abs (cyx * czx * qxx))) * 3.0 * tol
        qzxperr = (abs (czz * cxx * qzx) + abs (czx * cxz * qzx) +
     &             abs (czx * cxy * qxy) + abs (czy * cxx * qxy) +
     &             abs (czy * cxz * qyz) + abs (czz * cxy * qyz) +
     &             2.0 * (abs (czz * cxz * qzz) +
     &                    abs (czx * cxx * qxx) +
     &                    abs (czy * cxy * qyy))) * 3.0 * tol
        qxxperr = (abs (cxx * cxy * qxy) +
     &             abs (cxy * cxz * qyz) +
     &             abs (cxz * cxx * qzx) +
     &             abs (cxx**2 * qxx) +
     &             abs (cxy**2 * qyy) +
     &             abs (cxz**2 * qzz)) * 3.0 * tol
        qyyperr = (abs (cyy * cyz * qyz) +
     &             abs (cyz * cyx * qzx) +
     &             abs (cyx * cyy * qxy) +
     &             abs (cyy**2 * qyy) +
     &             abs (cyz**2 * qzz) +
     &             abs (cyx**2 * qxx)) * 3.0 * tol
        qzzperr = (abs (czz * czx * qzx) +
     &             abs (czx * czy * qxy) +
     &             abs (czy * czz * qyz) +
     &             abs (czz**2 * qzz) +
     &             abs (czx**2 * qxx) +
     &             abs (czy**2 * qyy)) * 3.0 * tol
cbugcbugc***DEBUG begins.
cbugcbug 9803 format (/ 'aptrois DEBUG 3:' /
cbugcbug     &  '  qc=(all err)',1pe22.14 /
cbugcbug     &  '  qx,qy,qz=   ',1p3e22.14 /
cbugcbug     &  '  qxy,qyz,qzx=',1p3e22.14 /
cbugcbug     &  '  qxx,qyy,qzz=',1p3e22.14)
cbugcbug      write ( 3, 9803) qcperr, qxperr, qyperr, qzperr,
cbugcbug     &  qxyperr, qyzperr, qzxperr, qxxperr, qyyperr, qzzperr
cbugcbugc***DEBUG ends.

        if (abs (qcp)  .le. qcperr) then
          qcp = 0.0
        endif

        if (abs (qxp)  .le. qxperr) then
          qxp = 0.0
        endif

        if (abs (qyp)  .le. qyperr) then
          qyp = 0.0
        endif

        if (abs (qzp)  .le. qzperr) then
          qzp = 0.0
        endif

        if (abs (qxyp) .le. qxyperr) then
          qxyp = 0.0
        endif

        if (abs (qyzp) .le. qyzperr) then
          qyzp = 0.0
        endif

        if (abs (qzxp) .le. qzxperr) then
          qzxp = 0.0
        endif

        if (abs (qxxp) .le. qxxperr) then
          qxxp = 0.0
        endif

        if (abs (qyyp) .le. qyyperr) then
          qyyp = 0.0
        endif

        if (abs (qzzp) .le. qzzperr) then
          qzzp = 0.0
        endif

c---- Tested tol.
      endif

c.... Store the new coefficients.

      qc  = qcp
      qx  = qxp
      qy  = qyp
      qz  = qzp
      qxy = qxyp
      qyz = qyzp
      qzx = qzxp
      qxx = qxxp
      qyy = qyyp
      qzz = qzzp
cbugcbugc***DEBUG begins.
cbugcbug 9804 format (/ 'aptrois DEBUG 4:' /
cbugcbug     &  '  qc=         ',1pe22.14 /
cbugcbug     &  '  qx,qy,qz=   ',1p3e22.14 /
cbugcbug     &  '  qxy,qyz,qzx=',1p3e22.14 /
cbugcbug     &  '  qxx,qyy,qzz=',1p3e22.14)
cbugcbug      write ( 3, 9804) qc, qx, qy, qz,
cbugcbug     &  qxy, qyz, qzx, qxx, qyy, qzz
cbugcbugc***DEBUG ends.

c.... Translate the origin back to the invariant point "a".

c---- Translate origin to point "a".
      if (da .gt. tol) then

      call apttris (1, ax, ay, az, qc, qx, qy, qz, qxy, qyz, qzx,
     &              qxx, qyy, qzz, tol, nerr)
cbugcbugc***DEBUG begins.
cbugcbug 9805 format (/ 'aptrois DEBUG 5:' /
cbugcbug     &  '  qc=         ',1pe22.14 /
cbugcbug     &  '  qx,qy,qz=   ',1p3e22.14 /
cbugcbug     &  '  qxy,qyz,qzx=',1p3e22.14 /
cbugcbug     &  '  qxx,qyy,qzz=',1p3e22.14)
cbugcbug      write ( 3, 9805) qc, qx, qy, qz,
cbugcbug     &  qxy, qyz, qzx, qxx, qyy, qzz
cbugcbugc***DEBUG ends.

c---- Tested da.
      endif

c.... Truncate small coefficients.

      psq   = qx**2  + qy**2  + qz**2
      qsq   = qxy**2 + qyz**2 + qzx**2
      ssq   = qxx**2 + qyy**2 + qzz**2
      if (qx**2  .le. tol**2 * psq) qx  = 0.0
      if (qy**2  .le. tol**2 * psq) qy  = 0.0
      if (qx**2  .le. tol**2 * psq) qx  = 0.0
      if (qxy**2 .le. tol**2 * qsq) qxy = 0.0
      if (qyz**2 .le. tol**2 * qsq) qyz = 0.0
      if (qzx**2 .le. tol**2 * qsq) qzx = 0.0
      if (qxx**2 .le. tol**2 * ssq) qxx = 0.0
      if (qyy**2 .le. tol**2 * ssq) qyy = 0.0
      if (qzz**2 .le. tol**2 * ssq) qzz = 0.0
cbugc***DEBUG begins.
cbug 9905 format (/ 'aptrois results:' /
cbug     &  '  qc=         ',1pe22.14 /
cbug     &  '  qx,qy,qz=   ',1p3e22.14 /
cbug     &  '  qxy,qyz,qzx=',1p3e22.14 /
cbug     &  '  qxx,qyy,qzz=',1p3e22.14)
cbug      write ( 3, 9905) qc, qx, qy, qz,
cbug     &  qxy, qyz, qzx, qxx, qyy, qzz
cbugc***DEBUG ends.

  210 return

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

UCRL-WEB-209832