subroutine aptsphk (r1, r2, r3, r4, tol, r5, r6,
     &                    x1, y1, z1, x2, y2, z2, x3, y3, z3,
     &                    x4, y4, z4, x5, y5, z5, x6, y6, z6, nerr)

ccbeg.
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
c
c                             SUBROUTINE APTSPHK
c
c     call aptsphk (r1, r2, r3, r4, tol, r5, r6,
c    &              x1, y1, z1, x2, y2, z2, x3, y3, z3,
c    &              x4, y4, z4, x5, y5, z5, x6, y6, z6, nerr)
c
c     Version:  aptsphk  Updated    2001 May 29 15:30.
c               aptsphk  Originated 1999 February 1 16:20.
c
c     Author:   Arthur L. Edwards, LLNL, L-298, Telephone (925) 422-4123.
c
c
c     Purpose:  For the four mutually tangent spheres with radii r1, r2, r3 and
c               r4, find the radii r5 and r6 of two additional spheres, each
c               tangent to those four.  Also find the coordinates of the centers
c               of each of the 6 spheres, with the first at the origin, the
c               second on the x axis, the third in the x-y plane.
c               Flag nerr indicates any input or result error, if not zero.
c
c     Method:   See aptcirk, aptcirl, aptcirt, aptsphl, aptspht.
c
c     Input:    r1, r2, r3, r4, tol.
c
c     Output:   r5, r6, x1, y1, z1, x2, y2, z2, x3, y3, z3,
c               x4, y4, z4, x5, y5, z5, x6, y6, z6, nerr.
c
c     Calls: aptcirl, aptcirt 
c
c     Glossary:
c
c     nerr      Output   Indicates an input error, if not 0.
c                          -1 if one or more of the spheres is so small, and its
c                             y and/or z center coordinate so small, that its
c                             sign or magnitude can not be determined.
c                           1 if two or more of the first four radii are
c                             negative, or one radius is negative, but not large
c                             enough in magnitude for that sphere to enclose the
c                             other three, or one sphere has a radius too small
c                             to touch each of the other three spheres.
c                           2 if any of the radii are zero.
c                           3 if r1 + r2 = 0.
c
c     r1-r4     Input    The radii of four mutually tangent spheres.
c                          A negative radius indicates a sphere that surrounds
c                          the other three spheres.  A very large radius,
c                          relative to the other three, indicates a plane.
c
c     r5        Output   The radius of a sphere tangent to the first four
c                          spheres, in the space between them, if the first
c                          four radii are all positive.
c                          Returned as -1.e99 if nerr is positive.
c
c     r6        Output   The radius of another sphere tangent to the first four
c                          spheres.  A negative value of r6 means that sphere 6
c                          surrounds the first four spheres.
c                          A value of r6 near 1.e99 indicates the surface of
c                          that sphere is a plane.
c                          Returned as -1.e99 if nerr is positive.
c
c     x, y, z   Output   The x, y, z coordinates of the center of a sphere,
c                          i.e., (xn, yn, zn) for the n'th sphere, n = 1, 6.
c                          Returned as -1.e99 if nerr is positive.
c
c     tol       Input    Numerical tolerance limit.
c                          On computers with 64-bit floating point numbers,
c                          recommend 1.e-5 to 1.e-11.
c
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
ccend.

cbugc***DEBUG begins.
cbug 9901 format (/ 'aptsphk finding spheres tangent to',
cbug     &  ' spheres with radii:' /
cbug     &  '  r1, r2 =    ',1p2e22.14 /
cbug     &  '  r3, r4 =    ',1p2e22.14 /
cbug     &  '  tol =       ',1pe22.14 )
cbug      write ( 3, 9901) r1, r2, r3, r4,  tol
cbugc***DEBUG ends.

c.... Initialize.

      nerr = 0

      r5 = -1.e99
      r6 = -1.e99

      x1 = -1.e99
      y1 = -1.e99
      z1 = -1.e99
      x2 = -1.e99
      y2 = -1.e99
      z2 = -1.e99
      x3 = -1.e99
      y3 = -1.e99
      z3 = -1.e99
      x4 = -1.e99
      y4 = -1.e99
      z4 = -1.e99
      x5 = -1.e99
      y5 = -1.e99
      z5 = -1.e99
      x6 = -1.e99
      y6 = -1.e99
      z6 = -1.e99

c.... Test for input errors.

      if (r1 * r2 * r3 * r4 .eq. 0.0) then
        nerr = 2
        go to 210
      endif

      s12 = r1 + r2
      if (abs (s12) .le. tol * (abs (r1) + abs (r2))) s12 = 0.0
      if (s12 .eq. 0.0) then
        nerr = 3
        go to 210
      endif

c.... Test for special case r1 + r2 + r3 = 0, r4 just fits.

      s123 = r1 + r2 + r3
      errs = tol * (abs (r1) + abs (r2) + abs (r3))
      if (abs (s123) .le. errs) then  ! Special case.

        b1 = 1.0 / r1
        b2 = 1.0 / r2
        b3 = 1.0 / r3
        b4 = sqrt (b1**2 + b2**2 + b3**2)

        rx = 1.0 / b4
        if (abs (rx - r4) .gt. tol * (rx + r4)) then
          nerr = 1
          go to 210
        endif

        r5 = rx
        r6 = rx

        x1 = 0.0
        y1 = 0.0
        z1 = 0.0

        x2 = r1 + r2
        y2 = 0.0
        z2 = 0.0

        x3 = r2
        y3 = 0.0
        z3 = 0.0

        x4 = r1 + r4 * (r1 - r2) / (r1 + r2)
        y4 = 2.0 * r4
        z4 = 0.0

        x5 = x4
        y5 = r4
        z5 = r4 * sqrt (3.0)

        x6 = x4
        y6 = r4
        z6 = -z5

        go to 210
      endif                           ! Special case.

c.... Find the center of sphere 1.  Arbitrarily at origin.

      x1 = 0.0
      y1 = 0.0
      z1 = 0.0

c.... Find the center of sphere 2.  Arbitrarily on x axis.

      x2 = r1 + r2
      y2 = 0.0
      z2 = 0.0

c.... Find the center of sphere 3.  Arbitrarily at z = 0.

      call aptcirl (r1, r2, r3, tol, x3, y3, nerra)

      if (nerra .ne. 0) then
        nerr = 1
        go to 210
      endif

      z3 = 0.0

c.... Find the radii of the spheres tangent to spheres 1, 2, 3  and 4.

      call aptspht (r1, r2, r3, r4, tol, r5, r6, nerra)

      if (nerra .gt. 0) then
        nerr = 1
        go to 210
      endif

c.... Find the center of sphere 4.

      call aptsphl (r1, r2, r3, r4, tol, x4, y4, z4, nerra)

      z4 = abs (z4)

      if (nerra .lt. 0) then
        nerr = -1
      endif

      if (nerra .gt. 0) then
        nerr = 1
        go to 210
      endif

c.... Find the center of sphere 5.

      call aptsphl (r1, r2, r3, r5, tol, x5, y5, z5, nerra)

      if (nerra .gt. 0) then
        nerr = 1
        go to 210
      endif

      if (nerra .lt. 0) then
        nerr = -1
      endif

      argt  = r1 * (r1 + r4 + r5) - (r4 * r5 + x4 * x5 + y4 * y5)
      test1 = argt - z4 * z5
      test2 = argt + z4 * z5
      terr  = 2.0 * tol * (r1**2 + (abs (r1 * r4) + abs (r1 * r5)) +
     &        abs (r4 * r5) + abs (x4 * x5) +
     &        abs (y4 * y5) + abs (z4 * z5))
cbugcbugc***DEBUG begins.
cbugcbug 9842 format ('DEBUG z:  test1,test2=',1p2e22.14)
cbugcbug      write ( 3, 9842) test1, test2
cbugcbugc***DEBUG ends.
      if (abs (test1) .le. terr) test1 = 0.0
      if (abs (test2) .le. terr) test2 = 0.0
cbugcbugc***DEBUG begins.
cbugcbug      write ( 3, 9842) test1, test2
cbugcbugc***DEBUG ends.

      if (abs (test2) .lt. abs (test1)) then
        z5 = -z5
      endif

      if (abs (test1) .eq. abs (test2)) then
        if (z5 .ne. 0.0) then
          nerr = -1
        endif
      endif

c.... Find the center of sphere 6.

      call aptsphl (r1, r2, r3, r6, tol, x6, y6, z6, nerra)

      if (nerra .gt. 0) then
        nerr = 1
        go to 210
      endif

      if (nerra .lt. 0) then
        nerr = -1
      endif

      argt  = r1 * (r1 + r4 + r6) - (r4 * r6 + x4 * x6 + y4 * y6)
      test1 = argt - z4 * z6
      test2 = argt + z4 * z6
      terr  = 2.0 * tol * (r1**2 + abs (r1 * r4) + abs (r1 * r6) +
     &        abs (r4 * r6) + abs (x4 * x6) +
     &        abs (y4 * y6) + abs (z4 * z6))
cbugcbugc***DEBUG begins.
cbugcbug      write ( 3, 9842) test1, test2
cbugcbugc***DEBUG ends.
      if (abs (test1) .le. terr) test1 = 0.0
      if (abs (test2) .le. terr) test2 = 0.0
cbugcbugc***DEBUG begins.
cbugcbug      write ( 3, 9842) test1, test2
cbugcbugc***DEBUG ends.
cbugcbugc***DEBUG begins.
cbugcbug 9851 format ('DEBUG 1:  z5,z6=',1p2e22.14)
cbugcbug      write ( 3, 9851) z5, z6
cbugcbugc***DEBUG ends.

      if (abs (test2) .lt. abs (test1)) then
        z6 = -z6
      endif
cbugcbugc***DEBUG begins.
cbugcbug 9852 format ('DEBUG 2:  z5,z6=',1p2e22.14)
cbugcbug      write ( 3, 9852) z5, z6
cbugcbugc***DEBUG ends.

      if (abs (test1) .eq. abs (test2)) then
        if (abs (z6 - z5) .le. tol * (abs (z6) + abs (z5))) then
          z6 = -z6
        elseif (z6 .ne. 0.0) then
          nerr = -1
        endif
      endif
cbugcbugc***DEBUG begins.
cbugcbug 9853 format ('DEBUG 3:  z5,z6=',1p2e22.14)
cbugcbug      write ( 3, 9853) z5, z6
cbugcbugc***DEBUG ends.

  210 continue

cbugc***DEBUG begins.
cbug 9902 format (/ 'aptsphk results:  nerr=',i3 /
cbug     &  '  r5, r6 =    ',1p2e22.14 /
cbug     &  '  x1, y1, z1 =',1p3e22.14 /
cbug     &  '  x2, y2, z2 =',1p3e22.14 /
cbug     &  '  x3, y3, z3 =',1p3e22.14 /
cbug     &  '  x4, y4, z4 =',1p3e22.14 /
cbug     &  '  x5, y5, z5 =',1p3e22.14 /
cbug     &  '  x6, y6, z6 =',1p3e22.14 )
cbug      write ( 3, 9902) nerr, r5, r6, x1, y1, z1, x2, y2, z2,
cbug     &  x3, y3, z3, x4, y4, z4, x5, y5, z5, x6, y6, z6
cbugc***DEBUG ends.

      return

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

UCRL-WEB-209832