SUBROUTINE regrid(lbase,rdbpts) 1,8
!
  LOGICAL :: rdbpts
  INCLUDE 'nodal.inc'
  INCLUDE 'agricpu.inc'
  INCLUDE 'agricst.inc'
!
! ******************************************************************
!  REGRID = FLAG POINTS ON EACH GRID WITH A LEVEL > = LBASE.
!  CLUSTER THEM, AND FIT NEW SUBGRIDS AROUND THE CLUSTERS.
!  THE LBASE GRIDS STAY FIXED DURING REGRIDDING OPERATION.
!  WHEN A PARENT GRID HAS ITS ERROR ESTIMATED, ADD ITS KID GRID
!  INFORMATION TO THE ERROR GRID BEFORE CLUSTERING. (PROJECT)
!  ORDER OF GRID EXAMINATION - ALL GRIDS AT THE SAME LEVEL, THEN
!  DO THE NEXT COARSER LEVEL.
!
!  NOTE:  THE ACTUAL GRIDFITTING IS DONE BY GRDFIT.  IN THIS
!      VERSION WE DO NOT HAVE POINT FLAGGING CAPABILITY IN
!      3-D (NOR GRIDFITTING CAPABILITY IN 3-D) HENCE THE
!      NEW GRIDS ARE SPECIFIED BY THE USER.  SEE GRDFIT.
!
!      RDBPTS = true for reading badpoints from file
!
! LOCAL VARIABLES:
!  LCHECK = THE LEVEL BEING EXAMINED.
!  LFNEW  = FINEST GRID TO BE. WILL REPLACE LFINE.
! GLOBAL
!    MSTART  = START OF VERY COARSEST GRIDS.
! *****************************************************************
!
  cpu0 = f_cputime()
!
!
  PRINT*,'REGRID called with LBASE=', lbase,' mxnest=',mxnest
  PRINT*,'LFINE =', lfine

!
! yuhe: LCHECK should go from lower to higher so that the grid numbers
!    will be set from lower to higher.
!
!  LCHECK    = MIN0(LFINE,MXNEST-1)
  lcheck    = lbase
  lfnew     = lbase

  DO i   = 1, mxnest
    newstl(i) = 0
  END DO

  time      = rnode(20, lstart(lbase))

  20   CONTINUE

  PRINT*,' lcheck =',lcheck,' lbase= ',lbase

!  IF (LCHECK .ge. LBASE) THEN
  IF ( lcheck <= MIN0(lfine,mxnest-1) ) THEN
!
! yuhe: Since lstart(lcheck) has not been set, the following statement
!    may run into a trouble.
!
!     IF (ABS(TIME-RNODE(20, LSTART(LCHECK))).gt..0001) THEN
!
!       WRITE(6,100) TIME
!100       FORMAT(41H  GRIDS AT DIFFERENT TIMES DURING REGRID ,E12.7)
!       STOP
!
!     ENDIF

    WRITE(6,'(''  IN REGRID, CALLING GRDFIT '')')

    CALL grdfit(lbase,lcheck,lfnew,time,rdbpts)

    PRINT*,' LBASE,LCHECK,LFNEW,TIME,RDBPTS =',                         &
             lbase,lcheck,lfnew,time,rdbpts, newstl(lcheck+1)

    IF (newstl(lcheck+1) /= 0) lfnew = MAX0(lcheck + 1,lfnew)
!
! note: this line is added for testing purpose
!
!    LFNEW = MAX0(LCHECK + 1,LFNEW)

!    LCHECK = LCHECK - 1
    lcheck = lcheck + 1

    GO TO 20

  END IF

  PRINT*,' LBASE,LCHECK,LFNEW,TIME,RDBPTS =',                           &
           lbase,lcheck,lfnew,time,rdbpts

  PRINT*,' END OF LEVEL LOOP '

!
!  END OF LEVEL LOOP
!
!  REMAINING TASKS LEFT IN REGRIDDING:
!
!  INTERPOLATE STORAGE FOR THE NEW GRIDS.  THE STARTING POINTERS
!  FOR EACH LEVEL ARE IN NEWSTL.
!
!  first we need to push the old data out temporarily
!
  PRINT*,' lfnew ', lfnew

  levd = lfnew
  DO levn=lfnew,lbase+1,-1

    PRINT*,' levn =', levn

    IF(lstart(levn) /= 0) THEN

      PRINT*,'calling dmplvl '

      CALL dmplvl(levn)
      levd = levn
    END IF
  END DO
!
!  now fill the new grids
!
  DO levn=lbase+1,lfnew
    IF( verbose6 ) WRITE(6,'(''  CALLING FILL FOR LEVEL '',I5)') levn

    PRINT*,' levd =', levd

    CALL fillngrd( levn, levd )
  END DO
!
!  clean get rid of disk files for the temp grid dump
!  performed by dmplvl
!
  PRINT*,' lfnew, lbase+1 ', lfnew, lbase+1

  DO levn=lfnew,lbase+1,-1

    PRINT*,' levn =',levn, lfnew, lbase+1

    mptr = lstart(levn)
    CALL cleanf( mptr )
    mptr = newstl(levn)
    CALL cleanf( mptr )
  END DO
!
!  MERGE DATA STRUCTURES (NEWSTL AND LSTART, LBACK)
!  FINISH STORAGE ALLOCATION, RECLAIM SPACE,
!  SET UP NEW SOURCE ARRAYS FOR INTERP AND UPDATE
!
  PRINT*,'calling join with LBASE, LFNEW=',lbase, lfnew

  CALL join(lbase, lfnew)
!
  cpu_regrid = cpu_regrid + f_cputime() - cpu0
!
  RETURN
END SUBROUTINE regrid
!


SUBROUTINE grdfit (lbase,lcheck,lfnew,time,rdbpts) 1,3
!
  INCLUDE 'nodal.inc'
  INCLUDE 'agricst.inc'
  LOGICAL :: rdbpts
  INTEGER :: lcheck,prvptr
  REAL :: ugrids(11,10)
!
!  GRDFIT CALLED BY SETGRD AND REGRID TO ACTUALLY FIT THE NEW GRIDS
!      ON EACH LEVEL. LCHECK IS THE LEVEL BEING ERROR ESTIMATED
!      SO THAT LCHECK+1 WILL BE THE LEVEL OF THE NEW GRIDS.
!
!  IN THIS VERSION WE JUST CALL A USER WRITTEN ROUTINE WHICH RETURNS
!  THE NEW GRID LOCATION IN UGRID.  UGRID(1-8,*) ARE THE FOUR CORNERS
!  OF THE NEW GRID, 9 AND 10 ARE THE BOTTOM AND TOP, 11 IS DZ.
!
  lckp1 = lcheck+1

  IF(ngrdnew(lcheck) == 0) GO TO 99

  CALL rdgrds(ugrids,lckp1)
!
!  SET UP GRID STRUCTURE FOR EACH NEW GRID
!
  levnew = lckp1
  prvptr=0
  DO ig=1,ngrdnew(lckp1-1)
    mnew = nodget(dummy)
    IF(prvptr /= 0) node(10,prvptr) = mnew
    IF(prvptr == 0) newstl(levnew)  = mnew
    node(12,mnew) = prvptr
    DO ip=1,8
      rnode(ip,mnew) = ugrids(ip,ig)
    END DO
!    CALL MOMENT( RNODE(1,MNEW),UGRIDS(1,IG),4,
!    *               USAGE,0.,0.,HXPOSS(LEVNEW),HYPOSS(LEVNEW) )
    rnode(20,mnew) = time
    rnode(29,mnew) = ugrids(9,ig)
    rnode(30,mnew) = ugrids(10,ig)
    rnode(31,mnew) = ugrids(11,ig)
    node(4,mnew) = levnew
    node(9,mnew) = 1
    prvptr = mnew
  END DO
!
  CALL sethk (newstl(levnew))
  CALL setrot(newstl(levnew))
!
!
  99   RETURN
END SUBROUTINE grdfit
!


SUBROUTINE rdgrds(ug,ln) 1
  DIMENSION ug(11,10), tmpg(8)
  INCLUDE 'nodal.inc'
  INCLUDE 'agricst.inc'
!
!  this routine returns the corners for the new grids
!  ln is the level for the new grids.  ngrdnew is the
!  numer of new grids on ln passed through common block
!  agri100.  ug(1-8) contains the x-y coordinates of the
!  corners, 9-10 the bottom and top height and 11 is dz.
!
!
!  we will read in the new grid information at present
!  xc and yc is the center point, xl and yl the
!  axis lengths, angle is the rotation angle, zo and
!  zt are the bottom and top of the grid boundaries
!
!  these are in coarse-grid normalized coordinates.
!
!
  WRITE(6,*) '  regridding'
  DO ig=1,ngrdnew(ln-1)

    pio2 = 1.570796
    angle = -pio2*gangle(ig,ln-1)/90.
    cosang = COS(angle)
    sinang = -SIN(angle)
    xld2 = 0.5*ixln(ig,ln-1)
    yld2 = 0.5*jyln(ig,ln-1)

    ug(1,ig) = (ixc(ig,ln-1) - xld2*cosang + yld2*sinang -1 ) *         &
                                   rnode( 9,mstart)
    ug(2,ig) = (jyc(ig,ln-1) - xld2*sinang - yld2*cosang -1 ) *         &
                                   rnode( 9,mstart)

    ug(3,ig) = (ixc(ig,ln-1) - xld2*cosang - yld2*sinang -1 ) *         &
                                   rnode( 9,mstart)
    ug(4,ig) = (jyc(ig,ln-1) - xld2*sinang + yld2*cosang -1 ) *         &
                                   rnode( 9,mstart)

    ug(5,ig) = (ixc(ig,ln-1) + xld2*cosang - yld2*sinang -1 ) *         &
                                   rnode( 9,mstart)
    ug(6,ig) = (jyc(ig,ln-1) + xld2*sinang + yld2*cosang -1 ) *         &
                                   rnode( 9,mstart)

    ug(7,ig) = (ixc(ig,ln-1) + xld2*cosang + yld2*sinang -1 ) *         &
                                   rnode( 9,mstart)
    ug(8,ig) = (jyc(ig,ln-1) + xld2*sinang - yld2*cosang -1 ) *         &
                                   rnode( 9,mstart)
!
! here we redo the points such that the point with max x is
! always the first point.  this means that the grids will
! always have an angle between 0 and -90 degrees in the interface.
! this does not change the actual grid placement in any way.
!
    i1 = 1
    IF(ug(3,ig) < ug(i1,ig)) i1 = 3
    IF(ug(5,ig) < ug(i1,ig)) i1 = 5
    IF(ug(7,ig) < ug(i1,ig)) i1 = 7
!
    IF(i1 > 1) THEN
      DO  i=i1,i1+7
        in = i
        IF(i > 8) in = i-8
        ii = i-i1+1
        tmpg(ii) = ug(in,ig)
      END DO
      DO  i=1,8
        ug(i,ig) = tmpg(i)
      END DO
    END IF
!
    ug(9,ig) = 0.
    ug(10,ig)= rnode(30,mstart)
    ug(11,ig)= rnode(31,mstart)
    WRITE(6,11)ig,(ug(ii,ig),ii=1,11)
  END DO

11  FORMAT(2X,' new grid ',i4,', location information ',3(/,2X,4E12.5) )
  RETURN
END SUBROUTINE rdgrds
!


SUBROUTINE join(lbase, lfnew) 1
!
  INCLUDE 'nodal.inc'
  LOGICAL :: printl
  INTEGER :: ptr
!
!  JOIN = HOOK UP OLD AND NEW LEVEL DATA STRUCTURES.
!      SET PREVLEVEL POINTERS.
!      RESET GLOBAL VARIABLE  LFINE.
!      RETURN FILES FROM OLD GRIDS.
!
!
  l = lbase + 1
  10   IF (l > lfine) GO TO 40
  mptr = lstart(l)
  20       IF (mptr == 0) GO TO 30
  mold = mptr
  mptr = node(10, mptr)
!          CALL PUTNOD(MOLD)
  GO TO 20
  30     CONTINUE
  l = l + 1
  GO TO 10
  40   CONTINUE
!
! MERGE NEWSTL INTO LSTART FOR FINISHING TOUCHES OF GRID STRUCTURE
!
  l = lbase + 1
  50   IF (l > 10) GO TO 60
  lstart(l) = newstl(l)
  l = l + 1
  GO TO 50
  60   CONTINUE

  lfine = lfnew
!
!  GRID STRUCTURE NOW COMPLETE AGAIN. SAFE TO PRINT, ETC. ASSUMING
!  THINGS INITIALIZED TO ZERO IN NODGET.
!
! here we'd set whatever else needs to be set
!
  printl = .true.
  l = lbase + 1
  70   IF (l > lfine) GO TO 105
  mptr = newstl(l)
  80       IF (mptr == 0) GO TO 90
  lm1=l-1
!           CALL SRCLST( MPTR,MPTRSC,DXYSRC,NUMBS,LM1,L )
!           CALL ZSOURCE( IZSRC(1,1,MPTR),MPTRSC,MPTR,NUMBS,
!  *                      BOUNDI,PRINTL )
  mptr = node(10, mptr)
  GO TO 80
  90       CONTINUE
  l = l + 1
  GO TO 70
  105   CONTINUE
!
! SET THE LBACK POINTER
!
  100  l      = lbase+1
  110  IF (l > lfine) GO TO 130
  ptr    = lstart(l)
  120      CONTINUE
  lback(l) = ptr
  ptr      = node(10,ptr)
  IF (ptr /=  0) GO TO 120
  l     = l + 1
  GO TO 110
  130  CONTINUE
!
!
  RETURN
END SUBROUTINE join
!


SUBROUTINE sethk(msave) 1
  INCLUDE 'nodal.inc'
  INTEGER :: mptr
  INTEGER :: pptr,n,mlevel
  REAL :: inner,norm1,norm2,cossqu,h1,h2
!  LOGICAL  OVRLAP
! ******************************************************************
! SETHK  - SET THE H'S, K, AND MAXNUMROW, COL FOR THE GRIDS
!       STARTING AT MSAVE.
! INPUT PARAMETER:
!    MPTR   - STARTING PTR TO GRID TO FIND HROW, HCOL, K, MAXI, MAXJ FOR
!
! NOTE ON ALGORITHM:
! SINCE THE STEP SIZES MAY BE DIFFERENT DIRECTIONS, A SMOOTH CHANGE
! FROM 0 TO PI/2 ORIENTATION ANGLE IS MADE BY COMPUTING THE ANGLE
! BETWEEN MPTR AND AN (OLD) PARENT.  CALL THIS ANGLE ALPHA.
! WE THEN FIND WHICH OF THE H'S BY INSISTING THAT IF ALPHA = 0,
! THEN THE NEW H IS JUST H(X OR Y)POSS; IF ALPHA = PI/2, THEN THE
! NEW H IS JUST H(Y OR X)POSS; AND THAT THE CHANGE IS SMOOTH.
! THE CHOICE MADE WAS (NOTE THAT THIS HAS NOTHING TO DUE WITH
! ROTATIONS):
!    NEW H1 = H1*COS**2(ALPHA) + H2*SIN**2(ALPHA)
! AND SIMILIARLY FOR H2.
! HERE THE H1 AND H2 ARE THE "APPROPRIATE" CHOICE OF H(X OR Y)POSS
! (BASED ON THE ORIENTATION OF MPTR)
! SPECIAL NOTE:
!    IT IS USUALLY THE CASE THAT THE SIDES OF THE RECTANGLE ARE NOT
! AN INTEGRAL MULTIPLE OF THE STEP SIZES.  SETHK INCREASES THE H'S
! TO THE SMALLEST H > ORIGINAL H. THIS IS TO KEEP THE METHOD STABLE,
! WHICH WOULD NOT BE TRUE IF WE USED AN H < ORIGINAL H.
! ******************************************************************
  mlevel = node(4,msave)
  mptr   = msave
!
  23000 IF(.NOT. (mptr /= 0))GO TO 23001
  pptr   = lstart(1)
!23002     IF(.NOT. (.NOT. OVRLAP(PPTR,MPTR)))GO TO 23003
!       PPTR = NODE(10, PPTR)
!       GO TO 23002
!23003     CONTINUE
!
!       COMPUTE INNER PRODUCT AND LENGTHS OF SIDES
  inner  = ( rnode(7,pptr)-rnode(1,pptr) ) *( rnode(7,mptr)-            &
      rnode(1,mptr) ) +( rnode(8,pptr)-rnode(2,pptr) ) *( rnode(8,mptr) &
      -rnode(2,mptr) )
  norm1  = ( ( rnode(7,pptr)-rnode(1,pptr) ) ** 2 +( rnode(8,           &
      pptr)-rnode(2,pptr) ) ** 2 )
  norm2  = ( ( rnode(7,mptr)-rnode(1,mptr) ) ** 2 +( rnode(8,           &
      mptr)-rnode(2,mptr) ) ** 2 )
!
  cossqu = (inner/norm1) * (inner/norm2)
!
  IF (cossqu < 0.5) GO TO 23004
  h1     = hxposs(mlevel)
  h2     = hyposs(mlevel)
  GO TO 23005
  23004     CONTINUE
  h1     = hyposs(mlevel)
  h2     = hxposs(mlevel)
  23005     CONTINUE
!
  hx    = (h1-h2)*cossqu + h2
  hy    = (h2-h1)*cossqu + h1
  rnode(11,mptr) = possk(mlevel)
!
!       NOW, WE ADJUST THE H'S SO THAT N*H = LENGTH OF SIDE FOR SOME
!       INTEGER N
!
  norm2 = SQRT( (rnode(3,mptr)-rnode(1,mptr))**2 +(rnode(4,mptr         &
      )-rnode(2,mptr))**2 )
  norm1 = SQRT( (rnode(7,mptr)-rnode(1,mptr))**2 +(rnode(8,mptr         &
      )-rnode(2,mptr))**2 )
!
  n     = IFIX(norm1/hx+.01 + 1)
!
! SET N,M ODD FOR ERREST (2DX GRID OVERLY)
!
!   IF(MOD(N,2) .NE. 0) N=N-1
  rnode(9,mptr) = norm1 / FLOAT(n-1)
  node(5,mptr) = n
!
  n     = IFIX(norm2/hy+.01 + 1)
!   IF(MOD(N,2) .NE. 0) N=N-1
  rnode(10,mptr) = norm2 / FLOAT(n-1)
  node(6,mptr) = n
!
!  NOW SET NUMBER OF LAYERS FOR THIS GRID
!
  node(14,mptr) = nint( (rnode(30,mptr)-rnode(29,mptr))                 &
                          /rnode(31,mptr) ) + 1
!
  mptr = node(10,mptr)
  GO TO 23000
  23001 CONTINUE
  RETURN
END SUBROUTINE sethk
!