! source file: /usr/local/models/UVic_ESCM/2.9/source/mom/denscoef.F
      subroutine eqstate (zt, km, ro0_den, to_den, so_den, c_den
     &,                   tmink, tmaxk, smink, smaxk)

!=======================================================================

!             E Q U A T I O N   O F   S T A T E   M O D U L E

!     Calculate polynomial coefficients for density computations in MOM.

!     To generate the coefficients:

!        1) set up the grid in "grids.F" module

!        2) compile and run this module by setting the options in and
!           executing the "run_denscoef" script

!     To install the coefficients in MOM:

!        3) follow the directions at the end of the output from 2)

!     This program calculates the 9 coefficients of a third order
!     polynomial approximation to the equation of state for sea water.
!       The program yields coefficients that will compute density as a
!     function of temperature, and salinity, at predetermined depths,
!     as used in the MOM subroutine "state".
!     More specifically, the densities calculated from the polynomial
!     formula are in the form of sigma anomalies.  The method is
!     taken from that described by Bryan & Cox (1972).
!       By default, the program uses the equation of state set by the
!     Joint Panel on Oceanographic Tables & Standards (UNESCO, 1981)
!     an described by Gill (1982).  An option exists to use the older
!     Knudsen-Ekman equation of state, as described by Fofonoff (1962),
!     if the user prefers.
!       Subroutine "lsqsl2" performs the iterative least-squares
!     polynomial fitting for the overdetermined system.  The algorithm
!     is outlined by Hanson and Lawson (1969), and the code looks as if
!     it has not be touched since that time.

!     references:
!        Bryan, K. & M. Cox, An approximate equation of state
!          for numerical models of ocean circulation, J. Phys.
!          Oceanogr., 2, 510-514, 1972.
!        Fofonoff, N., The Sea: Vol 1, (ed. M. Hill). Interscience,
!          New York, 1962, pp 3-30.
!        Gill, A., Atmosphere-Ocean Dynamics: International Geophysical
!          Series No. 30. Academic Press, London, 1982, pp 599-600.
!        Hanson, R., & C. Lawson, Extensions and applications of the
!          Householder algorithm for solving linear least squares
!          problems. Math. Comput., 23, 787-812, 1969.
!        UNESCO, 10th report of the joint panel on oceanographic tables
!          and standards. UNESCO Tech. Papers in Marine Sci. No. 36,
!          Paris, 1981.

!    ifdef options:
!       "knudsen"
!       To over-ride the default of using the UNESCO equation of state
!     and to instead employ the Knudsen-Ekman formula.
!     The default assumption is that potential temperatures will be used
!     (asin the ocean model code).
!-----------------------------------------------------------------------

      implicit none

      include "stdunits.h"
      character(10) :: fname

      integer kmax, kx, kxx, kk, ksdim, krdim, km, k, io, i, j, ka
      integer ndim, nrow, ncol, in, itmax, it, ieq, irank, nn, nhdim
      parameter (kmax=200)
      parameter (kx = 5, kxx = 2*kx, kk = kx*kxx )
      parameter (ksdim = kk+72, krdim = kk+36 )

      real (kind=8) c0, c1, c2, cmtocm, fkx, fi, t1, s1, tot, th1
      real (kind=8) fkk, d, s, t, densit, theta, tot1, tanom, sanom
      real (kind=8) eps, enorm

      real (kind=8) a(kk,9), sigma(kk), sigman(kk), c(kk,9), x(9)
      real (kind=8) sb(ksdim), r(krdim)
      real (kind=8) tmin(kmax), smin(kmax), tmax(kmax), smax(kmax)
      real (kind=8) z(kmax), dd(kmax), ss(kmax), ab(13,kmax), ts(33,4)
      real (kind=8) ta(kxx), sa(kxx), tp(kk), sp(kk), th(kk)

      real ro0_den(km), to_den(km), so_den(km), c_den(km,9), zt(km)
      real tmink(km), tmaxk(km), smink(km), smaxk(km), realz

      data fname /'dncoef.new'/

!  enter bounds for polynomial fit: at 33 levels from sfc to 8000 m.
!           ts(k,1)=lower bnd of t at z=(k-1)*250 meters
!           ts(k,2)=upper bnd of t
!           ts(k,3)=lower bnd of s
!           ts(k,4)=upper bnd of s
!  The user should review the appropriateness of the "ts" values set
!  below, and modify them if the intended modelling application could
!  be expected to yield temperature and salinity values outside of the
!  "ts" ranges set by default.

      data (ts(k,1),k=1,33) / 4*-2.0, 15*-1.0, 14*0.0 /
      data (ts(k,2),k=1,33) / 29.0, 19.0, 14.0, 11.0, 9.0, 28*7.0 /
      data (ts(k,3),k=1,33) / 28.5, 33.7, 34.0, 34.1, 34.2, 34.4,
     &                        2*34.5, 15*34.6, 10*34.7 /
      data (ts(k,4),k=1,33) / 37.0, 36.6, 35.8, 35.7, 35.3, 2*35.1,
     &                        26*35.0 /

!     z       = model levels (midpoint of model layers)
!     tmin, tmax, smin, smax = minimum and maximum in situ temperature
!               and salinity values which define the ranges to be used
!               when computing the polynomials at each model level
!     dd, ds  = increment between temperature and salinity values at
!               each model level to be used in constructing array of
!               temperature, salinity and density for curve fitting
!     ta, sa  = in situ temperature and salinity values available for
!               constructing array of data for curve fitting at each
!               model level
!     tp, sp  = in situ temperature and salinity values constructed from
!               all combinations of ta & sa
!     th      = potential temperature values associated with "tp" at a
!               given level and salinity
!     t1, s1, tot1, th1 = level mean insitu temp., salinity, density,
!               and potential temp. used in polynomial fitting
!     tot     = density (in sigma units) calculate from t1 and s1 at a
!               given model level
!     sigma   = insitu densities (in sigma units) calculated from "tp"
!               and "sp" values
!     sigman  = insitu density anomalies at a given level (formed by
!               subtracting "tot" from sigma)
!     tanom, sanom = temperature and salinity anomalies used in loading
!               array "a" for use in lsqsl2 curve fitting
!     x       = the 9 polynomial coefficients
!     r, sb   = used only in lsqsl2

!=======================================================================

      if (km .gt. kmax) then
        write (stdout,*) '=>Error: increase "kmax" > ',km,' in eqstate'
        stop
      endif

!     set some constants

      c0 = 0.0
      c1 = 1.0
      c2 = 2.0

!     construct depths (meters) from surface to midpoint of levels

      cmtocm = 1.0d-2
      do k=1,km
        z(k) = zt(k) * cmtocm
        if (z(k) .gt. 8000.0) then
          write (stdout,*) '=>Error:depth can`t exceed 8000m in eqstate'
          stop
        endif
      enddo

!     set the temperature and salinity ranges to be used for each
!     model level when performing the polynomial fitting

      do k=1,km
        realz = z(k)/250.0
        i = ifix (realz) + 1
        tmin(k) = ts(i,1)
        tmax(k) = ts(i,2)
        smin(k) = ts(i,3)
        smax(k) = ts(i,4)
      enddo

!  set temperature and salinity increments to be used in creating
!  curve fitting array at each level (twice as many temperature values
!  than salinity values)

      fkx = kx
      do k=1,km
        dd(k) = (tmax(k)-tmin(k)) / (c2*fkx-c1)
        ss(k) = (smax(k)-smin(k)) / (fkx-c1)
      enddo

!     loop over all model levels

      do k=1,km

        do i=1,kxx
          fi = i
          ta(i) = tmin(k) + (fi-c1)*dd(k)
          sa(i) = smin(k) + (fi-c1)*ss(k)
        enddo

!       load the "kxx" combinations of the 2*"kx" insitu temp. and "kx"
!       salinity values into "tp" and "sp"

        do i=1,kxx
          do j=1,kx
            ka = kx*i + j - kx
            tp(ka) = ta(i)
            sp(ka) = sa(j)
          enddo
        enddo

        t1  = c0
        s1  = c0
        tot = c0
        th1 = c0
        fkk = kk

!       calculate insitu density "sigma" for each t,s combination at
!       this depth "d"

        do ka=1,kk
          d = z(k)
          s = sp(ka)
          t = tp(ka)

!         "unesco" returns density (kg per m**3) from insitu
!         temperature, salinity, & depth (pressure) using the UNESCO
!         equation of state

          call unesco(t,s,d,densit)

          sigma(ka) = densit - 1.0d3 + 2.5d-2

!         "potem" returns potential temp. from from insitu temperature,
!         salinity, & depth (pressure)

          call potem(t,s,d,theta)

          th(ka) = theta
          t1 = t1 + tp(ka)
          s1 = s1 + sp(ka)
          tot = tot + sigma(ka)
          th1 = th1 + th(ka)
        enddo

!       form layer averages "t1", "s1", "th1", and "tot1", and compute
!       reference density "tot" from "t1" and "s1" at this depth "d"

        t1 = t1/fkk
        s1 = s1/fkk
        th1 = th1/fkk
        tot1 = tot/fkk

!       "unesco" returns density from insitu temp., salinity, & depth
!       (pressure) using the UNESCO equation of state

        call unesco (t1, s1, d, densit)
        tot = densit - 1.0d3 + 2.5d-2

!       define insitu
        t1 = th1

!       begin loading "ab" array with level averages

        ab(1,k) = z(k)
        ab(2,k) = tot
        ab(3,k) = t1
        ab(4,k) = s1

        do ka=1,kk

!         define insitu
          tp(ka) = th(ka)

!         create anomalies for temperature, salinity & density and
!         load work array "a" with the anomalies and their products

          tanom = tp(ka) - t1
          sanom = sp(ka) - s1
          sigman(ka) = sigma(ka) - tot
          a(ka,1) = tanom
          a(ka,2) = sanom
          a(ka,3) = tanom * tanom
          a(ka,4) = tanom * sanom
          a(ka,5) = sanom * sanom
          a(ka,6) = a(ka,3) * tanom
          a(ka,7) = a(ka,5) * tanom
          a(ka,8) = a(ka,3) * sanom
          a(ka,9) = a(ka,5) * sanom
        enddo

!       set the arguments used in call to "lsqsl2"
!       ndim = first dimension of array a
!       nrow =number of rows of array a
!       ncol = number of columns of array a
!       in = option number of lsqsl2
!       itmax = number of iterations

        ndim = 50
        nrow = kk
        ncol = 9
        in = 1
        itmax = 4

        it = 0
        ieq = 2
        irank = 0
        eps = 1.0e-7
        nhdim = 9

!       LSQL2 is  a Jet Propulsion Laboratory subroutine that
!       computes the least squares fit in an iterative manner for
!       overdetermined systems.

        call lsqsl2 (ndim, a, nrow, ncol, sigman, x, irank, in, itmax,
     &               it, ieq, enorm, eps, nhdim, c, r, sb)

        do i=1,ncol
          ab(i+4,k) = x(i)
        enddo

!       end loop on model levels

      enddo

      nn = ncol + 4

      do k=1,km
        ab(2,k)  = 1.e-3 * ab(2,k)
        ab(4,k)  = 1.e-3 * ab(4,k) - 0.035
        ab(5,k)  = 1.e-3 * ab(5,k)
        ab(7,k)  = 1.e-3 * ab(7,k)
        ab(10,k) = 1.e-3 * ab(10,k)
        ab( 9,k) = 1.e+3 * ab( 9,k)
        ab(11,k) = 1.e+3 * ab(11,k)
        ab(13,k) = 1.e+6 * ab(13,k)
      enddo

!     save this data for a model execution converting insitu
!     temperatures to potential temperatures

      do k=1,km
        ro0_den(k) = ab(2,k)
        to_den(k)  = ab(3,k)
        so_den(k)  = ab(4,k)
        d = z(k)
        s = smin(k)
        t = tmin(k)
        call potem(t,s,d,theta)
        tmink(k)   = theta
        s = smax(k)
        t = tmax(k)
        call potem(t,s,d,theta)
        tmaxk(k)   = theta
        smink(k)   = smin(k)
        smaxk(k)   = smax(k)
        do i=5,13
          c_den(k,i-4) = ab(i,k)
        enddo
      enddo

      write (stdout,9531)
      write (stdout,9532)
     & (i,z(i),tmin(i),tmax(i),smin(i),smax(i),tmink(i),tmaxk(i),i=1,km)

      write (stdout,'(/a/a/)')
     & 'Note: density coefficients were calculated using the UNESCO'
     &,'      formulation.'

 9531 format('    density coefficients were calculated  ',
     &       /'    (employing the UNESCO equation of state)',
     &       /'    and are valid for the following depths and',
     &       ' both INSITU and POTENTIAL T and S ranges'
     &       /' ',t7,'k',t14,'depth',t27,'tmin',t37,
     &       'tmax',t52,'smin',t62,'smax',t70,'Pot tmin',t80,'Pot tmax')
 9532 format(' ',t5,i3,t12,f7.2,'e2',t25,f7.3,t35,f7.3,t50,f7.4,
     &       t60,f7.4,t70,f7.3,t80,f7.3)

      return
      end

      subroutine knuekm (t, s, d, rho)
!=======================================================================
!     this subroutine calculates the density of seawater using the
!     Knudsen-Ekman equation of state.

!     input [units]:
!       in-situ temperature (t): [degrees centigrade]
!       salinity (s): [per mil]
!       depth (d): [meters of depth, to approximate pressure]
!     output [units]:
!       density (rho): sigma units

!     reference:
!        Fofonoff, N., The Sea: Vol 1, (ed. M. Hill). Interscience,
!          New York, 1962, pp 3-30.

!-----------------------------------------------------------------------

      implicit none

      real (kind=8) eps2, t2, t, t3, s2, s, s3, f1, f2, f3, fs, sigma
      real (kind=8) a, d, b1, b2, b, co, alpha, rho

      data eps2/1.d-16/

      t2 = t*t
      t3 = t2*t
      s2 = s*s
      s3 = s2*s
      f1 = -1.0d0 * (t - 3.98d0)**2 * (t + 2.83d2) /
     &     (5.0357d2*(t + 6.726d1))
      f2 = t3*1.0843d-6 - t2*9.8185d-5 + t*4.786d-3
      f3 = t3*1.6670d-8 - t2*8.1640d-7 + t*1.803d-5
      fs = s3*6.76786136d-6 - s2*4.8249614d-4 + s*8.14876577d-1

      sigma= f1 + (fs + 3.895414d-2)*
     &      (1.0d0 - f2 + f3*(fs - 2.2584586d-1))

      a= d*1.0d-4*(1.055d2 + t*9.50d0 - t2*1.58d-1 - d*t*1.5d-4)  -
     &   (2.27d2 + t*2.833d1 - t2*5.51d-1 + t3*4.0d-3)
      b1 = (fs - 2.81324d1)*1.d-1
      b2 = b1 * b1
      b  = -b1* (1.473d2 - t*2.72d0 + t2*4.0d-2 - d*1.0d-4*
     &     (3.24d1 - 0.87d0*t + 2.0d-2*t2))
      b  = b + b2*(4.5d0 - 1.0d-1*t - d*1.0d-4*(1.8d0 - 6.0d-2*t))
      co = 4.886d3/(1.0d0 + 1.83d-5*d)

      alpha = d*1.0d-6*(co + a + b)

      rho = (sigma + alpha)/(1.d0 - 1.0d-3*alpha)

      return
      end

      subroutine lsqsl2 (ndim,a,d,w,b,x,irank,in,itmax,it,ieq,enorm,eps1
     &,nhdim,aa,r,s)

!     this routine is a modification of lsqsol. march,1968. r. hanson.
!     linear least squares solution

!     this routine finds x such that the euclidean length of
!     (*) ax-b is a minimum.

!     here a has k rows and n columns, while b is a column vector with
!     k components.

!     an orthogonal matrix q is found so that qa is zero below
!     the main diagonal.
!     suppose that rank (a)=r
!     an orthogonal matrix s is found such that
!     qas=t is an r x n upper triangular matrix whose last n-r columns
!     are zero.
!     the system tz=c (c the first r components of qb) is then
!     solved. with w=sz, the solution may be expressed
!     as x = w + sy, where w is the solution of (*) of minimum euclid-
!     ean length and y is any solution to (qas)y=ty=0.

!     iterative improvements are calculated using residuals and
!     the above procedures with b replaced by b-ax, where x is an
!     approximate solution.

      implicit none

      integer nhdim, k, n, it, isw, l, m, j1, j2, j3, j4, j5, j6, j7
      integer j8, j9, lm, irank, in, j, i, ieq, n2, n7, n1, ip, km
      integer n8, ipm1, ii, n3, ipp1, n4, irp1, irm1, n6, itmax, ns
      integer k1, d, w, ndim

      logical erm

      real (kind=8) top1, top, eps2, am, a1, eps1, sp, enorm, top2
      real (kind=8) enm1, a2, sj, dp, up, bp, aj

!     in=1 for first entry.
!                   a is decomposed and saved. ax-b is solved.
!     in = 2 for subsequent entries with a new vector b.
!     in=3 to restore a from the previous entry.
!     in=4 to continue the iterative improvement for this system.
!     in = 5 to calculate solutions to ax=0, then store in the array h.
!     in  =  6   do not store a  in aa.  obtain  t = qas, where t is
!     min(k,n) x min(k,n) and upper triangular. now return.do not obtain
!     a solution.
!     no scaling or column interchanges are performed.
!     in  =  7   same as with  in = 6  except that soln. of min. length
!                is placed into x. no iterative refinement.  now return.
!     column interchanges are performed. no scaling is performed.
!     in  = 8    set addresses. now return.

!     options for computing  a matrix product   y*h  or  h*y are
!     available with the use of the entry points  myh and mhy.
!     use of these options in these entry points allow a great saving in
!     storage required.

      include "stdunits.h"

      real (kind=8) a(d,w), b(d), aa(d,w), s(d+72), x(w), h(nhdim,nhdim)
      real (kind=8) r(d+36)
!     d = depth of matrix.
!     w = width of matrix.
      k=d
      n=w
      erm=.true.
      top1 = 0.0
      top = 0.0
      eps2 = 0.0

!     if it=0 on entry, the possible error message will be suppressed.

      if (it.eq.0) erm=.false.

!     ieq = 2      if column scaling by least max. column length is
!     to be performed.

!     ieq = 1       if scaling of all components is to be done with
!     the scalar max(abs(aij))/k*n.

!     ieq = 3 if column scaling as with in =2 will be retained in
!     rank deficient cases.

!     the array s must contain at least max(k,n) + 4n + 4min(k,n) cells
!        the   array r must contain k+4n s.p. cells.

!     the last card controls desired relative accuracy.
!     eps1  controls  (eps) rank.

      isw=1
      l=min0(k,n)
      m=max0(k,n)
      j1=m
      j2=n+j1
      j3=j2+n
      j4=j3+l
      j5=j4+l
      j6=j5+l
      j7=j6+l
      j8=j7+n
      j9=j8+n
      lm=l
      if (irank.ge.1.and.irank.le.l) lm=irank
      if (in.eq.6) lm=l
      if (in.eq.8) return

!     return after setting addresses when in=8.

      if (in.eq.1) goto 10
      if (in.eq.2) goto 360
      if (in.eq.3) goto 810
      if (in.eq.4) goto 390
      if (in.eq.5) goto 830
      if (in.eq.6) goto 10
      if (in.eq.7) goto 10

!     equilibrate columns of a (1)-(2).

!     (1)

   10 continue

!     save data when in = 1.

      if (in.gt.5) go to 30
        do j=1,n
          do i=1,k
            aa(i,j)=a(i,j)
          enddo
        enddo
   30 continue
      if (ieq.eq.1) go to 60
        do j=1,n
!          am=0.e0
          am=1.e-30
          do i=1,k
            am = max(am,abs(a(i,j)))
          enddo

!         s(m+n+1)-s(m+2n) contains scaling for output variables.

          n2=j2+j
          if (in.eq.6) am=1.d0
          s(n2)=1.d0/am
          do i=1,k
            a(i,j)=a(i,j)*s(n2)
          enddo
        enddo
        go to 100
60      continue
!        am=0.d0
          am=1.e-30
        do j=1,n
          do i=1,k
            am= max(am,abs(a(i,j)))
          enddo
        enddo
        am=am/float(k*n)
        if (in.eq.6) am=1.d0
        do j=1,n
          n2=j2+j
          s(n2)=1.d0/am
        enddo
        do j=1,n
          n2=j2+j
          do i=1,k
            a(i,j)=a(i,j)*s(n2)
          enddo
        enddo
!       compute column lengths with d.p. sums finally rounded to s.p.

!     (2)

100     continue
        do j=1,n
          n7=j7+j
          n2=j2+j
          s(n7)=s(n2)
        enddo

!       s(m+1)-s(m+ n) contains variable permutations.

!       set permutation to identity.

        do j=1,n
          n1=j1+j
          s(n1)=j
        enddo

!       begin elimination on the matrix a with orthogonal matrices .

!       ip=pivot row

        do ip=1,lm
          dp=0.d0
          km=ip
          do j=ip,n
            sj=0.d0
            do i=ip,k
              sj=sj+a(i,j)**2
            enddo
            if (dp.gt.sj) go to 140
              dp=sj
              km=j
              if (in.eq.6) go to 160
140         continue
          enddo

!         maximize (sigma)**2 by column interchange.

!         suppress column interchanges when in=6.

!         exchange columns if necessary.

          if (km.eq.ip) go to 160
            do i=1,k
              a1=a(i,ip)
              a(i,ip)=a(i,km)
              a(i,km)=a1
            enddo

!           record permutation and exchange squares of column lengths.

            n1=j1+km
            a1=s(n1)
            n2=j1+ip
            s(n1)=s(n2)
            s(n2)=a1
            n7=j7+km
            n8=j7+ip
            a1=s(n7)
            s(n7)=s(n8)
            s(n8)=a1
160       continue
          if (ip.eq.1) go to 180
            a1=0.d0
            ipm1=ip-1
            do i=1,ipm1
              a1=a1+a(i,ip)**2
            enddo
            if (a1.gt.0.d0) go to 190
180       continue
          if (dp.gt.0.d0) go to 200

!           test for rank deficiency.

190         continue
            if (sqrt(dp/a1).gt.eps1) go to 200
            if (in.eq.6) go to 200
            ii=ip-1
            if (erm) write (stdout,1140) irank,eps1,ii,ii
            irank=ip-1
            erm=.false.
            go to 260

!           (eps1) rank is deficient.

200       continue
          sp=sqrt(dp)

!         begin front elimination on column ip.

!         sp=sqroot(sigma**2).

          bp=1.d0/(dp+sp*abs(a(ip,ip)))

!         store beta in s(3n+1)-s(3n+l).

          if (ip.eq.k) bp=0.d0
          n3=k+2*n+ip
          r(n3)=bp
          up=sign(dble(sp)+abs(a(ip,ip)),dble(a(ip,ip)))
          if (ip.ge.k) go to 250
            ipp1=ip+1
            if (ip.ge.n) go to 240
              do j=ipp1,n
                sj=0.d0
                do i=ipp1,k
                  sj=sj+a(i,j)*a(i,ip)
                enddo
                sj=sj+up*a(ip,j)
                sj=bp*sj

!               sj=yj now

                do i=ipp1,k
                  a(i,j)=a(i,j)-a(i,ip)*sj
                enddo
                a(ip,j)=a(ip,j)-sj*up
              enddo
240         continue
            a(ip,ip)=-sign(sp,a(ip,ip))

            n4=k+3*n+ip
            r(n4)=up
250       continue
        enddo
        irank=lm
260     continue
        irp1=irank+1
        irm1=irank-1
        if (irank.eq.0.or.irank.eq.n) go to 360
        if (ieq.eq.3) go to 290

!       begin back processing for rank deficiency case
!       if irank is less than n.

        do j=1,n
          n2=j2+j
          n7=j7+j
          l=min0(j,irank)

!         unscale columns for rank deficient matrices when ieq.ne.3.

          do i=1,l
            a(i,j)=a(i,j)/s(n7)
          enddo
          s(n7)=1.d0
          s(n2)=1.d0
        enddo
290     continue
        ip=irank
300     continue
        sj=0.d0
        do j=irp1,n
          sj=sj+a(ip,j)**2
        enddo
        sj=sj+a(ip,ip)**2
        aj=sqrt(sj)
        up=sign(dble(aj)+abs(a(ip,ip)),dble(a(ip,ip)))

!       ip th element of u vector calculated.

        bp=1.d0/(sj+abs(a(ip,ip))*aj)

!       bp = 2/length of u squared.

        ipm1=ip-1
        if (ipm1.le.0) go to 340
        do i=1,ipm1
          dp=a(i,ip)*up
          do j=irp1,n
            dp=dp+a(i,j)*a(ip,j)
          enddo
          dp=dp/(sj+abs(a(ip,ip))*aj)

!         calc. (aj,u), where aj=jth row of a

          a(i,ip)=a(i,ip)-up*dp

!         modify array a.

          do j=irp1,n
            a(i,j)=a(i,j)-a(ip,j)*dp
          enddo
        enddo
340     continue
        a(ip,ip)=-sign(dble(aj),dble(a(ip,ip)))

!       calc. modified pivot.

!       save beta and ip th element of u vector in r array.

        n6=k+ip
        n7=k+n+ip
        r(n6)=bp
        r(n7)=up

!       test for end of back processing.

        if (ip-1.gt.0) goto 350
        if (ip-1.le.0) goto 360
350     continue
        ip=ip-1
        go to 300
360     continue
        if (in.eq.6) return
        do j=1,k
          r(j)=b(j)
        enddo
        it=0

!       set initial x vector to zero.

        do j=1,n
          x(j)=0.d0
        enddo
        if (irank.eq.0) go to 690

!       apply q to rt. hand side.

390     continue
        do ip=1,irank
          n4=k+3*n+ip
          sj=r(n4)*r(ip)
          ipp1=ip+1
          if (ipp1.gt.k) go to 410
            do i=ipp1,k
              sj=sj+a(i,ip)*r(i)
            enddo
410       continue
          n3=k+2*n+ip
          bp=r(n3)
          if (ipp1.gt.k) go to 430
            do i=ipp1,k
              r(i)=r(i)-bp*a(i,ip)*sj
            enddo
430       continue
          r(ip)=r(ip)-bp*r(n4)*sj
        enddo
        do j=1,irank
          s(j)=r(j)
        enddo
        enorm=0.d0
        if (irp1.gt.k) go to 510
          do j=irp1,k
            enorm=enorm+r(j)**2
          enddo
          enorm=sqrt(enorm)
          go to 510
460       continue
          do j=1,n
            sj=0.d0
            n1=j1+j
            ip=s(n1)
            do i=1,k
              sj=sj+r(i)*aa(i,ip)
            enddo

!           apply at to rt. hand side.
!           apply scaling.

            n7=j2+ip
            n1=k+n+j
            r(n1)=sj*s(n7)
          enddo
          n1=k+n
          s(1)=r(n1+1)/a(1,1)
          if (n.eq.1) go to 510
          do j=2,n
            n1=j-1
            sj=0.d0
            do i=1,n1
              sj=sj+a(i,j)*s(i)
            enddo
            n2=k+j+n
            s(j)=(r(n2)-sj)/a(j,j)
          enddo

!         entry to continue iterating.  solves tz = c = 1st irank
!         components of qb .

510     continue
        s(irank)=s(irank)/a(irank,irank)
        if (irm1.eq.0) go to 540
          do j=1,irm1
            n1=irank-j
            n2=n1+1
            sj=0.
            do i=n2,irank
              sj=sj+a(n1,i)*s(i)
            enddo
            s(n1)=(s(n1)-sj)/a(n1,n1)
          enddo

!         z calculated.  compute x = sz.

540     continue
        if (irank.eq.n) go to 590
          do j=irp1,n
            s(j)=0.d0
          enddo
          do i=1,irank
            n7=k+n+i
            sj=r(n7)*s(i)
            do j=irp1,n
              sj=sj+a(i,j)*s(j)
            enddo
            n6=k+i
            do j=irp1,n
              s(j)=s(j)-a(i,j)*r(n6)*sj
            enddo
            s(i)=s(i)-r(n6)*r(n7)*sj
          enddo

!         increment for x of minimal length calculated.

590     continue
        do i=1,n
          x(i)=x(i)+s(i)
        enddo
        if (in.eq.7) go to 750

!         calc. sup norm of increment and residuals

          top1=0.d0
          do j=1,n
            n2=j7+j
            top1= max(top1,abs(s(j))*s(n2))
          enddo
          do i=1,k
            sj=0.d0
            do j=1,n
              n1=j1+j
              ip=s(n1)
              n7=j2+ip
              sj=sj+aa(i,ip)*x(j)*s(n7)
            enddo
            r(i)=b(i)-sj
          enddo
        if (itmax.le.0) go to 750

!         calc. sup norm of x.

          top=0.d0
          do j=1,n
            n2=j7+j
            top= max(top,abs(x(j))*s(n2))
          enddo

!         compare relative change in x with tolerance eps .

          if (top1-top*eps2.lt.0.) goto 690
          if (top1-top*eps2.ge.0.) goto 650
650   continue
      if (it-itmax.lt.0) goto 660
      if (it-itmax.ge.0) goto 680
660   continue
      it=it+1
      if (it.eq.1) go to 670
      if (top1.gt..25*top2) go to 690
670   continue
      top2=top1
      if (isw.eq.1) go to 390
      if (isw.eq.2) go to 460
680   continue
      it=0
690   continue
      sj=0.d0
      do j=1,k
        sj=sj+r(j)**2
      enddo
      enorm=sqrt(sj)
      if (irank.eq.n.and.isw.eq.1) go to 710
      go to 730
710   continue
      enm1=enorm

!     save x array.

      do j=1,n
        n1=k+j
        r(n1)=x(j)
      enddo
      isw=2
      it=0
      go to 460

!     choose best solution

730   continue
      if (irank.lt.n) go to 750
      if (enorm.le.enm1) go to 750
      do j=1,n
        n1=k+j
        x(j)=r(n1)
      enddo
      enorm=enm1

!     norm of ax - b located in the cell enorm .

!     rearrange variables.

750   continue
      do j=1,n
        n1=j1+j
        s(j)=s(n1)
      enddo
      do j=1,n
        do i=j,n
          ip=s(i)
          if (j.eq.ip) go to 780
        enddo
780     continue
        s(i)=s(j)
        s(j)=j
        sj=x(j)
        x(j)=x(i)
        x(i)=sj
      enddo

!     scale variables.

      do j=1,n
        n2=j2+j
        x(j)=x(j)*s(n2)
      enddo
      return

!     restore a.

810   continue
      do j=1,n
        n2=j2+j
        do i=1,k
          a(i,j)=aa(i,j)
        enddo
      enddo
      return

!     generate solutions to the homogeneous equation ax = 0.

  830 if (irank.eq.n) return
      ns=n-irank
      do i=1,n
        do j=1,ns
          h(i,j)=0.d0
        enddo
      enddo
      do j=1,ns
        n2=irank+j
        h(n2,j)=1.d0
      enddo
      if (irank.eq.0) return
      do j=1,irank
        do i=1,ns
          n7=k+n+j
          sj=r(n7)*h(j,i)

!         this part of the code should not be executed. However some
!         compilers generate warning msgs that "irp1" is not defined
!         so it is arbitrarily set here to fool the compilers

          irp1 = 1
          if (i .gt. 0) then
            write (stdout,*) ' Error in lsqsl2: search for this msg'
            stop
          endif
          do k1=irp1,n
            sj=sj+h(k1,i)*a(j,k1)
          enddo
          n6=k+j
          bp=r(n6)
          dp=bp*r(n7)*sj
          a1=dp
          a2=dp-a1
          h(j,i)=h(j,i)-(a1+2.*a2)
          do k1=irp1,n
            dp=bp*a(j,k1)*sj
            a1=dp
            a2=dp-a1
            h(k1,i)=h(k1,i)-(a1+2.*a2)
          enddo
        enddo
      enddo

!     rearrange rows of solution matrix.

      do j=1,n
        n1=j1+j
        s(j)=s(n1)
      enddo
      do j=1,n
        do i=j,n
          ip=s(i)
          if (j.eq.ip) go to 900
        enddo
900     continue
        s(i)=s(j)
        s(j)=j
        do k1=1,ns
          a1=h(j,k1)
          h(j,k1)=h(i,k1)
          h(i,k1)=a1
        enddo
      enddo
      return

 1140 format (/'warning. irank has been set to',i4,'  but(',1pe10.3,
     1 ') rank is',i4,'.  irank is now taken as ',i4)
      end

      subroutine potem (t, s, p, theta)

!=======================================================================
!     this subroutine calculates potential temperature as a function
!     of in-situ temperature, salinity, and pressure.

!     input [units]:
!       in-situ temperature (t): [degrees centigrade]
!       salinity (s): [per mil]
!       pressure (p): [decibars, approx. as meters of depth]
!     output [units]:
!       potential temperature (theta): [degrees centigrade]

!     references:
!        based on Fofonoff and Froese (1958) as shown in ...
!        Fofonoff, N., The Sea: Vol 1, (ed. M. Hill). Interscience,
!          New York, 1962, page 17, table iv.

!-----------------------------------------------------------------------

      implicit none

      real (kind=8) b1, p, b2, t, t2, t3, b3, b4, b5, s, b6, s2
      real (kind=8) p2, b7, b8, b9, b10, b11, potmp, theta

      b1    = -1.60d-5*p
      b2    = 1.014d-5*p*t
      t2    = t*t
      t3    = t2*t
      b3    = -1.27d-7*p*t2
      b4    = 2.7d-9*p*t3
      b5    = 1.322d-6*p*s
      b6    = -2.62d-8*p*s*t
      s2    = s*s
      p2    = p*p
      b7    = 4.1d-9*p*s2
      b8    = 9.14d-9*p2
      b9    = -2.77d-10*p2*t
      b10   = 9.5d-13*p2*t2
      b11   = -1.557d-13*p2*p
      potmp = b1+b2+b3+b4+b5+b6+b7+b8+b9+b10+b11
      theta = t-potmp

      return
      end

      subroutine unesco (t, s, pin, rho)

!=======================================================================
!     this subroutine calculates the density of seawater using the
!     standard equation of state recommended by unesco(1981).

!     input [units]:
!       in-situ temperature (t): [degrees centigrade]
!       salinity (s): [practical salinity units]
!       pressure (pin): [decibars, approx. as meters of depth]
!     output [units]:
!       density(rho): kilograms per cubic meter

!     references:
!        Gill, A., Atmosphere-Ocean Dynamics: International Geophysical
!         Series No. 30. Academic Press, London, 1982, pp 599-600.
!        UNESCO, 10th report of the joint panel on oceanographic tables
!          and standards. UNESCO Tech. Papers in Marine Sci. No. 36,
!          Paris, 1981.

!-----------------------------------------------------------------------

      implicit none

      real (kind=8) c1p5, p, pin, rw, t, rsto, s, xkw, xksto, xkstp, rho

      c1p5 = 1.5d0

!  convert from depth [m] (decibars) to bars
      p = pin * 1.0d-1

      rw =     9.99842594d2 + 6.793952d-2*t - 9.095290d-3*t**2
     &        + 1.001685d-4*t**3 - 1.120083d-6*t**4 + 6.536332d-9*t**5

      rsto =   rw + (8.24493d-1 - 4.0899d-3*t + 7.6438d-5*t**2
     &        - 8.2467d-7*t**3 + 5.3875d-9*t**4) * s
     &       + (-5.72466d-3 + 1.0227d-4*t - 1.6546d-6*t**2) * s**c1p5
     &       + 4.8314d-4 * s**2

      xkw =     1.965221d4 + 1.484206d2*t - 2.327105d0*t**2 +
     &         1.360477d-2*t**3 - 5.155288d-5*t**4

      xksto =   xkw + (5.46746d1 - 6.03459d-1*t + 1.09987d-2*t**2
     &        - 6.1670d-5*t**3) * s
     &       + (7.944d-2 + 1.6483d-2*t - 5.3009d-4*t**2) * s**c1p5

      xkstp =   xksto + (3.239908d0 + 1.43713d-3*t + 1.16092d-4*t**2
     &        - 5.77905d-7*t**3) * p
     &       + (2.2838d-3 - 1.0981d-5*t - 1.6078d-6*t**2) * p * s
     &       + 1.91075d-4 * p * s**c1p5
     &       + (8.50935d-5 - 6.12293d-6*t + 5.2787d-8*t**2) * p**2
     &       + (-9.9348d-7 + 2.0816d-8*t + 9.1697d-10*t**2) * p**2 * s

      rho =    rsto / (1.0d0 - p/xkstp)

      return
      end
