subroutine aptprcy (nopt, ax, ay, az, bx, by, bz, rcyl,
     &                    px, py, pz, np, tol, qx, qy, qz, nerr)

ccbeg.
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
c
c                             SUBROUTINE APTPRCY
c
c     call aptprcy (nopt, ax, ay, az, bx, by, bz, rcyl,
c    &              px, py, pz, np, tol, qx, qy, qz, nerr)
c
c     Version:  aptprcy  Updated    1990 November 29 10:50.
c               aptprcy  Originated 1990 October 3 11:40.
c
c     Author:   Arthur L. Edwards, LLNL, L-298, Telephone (925) 422-4123.
c
c
c     Purpose:  To project the np points p = (px, py, pz) onto the cylindrical
c               surface which has an axis passing through point a = (ax, ay, az)
c               in the direction of the vector b = (bx, by, bz), and a radius
c               of rcyl.  The projection option is specified by nopt.
c               The projection of each point "p" is point q = (qx, qy, qz).
c
c               Flag nerr indicates any input error.
c
c     Input:    nopt, ax, ay, az, bx, by, bz, rcyl, px, py, pz, np, tol.
c
c     Output:   qx, qy, qz, nerr.
c
c     Calls: aptmopv, aptrotv, apttran, aptvunb 
c               
c
c     Glossary:
c
c     ax,ay,az  Input    The x, y, z coordinates of a point on the axis of
c                          the cylindrical projection surface.
c
c     bx,by,bz  Input    The x, y, z components of the vector parallel to the
c                          axis of the cylindrical projection surface.
c
c     nerr      Output   Indicates an input error, if not 0.
c                          1 if np is not positive.
c                          2 if the vector "b" is too short, based on tol.
c                          3 if nopt is not 0, 1 or 2.
c
c     nopt      Input    Each vector "ap", from point "a" to each point "p", has
c                          a component in the radial direction from the axis of
c                          the cylinder and a component in the axial direction,
c                          relative to point "a".  The projection options are:
c                          0 to project in the cylindrical radial direction.
c                            This gives the radial component a length rcyl, and
c                            leaves the axial component unchanged.
c                          1 to project in the spherical radial direction, based
c                            on point "a".  This gives the radial component a
c                            length rcyl, and multiplies the axial component by
c                            the ratio of rcyl to the initial radial component.
c                          2 to project the radial component in the cylindrical
c                            radial direction, giving it a length rcyl, and to
c                            replace the axial component with the cosine of the
c                            angle formed by the axis, point "a", and point "p".
c                            This is a projection which preserves relative areas
c                            when projecting points from a sphere centered at
c                            point "a" onto the cylinder.
c
c     np        Input    Size of arrays px, py, pz, qx, qy, qz.
c                          The number of points projected.
c
c     px,py,pz  Input    The x, y, z coordinates of point "p".  Size np.
c
c     qx,qy,qz  Output   The x, y, z coordinates of the projection of the point
c                          "p" on the projection surface, which is a cylinder of
c                          radius rcyl with an axis through point "a", parallel
c                          to the vector "b".  For any point "p" which is on
c                          the axis of the cylinder, based on tol, the
c                          coordinates of point "q" will be very large.
c                          Size np.
c
c     rcyl      Input    The radius of the cylindrical projection surface,
c                          measured from the axis, which passes through point
c                          "a" in the direction of vector "b".
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 x of point "p".
      dimension px      (1)
c---- Coordinate y of point "p".
      dimension py      (1)
c---- Coordinate z of point "p".
      dimension pz      (1)
c---- Coordinate x of point "q".
      dimension qx      (1)
c---- Coordinate y of point "q".
      dimension qy      (1)
c---- Coordinate z of point "q".
      dimension qz      (1)

c.... Local variables.


c---- A very big number.
      common /laptprcy/ big

c---- Distance between points "a" and "p".
      common /laptprcy/ dap
c---- Distance from the axis to point "p".
      common /laptprcy/ daxis

c---- A very small number.
      common /laptprcy/ fuz

c---- Index in arrays.
      common /laptprcy/ n
c---- Rotation matrix.
      common /laptprcy/ rotm   (3,3)
c---- Component x of unit vector "ub".
      common /laptprcy/ ubx
c---- Component y of unit vector "ub".
      common /laptprcy/ uby
c---- Component z of unit vector "ub".
      common /laptprcy/ ubz
c---- Length of axis vector "b".
      common /laptprcy/ vlenb
cbugc***DEBUG begins.
cbug 9901 format (/ 'aptprcy projecting points onto a cylinder:' /
cbug     &  '  rcyl=',1pe22.14,'  nopt=',i2 /
cbug     &  '  The axis goes through the point:' /
cbug     &  '  ax,ay,az=   ',1p3e22.14 /
cbug     &  '  parallel to the vector:' /
cbug     &  '  bx,by,bz=   ',1p3e22.14 /
cbug     &  '  The points projected are:' /
cbug     &  (i3,"  px,py,pz=",1p3e22.14))
cbug      write ( 3, 9901) rcyl, nopt, ax, ay, az, bx, by, bz,
cbug     &  (n, px(n), py(n), pz(n), n = 1, np)
cbugc***DEBUG ends.

c.... Initialize.

c---- A very big number.
      big = 1.e+99

c---- A very small number.
      fuz = 1.e-99

      nerr = 0

c.... Test for input errors.

      if (np .le. 0) then
        nerr = 1
cbugc***DEBUG begins.
cbug      write ( 3, '(/ "np = 0")')
cbugc***DEBUG ends.
        go to 210
      endif

c.... Find the length of the axis vector "b".

      call aptvunb (bx, by, bz, 1, 0., ubx, uby, ubz, vlenb, nerr)

      if (vlenb .le. tol) then
        nerr = 2
cbugc***DEBUG begins.
cbug      write ( 3, '(/ "Vector b is too short.")')
cbugc***DEBUG ends.
        go to 210
      endif

      if ((nopt .lt. 0) .or. (nopt .gt. 2)) then
        nerr = 3
cbugc***DEBUG begins.
cbug      write ( 3, '(/ "nop not between 0 and 2")')
cbugc***DEBUG ends.
        go to 210
      endif

c.... Find the rotation matrix to rotate vector "b" onto the z axis.

      call aptrotv (bx, by, bz, 0., 0., 1., tol, rotm, nerr)

c.... Initialize the projected points "q".

c---- Loop over data.
      do 110 n = 1, np

        qx(n) = px(n)
        qy(n) = py(n)
        qz(n) = pz(n)

c---- End of loop over data.
  110 continue

c.... Move the origin to point "a".

      call apttran (ax, ay, az, qx, qy, qz, np, tol, nerr)

c.... Rotate the vector "b" to the z axis.

      call aptmopv (rotm, 0, 0., 0., 0., qx, qy, qz, np, tol, nerr)

c.... Find the projection option.

      if (nopt .eq. 0) then

c....   Project in the cylindrical radial direction.
c....     Does not change the axial component, relative to point "a".

c---- Loop over data.
        do 120 n = 1, np

          daxis = sqrt (qx(n)**2 + qy(n)**2)

          qx(n) = rcyl * qx(n) / (daxis + fuz)
          qy(n) = rcyl * qy(n) / (daxis + fuz)

          if (daxis .le. tol) then
            qx(n) = big
            qy(n) = big
          endif

c---- End of loop over data.
  120   continue

      elseif (nopt .eq. 1) then

c....   Project in the spherical radial direction, based on point "a".

c---- Loop over data.
        do 130 n = 1, np

          daxis = sqrt (qx(n)**2 + qy(n)**2)

          qx(n) = rcyl * qx(n) / (daxis + fuz)
          qy(n) = rcyl * qy(n) / (daxis + fuz)
          qz(n) = rcyl * qz(n) / (daxis + fuz)

          if (daxis .le. tol) then
            qx(n) = big
            qy(n) = big
            qz(n) = big
          endif

c---- End of loop over data.
  130   continue

      elseif (nopt .eq. 2) then

c....   Project the radial components in the cylindrical radial direction.
c....     Replace the axial component with the cosine of the angle formed
c....     by the axis, point "a", and point "p".

c---- Loop over data.
        do 140 n = 1, np

          daxis = sqrt (qx(n)**2 + qy(n)**2)
          dap   = sqrt (qx(n)**2 + qy(n)**2 + qz(n)**2)

          qx(n) = rcyl * qx(n) / (daxis + fuz)
          qy(n) = rcyl * qy(n) / (daxis + fuz)
          qz(n) =        qz(n) / (dap   + fuz)

          if (daxis .le. tol) then
            qx(n) = big
            qy(n) = big
          endif
          if (dap .le. tol) then
            qz(n) = big
          endif

c---- End of loop over data.
  140   continue

c---- Tested nopt.
      endif

c.... Rotate the z axis back to vector "b".

      call aptmopv (rotm, 1, 0., 0., 0., qx, qy, qz, np, tol, nerr)

c.... Restore the original origin.

      call apttran (-ax, -ay, -az, qx, qy, qz, np, tol, nerr)
cbugc***DEBUG begins.
cbug 9902 format (/ 'aptprcy results:' /
cbug     &  (i3,'  qx,qy,qz=',1p3e22.14))
cbug      write ( 3, 9902) (n, qx(n), qy(n), qz(n), n = 1, np)
cbugc***DEBUG ends.

  210 return

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

UCRL-WEB-209832