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

ccbeg.
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
c
c                             SUBROUTINE APTPRSP
c
c     call aptprsp (nopt, ax, ay, az, bx, by, bz, rsph,
c    &              px, py, pz, np, tol, qx, qy, qz, nerr)
c
c     Version:  aptprsp  Updated    1990 November 29 10:50.
c               aptprsp  Originated 1990 October 4 17:30.
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 spherical
c               surface centered at the point a = (ax, ay, az), with the polar
c               axis in the direction of the vector b = (bx, by, bz), and with
c               radius rsph.  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, rsph, 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 the center of the sphere.
c
c     bx,by,bz  Input    The x, y, z components of the vector parallel to the
c                          polar axis of the sphere.
c
c     nerr      Output   Indicates an input error, if not 0.
c                          1 if np is not positive.
c                          2 if nopt is not 0, 1 or 2.
c                          3 if rsph is not positive.
c                          4 if the vector "b" is too short, based on tol,
c                            and nopt is not 0.
c
c     nopt      Input    Each vector "ap", from point "a" to each point "p", has
c                          a radial component "apr" perpendicular to the polar
c                          axis, and an axial component "apz" parallel to the
c                          polar axis.  The projection options are:
c                          0 to project in the spherical radial direction.
c                            This makes the vector "aq" parallel to "ap", with a
c                            length rsph.  Any point "p" at point "a" is
c                            projected to very large coordinates.
c                          1 to project in the direction perpendicular to the
c                            polar axis.  This does not change the vector "apz",
c                            except that magnitudes greater than rsph are
c                            reduced to rsph, putting the point "q" on a pole.
c                            Any point "p" on the polar axis is projected to
c                            very large coordinates.
c                          2 to project in the axial direction.  This does not
c                            change the vector "apr", except that magnitudes
c                            greater than rsph are reduced to rsph, putting the
c                            point "q" on the equator.  Any point "p" on the
c                            equatorial plane is projected to very large
c                            coordinates.
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 sphere
c                          centered at point "a", with a polar axis parallel to
c                          vector "b", and a radius rsph.  The coordinates of
c                          of point "q" will be very large for any point "p"
c                          which, based on tol, is:
c                          For nopt = 0, at point "a".
c                          For nopt = 1, on the polar axis.
c                          For nopt = 2, on the equatorial plane.
c                          Size np.
c
c     rsph      Input    The radius of the spherical projection surface,
c                          measured from point "a".  Must be positive.
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---- Argument of square root.
      common /laptprsp/ arg

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

c---- Distance between points "a" and "p".
      common /laptprsp/ dap
c---- Distance from the axis to point "p".
      common /laptprsp/ daxis
c---- Distance from the equatorial plane.
      common /laptprsp/ deq
c---- Projection factor.
      common /laptprsp/ fact

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

c---- Index in arrays.
      common /laptprsp/ n
c---- Rotation matrix.
      common /laptprsp/ rotm   (3,3)
c---- Component x of unit vector "ub".
      common /laptprsp/ ubx
c---- Component y of unit vector "ub".
      common /laptprsp/ uby
c---- Component z of unit vector "ub".
      common /laptprsp/ ubz
c---- Length of axis vector "b".
      common /laptprsp/ vlenb
cbugc***DEBUG begins.
cbug 9901 format (/ 'aptprsp projecting points onto a sphere:' /
cbug     &  '  rsph=',1pe22.14,'  nopt=',i2,'  tol=',1pe13.5 /
cbug     &  '  The center is at the point:' /
cbug     &  '  ax,ay,az=   ',1p3e22.14 /
cbug     &  '  the polar axis is 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) rsph, nopt, tol, 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++++ Disallowed value of nopt.
      if ((nopt .lt. 0) .or. (nopt .gt. 2)) then
        nerr = 2
cbugc***DEBUG begins.
cbug      write ( 3, '(/ "nop not between 0 and 2")')
cbugc***DEBUG ends.
        go to 210
c---- Tested nopt.
      endif

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

      if (nopt .ne. 0) then

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

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

c---- Vector "b" is too short.
        if (vlenb .le. tol) then
          nerr = 4
cbugc***DEBUG begins.
cbug          write ( 3, '(/ "Vector b is too short.")')
cbugc***DEBUG ends.
          go to 210
c---- Tested vlenb.
        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---- Tested nopt.
      endif

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)

      if (nopt .ne. 0) then

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

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

c---- Tested nopt.
      endif

c.... Find the projection option.

      if (nopt .eq. 0) then

c....   Project in the spherical radial direction.

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

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

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

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

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

      elseif (nopt .eq. 1) then

c....   Project in the direction perpendicular to the polar axis.
c....     Put points projected outside the sphere onto the poles.

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

          daxis = sqrt (qx(n)**2 + qy(n)**2)
          arg   = amax1 (0.0, rsph**2 - qz(n)**2)
          fact  = sqrt (arg) / (daxis + fuz)

          qx(n) = fact * qx(n)
          qy(n) = fact * qy(n)
          qz(n) = amin1 (qz(n),  rsph)
          qz(n) = amax1 (qz(n), -rsph)

          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 in the direction of the polar axis.
c....     Put points projected outside the sphere onto the equator.

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

          daxis = sqrt (qx(n)**2 + qy(n)**2)
          arg   = amax1 (0.0, rsph**2 - daxis**2)
          fact  = amin1 (rsph / (daxis + fuz), 1.0)
          deq   = abs (qz(n))

          qx(n) = fact * qx(n)
          qy(n) = fact * qy(n)
          qz(n) = sign (sqrt (arg), qz(n))

          if (deq .le. tol) then      ! Do not know which way to go.
            qx(n) = big
            qy(n) = big
            qz(n) = big
          endif

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

c---- Tested nopt.
      endif

      if (nopt .ne. 0) then

c....   Restore the initial z axis.

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

c---- Tested nopt.
      endif

c.... Restore the original origin.

      call apttran (-ax, -ay, -az, qx, qy, qz, np, tol, nerr)
cbugc***DEBUG begins.
cbug 9902 format (/ 'aptprsp 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 aptprsp.      (+1 line.)
      end

UCRL-WEB-209832