c
      program peomod
c      
c   To compile on an HP-C160, try:
c   f77 +O2 +autodblpad +DA2.0N +DS2.0A basin.f basinsubs.f -o basin.x
c
c   The main program of a layered, primitive equation ocean model. 
c   The necessary subrotuines are in basinsubs.f.
c
c   This model may be used to compute the response of an 
c   ocean basin or a channel to a prescribed wind field. It may
c   also be used to study geostrophic adjustment of an 
c   initial density anomaly.  This model is intended to be more an
c   educational tool than a first line research tool.
c 
c   The model is layered in the vertical, and uses a 
c   staggered grid (a C grid) in the horizontal. It uses 
c   an energy-conserving finite differencing scheme. 
c   Time stepping is by a leap-frog with an occasional
c   trapezoidal correction in order to supress time-splitting.
c   Hydrostatic pressure is computed by a reduced gravity or
c   a free surface pressure model. A rigid lid 'pressure' can 
c   also be applied.
c
c   The code is intended to be completely portable Fortran 77.
c
c
c   Written by Jim Price beginning in March, 1994. Changes were 
c   ongoing at least as late as December, 1997. 
c
c   NOTE: This model code is developmental, and has not been fully
c   tested.  
c
c   The variables are:
c   
c   (u, v) are the (east, north) components of the transport,
c   h is the layer thickness,
c   p is the hydrostatic pressure,
c   s is a streamfunction for the transport (or the net force if rigid lid), 
c   t is a passive tracer,
c   (taux, tauy) are (east, north) wind stress components,
c   (x, y) are east and north coordinates.
c
c   These variables are laid out on a C grid as follows: 
c
c      h u | h u | h u
c      v s | v s | v s
c      ---------------
c      h u | h u | h u 
c      v s | v s | v s 
c      ---------------
c      h u | h u | h u
c      v s | v s | v s 
c  
c   Pressure is defined at the h points, as is the tracer, t, and
c   and the Coriolis parameter, f. The x,y coordinates
c   are also centered on the h points.  Wind stress is
c   defined at the corresponding u,v points.  This grid scheme is 
c   a crucial aspect of the numerical method to which you have to pay
c   rigorous attention if you change any aspect of the finite differencing
c   or the boundary conditions!  For example, u is the east component of 
c   transport; to compute the velocity, ui, you must divide by the
c   appropriately averaged (horizontally) layer thickness as follows:
c   ui(j,k,m) = u(j,k,m)/(0.5*(h(j,k,m) + h(j+1,k,m))).  This is highly
c   tedious, but necessary to achieve accurate solutions. 
c
c   Rows and columns and the x and y directions are defined as follows:
c
c      (1,ny) ....  (nx,ny)
c        .             .
c        .             .
c        . . . . . . . .
c        .             .
c        .             .
c      (1,1)  ....  (nx,1)
c
c   The top most row (h and u only) and the left most column (h and v only) 
c   are junk (not meanignful) if the BCs are for solid boundaries. 
c                                                                             
c   The variables are stored in four-dimensional arrays, i.e.,  
c   u(nx,ny,nz,3), where the last index refers to time level or otherwise
c   as follows:
c     u(...1) is the present time 
c     u(...2) is the past time
c     u(...3) is the tendency for this variable (i.e., du/dt).
c 
c   As of December 1995, the following problems remained:
c
c   1) The most troubling (problematic) aspects of the model seem to be
c   almost anything to do with the rigid lid calculations.  The rigid lid
c   version works much better when the sum of the layer thicknesses are
c   required to equal the water column depth. This may be 
c   a warning of a small error in the rigid lid code. In any case, the long-
c   term behavior can be sensitive to the details of how the rigid lid 
c   pressure is solved (for times in excess of 1500 days), and e.g., the
c   rigid lid calculation works much better when double precision
c   arithmetic is used throughout (a must, actually). 
c
c   2) Part of the whining above probably comes from the 
c   rather simple elliptic solver included here.  These errors are made
c   noticably worse as the size of the model domain (number of points
c   in the x and y directions) is increased beyond about 40.    
c 
c   3) The various boundary condition options (i.e., basin, channel or fully
c   symmetric) and pressure models (reduced gravity, free surface and
c   rigid lid) have not all been checked in every possible configuration.
c
c
c............................. Data Allocation ..........................
c
      parameter (nx=41, ny=41, nz=2, nxp=nx+1, nyp=ny+1, 
     1    nf=4, nf2=2*nz*nf)
c
      dimension h(nx,ny,nz,3),u(nx,ny,nz,3),v(nx,ny,nz,3),t(nx,ny,nz,3)
c     
      dimension h0(nz),delr0(nz),gprime(nz),x(nx),y(ny),
     1 p(nx,ny,nz),f(ny),taux(nx,ny),tauy(nx,ny),
     3 kpa(ny),jpa(nx),kma(ny),jma(nx),ctu(nx,ny,nz),ctv(nx,ny,nz),
     5 kmd(ny),kpd(ny),jmd(nx),jpd(nx),eta(nx,ny,nz)
c 
      dimension ui(nx,ny,nz,3),vi(nx,ny,nz,3),uuhath(nx,ny,nz),
     1 vvhath(nx,ny,nz),uvhats(nx,ny,nz),ud24(nx,ny,nz),
     2 vd24(nx,ny,nz),td24(nx,ny,nz),work24(nx,ny,nz)
c     
      dimension work1(nx,ny),work2(nx,ny),work3(nx,ny),work4(nx,ny),
     1 work5(nx,ny),work6(nx,ny),work7(nx,ny),work8(nx,ny)         
c
c  The arrays below are required solely for the rigid lid calculation.
c
      dimension ua(nx,ny),va(nx,ny),del2st(nx,ny),st(nx,ny),
     1 prp(nxp,nyp),d2pr(nxp,nyp),prm(nx,ny),prx(nxp,nyp),pry(nxp,nyp),
     2 jpap(nxp),jmap(nxp),kmap(nyp),kpap(nyp),uapr(nx,ny),vapr(nx,ny),
     3 pr(nx,ny),dprdx(nx,ny),dprdy(nx,ny)     
c
c  The arrays below are needed for float tracking and float data storage.
c
      dimension xf(nf,nz),yf(nf,nz),xyfk(nf2),
     1 ufl(nx,ny,nz),vfl(nx,ny,nz)
c
c  These arrays are used to store the time averages and other diagnsotics. 
c
      dimension savg(nx,ny),pavg(nx,ny,nz),pvavg(nx,ny,nz),
     1 eavg(nx,ny,nz),avprof(ny,nz),pvprof(ny,nz),rvprof(ny,nz),
     2 uavg(nx,ny,nz),vavg(nx,ny,nz)
c      
      integer sidebc, basin, rgrav, rlid 
      character*60 ifile, alf 
c
      ncx = nx/2 + 1 
      nxm = nx - 1
      ncy = ny/2 + 1
      nym = ny - 1
      if(nym.eq.0) nym = 1
      nzm = nz - 1
      if(nz.eq.1) nzm = 1
c
      g = 9.8
      r0 = 1025.      
      tpi = 2.*4.*atan(1.)
      time = 0. 
      wworks = 0.
      fworks = 0. 
      bworks = 0.
      timd = 0.
      timm = 0.
      timt = 0.
      iblow = 0
c      
c  rnonl can be set to zero to remove nonlinear terms from the momentum and 
c   tracer equations (but you had better be careful with this !).
      rnonl = 1.0
c      
c 
c ........................ Restart, and Open Files .........................                       
c
c  Check to see if you want to begin from a restart file.
c     
      irest = 0
      iapp = 0
      write (6,7000)
 7000 format (1x,//,
     1 '  Should we restart from a previous run?',/,
     2 '   restart?                    (0 = no (default), 1 = yes)',/,
     3 '   append data to old files?   (0 = no (default), 1 = yes)',/,
     4 '   (enter both data or default with ,,)')  
      read (5,*) irest, iapp 
c 
c  The files opened below are used to save results for later Matlab 
c  plotting program. Add data on to some of these these files if iapp 
c  is set on (= 1). 
c
      if(iapp.eq.1) then
      open (unit=32,file='looktim.dat',access='append',status='unknown')
      open (unit=1,file='basin1.dat',access='append',status='unknown')
      open (unit=2,file='basin2.dat',access='append',status='unknown')
      open (unit=3,file='basin3.dat',access='append',status='unknown')
      open (unit=4,file='basin4.dat',access='append',status='unknown')
      open (unit=15,file='basin5.dat',access='append',status='unknown')
      open (unit=16,file='basin6.dat',access='append',status='unknown')      
c       
      open (unit=10,file='basin10.dat',access='append',status='unknown')
      open (unit=40,file='basin40.dat',access='append',status='unknown')      
c      
      open (unit=31,file='movtim.dat',access='append',status='unknown')
      open (unit=11,file='basin11.dat',access='append',status='unknown')
c      
      open (unit=35,file='bfloat.dat',access='append',status='unknown')
      open (unit=36,file='pvprof.dat',access='append',status='unknown')      
c      
      else 
      open (unit=32,file='looktim.dat') 
      open (unit=1,file='basin1.dat')
      open (unit=2,file='basin2.dat')
      open (unit=3,file='basin3.dat')
      open (unit=4,file='basin4.dat')
      open (unit=15,file='basin5.dat')
      open (unit=16,file='basin6.dat')       
c      
      open (unit=10,file='basin10.dat')
      open (unit=40,file='basin40.dat')      
c      
      open (unit=31,file='movtim.dat')
      open (unit=11,file='basin11.dat')
c      
      open (unit=35,file='bfloat.dat')
      open (unit=36,file='pvprof.dat')      
c      
      end if 
c
      open (unit=12,file='basin12.dat',status='unknown')
      open (unit=30,file='what.dat')
c 
c  Unit 39 is connected to a file called stopfile.dat that has a single
c  number that can be set to 1 to gracefully stop a model run under DOS. 
c 
c      open (unit=39,file='stopfile.dat',status='unknown',
c     1        form='formatted')
c      istop = 0
c      write (39,3939) istop
c 3939 format (i1)
c      close (39)
c      rewind(39)            
c
c  Open the restart file here, if need be.
c      
      if(irest.eq.1) then   
      write (6,7052)
      read (5,7001) ifile
 7001 format (a24)
      open(unit=20,file=ifile,form='unformatted',status='old')
c      
      read (20) nx4,ny4,nz4,nf4
c
c  Verify that the dimensions are consistent with the restart file data set.
c
      if(nx4.ne.nx.or.ny4.ne.ny.or.nz4.ne.nz.or.nf4.ne.nf) then
      write (6,7010) nx4,ny4,nz4,nf4,nx,ny,nz,nf
 7010 format (1x,///,
     1'  Sorry bud, the dimensions in startup do not match.', 6i5)
      go to 9999
      end if           
c      
      read (20) time9,timd,timm,timt,
     1 sidebc,basin,rgrav,rlid,ibhm,cdb,
     2 rnonl,dt,dx,dy,diff,hbot,h0,delr0,rtcl,x,y,f,f0,beta,tau,gprime,
     3 wworks,fworks,bworks,xf,yf,taux,tauy,u,v,h,t,pr,ui,vi 
c
c  Write out some information on this case just as a reminder.
c     
      write (6,8811) time9, sidebc, basin, rgrav, rlid
 8811 format (1x,/,' time, sidebc, basin, rgrav, rlid',
     1 /, 1x, f12.2, 6i5,/)
      write (6,8812) dt, dx, dy, diff, hbot
 8812 format (1x,/,' dt, dx, dy, diff, hbot',/,1x,5f9.2,/)
c
      twodt = 2.*dt
      halfdt = 0.5*dt     
      sdx = 1./dx
      sdy = 1./dy
c
      go to 7100
      end if           
c 
c ......... Initialize Basin Geometry and Boundary Conditions ..............
c
c  The geometry and boundary conditions are specified via the flags:
c  
c  The basin geometry is set by: 
c  basin = 0 for solid walls all the way around (a closed basin, the default),
c  basin = 1 for open BCs on east and west sides and walls on the 
c   north and south sides (this makes a channel),
c  basin = 2 for open BCs all the way around (probably makes sense only if
c   beta is zero). This makes an open ocean.
c
c  The BC for tangential velocity on the sidewalls is set by:
c  sidebc = 0 for no-slip BCs on the sidewalls, or, 
c  sidebc = 1 for free-slip BCs on the sidewalls (the default).
c
c  The BC for open boundaries (if there are any) is set by:
c  openbc = 0 for wrap-around BCs, or,
c  openbc = 1 for radiation BCs on all open sides.

c  For example, the default is a closed basin with free-slip BCs, and thus the 
c  default is basin = 0 and sidebc = 1. To have no-slip boundary conditions 
c  in a channel you would need to set basin = 1 and sidebc = 0.  To have a
c  completely open domain with radiation BCs (say for a geostrophic adjustment 
c  problem) set basin = 2 and openbc =1. 
c
      basin = 0 
      sidebc = 1
      openbc = 0 
c
      write (6,9929) 
 9929 format
     1 (1x,/,'  Basin configuration: ',/,
     2 '   closed basin       = 0 (default), or,',/,
     3 '   east-west channel  = 1, or,',/,
     4 '   open all sides     = 2',/,
     5 '   (enter one, or default with ,)')
      read (5,*) basin            
c
      if(basin.ne.2) then
      write (6,9922) 
 9922 format
     1 (1x,/,'  Sidewall boundary conditions: '/,
     2 '   no-slip            = 0 ',/,
     3 '   free-slip          = 1 (default)',/,
     4 '   (enter one, or default with ,)')
      read (5,*) sidebc
      end if
c
      if(basin.ge.1) then
      write (6,9928) 
 9928 format (1x,/,'  Open boundary boundary conditions:',/,
     1 '  wrap-around         = 0 (default), or,',/,
     2 '  radiation BC        = 1',/,
     3 '  (enter one, or default with ,)',)
      read (5,*) openbc
      end if      
c  
c ....................... Specify the Pressure Model .....................
c
c  The pressure model is set by the following flags:
c   
c  rgrav = 0 for a free surface pressure model, or,
c  rgrav = 1 for a reduced gravity pressure model (the default), and,
c  rlid = 0 (or 1) if you do (or do not) want to apply a rigid lid pressure
c   correction.  This is allowed only with a reduced gravity model.
c
c  Most of the time you will probably use a reduced gravity model.  The free
c  surface model is included as well mainly as a possible future alternative
c  to the damned rigid lid approximation.
c
c
 9135 continue 
c     
      rgrav = 1
      rlid = 2
c     
      write (6,9923)  
 9923 format (1x,/, 
     1 '  Pressure model: ',/,
     2 '   free surface       = 0',/,
     3 '   reduced gravity    = 1 (default)',/,
     4 '   (enter one, or default with ,)' )
      read (5,*) rgrav 
      if(rgrav.eq.1) then
      write (6,9972) 
 9972 format (1x,/,
     1 '  Apply a rigid lid ?',/,
     2 '   no                           = 0',/,
     3 '   yes                          = 1',/,
     4 '   yes, w/ corrected thickness  = 2 (default)',/,
     5 '   (enter one, or default with ,)' ) 
      read (5,*) rlid
      end if 
c
c 
c ....................... Initialize the Density Profile .....................
c
c  This next section sets the initial density 'profile' by defining the initial 
c  layer thicknesses and density differences as follows: 
c
c  hbot is the depth of the water column (m),
c  htcl is the thickness of the surface and thermocline layer(s) (m),
c  rtcl is the density difference across the thermocline (kg/m**3),
c  delradd is a density that may be added to the upper layer (i.e., to make
c   a free surface model with a realistic air-sea density difference you
c   should set delradd = 1025.).
c
c  From these input data the model then computes what it needs:
c
c  h0 are the initial layer thicknesses (m),
c  delr0 are the fixed density differences across the layer interfaces.
c 
c  The details of all of this are a little involved and depend upon the
c  kind of pressure model.  Be sure to check the resulting h0 and delr0.
c 
      hbot = 4000.
      htcl = 1000.
      rtcl = 2.0 
      delradd = 0.
c                 
      write (6,9924) htcl, hbot 
 9924 format (1x,/, 
     1 '  Layer thicknesses and bottom depth: ',/,
     2 '   surface and thermocline layer    (default = ',f6.0,' m)',/,
     3 '   bottom depth                     (default = ',f6.0,' m)',/,
     4 '   (enter both data, or default with  ,,)') 
      read (5,*) htcl, hbot
c        
      write (6,9925) rtcl, delradd
 9925 format (1x,/,
     1 '  Density differences: ',/,
     2 '   thermocline density diff.  (default = ',f6.1,' kg/m**3)',/,
     3 '   surface density diff.      (default = ',f6.1,' kg/m**3)',/,
     4 '   (enter both data, or default with  ,,)') 
      read (5,*) rtcl, delradd
c            
c  Set the density profile for a reduced gravity model. In this case the
c  density differences are associated with the lower interface of a layer.
c  The layer thicknesses are all set to htcl/nz, and the abyssal layer below 
c  (which is not explicitly represented) is presumed motionless.
c          
      if(rgrav.eq.1.and.nz.eq.1) then
      h0(1) = htcl
      delr0(1) = rtcl
      end if
c
      if(rgrav.eq.1.and.nz.gt.1) then
      hs = 0.
      do 780 m=1,nz
      h0(m) = htcl/float(nz)
      hs = hs + h0(m)
      delr0(m) = rtcl/float(nz)
  780 continue     
      end if
c
c  Set the density profile for a reduced gravity model that will also have
c  a rigid lid condition applied.  In this case, the sum of the layers has
c  to sum up to hbot, and there is no density difference across the lowest
c  layer. 
c
      if(rlid.ge.1) then
c
      if(nz.eq.1) then
      h0(1) = htcl
      delr0(1) = 0.
      end if
c
      if(nz.gt.1) then
      nzm = nz - 1
      hs = 0.
      do 781 m=1,nzm
      delr0(m) = rtcl/float(nzm)
      h0(m) = htcl/float(nzm)
      hs = hs + h0(m)
  781 continue
      delr0(nz) = 0.
      h0(nz) = hbot - hs
      end if
c
      end if      
c
c  Set the density profile for a free surface model. In this case, the density
c  differences are associated with the top of the layer and delradd is added to
c  the topmost layer (the sea surface).
c      
      if(rgrav.eq.0) then 
      delr0(1) = rtcl/(float(nz)) + delradd
      h0(1) = hbot/(float(nz))
      if(nz.gt.1) then
      hs = 0.
      do 782 m=1,nzm
      delr0(m) = rtcl/float(nz)
      h0(m) = htcl/float(nzm)
      hs = hs + h0(m)
  782 continue 
      delr0(1) = delr0(1) + delradd
      delr0(nz) = rtcl/float(nz)
      h0(nz) = hbot - hs
      end if
      end if  
c 
c  Compute the reduced gravity for each layer (used in pressure calculations).
c
      do 785 m=1,nz
      gprime(m) = g*delr0(m)/r0
 785  continue          
c
c  Print out the density 'profile'.
c
      write (6,8821) 
 8821 format (1x, 
     1 ' These parameters gave the following layered profile:',/,
     2 '   layer no.     density diff.     thickness ')
      do 7854 m=1,nz
      write (6,8822) m, delr0(m), h0(m)
 8822 format (1x,5x, i4, 3x, f10.2, 8x, f7.0)             
 7854 continue          
c
c ................... Initialize the Time and Space Intervals .................
c 
c  Set the time step, dt,  and the horizontal resolution, dx, dy.
c
 1177 continue
c 
      dt = 600.
      dx = 25.e3 
      dy = 25.e3    
c
      dxk = dx/1000.
      dyk = dy/1000.
      write (6,442) dt, dxk, dyk
  442 format (1x,/,
     1 '  Time and space resolution:',/,
     2 '   time step                     (default = ',f7.0,' sec)',/,
     3 '   east-west space difference     (default = ',f7.0,' km)',/,
     4 '   north-south space difference   (default = ',f7.0,' km)',/,
     5 '   (enter all three data, or default with  ,,,)')          
      read (5,*) dt, dxk, dyk 
      twodt = 2.*dt
      halfdt = 0.5*dt      
c
      dx = dxk*1000.
      dy = dyk*1000. 
      sdx = 1./dx
      sdy = 1./dy
c
c  Estimate the CFL limit on dt from the long wave phase speed only.
c  (the present form of this works for two layers only)
c
      cph = sqrt(g*rtcl*(h0(1)*h0(nz)/hbot)/r0) + 0.1
      if(rgrav.eq.0) cph = sqrt(g*(delradd + rtcl)*hbot/r0) + 0.01 
c      
      dtcfl = (dx/2.)/cph
      if(dtcfl.lt.dt) then
      write (6,3378) dt, dtcfl
 3378 format (1x,/,'  This dt exceeds the CFL limit:', 2f8.1,/)
      go to 1177
      end if      
c
c     
c ................... Initialize Spatially Dependent Fields ..................
c       
c  Set the latitude and beta (on or off by way of the flag ibeta). The choice
c  rlat = 0. should be OK, and note that beta could be made negative by
c  setting ibeta = -1
c 
      rlat = 30.
      ibeta = 1 
c
      write (6,4467) rlat 
 4467 format (1x,/,
     1 '  Earths rotation:',/,
     2 '   latitude                     (default = ',f8.1,' deg)',/,
     3 '   beta   (0 = off, 1 = on (default), -1 (change sign) )',/,
     4 '   (enter both data or default with  ,,)')
      read (5,*) rlat, ibeta
c
      f0 = 2.*7.292e-5*sin(rlat*tpi/360.)
      beta = float(ibeta)*2.*7.292e-5*cos(rlat*tpi/360.)/6370.e3 
c 
c  Define east and north coordinates,  x and y, in meters, and the variable
c  Coriolis parameter, f.  Note that the origin of x, y is centered on 
c  model domain. 
c                     
      do 10 j=1,nx
      x(j) = float(j-ncx)*dx
   10 continue     
c      
      do 107 k=1,ny
      y(k) = float(k-ncy)*dy
      f(k) = f0 + y(k)*beta  
  107 continue
c
c  Estimate some long baroclinic and Rossby wave phase speeds.
c     
      if(abs(f0).gt.1.e-9) then
      rcph = -(cph**2)*beta/f0**2
      rcphkd = rcph*8.64e4/1000.
      rdef = (cph/f0)/1000.
c      
      bsize = sqrt(1./(x(nx)-x(1))**2 + 1./(y(ny)-y(1))**2 )
      btrm1 = ( (2.*3.1415)**2*bsize/beta )/8.64e4 
c
c  compute and print some higher Ro modes as well
c
      do 2259 m1 = 1,3
      do 2259 m2 = 1,3
      rmn = float(m1)
      rnn = float(m2)
      bsize = sqrt(1./
     c   ( rmn**2*(x(nx)-x(1))**2) + 1./(rnn**2*(y(ny)-y(1))**2) )
      btrm = ( (2.*3.1415)**2*bsize/beta )/8.64e4 
      write (6,2256) m1, m2, btrm
 2256 format (1x,' m1, m2, btrm1m2', 2i5, f10.3)
 2259 continue
c
      write (6,3045) f0, beta, cph, rdef, rcph, btrm1 
 3045 format (1x,//,1x,
     1' Given this latitude and density profile, the:       ',//,
     2'  middle f and beta are               ',    2e12.3,/,
     3'  long (nondispersive) gravity wave speed (m/sec) is ',f9.2,/,
     4'  radius of deformation (km) is                      ',f9.2,/,
     5'  long (nondispersive) baroclinic Ro wave speed is   ',f9.3,/,
     6'  period of the first barotropic Ro mode (days) is   ',f9.2,)
      end if
c       
c  Define the field of wind stress. The form can be a single gyre, as in 
c  Stommel 1948 in which case use cos(y), or a double gyre. In either case,
c  the amplitude and sign are set by tau, which should be positive for an 
c  anticyclonic curl in the single gyre case. tau is immediately divided by
c  density to give the friction velocity.  The nominal wind stress
c  pattern is multiplied by tautim to give a seasonally varying wind;
c  tautim = 0 gives no seasonal variation; tautim = 1. gives 100% variation
c  with no steady part.
c 
      tau = 0.1
      igyres = 1
      tautim = 0.000
      wtfac = 0.      
c
      write(6,4001) tau
 4001 format (1x,/,
     1 '  Wind stress: ',/,
     2 '   stress magnitude                (default = ',f6.1,' Pa)',/,
     3 '   seasonal variation  (0. = none (default), 1.0 = 100%)',/,
     4 '   number of gyres         (0 = none, 1 (default), or 2)',/,
     5 '   (enter all three data, or default with ,,,)') 
      read (5,*) tau, tautim, igyres
      tau = tau/r0 
c                  
      do 1080 j=1,nx
      do 1080 k=1,ny
c
      yphas = 3.1415*(y(k)-y(1))/(y(ny) - y(1))
c
c  No gyres, i.e., a spatially uniform wind:
c
      if(igyres.eq.0) then
      tauy(j,k) = 0.
      taux(j,k) = tau
      end if 
c
c  One gyre, a la the subtropical gyre, say:
c
      if(igyres.eq.1) then
      tauy(j,k) = 0.      
      taux(j,k) = -tau*cos(yphas)
      end if     
c
c  Two gyres, with the boundary current squirting out into the middle:
c     
      if(igyres.eq.2) then
      tauy(j,k) = 0.
      taux(j,k) = tau*(sin(yphas) - 0.5)
      end if 
c            
 1080 continue 
c 
c  Zero out the wind stress on the west edge (left most column) where u
c  and v are set to zero normal derivative (junk). This is done solely to
c  refine the energy budget. (Depends upon the BCs, of course.)
c   
      if(basin.eq.2) go to 8323
      do 8320 k=1,ny
 8320 tauy(1,k) = 0.
      if(basin.eq.1) go to 8323
      do 8321 j=1,nx
 8321 taux(j,ny) = 0.                   
 8323 continue     
c
c
c ........  Initialize the Layer Thicknesses and Tracer Field  .............
c
c  Initialize the layer thicknesses. 
c
      do 8301 j=1,nx
      do 8301 k=1,ny
      do 8301 m=1,nz
      h(j,k,m,1) = h0(m)
 8301 continue
c
c  As an option, you can add on an initial thickness anomaly (a front or
c  an eddy) in the h field.
c
      delh = 0.
      hscale = 300.
c
      write (6,4007) delh, hscale
 4007 format (1x,/,
     1 '  Thickness anomaly of an initial eddy:',/,
     2 '   amplitude                      (default = ',f7.0,' m)',/,
     3 '   horizontal scale              (default = ',f7.0,' km)',/,
     4 '   (enter both data or default with ,,)')
      read (5,*) delh, hscale                            
c
      do 1081 j=1,nx
      do 1081 k=1,ny
c      
      rr = sqrt( (x(j)/1000.)**2 + (y(k)/1000.)**2 )
c
c  The form below gives a very sharp cutoff of the eddy amplitude; a Gaussian
c  form is also possible (but c'd out for now).
c
      eddyh = 0.
      if(rr.lt.hscale) eddyh = delh
c      
c      eddyh = delh*exp(-rr**/hscale**2)
c            
      do 1050 m=1,nz
      h(j,k,m,1) = h(j,k,m,1) + eddyh
 1050 continue 
c
c  If this is a rigid lid model, then reset the lower layer thickness
c  to make the sum of the layers equal to hbot.      
c             
      if(nz.gt.1.and.rlid.ge.1) then
      hs = 0.
      do 1058 m=1,nzm
      hs = hs + h(j,k,m,1)
 1058 continue
      h(j,k,nz,1) = hbot - hs
      end if
c
c  Define an initial tracer field (note that t is tracer times h). t1 is
c  the horizontal scale of the tracer patch.
c      
      tl = 150.
      rr = (x(j)/1000.)**2  
      t(j,k,1,1) = h(j,k,1,1)*exp(-rr/tl**2)
      if(sqrt(rr).gt.(2.*tl)) t(j,k,1,1) = 0.  
c  
 1081 continue
c
c  
c ......................... Diffusion and Bottom Drag ....................
c
c  Define the subgridscale diffusivity, and whether it is to be applied by 
c  a Laplacian or a biharmonic operator.  Also define the bottom drag
c  coefficient; should be suitable for a gesotrophic velocity.
c   
      diff = 3.0e2
      ibhm = 0
      cdb = 0.
c
      write (6,1188) diff, cdb
 1188 format (1x,/,
     1 '  Horizontal diffusion and bottom drag:',/,
     2 '   eddy diffusion coeff.     (default =',e10.2,' m**2/sec)',/,
     3 '   biharmonic friction?         (0 = no (default), 1 = yes)',/,
     4 '   bottom drag coeffic.              (default = ',e10.2, ')',/,
     5 '   (enter all three data or default with ,,,)' )
      read (5,*) diff, ibhm, cdb
c
c
c.........................  Miscellaneous Initialization ......................
c
c
c  Specify the initial position of the floats.
c  This scheme lays them out in a circle of radius 1/4 the domain size.
c  
      if(nf.ge.1) then
      radf = (y(ny) - y(ncy))/2.
      angf = 0.
      do 9305 i=1,nf
      angf = float(i-1)*360./float(nf)
      do 9305 m=1,nz
      xf(i,m) = radf*cos(angf*3.1415/180.)
      yf(i,m) = radf*sin(angf*3.1415/180.)
 9305 continue   
      end if
c
c Initialize the old fields.
c
      do 16 j=1,nx
      do 16 k=1,ny
      do 16 m=1,nz
      u(j,k,m,1) = 0.
      v(j,k,m,1) = 0.
      u(j,k,m,2) = u(j,k,m,1)
      v(j,k,m,2) = v(j,k,m,1)
      t(j,k,m,2) = t(j,k,m,1)
      h(j,k,m,2) = h(j,k,m,1)
   16 continue  
c
c  Come here to begin integrating, whether you have done a restart or not.
c 
 7100 continue
c 
c  Set up some arrays used to specify indices when horizontal differences
c  are taken. These are set up differently for solid and open boundaries.
c  kma, jpa, etc are for the advection operations;
c  kmd, jpd, etc are for the Laplacian.
c
      do 81 j=1,nx
      jpa(j) = j + 1
      jma(j) = j - 1
      jpd(j) = j + 1
      jmd(j) = j - 1 
   81 continue       
      jma(1) = 1
      jpa(nx) = nx  
      jmd(1) = 2
      jpd(nx) = nx - 1
c       
c In the case of a channel, u(1,k) = u(nx,k), and so:    
c
      if(basin.eq.1) then
      jma(1) = nx
      jpa(nx) = 1  
      jmd(1) = nx
      jpd(nx) = 1
      end if 
c
      do 80 k=1,ny
      kpa(k) = k + 1
      kma(k) = k - 1
      kpd(k) = k + 1
      kmd(k) = k - 1
   80 continue
      kpa(ny) = ny  
      kma(1) = 1
      kpd(ny) = ny - 1
      kmd(1) = 2     
c
c For a completely open domain, v(j,1) = v(j,ny), and so:
c
      if(basin.eq.2) then
      kpa(ny) = 1 
      kma(1) = ny 
      kpd(ny) = 1
      kmd(1) = ny
      end if
c
      if(rnonl.ne.1.0) write (6,8234) rnonl
 8234 format (1x,///,
     1  '   Did you know that rnonl is not equal 1.0, =', f5.2)      
c 
c
c ....................... Define Some Control Variables .......................
c 
c  Define some times used to control the integration and the ouput
c  to disk files.
c
c  runto is the time in days at which to stop the integration,
c  wrtd is the time interval (days) between writing to the Matlab disk files, 
c  wrtm is the time between writing to a Matlab move file, and, 
c  wrtt is time between writing to the screen. 
c
      runto = 21.
      wrtd = 10.
      wrtm = 25.
      wrtt = 1.
c     
      if(irest.eq.1) then
      write (6,7020) time9
 7020 format (1x,//' Time up to now is  ',f9.2)
      time = time9*8.64e4
      end if       
      write (6,777) runto, wrtd, wrtm, wrtt  
  777 format (1x,/,
     1 '  Set the time to run and frequency of plotting :',/,
     2 '   time to run to               (default = ',f5.1,' days)',/,
     3 '   time between data saves      (default = ',f5.1,'  " )',/,
     4 '   time between movie frames    (default = ',f5.1,'  " )',/,
     5 '   time between terminal output (default = ',f5.1,'  " )',/,
     6 '   (enter all four or default with ,,,,)') 
      read (5,*) runto, wrtd, wrtm, wrtt
c
c  Define when and how frequently to sum for time averages:
c  tavg1 is the day on which to start the sum,
c  tavg2 is the day on which to end summing,
c  avgint is the time interval between summing.
c 
      tavg1 = 0.
      tavg2 = 0.
      avgint = 1.0
      write (6,776) 
  776 format (1x,/,
     1 '  Start and stop times for time-averaging (days):',/,
     2 '   starting day         (default = 0)',/,
     3 '   ending day           (default = 0)',/,
     4 '   (enter both data or default with ,,)')
      read (5,*) tavg1, tavg2
c
      navg = 0
      do 4507 j=1,nx
      do 4507 k=1,ny
      savg(j,k) = 0.
      do 4507 m=1,nz
      pavg(j,k,m) = 0.
      pvavg(j,k,m) = 0.
      eavg(j,k,m) = 0.
      uavg(j,k,m) = 0.
      vavg(j,k,m) = 0.
 4507 continue        
c
c  nstep is the number of time steps actually taken in this integration.
c
      nstep = 0
c
c ......................... Start a Full Time Step ........................         
c
   90 continue  
c                   
c  Reset the flag leap to zero.
c
      leap = 0
      nstep = nstep + 1
c                                            
      inow = 0
c
      if(nstep.eq.1.and.irest.eq.0) inow = 1      
c
      time = time + dt
      dtime = time/(24.*3600.) 
c
c                                                                      
c ...................... Diagnostics and Data Storage ........................
c
c  Write some basic data defining this integration to the file what.dat.
c
      if(nstep.eq.1) then
      nff = nf*nz
      write (30,2020) nx,ny,nz,nff,dx,dy,x(1),x(nx),y(1),y(ny),
     1  f0,beta,tau,rtcl,hbot
 2020 format(4i5,12e15.5)
      close (30)
      end if
c
c  Write to a disk file for time series plots, if wrtt has passed.
c
      if(timt.gt.wrtt.or.inow.eq.1) then
c
c  Compute KE and PE to check on the energy budget.
c                                            
      call kepe(h,ui,vi,eta,h0,delr0,nx,ny,nz,
     1            rgrav,basin,rke1,rketc,rpe,ah1,ah2)
      enet = rke1 + rketc + rpe 
c
c  Compute some tracer statistics.
c    
      do 9921 j=1,nx
      do 9921 k=1,ny
 9921 work5(j,k) = t(j,k,1,1)/h(j,k,1,1)
      call tracer(work5,nx,ny,ta,tsa,dtsa)      
c
c  Write out a time series of data from a single point.
c      
      nxw = 0.8*nx      !  this point is in a quiet region
      nyw = 0.3*ny
c
      u9 = ui(nxw,nyw,1,1)
      v9 = vi(nxw,nyw,1,1)
      h9 = h(nxw,nyw,1,1) - h0(1)
      t9 = eta(nxw,nyw,1)
      write (10,2234) dtime, u9, v9, h9, t9, rke1, rketc,
     1 rpe, enet, wworks, fworks, bworks, ah1, ah2,
     2   ta, tsa, dtsa
 2234 format (1x, 25e12.5)
      call flush(10)
c
c 
c
c  Compute and store the transport at three interior positions.  This is
c  useful for diagnosing the Sverdrup transport, for example.
c
c  First compute the stress curl and expected Sverdrup transport.
c
      if(nstep.eq.1) then
      nyw = int(ny*1/4)
      nx2 = nx/2
      curlt = r0*(taux(nx2,nyw+1) - taux(nx2,nyw-1))/
     1                                   (y(nyw+1) - y(nyw-1))
      svtran = curlt/(beta*r0)
      write(6,2229) curlt, beta, svtran
 2229 format (1x,'  Curlt, Beta and Svtran are ..', 3e12.3)
      end if 
c      
      mm = 0
      do 2235 m=1,3
      nyw = int(ny*1/4)
      nxw = nx - int(nx*m/4)
      u9 = 0.
      v9 = 0.
      t9 = 0.
      do 2236 kk = 1,nz 
      u9 = u9 + u(nxw,nyw,kk,1)
      v9 = v9 + v(nxw,nyw,kk,1)
      t9 = t9 + eta(nxw,nyw,kk)
 2236 continue
      mm = mm + 1
      work7(mm,1) = u9
      mm = mm + 1
      work7(mm,1) = v9
      mm = mm + 1
      work7(mm,1) = t9
 2235 continue
c 
c  Now compute the average over the eastern half of the basin.
c
      nyw = int(ny*1/2)
      nxw = nx - int(nx*2/4)
      u9 = 0.
      v9 = 0.
      t9 = 0.
      nx2s = 0
      do 2245 nx2 = nxw,nx
      nx2s = nx2s + 1
      do 2245 kk = 1,nz 
      u9 = u9 + u(nx2,nyw,kk,1)
      v9 = v9 + v(nx2,nyw,kk,1)
      t9 = t9 + eta(nx2,nyw,kk)
 2245 continue
      u9 = u9/float(nx2s)
      v9 = v9/float(nx2s)
      t9 = t9/float(nx2s)
      mm = mm + 1
      work7(mm,1) = u9
      mm = mm + 1
      work7(mm,1) = v9
      mm = mm + 1
      work7(mm,1) = t9
c 
c  Now compute the average over the western one fifth of the basin.
c
      nyw = int(ny*1/2)
      nxw = int(nx/5) 
      u9 = 0.
      v9 = 0.
      t9 = 0.
      nx2s = 0
      do 2247 nx2 = 1,nxw
      nx2s = nx2s + 1
      do 2247 kk = 1,nz 
      u9 = u9 + u(nx2,nyw,kk,1)
      v9 = v9 + v(nx2,nyw,kk,1)
      t9 = t9 + eta(nx2,nyw,kk)
 2247 continue
      u9 = u9/float(nx2s)
      v9 = v9/float(nx2s)
      t9 = t9/float(nx2s)
      mm = mm + 1
      work7(mm,1) = u9
      mm = mm + 1
      work7(mm,1) = v9
      mm = mm + 1
      work7(mm,1) = t9
c
c  Now compute the overall curl, too (use the old wtfac).
c
      curlt = wtfac*(taux(10,ny) - taux(10,1))/(y(ny) - y(1))       
c       
      write (40,2234) dtime, (work7(n,1),n=1,mm), curlt, wtfac 
      call flush(40)
c
c  Write to the terminal occasionally to show that something is happening.
c
      nxw = nx/6 + 1 
      nyw = 2*(ny/3) + 1
      u9 = ui(nxw,nyw,1,1)
      v9 = vi(nxw,nyw,1,1)
      rn9 = eta(nxw,nyw,1)
      epse = -(wworks + fworks + bworks - enet)/(wworks + 0.001)
      write (6,653) 
     1   dtime, nits, rn9, u9, v9, rke1, rketc, rpe,
     2  enet, wworks, fworks, bworks, epse  
  653 format (1x,f7.2,i7,3f7.2,2x,3f7.2,2x,4f7.2,f8.3)
c  
c
c  At this point, check to see if the stopfile flag has been set on (=1).
c  (This serves as a way to stop this program gracefully when run on
c   a DOS machine (provided it can share files)).
c
c      open (unit=39,file='stopfile.dat',status='old',
c     1        form='formatted')
c      read (39,3939) istop
c      close (39)
c      
c      if(istop.eq.1) go to 9999
c
      if(nstep.ne.1) timt = timt - wrtt
      end if
      timt = timt + dt/8.64e4    
c 
c  Check to see if it is time to sum for time averages.
c
      if(timavg.gt.avgint) then
      if(dtime.gt.tavg1.and.dtime.lt.tavg2) then
c
c  Load the relative vorticity of the depth-integarted transport into work5, 
c  then solve for the streamfunction. The Laplacian is computed over
c  the entire domain, however, it is not used on the solid boundaries
c  where s = 0. 
c 
      do 7307 j=1,nx
      do 7307 k=1,ny
 7307 work5(j,k) = 0.
      do 7301 j=1,nx 
      jp = jpa(j)
      do 7301 k=1,ny
      km = kma(k)
      do 7302 m=1,nz 
      work5(j,k) = work5(j,k) + ( sdx*(v(jp,k,m,1) - v(j,k,m,1)) - 
     1  sdy*(u(j,k,m,1) - u(j,km,m,1)) )
 7302 continue 
 7301 continue 
c
      call sorpsi(1,work5,basin,dx,dy,nx,ny,jma,jpa,kma,kpa,work6,nnn) 
c      
      do 5001 j=1,nx
      jp = jpa(j)
      do 5001 k=1,ny
      km = kma(k)
      savg(j,k) = savg(j,k) + work6(j,k)
      do 5001 m=1,nz
      pavg(j,k,m) = pavg(j,k,m) + (p(j,k,m) + pr(j,k))/g
      eavg(j,k,m) = eavg(j,k,m) + eta(j,k,m)
      uavg(j,k,m) = uavg(j,k,m) + ui(j,k,m,1)
      vavg(j,k,m) = vavg(j,k,m) + vi(j,k,m,1)      
      pvavg(j,k,m) = pvavg(j,k,m) +  
     1  ( sdx*(vi(jp,k,m,1) - vi(j,k,m,1)) - 
     2         sdy*(ui(j,k,m,1) - ui(j,km,m,1)) )
 5001 continue
      navg = navg + 1
      end if 
c      
      timavg = timt - avgint
      end if
      timavg = timavg + dt/8.64e4 
c  
c  End of summing for the time averages.           
c      
c
c  Write out some data to disk files for general plotting.     
c 
      if(timd.gt.wrtd.or.inow.eq.1) then
c
 9998 continue
c 
      write (32,2121) dtime
 2121 format (f10.3)
      call flush(32)            
c      
c  Load the relative vorticity of the depth-integrated transport into work5, 
c  then solve for the streamfunction. The Laplacian is computed over
c  the entire domain but is not used on the solid boundaries where s = 0. 
c 
      do 1301 j=1,nx 
      jp = jpa(j)
      do 1301 k=1,ny
      km = kma(k)
      work5(j,k) = 0.
      do 1302 m=1,nz 
      work5(j,k) = work5(j,k) + ( sdx*(v(jp,k,m,1) - v(j,k,m,1)) - 
     1  sdy*(u(j,k,m,1) - u(j,km,m,1)) )
 1302 continue 
 1301 continue 
c
      call sorpsi(1,work5,basin,dx,dy,nx,ny,jma,jpa,kma,kpa,work6,nnn) 
c 
c  Load pressures (divided by g) into work1, work2
c
      if(rlid.ge.1) then
      do 1308 j=1,nx
      do 1308 k=1,ny
      work1(j,k) = (pr(j,k) + p(j,k,1))/g
      work2(j,k) = (pr(j,k) + p(j,k,2))/g
 1308 continue
      else
      do 1318 j=1,nx
      do 1318 k=1,ny
      work1(j,k) =  p(j,k,1)/g
      work2(j,k) =  p(j,k,2)/g
 1318 continue
      end if      
c  
c  Write out some matrices that can be used for Matlab plotting.
c 
      do 1206 k=1,ny
c            
      write (1,1298) (eta(j,k,1),j=1,nx)
      write (2,1298) (work1(j,k),j=1,nx) 
      write (3,1298) (work5(j,k),j=1,nx) 
      write (4,1298) (work2(j,k),j=1,nx)
c
 1206 continue
 1298 format (120e12.5)
      call flush(1)
      call flush(2)
      call flush(3)
      call flush(4)
c
c  Compute the potential vorticity and absolute vorticity along a meridional
c  section and output to a disk file for plotting.
c
      do 9080 k=1,ny
      do 9080 m=1,nz
      rv = sdx*(vi(ncx+1,k,m,1) - vi(ncx,k,m,1)) - 
     1         sdy*(ui(ncx,k,m,1) - ui(ncx,kma(k),m,1))
      pvprof(k,m) = (rv + f(k))/h(ncx,k,m,1)
      avprof(k,m) = rv + f(k)
      rvprof(k,m) = rv
 9080 continue
      do 9081 k=1,ny 
      write (36,1298) (pvprof(k,m),m=1,nz), (avprof(k,m),m=1,nz), 
     1    (rvprof(k,m),m=1,nz)
 9081 continue
      call flush(36)
c       
c      write (6,3680) 
c 3680 format (1x,'   Wrote data to disk for general plotting')
c 
      if(iblow.eq.1) go to 9999    
      if(inow.ne.1) timd = timd - wrtd 
      end if
      timd = timd + dt/8.64e4 
c
c  Write out some matrices for a matlab movie.
c     
      if(timm.gt.wrtm.or.inow.eq.1) then
c
c  Load pressures (divided by g) into work1, work2
c
      do 1346 j=1,nx
      do 1346 k=1,ny
      work1(j,k) = eta(j,k,1)
      work2(j,k) = eta(j,k,2)
 1346 continue

      write (31,2121) dtime
      call flush(31)
c    
      do 9300 k=1,ny
      write (11,1298) (work1(j,k),j=1,nx)
 9300 continue 
      call flush(11)
c
      if(nstep.ne.1) timm = timm - wrtm
      end if
      timm = timm + dt/8.64e4     
c
c      alf = 'at end of diag' 
c      call blowup(nstep,alf,nx,ny,nz,h0,h,ui,vi,iblow)
c             
c.................. Come Here to Begin a Trapezoidal Correction ...............
c
c  Come here to start the second pass of a leap-frog tapezoidal correction.
c  This avoids adding to the time or to nstep.
c
  901 continue 
c
c .......................... Hydrostatic Pressure .............................
c
c  Compute eta and hydrostatic pressure, just how depending upon the kind 
c  of pressure model.
c 
c  The following is for a reduced gravity model, in which case
c  eta is defined to be at the lower boundary of a layer. 
c     
      if(rgrav.eq.1) then
      do 370 j=1,nx 
      do 370 k=1,ny 
c
c  Compute eta for a reduced gravity model. Start from the surface, and
c  integrate eta downwards. 
c       
      etas = 0.
      do 371 m=1,nz
      etas = etas - (h(j,k,m,1) - h0(m)) 
      eta(j,k,m) = etas 
  371 continue
c
c  Compute the pressure for a reduced gravity model. Note that this 
c  starts from the bottom, where pressure is assumed to vanish in
c  a deep abyssal layer, and integrates upward.
c 
      ps = 0.
      do 372 m=1,nz
      mm = nz + 1 - m
      ps = ps - gprime(mm)*eta(j,k,mm)
      p(j,k,mm) = ps 
  372 continue
c       
  370 continue
      end if      
c
c  The free surface versions of eta and pressure are computed below.
c  Note that the direction of itegration and the identification of
c  eta with the layer boundaries is different from that used above. 
c                                  
      if(rgrav.eq.0) then
      do 379 j=1,nx 
      do 379 k=1,ny 
c      
      etas = 0.
      do 377 m=1,nz
      mm = nz + 1 - m
      etas = etas + (h(j,k,mm,1) - h0(mm)) 
      eta(j,k,mm) = etas 
  377 continue
c
      ps = 0.
      do 378 m=1,nz
      ps = ps + gprime(m)*eta(j,k,m)
      p(j,k,m) = ps 
  378 continue 
c
  379 continue
      end if               
c
c  The end of the pressure calculations.
c
c ........................ Evaluate the Budget Equations ......................
c
c  Compute some fields that will have to be differentiated to 
c  estimate horizontal advection terms in the budget equations.
c 
c  Compute the intensive velocities, ui, vi from the mass transports.
c
      do 5680 j=1,nx
      jp = jpa(j)
      do 5680 k=1,ny
      km = kma(k)
      do 5680 m=1,nz
      do 5680 n=1,2
c     
      ui(j,k,m,n) = 2.*u(j,k,m,n)/(h(jp,k,m,n) + h(j,k,m,n))
      vi(j,k,m,n) = 2.*v(j,k,m,n)/(h(j,k,m,n) + h(j,km,m,n))
c      
 5680 continue
c
      do 100 j=1,nx
      jp = jpa(j)
      jm = jma(j)
c      
      do 100 k=1,ny
      kp = kpa(k)
      km = kma(k) 
c
      do 100 m=1,nz
c
c  Compute the tracer transports at the velocity points. 
c
      ctu(j,k,m) = 0.5*(t(j,k,m,1) + t(jp,k,m,1))*ui(j,k,m,1)
      ctv(j,k,m) = 0.5*(t(j,k,m,1) + t(j,km,m,1))*vi(j,k,m,1)
c
c  Compute the several different velocity and transport fields needed
c  for momentum advection.
c
      uuhath(j,k,m) = (h(j,k,m,1)*(ui(j,k,m,1) + ui(jm,k,m,1))**2)/4. 
      vvhath(j,k,m) = (h(j,k,m,1)*(vi(j,k,m,1) + vi(j,kp,m,1))**2)/4. 
      hats = (h(j,k,m,1) + h(jp,k,m,1) + h(j,km,m,1) + h(jp,km,m,1))/4.
      uvhats(j,k,m) = hats*
     1     (ui(j,k,m,1) + ui(j,km,m,1))*(vi(j,k,m,1) + vi(jp,k,m,1))/4.
c
  100 continue 
c
c  Compute the diffusion terms, using either a Laplacian or biharmonic 
c  (if ibhm=1) form.
c
      if(diff.gt.1.e-4) then
      call d24(ui,nx,ny,nz,dx,dy,diff,ibhm,work24,jmd,jpd,kmd,kpd,ud24)
      call d24(vi,nx,ny,nz,dx,dy,diff,ibhm,work24,jmd,jpd,kmd,kpd,vd24)
      call d24(t,nx,ny,nz,dx,dy,diff,ibhm,work24,jmd,jpd,kmd,kpd,td24)
      end if  
c
      wwork = 0.
      fwork = 0.
      bwork = 0.
c
c  Compute the time-dependent wind stress amplitude.   Note that tautim is
c  a factor that determines the size of the seasonal cycle of the wind stress.
c
      wtfac = (1. - tautim) + tautim*sin(dtime*2.*3.14156/365.)
c
      do 2001 j=1,nx
      jp = jpa(j)
      jm = jma(j)
c
      do 2001 k=1,ny
      kp = kpa(k)
      km = kma(k)
c 
c  Apply wind stress and bottom drag to the upper and lower layers.
c      
      wx = wtfac*taux(j,k)  
      wy = wtfac*tauy(j,k)
      u(j,k,1,3) = u(j,k,1,3) + wx
      v(j,k,1,3) = v(j,k,1,3) + wy
c
      ua(j,k) = ua(j,k) + wx
      va(j,k) = va(j,k) + wy      
c
      bdx = cdb*ui(j,k,nz,1)*abs(ui(j,k,nz,1))
      bdy = cdb*vi(j,k,nz,1)*abs(vi(j,k,nz,1))
      u(j,k,nz,3) = u(j,k,nz,3) - bdx
      v(j,k,nz,3) = v(j,k,nz,3) - bdy 
c 
      ua(j,k) = ua(j,k) - bdx
      va(j,k) = va(j,k) - bdx
c      
      do 2000 m=1,nz
c
      hxa = (h(j,k,m,1) + h(jp,k,m,1))/2. 
      hya = (h(j,k,m,1) + h(j,km,m,1))/2. 
c      
      udiff = ud24(j,k,m)*hxa 
      vdiff = vd24(j,k,m)*hya
c 
c  East-west momentum budget.
c 
c  Note that you must account for the C grid when evaluating the 
c  Coriolis term in the east-west momentum budget, i.e., 
c  that f is defined at the h points.
c
      fp = 0.5*(f(k) + f(kp))
      fm = 0.5*(f(k) + f(km))     
      avf = 0.25*(  fm*(v(j,k,m,1) + v(jp,k,m,1)) + 
     1  fp*(v(j,kp,m,1) + v(jp,kp,m,1)) )
c 
      ulin = avf + udiff
     1  - sdx*(p(jp,k,m) - p(j,k,m))*hxa
      uadv = sdx*(uuhath(jp,k,m) - uuhath(j,k,m)) + 
     1  sdy*(uvhats(j,kp,m) - uvhats(j,k,m)) 
c 
      u(j,k,m,3) = u(j,k,m,3) + ulin - rnonl*uadv 
      ua(j,k) = ua(j,k) + ulin - rnonl*uadv
c
c  North-south momentum budget.
c
      auf = 0.25*( f(k)*(u(j,k,m,1) + u(jm,k,m,1)) + 
     1  f(km)*(u(jm,km,m,1) + u(j,km,m,1)) )
c     
      vlin =  vdiff - ( auf +
     1  sdy*(p(j,k,m) - p(j,km,m))*hya )
      vadv = sdx*(uvhats(j,k,m) - uvhats(jm,k,m)) + 
     1 sdy*(vvhath(j,k,m) - vvhath(j,km,m))                  
c     
      v(j,k,m,3) = v(j,k,m,3) + vlin - rnonl*vadv 
      va(j,k) = va(j,k) + vlin - rnonl*vadv   
c
c  A tracer budget.
c
      t(j,k,m,3) = t(j,k,m,3) + td24(j,k,m) - 
     1 ( sdx*(ctu(j,k,m) - ctu(jm,k,m)) 
     2       + sdy*(ctv(j,kp,m) - ctv(j,k,m)) )           
c
c  Evaluate the continuity equation.
c 
      h(j,k,m,3) = h(j,k,m,3)  - 
     1 ( sdx*(u(j,k,m,1) - u(jm,k,m,1)) + 
     2    sdy*(v(j,kp,m,1) - v(j,k,m,1)) )
c 
c  Sum the viscous frictional work on all the layers.
c
      fwork = fwork + r0*( udiff*ui(j,k,m,1) +  vdiff*vi(j,k,m,1) ) 
c 
 2000 continue
c 
c  Sum the work by bottom drag on the lower layer.
c
      bwork = bwork + r0*( bdx*ui(j,k,nz,1) + bdy*vi(j,k,nz,1) ) 
c  
c  Sum the work by the windstress on the surface current.
c
      wwork = wwork + r0*( wx*ui(j,k,1,1) + wy*vi(j,k,1,1) )
c 
c   
 2001 continue 
c
c ................... Apply a Rigid Lid Pressure Condition ....................
c 
      if(rlid.le.0) go to 6000
c
c  The next section applies a rigid lid condition in one of two ways. The
c  first method attempted here is to require that the depth-averaged force have 
c  zero divergence (the so-called 'pressure version'); the second and the more 
c  conventional way is to require that the depth-averaged force be computed from
c  a streamfunction, in which case it also has zero divergence. As implemented
c  here, the latter method seems to be the better one, (it works better),
c  though in principal the former should be prefferred since the correction 
c  made is smaller. 
c 
c  Apply some solid wall boundary conditions on ua, va (the 'force') before 
c  computing the curl or divergence, if this is not a channel or symmetric
c  domain. (Boundary conditions are not so clear for this.  Oh well.)
c     
      if(basin.ne.2) then       
      do 6999 j=1,nx
      va(j,1) = 0.
      va(j,ny) = 0.
 6999 continue 
      end if
      if(basin.lt.1) then
      do 6998 k=1,ny
      ua(1,k) = 0.
      ua(nx,k) = 0.
 6998 continue 
      end if
c
      ivort = 1
      if(ivort.eq.1) go to 3311
c 
c  The so-called pressure version follows next.
c    
c  Just a reminder of the grid. The rightmost column and the lowest row are
c  added on here in order to allow application of suitable boundary conditions.
c
c      h u | h u | h u | h
c      v s | v s | v s | v
c      --------------- . 
c      h u | h u | h u | h
c      v s | v s | v s | v
c      --------------- . 
c      h u | h u | h u | h
c      v s | v s | v s | v
c      _______________ .
c      h u | h u | h u | h
c
c    
c  Compute the rigid lid pressure by requiring that the divergence of the net
c  force, ua + dprdx (for x component), must vanish if the column height is to
c  remain constant for all times. 
c      
c
c  Compute the divergence of the net force. This will be the source term in a 
c  Poisson equation for the rigid lid pressure, pr, that is solved for on a 
c  grid that is one row and one column wider than the regular grid so that h
c  is on the outside all the way around the regular grid (see above). The
c  extra row is along the bottom, and the extra column is on the right side.
c  This also allows sensible boundary conditions (zero normal derivative) to 
c  be used in the elliptic solver for pr (apparently). 
c  
c  Try setting dx, dy to 1 for this purpose.  Also, divide by hbot.
c
      dxp = 1.
      sdxp = 1./dxp
      dyp = dy/dx
      sdyp = 1./dyp
c 
      prsc = 1.
c   
      j1 = 2
      if(basin.ge.1) j1 = 1
      do 7700 j=j1,nx
      do 7700 k=2,ny
      d2pr(j,k) = prsc*( sdxp*(ua(j,k-1) - ua(jma(j),k-1)) + 
     1   sdyp*(va(j,kpa(k-1)) - va(j,k-1)) )
 7700 continue                             
c
c  Use a successive relaxation method to solve for the rigid lid pressure.
c  This subr assumes that the boundary condition is zero normal derivative
c  on all sides (i.e., this works for an enclosed basin only).
c 
c  Generally, it makes sense to use the old pr as the first guess for the
c  new one. However, it may be a good idea to occasionally set the first
c  guess (pr) back to zero and start from scratch. (Sounds good, but this
c  didn't help).
c
      go to 8891
      jsetpr = 2000
      if(mod(nstep,jsetpr).eq.1) then
      do 4780 j=1,nxp
      do 4780 k=1,nyp
      prp(j,k) = 0.
 4780 continue
      write (6,4781) nstep
 4781 format (1x, '  I set pr to zero; nstep =', i4)
      end if
 8891 continue
c
      eps = 1.e-5
      eps = 0.5e-5
      if(dtime.gt.25.) eps = 0.5e-5            
      call sorpr
     1  (nstep,nits,eps,d2pr,basin,dxp,dyp,nxp,nyp,
     2        jmap,jpap,kmap,kpap,prp) 
c
c  prm is the isopycnal displacement that corresponds to the rigid
c  lid pressure (used to plot the rigid lid pressure).
c    
      do 7760 j=1,nx
      do 7760 k=1,ny
      prm(j,k) = prp(j,k+1)/(g*rtcl*prsc)
 7760 continue
c
c  Now add on the rigid lid pressure gradient so that the depth-averaged
c  force will have zero divergence. 
c
      twoh = 2.*hbot
c              
      do 7750 j=2,nxm
      jp = jpa(j)
      do 7750 k=2,nym 
      km = kma(k)
c
c  In the lines below the k index is shifted by +1 to account for the 
c  extra (lower) row added onto pr.
c      
      prx(j,k) = sdxp*(prp(jp,k+1) - prp(j,k+1))/prsc
      pry(j,k) = sdyp*(prp(j,k+1) - prp(j,k))/prsc
c                     
      do 7750 m=1,nz
      u(j,k,m,3) = u(j,k,m,3) -
     1   prx(j,k)*(h(j,k,m,1) + h(jp,k,m,1))/twoh 
      v(j,k,m,3) = v(j,k,m,3) - 
     1   pry(j,k)*(h(j,k,m,1) + h(j,km,m,1))/twoh
c
c  Store some things for diagnostic use.
c
      uapr(j,k) = ua(j,k) - prx(j,k)
      vapr(j,k) = va(j,k) - pry(j,k) 
 7750 continue 
c
c  One row and one column were not specified by the bcs and were missed 
c  in the above; do the u component along the first row.
c     
      k = 1
      do 7751 j=2,nxm
      prx(j,k) = sdxp*(prp(j+1,k+1) - prp(j,k+1))
      do 7751 m=1,nz
      u(j,k,m,3) = u(j,k,m,3) - 
     1  prx(j,k)*(h(j,k,m,1) + h(j+1,k,m,1))/twoh
 7751 continue
c
c  Now do the v component in the last column. 
c     
      j = nx
      do 7752 k=2,nym
      pry(j,k) = sdyp*(prp(j,k+1) - prp(j,k))
      do 7752 m=1,nz
      v(j,k,m,3) = v(j,k,m,3) - 
     1  pry(j,k)*(h(j,k,m,1) + h(j,k-1,m,1))/twoh
 7752 continue      
c 
c 
c  That takes care of the pressue-inferred version of the rigid lid. 
c
      go to 6000                      
c  
c 
 3311 continue
c
c  In this next version we attempt to apply the rigid lid constraint by
c  computing the net force from a streamfunction-like field. This has
c  an analogy with barotropic vorticity conservation, but the most direct
c  way to think of this is that the net force has to be divergence-free
c  if the net transport is intended to always be divergence-free.  
c
c  Compute the curl of the net force saved in ua,va. This will be inserted
c  into an elliptic solver, and then differentiated to get a net force that
c  should have not diveregence.  
c
      do 6060 j=2,nxm
      jp = jpa(j)
      do 6060 k=2,nym
      km = kma(k)
      del2st(j,k) = sdx*(va(jp,k) - va(j,k)) - sdy*(ua(j,k) - ua(j,km)) 
 6060 continue
c
c  Solve a Poisson equation for a streamfunction of the total force, st. This 
c  subroutine assumes that st is zero on the boundaries.
c
c  To try to avoid instability, set the first guess field, st, to zero 
c  every nto time steps.
c
c      nto = 300
c      if(mod(nstep,nto).eq.-1) then
c      do 7328 j=1,nx
c      do 7328 k=1,ny
c      st(j,k) = 0.
c 7328 continue
c      write (6,7329)
c 7329 format (1x, ' I set st to zero, just like you said')
c      end if
c
c      if(leap.eq.2) then
c      do 1420 j=1,nx
c      do 1420 k=1,ny
c      del2st(j,k) = 0.5*(del2st(j,k))
c 1420 continue
c      end if
c 
      call sorpsi(nstep,del2st,basin,dx,dy,nx,ny,jma,jpa,
     1 kma,kpa,st,nits)
c
c  Require that the momentum balance be consistent with this
c  streamfunction.
c 
c
c  special diagnostic......................................................
c
      do 5400 j=1,nx
      do 5400 k=1,ny
      work1(j,k) = u(j,k,1,3)*htcl
      work2(j,k) = v(j,k,1,3)*htcl
 5400 continue
c      
c      do 6061 j=2,nx   ***********************************************
      do 6061 j=1,nx
      jm = jma(j)
      jp = jpa(j) 
c      do 6061 k=1,nym    ********************************************
      do 6061 k=1,ny
      km = kma(k)
      kp = kpa(k)
      dsdx = sdx*(st(j,k) - st(jm,k))                                          
      dsdy = sdy*(st(j,kp) - st(j,k))
      dprdx(j,k) = (ua(j,k) + dsdy)/hbot
      dprdy(j,k) = (va(j,k) - dsdx)/hbot
      do 6061 m=1,nz
      u(j,k,m,3) = u(j,k,m,3) - dprdx(j,k)*(h(j,k,m,1) + h(jp,k,m,1))/2.
      v(j,k,m,3) = v(j,k,m,3) - dprdy(j,k)*(h(j,k,m,1) + h(j,km,m,1))/2.
 6061 continue
c
c  Apply BCS that are appropriate to a closed basin.
c
      do 9703 m=1,nz
      do 9701 j=1,nx
      u(j,ny,m,3) = u(j,nym,m,3)
      h(j,ny,m,3) = h(j,nym,m,3)
 9701 continue
      do 9702 k=1,ny
      v(1,k,m,3) = v(2,k,m,3)
      h(1,k,m,3) = h(2,k,m,3)      
 9702 continue
 9703 continue
c 
      do 5401 j=1,nx
      do 5401 k=1,ny
      work3(j,k) = u(j,k,1,3)*htcl
      work4(j,k) = v(j,k,1,3)*htcl
 5401 continue
c
c  special diagnostic......................................................
c  
c
c  Compute the rigid lid pressure field from the pressure derivatives  
c  (this is used for diagnostics only).
c 
      pr(2,1) = 0.
      do 6004 j=2,nx
      do 6003 k=2,ny
      pr(j,k) = pr(j,k-1) + dy*dprdy(j,k)
 6003 continue 
      pr(j,1) = pr(j-1,1) + dx*dprdx(j-1,1)
 6004 continue 
      do 6005 k=1,ny
      pr(1,k) = pr(2,k)
 6005 continue 
c      
 6000 continue
c
c  If you really want to insure a rigid lid then require that the layer
c  thickness tendencies must sum to zero (or set ijk = 0 to skip this).  
c     
      ijk = 1
      if(rlid.eq.2.and.ijk.eq.1) then
      do 4680 j=1,nx
      do 4680 k=1,ny 
      ws = 0.
      do 4681 m=1,nz
 4681 ws = ws + h(j,k,m,3)
      h(j,k,nz,3) = h(j,k,nz,3) - ws 
 4680 continue               
      end if
c    
c  The end of all of the rigid lid calculations.       
c
c  Apply radiation boundary conditions, if required.
c 
      if(basin.ge.1.and.openbc.eq.1) then
c
c  Apply a radiation BC to the east and west sides, assuming that cph is 
c  the relevent speed. 
c           
      do 3500 k=1,ny 
      do 3500 m=1,nz
c
      u(1,k,m,3) = cph*( u(2,k,m,1) - u(1,k,m,1) )/dx
      u(nx,k,m,3) = -cph*( u(nx,k,m,1) - u(nxm,k,m,1) )/dx
      v(1,k,m,3) = cph*( v(2,k,m,1) - v(1,k,m,1) )/dx
      v(nx,k,m,3) = -cph*( v(nx,k,m,1) - v(nxm,k,m,1) )/dx      
      h(1,k,m,3) = cph*( h(2,k,m,1) - h(1,k,m,1) )/dx
      h(nx,k,m,3) = -cph*( h(nx,k,m,1) - h(nxm,k,m,1) )/dx
 3500 continue
      end if
c
      if(basin.eq.2.and.openbc.eq.1) then
c
c  Apply a radiation BC to the north and south sides, if required.
c       
      do 3501 j=1,nx
      do 3501 m=1,nz 
c
      u(j,1,m,3) = cph*( u(j,2,m,1) - u(j,1,m,1) )/dy
      u(j,ny,m,3) = -cph*( u(j,ny,m,1) - u(j,nym,m,1) )/dy
      v(j,1,m,3) = cph*( v(j,2,m,1) - v(j,1,m,1) )/dy
      v(j,ny,m,3) = -cph*( v(j,ny,m,1) - v(j,nym,m,1) )/dy
      h(j,1,m,3) = cph*( h(j,2,m,1) - h(j,1,m,1) )/dy
      h(j,ny,m,3) = -cph*( h(j,ny,m,1) - h(j,nym,m,1) )/dy 
 3501 continue
      end if
c 
                                    
c ............................. Time Step Ahead .............................
c
c  Step ahead, noting whether this particular step is a:
c   straight leap-frog (leap = 0), or a 
c   leap-frog to be followed by a trapeozoidal correction (leap = 1), or
c   the trapezoidal correction itself (leap = 2).
c  The frequency of the trapezoidal correction is set by n7 and n8, i.e., do
c   a correction on n8 consecutive steps every n7 steps.  Reasonable
c   values seem to be n7 = 15, n8 = 2.  To avoid doing any trapezoidal 
c   correction steps, you could set n8 < 0.
c
      n7 = 25
      n8 = 3
c
      if(mod(nstep,n7).ge.(n7-n8)) leap = leap + 1 
c 
c  A straight leap-frog step.
c    
      if(leap.eq.0) then
c      
      do 300 j=1,nx
      do 300 k=1,ny
c
      ua(j,k) = 0.
      va(j,k) = 0.
c      
      do 300 m=1,nz 
c      
      uold = u(j,k,m,2) 
      u(j,k,m,2) = u(j,k,m,1)
      u(j,k,m,1) = uold + twodt*u(j,k,m,3)
      u(j,k,m,3) = 0.
c      
      vold = v(j,k,m,2) 
      v(j,k,m,2) = v(j,k,m,1)
      v(j,k,m,1) = vold + twodt*v(j,k,m,3)
      v(j,k,m,3) = 0.      
c      
      hold = h(j,k,m,2) 
      h(j,k,m,2) = h(j,k,m,1)
      h(j,k,m,1) = hold + twodt*h(j,k,m,3)
      h(j,k,m,3) = 0.
c
      told = t(j,k,m,2) 
      t(j,k,m,2) = t(j,k,m,1)
      t(j,k,m,1) = told + twodt*t(j,k,m,3)
      t(j,k,m,3) = 0.
  300 continue
c 
c  Sum and normalize the wind and frictional work. 
c     
      rnxy = float(nx*ny)
      if(basin.eq.0) rnxy = float((nx-1)*(ny-1))
      wworks = wworks + dt*wwork/(rnxy*r0)
      fworks = fworks + dt*fwork/(rnxy*r0)
      bworks = bworks - dt*bwork/(rnxy*r0)
c      
      go to 303
      end if
c
c  A leap-frog that will be followed by a trapezoidal correction.
c  (So in this case you do not zero out the accelerations).
c
      if(leap.eq.1) then 
c      
      do 301 j=1,nx
      do 301 k=1,ny            
      do 301 m=1,nz 
c 
      ua(j,k) = 0.
      va(j,k) = 0.
c      
      uold = u(j,k,m,2) 
      u(j,k,m,2) = u(j,k,m,1)
      u(j,k,m,1) = uold + twodt*u(j,k,m,3)
c 
      vold = v(j,k,m,2) 
      v(j,k,m,2) = v(j,k,m,1)
      v(j,k,m,1) = vold + twodt*v(j,k,m,3)
c 
      hold = h(j,k,m,2) 
      h(j,k,m,2) = h(j,k,m,1)
      h(j,k,m,1) = hold + twodt*h(j,k,m,3)
c
      told = t(j,k,m,2) 
      t(j,k,m,2) = t(j,k,m,1)
      t(j,k,m,1) = told + twodt*t(j,k,m,3)
c
  301 continue 
      go to 303
      end if
c
c  A trapezoidal correction.
c
      if(leap.eq.2) then
c      
      do 302 j=1,nx
      do 302 k=1,ny
c
      ua(j,k) = 0.
      va(j,k) = 0.
c      
      do 302 m=1,nz 
c      
      u(j,k,m,1) = u(j,k,m,2) + halfdt*u(j,k,m,3)
      u(j,k,m,3) = 0.
c       
      v(j,k,m,1) = v(j,k,m,2) + halfdt*v(j,k,m,3)
      v(j,k,m,3) = 0.
c      
      h(j,k,m,1) = h(j,k,m,2) + halfdt*h(j,k,m,3)
      h(j,k,m,3) = 0.
c 
      t(j,k,m,1) = t(j,k,m,2) + halfdt*t(j,k,m,3)
      t(j,k,m,3) = 0.
  302 continue 
c
c  Sum and normalize the wind and frictional work. 
c     
      rnxy = float(nx*ny)
      if(basin.eq.0) rnxy = float((nx-1)*(ny-1))
      wworks = wworks + dt*wwork/(rnxy*r0) 
      fworks = fworks + dt*fwork/(rnxy*r0)
      bworks = bworks - dt*bwork/(rnxy*r0)      
c 
c           
      end if  
c
  303 continue
c
c      alf = 'after dt, before bcs'
c      call blowup(nstep,alf,nx,ny,nz,h0,h,ui,vi,iblow)

c  
c
c.......................... Apply Boundary Conditions .........................        
c        

c  Apply BCs to all solid boundaries. Recall that the BCs are specified 
c  via the following flags:
c
c  The basin configuration is set by:
c  basin = 0 for solid walls all the way around,
c  basin = 1 for open BCs on east and west sides, (this makes a channel),
c  basin = 2 for open BCs all the way around. 
c  
c  The tangential velocity on side boundaries is set by:
c  sidebc = 0 for no-slip BCs on the sidewalls of a basin, or, 
c  sidebc = 1 for free-slip BCs on the sidewalls of a basin (the default).
c
      if(basin.eq.2) go to 3100
c             
      if(basin.eq.1) go to 3003        
c
c  East and west sides, required for a fully enclosed basin only.
c
c  Apply zero normal flow bcs to the east and west sides.
c      
      do 3000 k=1,ny 
      do 3000 m=1,nz
      u(1,k,m,1) = 0. 
      u(nx,k,m,1) = 0. 
c      
c  Apply no slip BCs to v if so required.
c
      if(sidebc.eq.0) then 
      v(2,k,m,1) = 0.
      v(nx,k,m,1) = 0. 
      end if 
c      
c  Set the junk column 1 h and v to zero normal derivative.      
c
      h(1,k,m,1) = h(2,k,m,1)
      t(1,k,m,1) = t(2,k,m,1)
      v(1,k,m,1) = v(2,k,m,1)
c      h(1,k,m,3) = h(2,k,m,3)
c      t(1,k,m,3) = t(2,k,m,3)
c      v(1,k,m,3) = v(2,k,m,3)
      
 3000 continue
c
c  Done with the east and west sides.
c
 3003 continue
c
c  South and north sides, required for a channel or a basin.
c
c  Apply zero normal flow.
c
      do 3001 j=1,nx
      do 3001 m=1,nz 
      v(j,1,m,1) = 0.
      v(j,ny,m,1) = 0. 
c      
c  Apply no slip BCs to u if so required.      
c
      if(sidebc.eq.0) then
      u(j,1,m,1) = 0.
      u(j,nym,m,1) = 0.
      end if
c      
c  Set the junk row ny u and h to zero normal derivative. 
c
      h(j,ny,m,1) = h(j,nym,m,1)
      u(j,ny,m,1) = u(j,nym,m,1)
      t(j,ny,m,1) = t(j,nym,m,1)
c      h(j,ny,m,3) = h(j,nym,m,3)
c      u(j,ny,m,3) = u(j,nym,m,3)
c      t(j,ny,m,3) = t(j,nym,m,3)
c       
 3001 continue
c 
c  Done with the north and south sides.
c 
c  Now do h and eta in the northwest corner of a closed basin.
c
      if(basin.eq.0) then
      do 3004 m=1,nz
      h(1,ny,m,1) = (h(1,nym,m,1) + h(2,ny,m,1))/2.
 3004 continue
      end if
c 
 3100 continue
c 
c  End of the boundary conditions.
c
c      alf = 'just after bcs'
c      call blowup(nstep,alf,nx,ny,nz,h0,h,ui,vi,iblow)

c
c......................... Control Time Stepping .............................
c
c  Go back up and re-do calculations for the trapezoidal correction if this
c  step has leap = 1.
c
      if(leap.eq.1) go to 901  
c
c................... Housekeeping Before the End of a Time Step ...............
c
c  Step ahead the stupid floats.
c                        
      if(nf.gt.1.and.nstep.gt.1) then
      nof = 0
      if(nof.ne.1) then
c 
c  Compute a time-averaged velocity that is centered on the h points and that
c  knows about the boundary conditions. This new velocity field was found 
c  to be necessary to keep the damned floats from going off of the grid 
c  and causing a blowup of the entire model. 
c
      do 7323 m=1,nz
      do 7320 j=1,nx
      jm = jma(j)
      do 7320 k=1,ny
      kp = kpa(k)
      ufl(j,k,m) = 0.25*( ui(j,k,m,1) + ui(jm,k,m,1) + 
     1                  ui(j,k,m,2) + ui(jm,k,m,2) )
      vfl(j,k,m) = 0.25*( vi(j,k,m,1) + vi(j,kp,m,1) +
     1                  vi(j,k,m,2) + vi(j,kp,m,2) )
 7320 continue
c
c  Apply BCs to this velocity, if required.
c
      if(basin.eq.0) then
      do 7322 k=1,ny
 7322 ufl(nx,k,m) = 0.
      if(basin.eq.1) then 
      do 7321 j=1,nx
 7321 vfl(j,1,m) = 0.
      end if 
      end if
 7323 continue
c     
      do 7300 m=1,nz
      do 7300 i=1,nf
      xx = xf(i,m)
      yy = yf(i,m)
      call floatxy(xx,yy,ufl,vfl,x,y,nx,ny,nz,m,dt,xxn,yyn,uf,vf)
      xf(i,m) = xxn
      yf(i,m) = yyn 
 7300 continue      
c
c  Store the float data on unit 35 if sufficient time has passed.
c
      if(mod(nstep,50).eq.2) then
      madd = nf*nz
      madd2 = 2*madd
      iii = 0
      do 7303 m=1,nz
      do 7303 i=1,nf
      iii = iii + 1
      xyfk(iii) = xf(i,m)/1000.
      xyfk(iii+madd) = yf(i,m)/1000.
 7303 continue     
      write (35,7362) (xyfk(k),k=1,madd2)
 7362 format (50f10.2)
      call flush(35)
c
      end if
      end if
c
      end if
c
c  End of float tracking.
c           
c                  
c  Check to see if time is up, or if you need to do the starting timestep.
c
      if(dtime.gt.runto) then 
      write (6,2255) 
 2255 format (1x,///,1x,
     1  ' You reached the end of the integration. ',//)
      go to 9999
      end if
      if(nstep.eq.1.and.irest.ne.1) go to 310 
c
c............................ End of a Time Step ............................
c
c  Go back up to start another time step.
c
      go to 90
c
c  Come here only once at the start of the integration. This gives an old and a
c  present time step needed to begin leap-frogging.
c 
  310 continue
c    
      if(nstep.eq.1) then
      do 400 j=1,nx
      do 400 k=1,ny
      do 400 m=1,nz  
      u(j,k,m,2) = u(j,k,m,1)
      v(j,k,m,2) = v(j,k,m,1)
      h(j,k,m,2) = h(j,k,m,1)
      t(j,k,m,2) = t(j,k,m,1)
      u(j,k,m,1) = u(j,k,m,1) + dt*u(j,k,m,3)
      v(j,k,m,1) = v(j,k,m,1) + dt*v(j,k,m,3)
      t(j,k,m,1) = t(j,k,m,1) + dt*t(j,k,m,3)
      h(j,k,m,1) = h(j,k,m,1) + dt*h(j,k,m,3)
  400 continue            
      end if
c           
c  This time step is complete; go back and do another one.
c
      go to 90
c
c................................. Close Up ..................................
c
 9999 continue
c 
c  Normalize the time averages, and write them out to unit 12.
c
      if(navg.gt.2) then
      rnavg = float(navg)
      do 8710 j=1,nx
      do 8710 k=1,ny
      savg(j,k) = savg(j,k)/rnavg
      do 8710 m=1,nz      
      pavg(j,k,m) = pavg(j,k,m)/rnavg
      pvavg(j,k,m) = pvavg(j,k,m)/rnavg
      eavg(j,k,m) = eavg(j,k,m)/rnavg
      uavg(j,k,m) = uavg(j,k,m)/rnavg
      vavg(j,k,m) = vavg(j,k,m)/rnavg      
 8710 continue
      do 8711 k=1,ny
 8711 write (12,1298) (savg(j,k),j=1,nx)
 8719 continue
      do 8712 m=1,nz
      do 8712 k=1,ny
 8712 write (12,1298) (pavg(j,k,m),j=1,nx)
      do 8713 m=1,nz
      do 8713 k=1,ny
 8713 write (12,1298) (pvavg(j,k,m),j=1,nx)
      do 8714 m=1,nz
      do 8714 k=1,ny
 8714 write (12,1298) (eavg(j,k,m),j=1,nx)
      do 8715 m=1,nz
      do 8715 k=1,ny
 8715 write (12,1298) (uavg(j,k,m),j=1,nx)
      do 8716 m=1,nz
      do 8716 k=1,ny
 8716 write (12,1298) (vavg(j,k,m),j=1,nx) 
      call flush(12)      
      end if
c 
c 
 7053 continue                  
      irest = 1
      write (6,7050)
 7050 format (1x,' Do you want to write a restart file? (1=yes)')
      read (5,7056,err=7053) irest
 7056 format(i3)
      if(irest.eq.1) then
      write (6,7052)
 7052 format (1x,' Enter the name of the restart file. ')     
      read (5,7051) ifile
 7051 format (a24)
      open(unit=20,file=ifile,form='unformatted',status='unknown')
c     
      rewind (20) 
      write (20) nx,ny,nz,nf     
      write (20) dtime,timd,timm,timt,
     1 sidebc,basin,rgrav,rlid,ibhm,cdb,
     2 rnonl,dt,dx,dy,diff,hbot,h0,delr0,rtcl,x,y,f,f0,beta,tau,gprime,
     3 wworks,fworks,bworks,xf,yf,taux,tauy,u,v,h,t,pr,ui,vi 
      end if
c
      stop 
      end
c
      subroutine blowup(nstep,alf,nx,ny,nz,h0,h,ui,vi,iblow)
c      
c  
c  Check for blowups.
c
      dimension h0(nz),h(nx,ny,nz,3),ui(nx,ny,nz,3),vi(nx,ny,nz,3)
      character*60 alf
c
      iblow = 0
c      
      ublow = 0.2
c     
      umax = 0.
      etamax = 0.     
      do 800 j=1,nx
      do 800 k=1,ny
      do 800 m=1,nz
      eta8 = h(j,k,m,1) - h0(m)
      if(abs(eta8).gt.etamax) then
      jemax = j
      kemax = k
      memax = m
      etamax = eta8
      end if
      v8 = sqrt(ui(j,k,m,1)**2 + vi(j,k,m,1)**2)
      if(v8.gt.umax) then
      jvmax = j
      kvmax = k
      mvmax = m
      umax = v8
      end if
c
  800 continue 
c
c  
      if(umax.gt.ublow) then
      write (6,803) jvmax, kvmax, mvmax, 
     1 ui(jvmax,kvmax,mvmax,1), vi(jvmax,kvmax,mvmax,1),
     1    h(jvmax,kvmax,mvmax,1) 
  803 format (1x,' ublow; j, k, m, ui, vi, h are ', 3i5, 3f10.3)
      iblow = 1
      end if
c
c  This limit on eta could be too small.
c
      etablow = 0.8*h0(1)
c 
      if(etamax.gt.etablow) then
      write (6,804) jemax, kemax, memax,
     1    h(jemax,kemax,memax,1), ui(jemax,kemax,memax,1), 
     2  vi(jemax,kemax,memax,1)
  804 format (1x,'etablow;  j, k, m, h, ui, vi', 3i6, 4f10.3)
      iblow = 1
      end if
c
      write (6,1) nstep, alf
    1 format (1x, 1x,i6, '  completed blowup check', a60)    
c 
c
c  End of the blowup check.
c 
      return
      end
      
