subroutine aptbrkn (ksys, iunit, u, du, v, dv, w, dw, pu, pv, pw,
     &                    np, tol, nside, fu, fv, fw, dsurf, nerr)

ccbeg.
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
c
c                             SUBROUTINE APTBRKN
c
c     call aptbrkn (ksys, iunit, u, du, v, dv, w, dw, pu, pv, pw,
c    &              np, tol, nside, fu, fv, fw, dsurf, nerr)
c
c     Version:  aptbrkn  Updated    1995 February 23 11:10.
c               aptbrkn  Originated 1994 March 3 12:00.
c
c     Author:   Arthur L. Edwards, LLNL, L-298, Telephone (925) 422-4123.
c
c
c     Purpose:  To find if np points p = (pu, pv, pw) are in the inside of the
c               volume element defined in the coordinate system ksys
c               (0 = rectangular, 1 = cylindrical, 2 = spherical) with angle
c               units iunit (0 = degrees, 1 = radians), bounded by the
c               coordinate surfaces at u, u + du, v, v + dv, w and w + dw.
c               The fractional distances across the volume element fu, fv and
c               fw, and the distances dsurf of each point from the six bounding
c               surfaces of the brick will also be returned.  Points on the
c               surface of the volume element, based on tol, will be considered
c               to be inside.
c               Flag nerr indicates any input error.
c
c     Input:    ksys, iunit, u, du, v, dv, w, dw, pu, pv, pw, np, tol.
c
c     Output:   nside, fu, fv, fw, dsurf, nerr.
c
c     Calls: None 
c
c     Glossary:
c
c     dsurf     Output   The distances of a point "p" from the bounding
c                          surfaces at u, u + du, v, v + dv, w and w + dw,
c                          respectively.  Size 6 by np.
c
c     fu,fv,fw  Output   The fractional distance (on a volume basis) of a
c                          point "p" across the volume element.  Size np.
c
c     iunit     Input    Indicates the unit used for angles:
c                          0 if angles theta and phi are in degrees.
c                          1 if angles theta and phi are in radians.
c                          Not used if ksys = 0.
c
c     ksys      Input    Indicates the coordinate system type:
c                          0 for Cartesian coordinates.  u = x, v = y, w = z.
c                          1 for cylindrical coordinates.  u = radius from z
c                            axis, v = angle theta in xy plane, counterclockwise
c                            from x axis, w = z.
c                          2 for spherical coordinates.  u = radius from origin,
c                            v = angle theta in xy plane, counterclockwise from
c                            x axis, w = angle phi from z axis.
c
c     nerr      Output   Indicates an input error, if not 0.
c                          1 if ksys is not 0, 1 or 2.
c                          2 if iunit is not 0 or 1.
c                          3 if np is not positive.
c
c     np        Input    Size of arrays pu, pv, pw, nside, fu, fv, fw.
c                          Number of points "p".
c
c     nside     Output   Indicates the point is in the volume element, if 1.
c                          Size np.
c
c     pu,pv,pw  Input    The coordinates of a spatial point "p".  Size np.
c
c     tol       Input    Numerical tolerance limit.
c                          On Cray computers, recommend 1.e-5 to 1.e-11.
c
c     u, du     Input    The coordinate and increment of the bounding coordinate
c                          surfaces of the volume element in the u direction.
c
c     v, dv     Input    The coordinate and increment of the bounding coordinate
c                          surfaces of the volume element in the v direction.
c
c     w, dw     Input    The coordinate and increment of the bounding coordinate
c                          surfaces of the volume element in the w direction.
c
c     Changes:  1995 February 23 11:10.  Added argument dsurf, to store
c               distances of the point from the bounding surfaces.

cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
ccend.

c____ Mathematical constant pi.  Dimensionless.

      parameter (pi = 3.14159265358979323)

c.... Dimensioned arguments.

c---- Coordinate u of point "p".
      dimension pu      (1)
c---- Coordinate v of point "p".
      dimension pv      (1)
c---- Coordinate w of point "p".
      dimension pw      (1)
c---- Fractional u distance of point "p".
      dimension fu      (1)
c---- Fractional v distance of point "p".
      dimension fv      (1)
c---- Fractional w distance of point "p".
      dimension fw      (1)
c---- Distances from 6 bounding surfaces.
      dimension dsurf   (6,1)
c---- Location flag, 1 for inside.
      dimension nside   (1)

c.... Local variables.

c---- Angular equivalent of 360 degrees.
      common /laptbrkn/ circle
c---- Cosine of angle phi at point.
      common /laptbrkn/ cosph
c---- Cosine of minimum angle phi.
      common /laptbrkn/ cosph1
c---- Cosine of maximum angle phi.
      common /laptbrkn/ cosph2
c---- Distance of point from max u.
      common /laptbrkn/ dumax
c---- Distance of point from min u.
      common /laptbrkn/ dumin
c---- Distance of point from max v.
      common /laptbrkn/ dvmax
c---- Distance of point from min v.
      common /laptbrkn/ dvmin
c---- Distance of point from max w.
      common /laptbrkn/ dwmax
c---- Distance of point from min w.
      common /laptbrkn/ dwmin
c---- Estimated error in location of pu.
      common /laptbrkn/ erru
c---- Estimated error in location of pv.
      common /laptbrkn/ errv
c---- Estimated error in location of pw.
      common /laptbrkn/ errw
c---- Angle conversion factor.
      common /laptbrkn/ fact
c---- Index in output array.
      common /laptbrkn/ n
c---- Square of minimum radius.
      common /laptbrkn/ r1sq
c---- Square of maximum radius.
      common /laptbrkn/ r2sq
c---- Square of minimum radius.
      common /laptbrkn/ r1cb
c---- Square of maximum radius.
      common /laptbrkn/ r2cb

cbugc***DEBUG begins.
cbug 9901 format (/ 'aptbrkn finding if points are in a brick.  np=',i3,
cbug     &  ' ksys=',i3,' iunit=',i2 /
cbug     &  ' tol=',1pe22.14 /
cbug     &  '  u, du=   ',1p2e22.14 /
cbug     &  '  v, dv=   ',1p2e22.14 /
cbug     &  '  w, dw=   ',1p2e22.14 )
cbug 9902 format (i3,'  pu,pv,pw=',1p3e22.14 )
cbug
cbug      write ( 3, 9901) np, ksys, iunit, tol, u, du, v, dv, w, dw
cbug      do 110 n = 1, np
cbug        write ( 3, 9902) n, pu(n), pv(n), pw(n)
cbug  110 continue
cbugc***DEBUG ends.

c.... initialize.

      nerr = 0

c.... Test for input errors.

      if ((ksys .lt. 0) .or. (ksys .gt. 2)) then
        nerr = 1
        go to 210
      endif

      if ((iunit .ne. 0) .and. (iunit .ne. 1)) then
        nerr = 2
        go to 210
      endif

      if (np .le. 0) then
        nerr = 3
        go to 210
      endif

c.... Find the angle conversion factor (degrees to radians).

      if (iunit .eq. 0) then
        fact = pi / 180.0
        circle = 360.0
      else
        fact = 1.0
        circle = 2.0 * pi
      endif

c.... See if the points are in the brick, and their fractional distances.

      do 180 n = 1, np                ! Loop over points.

        nside(n) = 0

c....   Find the distances of the point from the ends of the brick.

        if (du .ge. 0.0) then
          dumin = pu(n) - u
          dumax = u + du - pu(n)
        else
          dumin = pu(n) - u - du
          dumax = u - pu(n)
        endif

        if (dv .ge. 0.0) then
          dvmin = pv(n) - v
          dvmax = v + dv - pv(n)
        else
          dvmin = pv(n) - v - dv
          dvmax = v - pv(n)
        endif

c....   Rotate the point 360 degrees, if necessary.

        if (ksys .ne. 0) then

  150     if (dvmin .lt. 0.0) then
            dvmin = dvmin + circle
            dvmax = dvmax - circle
            go to 150
          endif

  160     if (dvmax .lt. 0.0) then
            dvmin = dvmin - circle
            dvmax = dvmax + circle
            go to 160
          endif

        endif

        if (dw .ge. 0.0) then
          dwmin = pw(n) - w
          dwmax = w + dw - pw(n)
        else
          dwmin = pw(n) - w - dw
          dwmax = w - pw(n)
        endif

c....   See if the point is in the brick.

        erru  = tol * (abs (pu(n)) + abs (u) + abs (du))
        errv  = tol * (abs (pv(n)) + abs (v) + abs (dv))
        errw  = tol * (abs (pw(n)) + abs (w) + abs (dw))

        if (abs (dumin) .lt. erru) dumin = 0.0
        if (abs (dumax) .lt. erru) dumax = 0.0
        if (abs (dvmin) .lt. errv) dvmin = 0.0
        if (abs (dvmax) .lt. errv) dvmax = 0.0
        if (abs (dwmin) .lt. errw) dwmin = 0.0
        if (abs (dwmax) .lt. errw) dwmax = 0.0

        if ((dumin .ge. 0.0) .and.
     &      (dumax .ge. 0.0) .and.
     &      (dvmin .ge. 0.0) .and.
     &      (dvmax .ge. 0.0) .and.
     &      (dwmin .ge. 0.0) .and.
     &      (dwmax .ge. 0.0)) then
          nside(n) = 1
        endif

c....   Find the fractional distances across the brick, on a volume basis.

        fu(n) = 0.0
        fv(n) = 0.0
        fw(n) = 0.0

        if     (ksys .eq. 0) then     ! Rectangular.
          if (du .ne. 0.0) fu(n) = dumin / du
          if (dv .ne. 0.0) fv(n) = dvmin / dv
          if (dw .ne. 0.0) fw(n) = dwmin / dw
        elseif (ksys .eq. 1) then     ! Cylindrical.
          if (du .ne. 0.0) then
            r1sq   = u**2
            r2sq   = (u + du)**2
            fu(n)  = (pu(n)**2 - r1sq) / (r2sq - r1sq)
          endif
          if (dv .ne. 0.0) fv(n) = dvmin / dv
          if (dw .ne. 0.0) fw(n) = dwmin / dw
        elseif (ksys .eq. 2) then     ! Spherical
          if (du .ne. 0.0) then
            r1cb   = u**3
            r2cb   = (u + du)**3
            fu(n)  = (pu(n)**3 - r1cb) / (r2cb - r1cb)
          endif
          if (dv .ne. 0.0) fv(n) = dvmin / dv
          if (dw .ne. 0.0) then
            cosph  = cos (fact * pw(n))
            cosph1 = cos (fact * w)
            cosph2 = cos (fact * (w + dw))
            fw(n)  = (cosph - cosph1) / (cosph2 - cosph1)
          endif
        endif

c....   Find the distances of the point from the six bounding surfaces.

        do 170 ns = 1, 6
          dsurf(ns,n) = -1.e99
  170   continue

        if     (ksys .eq. 0) then     ! Rectangular.

          dsurf(1,n) = u - pu(n)
          dsurf(2,n) = u - pu(n) + du
          dsurf(3,n) = v - pv(n)
          dsurf(4,n) = v - pv(n) + dv
          dsurf(5,n) = w - pw(n)
          dsurf(6,n) = w - pw(n) + dw

          err = tol * (abs (u) + abs (pu(n)))
          if (abs (dsurf(1,n)) .le. err) dsurf(1,n) = 0.0
          err = tol * (abs (u) + abs (pu(n)) + abs (du))
          if (abs (dsurf(2,n)) .le. err) dsurf(2,n) = 0.0
          err = tol * (abs (v) + abs (pv(n)))
          if (abs (dsurf(3,n)) .le. err) dsurf(3,n) = 0.0
          err = tol * (abs (v) + abs (pv(n)) + abs (dv))
          if (abs (dsurf(4,n)) .le. err) dsurf(4,n) = 0.0
          err = tol * (abs (w) + abs (pw(n)))
          if (abs (dsurf(5,n)) .le. err) dsurf(5,n) = 0.0
          err = tol * (abs (w) + abs (pw(n)) + abs (dw))
          if (abs (dsurf(6,n)) .le. err) dsurf(6,n) = 0.0

        elseif (ksys .eq. 1) then     ! Cylindrical.

          costhmin   = cos (fact * v)
          sinthmin   = sin (fact * v)
          costhmax   = cos (fact * (v + dv))
          sinthmax   = sin (fact * (v + dv))

          costhp     = cos (fact * pv(n))
          sinthp     = sin (fact * pv(n))

          dsurf(1,n) = u - pu(n)
          dsurf(2,n) = u - pu(n) + du
          dsurf(3,n) = pu(n) * (sinthmin * sinthp - costhmin * costhp)
          dsurf(4,n) = pu(n) * (sinthmax * sinthp - costhmax * costhp)
          dsurf(5,n) = w - pw(n)
          dsurf(6,n) = w - pw(n) + dw

          err = tol * (abs (u) + abs (pu(n)))
          if (abs (dsurf(1,n)) .le. err) dsurf(1,n) = 0.0
          err = tol * (abs (u) + abs (pu(n)) + abs (du))
          if (abs (dsurf(2,n)) .le. err) dsurf(2,n) = 0.0
          err = tol * abs (pu(n)) * 
     &          (abs (sinthmin * sinthp) + abs (costhmin * costhp))
          if (abs (dsurf(3,n)) .le. err) dsurf(3,n) = 0.0
          err = tol * abs (pu(n)) * 
     &          (abs (sinthmax * sinthp) + abs (costhmax * costhp))
          if (abs (dsurf(4,n)) .le. err) dsurf(4,n) = 0.0
          err = tol * (abs (w) + abs (pw(n)))
          if (abs (dsurf(5,n)) .le. err) dsurf(5,n) = 0.0
          err = tol * (abs (w) + abs (pw(n)) + abs (dw))
          if (abs (dsurf(6,n)) .le. err) dsurf(6,n) = 0.0

        elseif (ksys .eq. 2) then     ! Spherical.

          costhmin   = cos (fact * v)
          sinthmin   = sin (fact * v)
          costhmax   = cos (fact * (v + dv))
          sinthmax   = sin (fact * (v + dv))
          costhp     = cos (fact * pv(n))
          sinthp     = sin (fact * pv(n))

          cosphmin   = cos (fact * w)
          sinphmin   = sin (fact * w)
          cosphmax   = cos (fact * (w + dw))
          sinphmax   = sin (fact * (w + dw))
          cosphp     = cos (fact * pw(n))
          sinphp     = sin (fact * pw(n))

          dsurf(1,n) = u - pu(n)
          dsurf(2,n) = u - pu(n) + du

          dsurf(3,n) = pu(n) * sinphp *
     &                 (sinthmin * costhp - costhmin * sinthp)
          dsurf(4,n) = pu(n) * sinphp *
     &                 (sinthmax * costhp - costhmax * sinthp)

          dsurf(5,n) = pu(n) * (sinphmin * cosphp - cosphmin * sinphp)
          dsurf(6,n) = pu(n) * (sinphmax * cosphp - cosphmax * sinphp)

          err = tol * (abs (u) + abs (pu(n)))
          if (abs (dsurf(1,n)) .le. err) dsurf(1,n) = 0.0
          err = tol * (abs (u) + abs (pu(n)) + abs (du))
          if (abs (dsurf(2,n)) .le. err) dsurf(2,n) = 0.0
          err = tol * abs (pu(n) * sinphp) *
     &          (abs (sinthmin * costhp) + abs (costhmin * sinthp))
          if (abs (dsurf(3,n)) .le. err) dsurf(3,n) = 0.0
          err = tol * abs (pu(n) * sinphp) *
     &          (abs (sinthmax * costhp) + abs (costhmax * sinthp))
          if (abs (dsurf(4,n)) .le. err) dsurf(4,n) = 0.0
          err = tol * abs (pu(n)) *
     &          (abs (sinphmin * cosphp) + abs (cosphmin * sinphp))
          if (abs (dsurf(5,n)) .le. err) dsurf(5,n) = 0.0
          err = tol * abs (pu(n)) *
     &          (abs (sinphmax * cosphp) + abs (cosphmax * sinphp))
          if (abs (dsurf(6,n)) .le. err) dsurf(6,n) = 0.0

        endif                         ! Tested coordinate system.

  180 continue                        ! End of loop over points.
cbugc***DEBUG begins.
cbug 9903 format (/ 'aptbrkn results:')
cbug 9904 format (i3,'  fu,fv,fw=',1p3e22.14 )
cbug 9905 format (i3,'  nside=',i2)
cbug 9906 format (i3,'  distances of point from surfaces:' /
cbug     &  '  d umin,umax=',1p2e22.14 /       
cbug     &  '  d vmin,vmax=',1p2e22.14 /       
cbug     &  '  d wmin,wmax=',1p2e22.14 )       
cbug
cbug      write ( 3, 9903)
cbug      do 205 n = 1, np
cbug        write ( 3, 9904) n, fu(n), fv(n), fw(n)
cbug        write ( 3, 9905) n, nside(n)
cbug        write ( 3, 9906) n, (dsurf(nn,n), nn = 1, 6)
cbug  205 continue
cbugc***DEBUG ends.

  210 return

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

UCRL-WEB-209832