subroutine aptsolv (a, s, nrows, w, nrowm, tol, q, b, qm, qr,
     &                    sm, sr, nerr)

ccbeg.
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
c
c                             SUBROUTINE APTSOLV
c
c     call aptsolv (a, s, nrows, w, nrowm, tol, q, b, qm, qr,
c    &              sm, sr, nerr)
c
c     Version:  aptsolv  Updated    1990 December 3 14:20.
c               aptsolv  Originated 1990 October 18 15:20.
c
c     Author:   Arthur L. Edwards, LLNL, L-298, Telephone (925) 422-4123.
c
c
c     Purpose:  To solve a set of nrows equations a * q = s for the nrows
c               unknowns "q", given the nrows by nrows coefficient matrix "a"
c               and the nrows right-side constants "s".  The method used is
c               Gauss-Jordan elimination with partial pivoting.  In addition
c               to "q", the inverse matrix b = a**-1, the recalculated unknowns
c               qm = b * s, the residuals of the unknowns qr = b * s - q,
c               the recalculated right-side constants sm = a * q, and the
c               residuals of the right-side constants sr = a * q - s, are
c               calculated and returned.  Failure to obtain a good solution
c               is indicated by a non-zero value of nerr, but results may be
c               usable with nerr = 2 or 3, which indicate numerical truncation
c               error.
c
c     Input:    a, s, nrows, w, nrowm, tol.
c
c     Output:   q, b, qm, qr, sm, sr, nerr.
c
c     Glossary:
c
c     a         Input    Matrix of coefficients of equations to be solved.
c                          Shape in memory is nrowm by nrows(+).
c                          Data is in first nrows rows and first nrows columns.
c
c     b         Output   The inverse of matrix "a".
c                          Shape in memory is nrowm by nrows(+).
c                          Data is in first nrows rows and first nrows columns.
c
c     nerr      Output   Error indicator.  0 if a good solution was obtained.
c                          1 if the matrix of coefficients "a" is singular.
c                            The determinant of the matrix "a" is zero.
c                          2 if any residual "qr" exceeds 1.e-6 times the
c                            maximum q value.  Results may be usable.
c                          3 if any residual "sr" exceeds 1.e-6 times the
c                            maximum r value.  Results may be usable.
c
c     nrowm     Input    First dimension of array "a".  Increment in array "a"
c                          between successive column values.
c
c     nrows     Input    Number of equations and number of unknowns.
c                          Size of square matrix "a".
c                          Size of arrays q, qm, qr, s, sm, sr.
c
c     q         Output   Unknowns, obtained by Gauss-Jordan elimination, with
c                          partial pivoting.  Size nrows.
c
c     qm        Output   Unknowns calculated from b * s.  Size nrows.
c
c     qr        Output   The residuals of the unknowns b * s - q.
c                          Small if the solution is good.  Size nrows.
c
c     s         Input    Solution vector.  Right-hand side of equations.
c                          Size nrows.
c
c     sm        Output   Solution vector calculated from a * q.  Size nrows.
c
c     sr        Output   The residuals of the right-side constants a * q - s.
c                          Small if the solution is good.  Size nrows.
c
c     w         Input    Working memory space for matrix calculations.
c                          Shape in memory is nrowm by nrows + 1(+).
c                          Data is in first nrows rows and in first nrows + 1
c                          columns.
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.

      dimension a  (nrowm,nrows)      ! Coefficient matrix.
      dimension b  (nrowm,nrows)      ! Inverse matrix by elimination.
      dimension q  (nrowm)            ! Unknowns by elimination.
      dimension qm (nrowm)            ! Unknowns from b * s.
      dimension qr (nrowm)            ! Residuals qr = qm - q.
      dimension s  (nrowm)            ! Solution vector s = a * q.
      dimension sm (nrowm)            ! Estimate sm = a * q.
      dimension sr (nrowm)            ! Residuals sr = sm - s.
      dimension w  (nrowm,nrows+1)    ! Working coefficient matrix.

c.... Local variables.

      common /laptsolv/ adiv          ! Matrix element at pivot row, column.
      common /laptsolv/ amax          ! Maximum matrix element in a column.
      common /laptsolv/ amaxabs       ! Abs value of max column element.
      common /laptsolv/ amult         ! Initial pivot column element of row.
      common /laptsolv/ atemp         ! Temporary matrix element.
      common /laptsolv/ npivot        ! Index of pivot point row and column.
      common /laptsolv/ nq            ! Index of q = row index.
      common /laptsolv/ nr            ! Row index.
      common /laptsolv/ nrmax         ! Index of row containing amax.
      common /laptsolv/ qmax          ! Maximum absolute value of q.
      common /laptsolv/ smax          ! Maximum absolute value of s.
cbugc***DEBUG begins.
cbug      common /laptsolv/ alabq  (12)
cbug      data (alabq(n), n = 1, 12) / 'q1', 'q2', 'q3', 'q4', 'q5', 'q6',
cbug     &                             'q7', 'q8', 'q9', 'q10', 'q11',
cbug     &                             'q12' /
cbug      common /laptsolv/ ns            ! Row index.
cbug      common /laptsolv/ u  (12,12)    ! Check matrix b * a.  Identity?
cbug 9901 format (/ 'aptsolv solving equation set.  tol=',1pe13.5)
cbug 9902 format (/ 'nrows=',i3,'.  matrix a and solution vector s:' /)
cbug 9903 format (1x,1p12e13.5)
cbug      write ( 3, 9901) tol
cbug      write ( 3, 9902) nrows
cbug      do 108 nr = 1, nrows            ! Loop over rows.
cbug        write ( 3, 9903) (a(nr,nc), nc = 1, nrows), s(nr)
cbug  108 continue                        ! End of loop over rows.
cbugc***DEBUG ends.

c.... Initialize.

      nerr  = 0
      ncols = nrows + 1

c.... Store coefficients "a" and solution vector "s" in working matrix "w".

      do 102 nr = 1, nrows            ! Loop over rows.
        do 100 nc = 1, nrows          ! Loop over first nrows columns.
          w(nr,nc) = a(nr,nc)
  100   continue                      ! End of loop over columns.
        w(nr,ncols) = s(nr)
  102 continue                        ! End of loop over rows.

c.... Form initial inverse matrix "b".

      do 106 nr = 1, nrows            ! Loop over rows.
        do 104 nc = 1, nrows          ! Loop over first nrows columns.
            b(nr,nc) = 0.0
  104   continue                      ! End of loop over columns.
        b(nr,nr) = 1.0
  106 continue                        ! End of loop over rows.
cbugcbugc***DEBUG begins.
cbugcbug 9904 format (/ 'nrows=',i3,'.  inverse matrix b:' /)
cbugcbug      write ( 3, 9904) nrows
cbugcbug      do 110 nr = 1, nrows            ! Loop over rows.
cbugcbug        write ( 3, 9903) (b(nr,nc), nc = 1, nrows)
cbugcbug  110 continue                        ! End of loop over rows.
cbugcbugc***DEBUG ends.

c.... Do Gauss-Jordan elimination with partial pivoting.

      do 140 npivot = 1, nrows        ! Loop over pivot rows.

c....   Find max element in column npivot.  Save row index.

        amax    = w(npivot,npivot)
        amaxabs = abs (amax)
        nrmax   = npivot

        if (npivot .lt. nrows) then

          do 112 nr = npivot + 1, nrows  ! Loop over pivot rows.

            if (abs (w(nr,npivot)) .gt. amaxabs) then
              amax    = w(nr,npivot)
              amaxabs = abs (amax)
              nrmax   = nr
            endif

  112     continue                    ! End of loop over pivot rows.

        endif
cbugcbugc***DEBUG begins.
cbugcbug 9905   format (/ 10("--------") //
cbugcbug     &    "largest lower triangular element in column",i3,
cbugcbug     &    " is",1pe13.5," in row",i3,".")
cbugcbug        write ( 3, 9905) npivot, amax, nrmax
cbugcbugc***DEBUG ends.

        if (amax .eq. 0.0) then
          nerr = 1
cbugcbugc***DEBUG begins.
cbugcbug 9906     format ('aptsolv results:  coefficient matrix a is singular.',
cbugcbug     &  '  no solution.' /
cbugcbug     &      2x,5("*****")," failed ",5("*****"))
cbugcbug          write ( 3, '(/ 10("--------"))')
cbugcbug          write ( 6, 9906)
cbugcbug          write ( 3, '(/)')
cbugcbug          write ( 3, 9906)
cbugcbugc***DEBUG ends.
          go to 210
        endif

c....   Swap maximum element to row npivot.

        if (nrmax .ne. npivot) then   ! Swap w row.

          do 114 nc = npivot, ncols   ! Loop over pivit columns.
            atemp        = w(npivot,nc)
            w(npivot,nc) = w(nrmax, nc)
            w(nrmax, nc) = atemp
  114     continue                    ! End of loop over pivot columns.

          do 116 nc = 1, nrows        ! Loop over first nrows columns.
            atemp        = b(npivot,nc)
            b(npivot,nc) = b(nrmax, nc)
            b(nrmax, nc) = atemp
  116     continue                    ! End of loop over columns.

        endif                         ! Tested nrmax vs. npivot.
cbugcbugc***DEBUG begins.
cbugcbug 9907   format (/ "swapped rows",i3," and",i3," of matrix.")
cbugcbug        if (nrmax .ne. npivot) then
cbugcbug          write ( 3, 9907) nrmax, npivot
cbugcbug          write ( 3, 9902) nrows
cbugcbug          do 118 nr = 1, nrows        ! Loop over rows.
cbugcbug            write ( 3, 9903) (w(nr,nc), nc = 1, ncols)
cbugcbug  118     continue                    ! End of loop over rows.
cbugcbug          write ( 3, 9904) nrows
cbugcbug          do 120 nr = 1, nrows        ! Loop over rows.
cbugcbug            write ( 3, 9903) (b(nr,nc), nc = 1, nrows)
cbugcbug  120     continue                    ! End of loop over rows.
cbugcbug        endif
cbugcbugc***DEBUG ends.

c....   Make element w(npivot,npivot) = 1.0.

        adiv = w(npivot,npivot)

        if (adiv .ne. 1.0) then       ! Divide column by adiv.

          w(npivot,npivot) = 1.0
          do 122 nc = npivot + 1, ncols  ! Loop over pivot columns.
            w(npivot,nc) = w(npivot,nc) / adiv
  122     continue                    ! End of loop over pivot columns.

          do 124 nc = 1, nrows        ! Loop over first nrows columns.
            b(npivot,nc) = b(npivot,nc) / adiv
  124     continue                    ! End of loop over columns.

        endif                         ! Tested adiv.
cbugcbugc***DEBUG begins.
cbugcbug 9908   format (/ "divided row",i3," by",1pe13.5,".")
cbugcbug        if (abs (adiv - 1.0) .gt. tol) then
cbugcbug          write ( 3, 9908) npivot, adiv
cbugcbug          write ( 3, 9902) nrows
cbugcbug          do 126 nr = 1, nrows        ! Loop over rows
cbugcbug            write ( 3, 9903) (w(nr,nc), nc = 1, ncols)
cbugcbug  126     continue                    ! End of loop over rows.
cbugcbug          write ( 3, 9904) nrows
cbugcbug          do 128 nr = 1, nrows        ! Loop over rows.
cbugcbug            write ( 3, 9903) (b(nr,nc), nc = 1, nrows)
cbugcbug  128     continue                    ! End of loop over rows.
cbugcbug        endif
cbugcbugc***DEBUG ends.

c....   Make other elements in pivot column zero.
cbugcbugc***DEBUG begins.
cbugcbug 9909   format ("  row",i3,", column",i3," reduced from",1pe13.5," to",
cbugcbug     &    1pe13.5,", truncated to zero.")
cbugcbug 9910   format ("subtracted",1pe13.5," * row",i3," from row",i3,".")
cbugcbug        write ( 3, '(/)')
cbugcbugc***DEBUG ends.

        amult = 0.0

        do 134 nr = 1, nrows          ! Loop over rows.

          if (nr .ne. npivot) then    ! Zero out row element.

            amult = w(nr,npivot)

            if (amult .ne. 0.0) then  ! Zero out row element.
cbugcbugc***DEBUG begins.
cbugcbug              write ( 3, 9910) amult, npivot, nr
cbugcbugc***DEBUG ends.

              w(nr,npivot) = 0.0

              do 130 nc = npivot + 1, ncols  ! Loop over pivot columns.
                atemp = abs (w(nr,nc))
                w(nr,nc) = w(nr,nc) - amult * w(npivot,nc)
                if (abs(w(nr,nc)) .lt. tol * atemp) then
cbugcbugc***DEBUG begins.
cbugcbug                  if (w(nr,nc) .ne. 0.0) then
cbugcbug                    write ( 3, 9909) nr, nc, atemp, w(nr,nc)
cbugcbug                  endif
cbugcbugc***DEBUG ends.
                  w(nr,nc) = 0.0
                endif
  130         continue                ! End of loop over pivot columns.

              do 132 nc = 1, nrows    ! Loop over first nrows columns.
                atemp = abs (b(nr,nc))
                b(nr,nc) = b(nr,nc) - amult * b(npivot,nc)
                if (abs(b(nr,nc)) .lt. tol * atemp) then
cbugcbugc***DEBUG begins.
cbugcbug                  if (b(nr,nc) .ne. 0.0) then
cbugcbug                    write ( 3, 9909) nr, nc, atemp, b(nr,nc)
cbugcbug                  endif
cbugcbugc***DEBUG ends.
                  b(nr,nc) = 0.0
                endif
  132         continue                ! End of loop over columns.

            endif                     ! Tested amult.

          endif                       ! Tested nr vs. npivot.

  134   continue                      ! End of loop over rows.
cbugcbugc***DEBUG begins.
cbugcbug        write ( 3, 9902) nrows
cbugcbug        do 136 nr = 1, nrows          ! Loop over rows.
cbugcbug          write ( 3, 9903) (w(nr,nc), nc = 1, ncols)
cbugcbug  136   continue                      ! End of loop over rows.
cbugcbug        write ( 3, 9904) nrows
cbugcbug        do 138 nr = 1, nrows          ! Loop over rows.
cbugcbug          write ( 3, 9903) (b(nr,nc), nc = 1, nrows)
cbugcbug  138   continue                      ! End of loop over rows.
cbugcbugc***DEBUG ends.

  140   continue                      ! End of loop over pivot rows.

c.... Get the residuals.

      qmax = 0.0
      smax = 0.0

      do 146 nq = 1, nrows            ! Loop over rows.
        q(nq) = w(nq,ncols)
        qmax  = amax1 (abs (q(nq)), qmax)
        smax  = amax1 (abs (s(nq)), smax)
  146 continue                        ! End of loop over rows.

      do 152 nr = 1, nrows            ! Loop over rows.

        qm(nr) = 0.0
        sm(nr) = 0.0

        do 150 nc = 1, nrows          ! Loop over first nrows columns.
          qm(nr) = qm(nr) + b(nr,nc) * s(nc)
          sm(nr) = sm(nr) + a(nr,nc) * q(nc)
cbugcbugc***DEBUG begins.
cbugcbug          u(nr,nc) = 0.0
cbugcbug          do 148 nu = 1,nrows         ! Loop over rows.
cbugcbug            u(nr,nc) = u(nr,nc) + b(nu,nc) * a(nr,nu)
cbugcbug  148     continue                    ! End of loop over rows.
cbugcbugc***DEBUG ends.
  150   continue                      ! End of loop over columns.

        qr(nr) = qm(nr) - q(nr)
        if (abs (qr(nr)) .lt. tol * abs (q(nr))) then
          qr(nr) = 0.0
        endif
        if (abs (qr(nr)) .gt. 1.e-6 * qmax) nerr = 2

        sr(nr) = sm(nr) - s(nr)
        if (abs (sr(nr)) .lt. tol * abs (s(nr))) then
          sr(nr) = 0.0
        endif
        if (abs (sr(nr)) .gt. 1.e-6 * smax) nerr = 3

  152 continue                        ! End of loop over rows.

  210 continue
cbugc***DEBUG begins.
cbug 9911 format ('nerr =',i2,'.  1 = singular matrix.',
cbug     &  '  2 = large q residuals.  3 = large s residuals.')
cbug 9912 format (/ 'unknowns q:' //
cbug     &  ' nq',8x,'q (fixed)',7x,'q (floating)' /
cbug     &  (1x,a2,0pf20.12,1pe20.12))
cbug 9913 format (/ 'unknowns q and residuals:' //
cbug     &  ' nq',4x,'q',19x,'b * s',15x,'b * s - q' /
cbug     &  (1x,a2,1p3e20.12))
cbug 9914 format (/ 'solution vector s and residuals:' //
cbug     &  ' ns',4x,'s',19x,'a * q',15x,'a * q - s' /
cbug     &  (i3,1p3e20.12))
cbug 9915 format (/ 'matrix product u = b * a:' /)
cbug 9916 format (1x,1p12e13.5)
cbug 9920 format (/ 'aptsolv results.  nerr = ',i2)
cbug
cbug      write ( 3, '(/ 10("--------"))')
cbug      write ( 3, 9920) nerr
cbug
cbug      if (nerr .ne. 0) then
cbug        write (  6 9911) nerr
cbug        write ( 3, '(/)')
cbug        write ( 3, 9911) nerr
cbug        if (nerr .eq. 1) go to 220
cbug      endif
cbug
cbug      write ( 6, 9912) (alabq(nq), q(nq), q(nq), nq = 1, nrows)
cbug      write ( 3, 9912) (alabq(nq), q(nq), q(nq), nq = 1, nrows)
cbug      write ( 3, 9913) (alabq(nq), q(nq), qm(nq), qr(nq), nq = 1, nrows)
cbug      write ( 3, 9914) (ns, s(ns), sm(ns), sr(ns), ns = 1, nrows)
cbug      write ( 3, 9915)
cbug
cbug      do 160 nr = 1, nrows            ! Loop over rows.
cbug        do 158 nc = 1, nrows          ! Loop over first nrows columns.
cbug          if (abs (u(nr,nc)) .lt. tol) then
cbug            u(nr,nc) = 0.0
cbug          endif
cbug  158   continue                      ! End of loop over columns.
cbug        write ( 3, 9916) (u(nr,nc), nc = 1, nrows)
cbug  160 continue                        ! End of loop over rows.
cbugc***DEBUG ends.

  220 return

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

UCRL-WEB-209832