C $Header: /u/gcmpack/MITgcm/pkg/gridalt/make_phys_grid.F,v 1.12 2012/08/12 01:28:03 jmc Exp $
C $Name:  $

#include "GRIDALT_OPTIONS.h"

       SUBROUTINE MAKE_PHYS_GRID(drF,hfacC,im1,im2,jm1,jm2,Nr,
     & nSx,nSy,i1,i2,j1,j2,bi,bj,Nrphys,Lbot,dpphys,numlevphys,nlperdyn)
C***********************************************************************
C SUBROUTINE MAKE_PHYS_GRID
C
C Purpose: Define the grid that the will be used to run the high-end
C          atmospheric physics.
C
C Algorithm: Fit additional levels of some (~) known thickness in
C          between existing levels of the grid used for the dynamics
C
C Need:    Information about the dynamics grid vertical spacing
C
C Input:   drF         - delta r (p*) edge-to-edge
C          hfacC       - fraction of grid box above topography
C          im1, im2    - beginning and ending i - dimensions
C          jm1, jm2    - beginning and ending j - dimensions
C          Nr          - number of levels in dynamics grid
C          nSx,nSy     - number of processes in x and y direction
C          i1, i2      - beginning and ending i - index to fill
C          j1, j2      - beginning and ending j - index to fill
C          bi, bj      - x-dir and y-dir index of process
C          Nrphys      - number of levels in physics grid
C
C Output:  dpphys      - delta r (p*) edge-to-edge of physics grid
C          numlevphys  - number of levels used in the physics
C          nlperdyn    - physics level number atop each dynamics layer
C
C NOTES: 1) Pressure levs are built up from bottom, using p0, ps and dp:
C              p(i,j,k)=p(i,j,k-1) + dp(k)*ps(i,j)/p0(i,j)
C        2) Output dp(s) are aligned to fit EXACTLY between existing
C           levels of the dynamics vertical grid
C        3) IMPORTANT! This routine assumes the levels are numbered
C           from the bottom up, ie, level 1 is the surface.
C           IT WILL NOT WORK OTHERWISE!!!
C        4) This routine does NOT work for surface pressures less
C           (ie, above in the atmosphere) than about 350 mb
C***********************************************************************

       IMPLICIT NONE

       integer im1,im2,jm1,jm2,Nr,nSx,nSy,Nrphys
       integer i1,i2,j1,j2,bi,bj
       integer numlevphys
       _RS hfacC(im1:im2,jm1:jm2,Nr,nSx,nSy)
       _RL dpphys(im1:im2,jm1:jm2,Nrphys,nSx,nSy)
       _RS drF(Nr)
       integer Lbot(im1:im2,jm1:jm2,nSx,nSy)
       integer nlperdyn(im1:im2,jm1:jm2,Nr,nSx,nSy)

       integer i,j,L,Lbotij,Lnew
C Require 12 (or 15) levels near the surface (300 mb worth) for fizhi.
C   the dp(s) are in the dptry arrays:
       integer ntry,ntry10,ntry40
       parameter (ntry10 = 12)
       parameter (ntry40 = 12)
       _RL dptry(15),dptry10(ntry10),dptry40(ntry40)
       _RL bot_thick,bot_thick40
       _RL dptry_accum(15)
       data dptry10/300.000,600.000,1000.000,1400.000,1700.000,2500.000,
     &            2500.000,2500.000,2500.000,5000.000,5000.000,5000.000/
       data dptry40/300.000,600.000, 800.000, 800.000,1250.000,
     &            1250.000,2500.000,2500.000,2500.000,2500.000,2500.000,
     &            2500.000/
       data bot_thick40/20000.000/
       _RL deltap, dpstar_accum
       integer nlbotmax, nstart, nlevs, nlphys, ndone
       _RL thindp

       if( (Nr.eq.10) .or. (Nr.eq.20) ) then
        ntry = ntry10
        bot_thick = bot_thick40
        do L = 1,ntry
         dptry(L) = dptry10(L)
        enddo
       elseif((Nr.eq.40).or.(Nr.eq.46).or.(Nr.eq.70)) then
        ntry = ntry40
        bot_thick = bot_thick40
        do L = 1,ntry
         dptry(L) = dptry40(L)
        enddo
       else
        print *,' Dont know how to make fizhi grid '
        stop
       endif

       thindp=100.
       if(Nr.eq.70)thindp=0.02

       do L = 1,Nr
        do j = j1,j2
        do i = i1,i2+1
         nlperdyn(i,j,L,bi,bj) = 0
        enddo
        enddo
       enddo

C Figure out how many physics levels there will be
C   (need 12 between sfc and 300 mb above it - see how many
C    there are in the dynamics if the surface pressure is at
C    the sum of drF, ie, the maximum dynamics grid layers possible)
       nlevs = 0
       dpstar_accum = 0.
       do L = 1,Nr
        dpstar_accum = dpstar_accum + drF(L)
        if(dpstar_accum.le.bot_thick) nlevs = nlevs+1
       enddo
       numlevphys = Nr - nlevs + ntry + 1

       dptry_accum(1) = dptry(1)
       do Lnew = 2,ntry
        dptry_accum(Lnew) = dptry_accum(Lnew-1) + dptry(Lnew)
       enddo

C      do for each grid point:
       do j = j1,j2
       do i = i1,i2
        Lbotij = Lbot(i,j,bi,bj)

C Find the maximum number of physics levels to fit in the bottom level

        nlbotmax = 0
        do Lnew = 1,ntry
         if ( (nlbotmax.eq.0) .and.
     & (dptry_accum(Lnew).gt.(hfacC(i,j,Lbotij,bi,bj)*drF(Lbotij))))then
          nlbotmax = Lnew
         endif
        enddo
        if(nlbotmax.eq.0)then
         nlbotmax = ntry
        endif

C See how many of the physics levs can fit in the bottom level

        nlphys = 0
        deltap = 0.
        do Lnew = 1,nlbotmax
C Test to see if the next physics level fits, if yes, add it
         if((hfacC(i,j,Lbotij,bi,bj)*drF(Lbotij)).ge.
     &                                           deltap+dptry(Lnew))then
          nlphys = nlphys + 1
          dpphys(i,j,nlphys,bi,bj) = dptry(Lnew)
          deltap = deltap + dptry(Lnew)
         else
C If the level does not fit, decide whether to make a new thinner
C  one or make the one below a bit thicker
          if((dptry(Lnew-1)+(hfacC(i,j,Lbotij,bi,bj)*
     &             drF(Lbotij)-deltap)) .gt. (dptry(Lnew-1)*1.5) ) then
C Add a new thin layer
           nlphys = nlphys + 1
           dpphys(i,j,nlphys,bi,bj) =
     &                      (hfacC(i,j,Lbotij,bi,bj)*drF(Lbotij))-deltap
          else
C Make the one below thicker
           dpphys(i,j,nlphys,bi,bj) = dpphys(i,j,nlphys,bi,bj) +
     &                      (hfacC(i,j,Lbotij,bi,bj)*drF(Lbotij)-deltap)
          endif
          deltap = deltap+(hfacC(i,j,Lbotij,bi,bj)*drF(Lbotij)-deltap)
         endif
        enddo

        nlperdyn(i,j,Lbotij,bi,bj) = nlphys

C Now proceed upwards - see how many physics levels fit in each
C   subsequent dynamics level - go through all 12 required levels

        do L = Lbotij+1,Nr
         ndone = 0
         if(nlphys.lt.ntry)then
          deltap = 0.
          nstart = nlphys + 1
          do Lnew = nstart,ntry
           if((hfacC(i,j,L,bi,bj)*drF(L)).ge.deltap+dptry(Lnew))then
            nlphys = nlphys + 1
            dpphys(i,j,nlphys,bi,bj) = dptry(Lnew)
            deltap = deltap + dptry(Lnew)
            ndone = 0
           elseif (ndone.eq.0) then
C If the level does not fit, decide whether to make a new thinner
C  one or make the one below a bit thicker
            ndone = 1
            if( (dptry(Lnew-1)+(hfacC(i,j,L,bi,bj)*drF(L)-deltap))
     &                    .gt. (dptry(Lnew-1)*1.5) ) then
C Add a new thin layer
             nlphys = nlphys + 1
             dpphys(i,j,nlphys,bi,bj) =
     &                             (hfacC(i,j,L,bi,bj)*drF(L))-deltap
             deltap = hfacC(i,j,L,bi,bj)*drF(L)
            else
C Make the one below thicker
             dpphys(i,j,nlphys,bi,bj) = dpphys(i,j,nlphys,bi,bj) +
     &                      (hfacC(i,j,L,bi,bj)*drF(L)-deltap)
             deltap = hfacC(i,j,L,bi,bj)*drF(L)
            endif
           endif
          enddo
C Need one more peice of logic - if we finished Lnew loop and
C  now we are done adding new physics layers, we need to be sure
C  that we are at the edge of a dynamics layer. if not, we need
C  to add one more layer.
          if(nlphys.ge.ntry)then
           if(abs(deltap-hfacC(i,j,L-1,bi,bj)*drF(L-1)).gt.0.001)then
            nlphys = nlphys + 1
            dpphys(i,j,nlphys,bi,bj) = hfacC(i,j,L-1,bi,bj)*drF(L-1)
     &                                                          - deltap
           endif
          endif

         elseif(nlphys.eq.ntry)then
C Mostly done with new layers - make sure we end at dynamics edge,
C      if not, make one more thinner (thinner than dyn grid) layer
          if(abs(deltap-hfacC(i,j,L-1,bi,bj)*drF(L-1)).gt.0.001)then
           nlphys = nlphys + 1
           dpphys(i,j,nlphys,bi,bj) = hfacC(i,j,L-1,bi,bj)*drF(L-1)
     &                                                          - deltap
           nlphys = nlphys + 1
           dpphys(i,j,nlphys,bi,bj) = hfacC(i,j,L,bi,bj)*drF(L)
          else
           nlphys = nlphys + 1
           dpphys(i,j,nlphys,bi,bj) = hfacC(i,j,L,bi,bj)*drF(L)
          endif
         else
C we are done adding new physics layers, just copy the rest
C    of the dynamics grid onto the physics grid
          nlphys = nlphys + 1
          dpphys(i,j,nlphys,bi,bj) = hfacC(i,j,L,bi,bj)*drF(L)
         endif
         nlperdyn(i,j,L,bi,bj) = nlphys
        enddo

C  All done adding layers - if we need more to make numlevphys, put
C     them as thin (1 mb) layers near the top
       if(nlphys.lt.numlevphys)then
        nlevs = numlevphys-nlphys
        dpphys(i,j,nlphys,bi,bj)=dpphys(i,j,nlphys,bi,bj)-thindp*nlevs
        do Lnew = nlphys+1,numlevphys
         dpphys(i,j,Lnew,bi,bj) = thindp
        enddo
        nlperdyn(i,j,Nr,bi,bj) = numlevphys
       endif
C END OF LOOP OVER GRID POINTS

       enddo
       enddo

       return
       end