SUBROUTINE moment (rect,badpts,npt,usage,rotate,buffer,hx,hy) 1
!
REAL :: rect(28),badpts(2,npt),evec1(2),evec2(2),buffer, &
rotate
!
! input parameters:
! badpts = x,y coords of flagged badpts grouped into clusters
! are in the first two rows
! npt = num. of badpts. in the cluster.
! buffer = expand new grids with buffer zone of size buffer
! this prevents degenerate point rectangles.
! output parameters:
! usage = ratio of flagged to unflagged badpts. in new grid
! measures goodness of fit and clustering
! rect( ) = stores some info. for grid created herein.
! sometimes rect = rnode, sometimes = temp. array.
! depending on calling prog. (grdfit or expand)
!
!
! moment = compute 2nd moments about the mean of flagged badpts.
! fit an ellipse. the eigenvectors determine rectangle orientation.
! same some info., even tho. usage might be low and rect. scrapped.
!
rn = FLOAT(npt)
xmean = 0.0
ymean = 0.0
cross = 0.0
xsq = 0.0
ysq = 0.0
DO ipt = 1, npt
xmean = xmean + badpts(1,ipt)
ymean = ymean + badpts(2,ipt)
xsq = xsq + badpts(1,ipt)**2
ysq = ysq + badpts(2,ipt)**2
cross = cross + badpts(1,ipt)*badpts(2,ipt)
END DO
!
xmean = xmean / rn
ymean = ymean / rn
xm2 = xmean ** 2
ym2 = ymean ** 2
xsq = xsq / rn
ysq = ysq / rn
cross = cross / rn - xmean * ymean
!
tl = xsq - xm2
br = ysq - ym2
!
eval1 = ( (tl+br) + SQRT((tl-br)**2 + 4.0*cross**2) ) / 2.0
eval2 = ( (tl+br) - SQRT((tl-br)**2 + 4.0*cross**2) ) / 2.0
!
! matrix = <tl, cross; cross, br>.
! determine eigenvectors. normalize for ease in later computation.
! make 1st evector lie in southeast quadrant.
! make 2nd evector lie in northeast quadrant.
!
IF (ABS(cross) <= rotate) GO TO 30
evec1(2) = (eval1-tl) / cross
evec2(2) = (eval2-tl) / cross
IF (evec1(2) <= evec2(2)) GO TO 20
temp = evec1(2)
evec1(2) = evec2(2)
evec2(2) = temp
20 CONTINUE
fac1 = SQRT(1.0+evec1(2)**2)
evec1(1) = 1.0 / fac1
evec1(2) = evec1(2) / fac1
fac2 = SQRT(1.0 + evec2(2)**2)
evec2(1) = 1.0 / fac2
evec2(2) = evec2(2) / fac2
GO TO 40
30 CONTINUE
evec1(1) = 1.0
evec2(1) = 0.0
evec1(2) = 0.0
evec2(2) = 1.0
40 CONTINUE
!
! compute length of enclosing rectangles to include all flagged badpts.
! take projection (dotproduct) of bad pt. on evectors to do this.
! expand on all sides by 'buffer' zone. this also prevents
! case of degenerate rectangle (line).
!
emx1 = badpts(1,1)*evec1(1) + badpts(2,1)*evec1(2)
emn1 = emx1
emx2 = badpts(1,1)*evec2(1) + badpts(2,1)*evec2(2)
emn2 = emx2
IF (npt == 1) GO TO 90
DO ipt = 2, npt
dot1 = badpts(1,ipt)*evec1(1) + badpts(2,ipt)*evec1(2)
dot2 = badpts(1,ipt)*evec2(1) + badpts(2,ipt)*evec2(2)
IF (dot1 <= emx1) GO TO 50
emx1 = dot1
50 IF (dot1 >= emn1) GO TO 60
emn1 = dot1
60 IF (dot2 <= emx2) GO TO 70
emx2 = dot2
70 IF (dot2 >= emn2) CYCLE
emn2 = dot2
END DO
90 emx1 = emx1 + buffer
emx2 = emx2 + buffer
emn1 = emn1 - buffer
emn2 = emn2 - buffer
!
! from length of the sides, determine the 4 rect. corners
! number the corners clockwise
!
rect(1) = emn1*evec1(1)+emn2*evec2(1)
rect(2) = emn1*evec1(2)+emn2*evec2(2)
rect(3) = emn1*evec1(1)+emx2*evec2(1)
rect(4) = emn1*evec1(2)+emx2*evec2(2)
rect(5) = emx1*evec1(1)+emx2*evec2(1)
rect(6) = emx1*evec1(2)+emx2*evec2(2)
rect(7) = emx1*evec1(1)+emn2*evec2(1)
rect(8) = emx1*evec1(2)+emn2*evec2(2)
!
! set some other fields here that would be difficult elsewhere.
!
rect(16) = emx1 +.00001
rect(17) = emn1 -.00001
rect(18) = emx2 +.00001
rect(19) = emn2 -.00001
rect(12) = evec1(1)
rect(13) = evec1(2)
rect(14) = evec2(1)
rect(15) = evec2(2)
dist = SQRT( (rect(7)-rect(1))**2 &
+(rect(8)-rect(2))**2 )
rect( 21)=(rect(7)-rect(1))/dist
rect( 22)=(rect(8)-rect(2))/dist
!
! compute volume cutoff ratio
!
iside1 = (hx+emx1-emn1-2.0*buffer+.00001) / hx
iside2 = (hy+emx2-emn2-2.0*buffer+.00001) / hy
gpall = iside1 * iside2
usage = rn / gpall
!
RETURN
END SUBROUTINE moment
!
! --------------------------------------------------------------------
!
SUBROUTINE outtre(mlev,ddsc,dmpc) 1,3
!
INCLUDE 'nodal.inc'
INCLUDE 'agricpu.inc'
INCLUDE 'agricst.inc'
LOGICAL :: ddsc,dmpc
!
! ******************************************************************
! OUTTRE - OUTPUT SUBTREE
! INPUT PARAMETERS:
! MLEV - PTR TO SUBTREE TO OUTPUT I.E., START AT LEVEL(MLEV)
! TREE IS OUTPUT FROM 'LEVEL' TO FINEST LEVEL.
! ******************************************************************
!
!
! dump out generic grid data if asked for
!
IF(ddsc) THEN
CALL dmpdsc
CALL dmpstr
END IF
!
! dump out tree if needed
!
IF( .NOT. verbose1 ) RETURN
!
time = rnode(20,mlev)/60.
WRITE(6,1) time
1 FORMAT(//,1X,' GRID STRUCTURE AT ',f10.3,' MINUTES ')
!
level = node(4, mlev)
!
IF( verbose6 ) WRITE(6,'('' LEVEL, MLEV,LFINE '',3I5)')level,mlev,lfine
!
23000 IF(.NOT. (level <= lfine))GO TO 23001
mptr = lstart(level)
23002 IF(.NOT. (mptr /= 0))GO TO 23003
CALL outmsh
(mptr)
!c if (dmpc) call dmpcnst(mptr)
mptr = node(10, mptr)
GO TO 23002
23003 CONTINUE
level = level + 1
GO TO 23000
23001 CONTINUE
!
RETURN
END SUBROUTINE outtre
!
! --------------------------------------------------------------------
!
SUBROUTINE outmsh(mptr) 1
INCLUDE 'nodal.inc'
!
! this routine prints out the grid information
!
IF( (node(4,mptr) < 1) ) RETURN
time = rnode(20,mptr)/60.
WRITE(6,1)mptr,node(4,mptr),time
1 FORMAT(/,1X,' ******** GRID ',i3,' LEVEL ',i3, &
' AT ',f10.3,' MINUTES ')
WRITE(6,2) (rnode(i,mptr),i=1,8),rnode(29,mptr),rnode(30,mptr)
2 FORMAT(/,10X,'corners x y ', &
/,13X,'1',3X,2(2X,e13.6),/,13X,'2',3X,2(2X,e13.6), &
/,13X,'3',3X,2(2X,e13.6),/,13X,'4',3X,2(2X,e13.6), &
//,' z at bottom = ',e13.6,' z at top = ',e13.6,/)
WRITE(6,3) (rnode(i,mptr),i=9,11),rnode(31,mptr)
3 FORMAT(3X,' dx = ',e12.5,' dy = ',e12.5, &
/,3X,' dt = ',e12.5,' dz = ',e12.5)
WRITE(6,4)rnode(21,mptr),rnode(22,mptr), &
(rnode(i,mptr),i=12,19), &
(rnode(i,mptr),i=23,28)
4 FORMAT(3X,' cos = ',e12.5,' sin = ',e12.5, &
//,' misc grid description information ', &
/,4(/,2X,4(1X,e12.5)) )
WRITE(6,5) node(5,mptr),node(6,mptr),node(14,mptr), &
node(7,mptr),node(8,mptr),node(16,mptr)
5 FORMAT(/,' NODAL INFORMATION ',/, &
1X,' nx = ',i4,' ny = ',i4,' nz = ',i4,/, &
1X,' bigstep file = ',i3,' smlstp file = ',i3, &
' constants file = ',i3)
WRITE(6,6) node(10,mptr),node(12,mptr),node(13,mptr)
6 FORMAT(1X,' next grid on level = ',i3, &
' previous grid on level = ',i3,/, &
1X,' number of timesteps taken = ',i4)
RETURN
END SUBROUTINE outmsh
!
! --------------------------------------------------------------------
!
SUBROUTINE outch( a,tmp,m,n,kk )
DIMENSION a(m,n,kk),tmp(1)
!
! plot out a few levels
!
kmid = kk/2
jmid = n/2
imid = m/2
! call parray(a(1,1,kmid),m,n)
DO k=1,kk
DO j=1,n
tmp(j+(k-1)*n) = a(imid,j,k)
END DO
END DO
! call parray(tmp,n,kk)
DO k=1,kk
DO i=1,m
tmp(i+(k-1)*m) = a(i,jmid,k)
END DO
END DO
! call parray(tmp,m,kk)
RETURN
END SUBROUTINE outch
!
! --------------------------------------------------------------------
!
SUBROUTINE dmpdsc 1
INCLUDE 'agrigrid.inc'
INCLUDE 'grddsc.inc'
INCLUDE 'agricst.inc'
!
! print the generic grid description information if wanted
!
IF( .NOT. verbose2 ) RETURN
!
WRITE(6,'('' GENERIC GRID INFORMATION '')')
WRITE(6,1) nsint,nsreal,nx1d,ny1d,nz1d, &
nxy2d,nxz2d,nyz2d,nxyz3d
!
IF (nxy2d > 0) THEN
DO i=1,nxy2d
WRITE(6,2) i
WRITE(6,3) stgxy(1,i),stgxy(2,i)
WRITE(6,4) idmxy(1,i),idmxy(2,i)
WRITE(6,5) ipkxy(i)
WRITE(6,6) iupxy(1,i),iupxy(2,i)
WRITE(6,7) ibdxy(1,i),ibdxy(2,i),ibdxy(3,i)
END DO
END IF
!
IF (nxz2d > 0) THEN
DO i=1,nxz2d
WRITE(6,12) i
WRITE(6,3) stgxz(1,i),stgxz(2,i)
WRITE(6,4) idmxz(1,i),idmxz(2,i)
WRITE(6,5) ipkxz(i)
WRITE(6,6) iupxz(1,i),iupxz(2,i)
WRITE(6,7) ibdxz(1,i),ibdxz(2,i)
END DO
END IF
!
IF (nyz2d > 0) THEN
DO i=1,nyz2d
WRITE(6,22) i
WRITE(6,3) stgyz(1,i),stgyz(2,i)
WRITE(6,4) idmyz(1,i),idmyz(2,i)
WRITE(6,5) ipkyz(i)
WRITE(6,6) iupyz(1,i),iupyz(2,i)
WRITE(6,7) ibdyz(1,i),ibdyz(2,i)
END DO
END IF
!
IF (nxyz3d > 0) THEN
DO i=1,nxyz3d
WRITE(6,32) i
WRITE(6,33) stgxyz(1,i),stgxyz(2,i),stgxyz(3,i)
WRITE(6,34) idmxyz(1,i),idmxyz(2,i),idmxyz(3,i)
WRITE(6,5) ipkxyz(i)
WRITE(6,6) iupxyz(1,i),iupxyz(2,i)
WRITE(6,7) ibdxyz(1,i),ibdxyz(2,i),ibdxyz(3,i)
END DO
END IF
!
1 FORMAT( /,2X,' nsint = ',i5, &
/,2X,' nsreal = ',i5, &
/,2X,' nx1d = ',i5, &
/,2X,' ny1d = ',i5, &
/,2X,' nz1d = ',i5, &
/,2X,' nxy2d = ',i5, &
/,2X,' nxz2d = ',i5, &
/,2X,' nyz2d = ',i5, &
/,2X,' nxyz3d = ',i5 )
!
2 FORMAT( /,' data for 2-D xy variable ',i4 )
!
3 FORMAT( ' x staggering ',f6.3,' y staggering ',f6.3 )
4 FORMAT( ' x max dimension ' ,i4,' y max dimension ',i4 )
5 FORMAT( ' pack variable - ',i2)
6 FORMAT( ' update - ',i2,' other vector ',i2)
7 FORMAT( ' boundi - ',i2,' other vector ',i2, &
' t-dt field - ',i2)
!
12 FORMAT( /,' data for 2-D xz variable ',i4 )
22 FORMAT( /,' data for 2-D yz variable ',i4 )
32 FORMAT( /,' data for 3-D xyz variable ',i4 )
33 FORMAT( ' x staggering ',f6.3,' y staggering ',f6.3, &
' z staggering ',f6.3 )
34 FORMAT( ' x max dimension ' ,i4,' y max dimension ',i4, &
' z max dimension ',i4 )
RETURN
END SUBROUTINE dmpdsc
!
SUBROUTINE settmp 4
INCLUDE 'agrialloc.inc'
INCLUDE 'manage.inc'
INCLUDE 'agricst.inc'
!
ntemp = lfree(2,1)
IF( verbose4 ) THEN
WRITE(6,'('' IN SETTMP '')')
WRITE(6,'('' NTEMP = '',I7)') ntemp
END IF
RETURN
END SUBROUTINE settmp
!
! --------------------------------------------------------------------
!
SUBROUTINE dmpstr 1
INCLUDE 'nodal.inc'
INCLUDE 'agrialloc.inc'
INCLUDE 'agrigrid.inc'
INCLUDE 'grddsc.inc'
INCLUDE 'agricst.inc'
!
! output storage locations for the grids if necessary
!
IF( .NOT. verbose4 ) RETURN
!
level = 1
10 IF(level > lfine) GO TO 999
mptr = lstart(level)
20 IF(mptr == 0) GO TO 100
!
WRITE(6,'(/,'' STORAGE LOCATIONS FOR GRID '',I4)') mptr
WRITE(6,1001) ipint(mptr),ipreal(mptr),ips1d(mptr),ipx(mptr), &
ipy(mptr),ipz(mptr)
!
IF(nxy2d > 0) THEN
WRITE(6,'('' STORAGE LOCATIONS FOR XY VARIABLES '')')
DO i=1,nxy2d
WRITE(6,1002) i,ipxy(i,mptr)
END DO
END IF
IF(nxz2d > 0) THEN
WRITE(6,'('' STORAGE LOCATIONS FOR XZ VARIABLES '')')
DO i=1,nxz2d
WRITE(6,1002) i,ipxz(i,mptr)
END DO
END IF
IF(nyz2d > 0) THEN
WRITE(6,'('' STORAGE LOCATIONS FOR YZ VARIABLES '')')
DO i=1,nyz2d
WRITE(6,1002) i,ipyz(i,mptr)
END DO
END IF
IF(nxyz3d > 0) THEN
WRITE(6,'('' STORAGE LOCATIONS FOR XYZ VARIABLES '')')
DO i=1,nxyz3d
WRITE(6,1002) i,ipxyz(i,mptr)
END DO
END IF
1001 FORMAT(2X,5(2X,i9))
1002 FORMAT(2X,i5,2X,i9)
!
mptr = node(10,mptr)
GO TO 20
100 level = level+1
GO TO 10
999 RETURN
END SUBROUTINE dmpstr
!
SUBROUTINE setrot(mlevel) 1
INCLUDE 'nodal.inc'
!
!
! SETROT: SET THE ROTATION FIELDS IN RNODE FOR ALL GRIDS AT
! THE SAME LEVEL AS MPTR. THESE FIELDS ARE
! COS AND SIN OF THE ANGLE OF ROTATION OF THE GRID.
! (THESE ARE SET ELSEWHERE).
! ALSO SET SLOPE/INTERCEPT FORM FOR ALL 4 LINES OF THE RECT.
! SET THE MAX/MIN PROJECTION ON EACH EIGENVECTOR FIELD.
!
mptr = mlevel
23000 IF(.NOT. (mptr /= 0))GO TO 23001
dist = SQRT( (rnode(7,mptr)-rnode(1,mptr))**2 &
+(rnode(8,mptr)-rnode(2,mptr))**2 )
rnode( 21,mptr)=(rnode(7,mptr)-rnode(1,mptr))/dist
rnode( 22,mptr)=(rnode(8,mptr)-rnode(2,mptr))/dist
!
rnode( 12,mptr) = rnode(21,mptr)
rnode( 13,mptr) = rnode(22,mptr)
rnode( 14,mptr) = -rnode(22,mptr)
rnode( 15,mptr) = rnode(21,mptr)
!
delx = rnode(3,mptr) - rnode(1,mptr)
dely = rnode(4,mptr) - rnode(2,mptr)
IF(.NOT. (ABS(delx) > .0001))GO TO 23002
rnode(23,mptr) = dely / delx
GO TO 23003
23002 CONTINUE
rnode(23,mptr) = 1000000000
23003 CONTINUE
IF(.NOT. (ABS(rnode(23,mptr)) > .0001))GO TO 23004
rnode(24,mptr) = -1.0 / rnode(23,mptr)
GO TO 23005
23004 CONTINUE
rnode(24,mptr) = - 1000000000
23005 CONTINUE
rnode(25,mptr) = rnode(2,mptr)-rnode(23,mptr)*rnode(1,mptr)
rnode(26,mptr) = rnode(2,mptr)-rnode(24,mptr)*rnode(1,mptr)
rnode(27,mptr) = rnode(6,mptr) - rnode(23,mptr)*rnode(5,mptr)
rnode(28,mptr) = rnode(6,mptr) - rnode(24,mptr)*rnode(5,mptr)
!
rnode( 16,mptr) = rnode(5,mptr)*rnode(12,mptr) +rnode(6,mptr) &
*rnode(13,mptr)+.0001
rnode( 17,mptr) = rnode(1,mptr)*rnode(12,mptr) +rnode(2,mptr) &
*rnode(13,mptr)-.0001
rnode( 18,mptr) = rnode(5,mptr)*rnode(14,mptr) +rnode(6,mptr) &
*rnode(15,mptr)+.0001
rnode( 19,mptr) = rnode(1,mptr)*rnode(14,mptr) +rnode(2,mptr) &
*rnode(15,mptr)-.0001
mptr = node(10, mptr)
GO TO 23000
23001 CONTINUE
!
RETURN
END SUBROUTINE setrot
!
SUBROUTINE cpyfld( mptr,ifldin,ifldout,idim ) 6,2
INCLUDE 'nodal.inc'
INCLUDE 'agrialloc.inc'
!
! this routine copies the data in xy or xyz field
! ifldin onto ifldout and replaces ifldout.
!
nx = node(5,mptr)
ny = node(6,mptr)
nz = node(14,mptr)
!
IF (idim == 2) THEN
inptrs = igtnxy( mptr, ifldin, 1 )
inptrr = igtnxy( mptr, ifldout, 1 )
!
DO ij=1,nx*ny
a(inptrr+ij-1) = a(inptrs+ij-1)
END DO
!
CALL retnxy
( mptr, ifldout, 1, inptrr, .true. )
!
ELSE IF (idim == 3) THEN
!
inptrs = igtxyz( mptr, ifldin, 1 )
inptrr = igtxyz( mptr, ifldout, 1 )
DO ijk=1,nx*ny*nz
a(inptrr+ijk-1) = a(inptrs+ijk-1)
END DO
CALL retxyz
( mptr, ifldout, 1, inptrr, .true. )
!
ELSE
WRITE(6,'('' ERROR, NOT 2-D OR 3-D IN CPYFLD '', &
& 4I9)') mptr,ifldin,ifldout,idim
END IF
RETURN
END SUBROUTINE cpyfld
SUBROUTINE addgrd( mptr ) 2,7
INCLUDE 'agrialloc.inc'
INCLUDE 'agrigrid.inc'
INCLUDE 'grddsc.inc'
INCLUDE 'agricst.inc'
CHARACTER (LEN=80) :: filenm
!
! this routine takes a grid stored at unit iunit
! and adds it to the end of the grid storage
!
CALL resett
CALL setstr
( mptr )
CALL settmp
in = ipint( mptr )
!
! get the proper file
!
CALL mkflnm
( 'tmpdmp',' ','.z',0.,mptr,filenm,length )
CALL fexist
( filenm(1:length),length,.true.,.false. )
iunit = igtunit( dum )
OPEN( UNIT=iunit,FILE=filenm(1:length),FORM='unformatted', &
STATUS='old' )
IF( verbose3 ) WRITE(6,*) ' read grid ',mptr,' from tmp file ', &
filenm(1:length),', io through unit ',iunit
REWIND( iunit )
!
! Yuhe: when EXBC turned on, we must add the EXBC arrays for grid 1.
!
IF ( lexbc == 1 .AND. mptr == 1 ) THEN
nwords = ipexbc(nexbc3d+1,mptr) - ipint(mptr)
ELSE
nwords = ipxyz(nxyz3d+1,mptr) - ipint(mptr)
END IF
IF( verbose3 ) WRITE(6,*) ' calling rdngrd ',mptr,iunit,nwords
CALL rdngrd
( iunit,a(in),nwords )
!
! close and delete file, return unit number
!
CLOSE( UNIT=iunit,STATUS='keep' )
CALL retnunit
( iunit )
!
! we're finished here
!
RETURN
END SUBROUTINE addgrd
!
SUBROUTINE dmpgrd( mptr,saved ) 3,7
LOGICAL :: saved
INCLUDE 'agrialloc.inc'
INCLUDE 'agrigrid.inc'
INCLUDE 'grddsc.inc'
INCLUDE 'agricst.inc'
CHARACTER (LEN=80) :: filenm
!
! this routine removes grid storage from the incore
! array and, if desired, writes it out to file iunit
! which, at present, will be the grid number plus 39
!
IF ( saved ) THEN
!
! dump data to disk file
!
CALL mkflnm
( 'tmpdmp',' ','.z',0.,mptr,filenm,length )
iunit = igtunit( dum )
CALL fexist
( filenm(1:length),length,.false.,.false. )
OPEN( UNIT=iunit,FILE=filenm(1:length),FORM='unformatted', &
STATUS='new' )
IF( verbose3 ) WRITE(6,*) ' dump grid ',mptr,' to tmp file ', &
filenm(1:length),', io through unit ',iunit
REWIND( iunit )
!
! Yuhe: when EXBC turned on, we must add the EXBC arrays for grid 1.
!
IF ( lexbc == 1 .AND. mptr == 1 ) THEN
nwords = ipexbc(nexbc3d+1,mptr) - ipint(mptr)
ELSE
nwords = ipxyz(nxyz3d+1,mptr) - ipint(mptr)
END IF
IF( verbose3 ) WRITE(6,*) ' calling wrtgrd ',mptr,iunit,nwords
CALL wrtgrd
( iunit, a(ipint(mptr)), nwords )
!
! close and delete file, return unit number
!
CLOSE( UNIT=iunit,STATUS='keep' )
CALL retnunit
( iunit )
!
END IF
!
! free up this space
!
IF( verbose4 ) WRITE(6,*) ' reclaiming space for grid ',mptr
CALL resett
CALL reclam
( ipint(mptr),nwords )
CALL settmp
!
! we're finished here
!
RETURN
END SUBROUTINE dmpgrd
!
SUBROUTINE rdngrd( iunit,a,nwords ) 2
DIMENSION a(nwords)
READ(iunit) a
RETURN
END SUBROUTINE rdngrd
!
SUBROUTINE wrtgrd( iunit,a,nwords ) 2
DIMENSION a(nwords)
WRITE(iunit) a
RETURN
END SUBROUTINE wrtgrd
!
SUBROUTINE dmplvl( level ) 1,1
INCLUDE 'nodal.inc'
INCLUDE 'agricst.inc'
!
! this dumps out all the grids at level 'level'
! into individual files using the dmpgrd subroutine
!
! grids in lstart are dumped, starting with the last one.
! it is assumed that the present level is the highest
! existing in memory
!
mptr = lback(level)
IF(mptr == 0) THEN
WRITE(6,*) ' error in dmplvl, no grids on level ',level
STOP
END IF
5 IF( mptr == 0) GO TO 99
IF( verbose3 ) WRITE(6,*) ' dumping grid - level ',mptr,level
CALL dmpgrd
( mptr,.true. )
mptr = node(12,mptr)
GO TO 5
!
99 RETURN
END SUBROUTINE dmplvl
!
SUBROUTINE exchng( level ) 1,3
INCLUDE 'nodal.inc'
INCLUDE 'agricst.inc'
!
! this subroutine calls the boundary condition exchange
! for overlapping fine grids
!
! this version doesn't do an overlap check first.
! later version should, we just need to put in overlap
! test to do so
!
cpu0 = f_cputime
()
mptr = lstart( level )
5 IF(mptr == 0) GO TO 999
!
mptre = node(10,mptr)
10 IF(mptre == 0) GO TO 20
!
! do boundary condition exchange between mptr and mptre
!
! here's where the overlap test will be
!
WRITE(6,*) ' b.c. exchange between ',mptr,mptre
CALL exchbc
( mptr,mptre )
mptre = node(10,mptre)
GO TO 10
!
20 CONTINUE
!
! we've gone through the list for grid mptr, now go
! to the next grid and go through the rest of the list
!
mptr = node(10,mptr)
GO TO 5
!
999 CONTINUE
cpu_bndexch = cpu_bndexch + f_cputime
() - cpu0
!
! we're finished here
!
RETURN
END SUBROUTINE exchng
!
SUBROUTINE dmpall( time ) 1,1
INCLUDE 'nodal.inc'
INCLUDE 'agricst.inc'
!
! this dumps out all the grids for a restart
! into individual files using the dumpgrid subroutine.
! this routine does not clear internal storage, thus integrations
! can be continued after this dump, as opposed to the
! dumps performed by dmplvl, which does clear the internal storage
!
! grids in lback are dumped, starting with the last one.
!
level = 1
mptr = lback(level)
!
IF(mptr == 0) THEN
WRITE(6,*) ' error in dmpall, no grids on level 1 '
STOP
END IF
!
5 IF( mptr == 0) GO TO 10
!
IF( verbose3 ) WRITE(6,*) ' dumping grid - level ',mptr,level
CALL dumpgrid
( mptr,time )
mptr = node(12,mptr)
GO TO 5
10 level = level + 1
mptr = lback(level)
IF(level <= lfine) GO TO 5
!
99 RETURN
END SUBROUTINE dmpall
!
SUBROUTINE readall( time ) 1,1
INCLUDE 'nodal.inc'
INCLUDE 'agricst.inc'
!
! this reads in all the grids for a restart
! from individual files using the readgrid subroutine.
! this routine assumes that the internal storage is
! already configured, thus no storage management needs to be
! done (as opposed to reading in a new grid using addgrd,
! which does allocate new mwmory for the grid)
!
level = 1
mptr = lback(level)
!
IF(mptr == 0) THEN
WRITE(6,*) ' error in readall, no grids on level 1 '
STOP
END IF
!
5 IF( mptr == 0) GO TO 10
!
IF( verbose3 ) WRITE(6,*) ' reading grid - level ',mptr,level
CALL readgrid
( mptr,time )
mptr = node(12,mptr)
GO TO 5
10 level = level + 1
mptr = lback(level)
IF(level <= lfine) GO TO 5
!
99 RETURN
END SUBROUTINE readall
!
!
SUBROUTINE dumpgrid( mptr,time ) 1,4
IMPLICIT NONE
INCLUDE 'agrialloc.inc'
INCLUDE 'agrigrid.inc'
INCLUDE 'grddsc.inc'
INCLUDE 'agricst.inc'
INCLUDE 'globcst.inc'
CHARACTER (LEN=80) :: filenm
INTEGER :: length
INTEGER :: mptr
INTEGER :: nwords
INTEGER :: iunit, igtunit
INTEGER :: machsti
REAL :: dum
REAL :: time
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! this routine dumps out grid data for an individual
! grid for later restart.
!
CALL mkflnm
( runname(1:lfnkey),' ','.t',time,mptr,filenm,length )
iunit = igtunit( dum )
WRITE(6,*) ' restart dump for run ',runname(1:lfnkey), &
', grid ',mptr,' at time ',time
IF( verbose3 ) WRITE(6,*) ' dumping to file ',filenm(1:length), &
' through unit ',iunit
CALL fexist
( filenm(1:length),length,.false.,.true. )
OPEN( UNIT=iunit,FILE=filenm(1:length),FORM='unformatted', &
STATUS='new' )
REWIND( iunit )
WRITE(iunit) runname,filenm,machst,lfnkey,mptr,time
!
! Yuhe: when EXBC turned on, we must add the EXBC arrays for grid 1.
!
IF ( lexbc == 1 .AND. mptr == 1 ) THEN
nwords = ipexbc(nexbc3d+1,mptr) - ipint(mptr)
ELSE
nwords = ipxyz(nxyz3d+1,mptr) - ipint(mptr)
END IF
IF( verbose3 ) WRITE(6,*) ' calling wrtgrd ',mptr,iunit,nwords
CALL wrtgrd
( iunit, a(ipint(mptr)), nwords )
CLOSE( UNIT=iunit,STATUS='keep' )
CALL retnunit
( iunit )
IF( verbose3 ) WRITE(6,*) ' closed ',filenm(1:length), &
' on unit ',iunit
!
! we're finished dumping this grid data
!
RETURN
END SUBROUTINE dumpgrid
!
SUBROUTINE readgrid( mptr,time ) 1,4
! implicit none
INCLUDE 'agrialloc.inc'
INCLUDE 'agrigrid.inc'
INCLUDE 'grddsc.inc'
INCLUDE 'agricst.inc'
! include 'globcst.inc'
CHARACTER (LEN=80) :: filenm
!
! this routine reads in grid data for an individual
! grid for restart.
!
CALL mkflnm
( runold(1:nmlntho),' ','.t',time,mptr,filenm,length )
iunit = igtunit( dum )
WRITE(6,*) ' restart read from run ',runold(1:nmlntho), &
', grid ',mptr,' at time ',time
IF( verbose3 ) WRITE(6,*) ' reading from file ',filenm(1:length), &
' through unit ',iunit
CALL fexist
( filenm(1:length),length,.true.,.false. )
OPEN( UNIT=iunit,FILE=filenm(1:length),FORM='unformatted', &
STATUS='old' )
REWIND( iunit )
READ( iunit ) runnami,filenmi,machsti,nmlnthi,mptri,timei
!
! here we assume everything is ok, we could check the
! runname and filenames etc... that come from the file
! if that is deemed necessary
!
!
! Yuhe: when EXBC turned on, we must add the EXBC arrays for grid 1.
!
IF ( lexbc == 1 .AND. mptr == 1 ) THEN
nwords = ipexbc(nexbc3d+1,mptr) - ipint(mptr)
ELSE
nwords = ipxyz(nxyz3d+1,mptr) - ipint(mptr)
END IF
IF( verbose3 ) WRITE(6,*) ' calling rdngrd ',mptr,iunit,nwords
CALL rdngrd
( iunit, a(ipint(mptr)), nwords )
CLOSE( UNIT=iunit,STATUS='keep' )
CALL retnunit
( iunit )
IF( verbose3 ) WRITE(6,*) ' closed ',filenm(1:length), &
' on unit ',iunit
!
! we're finished reading this grid data
!
RETURN
END SUBROUTINE readgrid
!
!
SUBROUTINE iosetup 1
COMMON / unitnmb / iunitn(10),nleft,ntot
DO i=1,10
iunitn(i) = 40+i
END DO
nleft = 10
ntot = 10
WRITE(6,'(/2(/1x,a)/)') &
'Fortran I/O units 40-50 reserved for AGR interface.', &
'Do not use them for other purposes.'
RETURN
END SUBROUTINE iosetup
!
!
INTEGER FUNCTION igtunit( dum )
COMMON / unitnmb / iunitn(10),nleft,ntot
INCLUDE 'agricst.inc'
!
IF(nleft == 0) THEN
WRITE(6,*) ' no more units left for io in iunitn list '
WRITE(6,*) ' error stop '
END IF
!
igtunit = iunitn( nleft )
IF( verbose3 ) WRITE(6,*) ' igtunit getting unit= ',igtunit
nleft = nleft-1
RETURN
END FUNCTION igtunit
!
!
SUBROUTINE retnunit( iunit ) 8
COMMON / unitnmb / iunitn(10),nleft,ntot
!
nleft = nleft+1
IF(nleft > ntot) THEN
WRITE(6,*) ' something is screwed, there are '
WRITE(6,*) ' more units in iunitn than when we started!! '
WRITE(6,*) ' returning unit ',iunit
WRITE(6,*) ' ntot, nleft = ',ntot,nleft
DO i=1,ntot
WRITE(6,2) i,iunitn(i)
END DO
END IF
2 FORMAT(2X,i5,1X,i5)
!
iunitn(nleft) = iunit
RETURN
END SUBROUTINE retnunit
!
!-----------------------------------------------------------------------
!
SUBROUTINE mkflnm( instr1,instr2,instr3, & 7
time,grid,outstr,length )
IMPLICIT NONE
REAL :: time
INTEGER :: i, j, k, length, grid, tlength,glength
CHARACTER (LEN=*) :: instr1, instr2, instr3, outstr
CHARACTER (LEN=80) :: tmp, chmake
EXTERNAL chmake
DATA tlength,glength/ 5, 2 /
!-----------------------------------------------------------------------
! Find lengths of the strings
!-----------------------------------------------------------------------
i = INDEX( instr1,' ' ) - 1
IF(i == -1) i = LEN( instr1 )
j = INDEX( instr2,' ' ) - 1
IF(j == -1) j = LEN( instr2 )
k = INDEX( instr3,' ' ) - 1
IF(k == -1) k = LEN( instr3 )
length = 0
!
IF( i > 0 ) THEN
outstr(1:i) = instr1(1:i)
length = i
END IF
!
IF( j > 0 ) THEN
outstr(length+1:length+j) = instr2(1:j)
length = length+j
END IF
!
!-----------------------------------------------------------------------
! if time is < 0, then all we want is this string
!-----------------------------------------------------------------------
!
IF( time < 0 ) RETURN
!
!-----------------------------------------------------------------------
! If TIME > 0 add time to the string
!-----------------------------------------------------------------------
!
tmp = chmake( IFIX(time),tlength )
!
IF(k > 0) THEN
outstr(i+j+1:) = instr3(1:k)//tmp(1:tlength)
ELSE
outstr(i+j+1:) = tmp(1:tlength)
END IF
!
length = length + tlength + k
!
!-----------------------------------------------------------------------
! Create the grid no string if grid number greater than zero
!-----------------------------------------------------------------------
!
IF( grid > 0 ) THEN
tmp = chmake( grid,glength )
! outstr(length+1:) = '.g'//tmp(1:glength)
! length = length + glength + 2
outstr(length+1:) = '.'//tmp(1:glength)
length = length + glength + 1
END IF
!
! we're finished
!
WRITE(6,'(a,a)') 'The file name created is ',outstr(1:length)
999 RETURN
END SUBROUTINE mkflnm
!
!
FUNCTION chmake( numb,length )
IMPLICIT NONE
INTEGER :: numb,length,numbc,i
CHARACTER (LEN=*) :: chmake
CHARACTER (LEN=16) :: tmp
!
! check for degenerate cases
!
IF(length <= 0) THEN
WRITE(6,*) ' length is <= zero in chmake ',length
WRITE(6,*) ' error exit '
STOP
END IF
!
IF(numb == 0) THEN
!
! make the string
!
DO i=1,length
chmake(i:i) = '0'
END DO
RETURN
END IF
!
numbc = INT(ALOG10(ABS(FLOAT(numb)))) + 1
IF( numb < 0 ) numbc = numbc+1
!
IF( numbc > length ) THEN
WRITE(6,*) ' number too large in chmake ', &
' for given length ',length,numb,numbc
WRITE(6,*) ' error exit '
STOP
END IF
!
IF( numbc > 16 ) THEN
WRITE(6,*) ' number has more than 16 chars ', &
' in chmake, you must be kidding!!! '
WRITE(6,*) ' error exit '
STOP
END IF
!
! make the string
!
DO i=1,length
chmake(i:i) = '0'
END DO
!
WRITE(tmp,2) numb
1 FORMAT(i1)
2 FORMAT(i16)
chmake(length-numbc+1:length) = tmp(16-numbc+1:16)
!
! we're finished here
!
RETURN
END FUNCTION chmake
!
!
SUBROUTINE cleanf( mptrs ) 2,2
INCLUDE 'nodal.inc'
INCLUDE 'agricst.inc'
CHARACTER (LEN=80) :: filenm
LOGICAL :: existf
!
! this routine closes the files for the temp grid
! data dumps used in regrid, mptr is the first grid
! on a level to be dumped
!
iunit = igtunit( dum )
mptr = mptrs
10 IF( mptr == 0) GO TO 99
CALL mkflnm
( 'tmpdmp',' ','.z',0.,mptr,filenm,length )
INQUIRE(FILE=filenm(1:length),EXIST=existf)
!
IF(existf) THEN
OPEN( UNIT=iunit,FILE=filenm(1:length), &
FORM='unformatted',STATUS='old' )
CLOSE(UNIT=iunit,STATUS='delete')
ELSE
WRITE(6,*) ' in cleanf, expected to find file ', &
filenm(1:length),', yet does not exist '
END IF
mptr = node(10,mptr)
GO TO 10
99 CONTINUE
CALL retnunit
( iunit )
RETURN
END SUBROUTINE cleanf
!
SUBROUTINE fexist( filenm,length,exst,incr ) 6
CHARACTER (LEN=*) :: filenm
INTEGER :: length
LOGICAL :: exst,incr,existf
!
! this subroutine checks on the existence of the file
! filenm(1:length).
!
! exst: true if the file should exist, false if it shouldn't
! exist
! incr: if true and exst is false but the file exists, then
! return a new name for a file that doesn't exist.
! here we just patch on a version number to the file
!
! if the file should exist but doesn't, error exit
! if the file shouldn't exist but does and no increment
! is wanted, then we error exit
! later we'll build in an erase option taht will allow
! removal of existing files that we do not want.
!
! first we check for file that should exist
!
IF( exst ) THEN
INQUIRE( FILE=filenm(1:length),EXIST=existf )
IF(.NOT.existf ) THEN
WRITE(6,*) ' exected to find file ',filenm(1:length)
WRITE(6,*) ' file does not exist, error exit '
STOP
ELSE
RETURN
END IF
END IF
!
! now for file that shouldn't exist
!
inc = 0
10 INQUIRE( FILE=filenm(1:length),EXIST=existf )
!
IF (.NOT. existf ) RETURN
!
IF (.NOT. incr ) THEN
WRITE(6,*) ' cannot overwrite pre-existing file ', &
filenm(1:length),', error exit '
STOP
END IF
!
! here we put a number onto the end of the file
!
inc = inc+1
IF(inc == 1) THEN
WRITE(filenm(length+1:length+2),15) inc
length = length+2
ELSE IF(inc < 10) THEN
WRITE(filenm(length-1:length ),15) inc
ELSE IF(inc > 10) THEN
WRITE(6,*) ' to many version numbers of file ', &
filenm(1:length-2),', error exit '
STOP
END IF
GO TO 10
!
999 RETURN
15 FORMAT('.',i1)
END SUBROUTINE fexist
SUBROUTINE filzero(a,n) 4
REAL :: a(n)
DO i=1,n
a(i) = 0.0
END DO
RETURN
END SUBROUTINE filzero
!
!-----------------------------------------------------------------------
!
! Created by Louis Wicker, November 1992
! Writes out the cpu usage for the model
!
! Modified for ARPS by Ming Xue, 12/10/1992.
!
!-----------------------------------------------------------------------
!
SUBROUTINE prtcpu(flag,UNIT) 2
INCLUDE 'agricpu.inc'
INTEGER :: flag, UNIT
!-----------------------------------------------------------------------
! Flag = 0, initialize values to zero
!-----------------------------------------------------------------------
IF( flag == 0 ) THEN
cpu_main = 0.0
cpu_advect = 0.0
cpu_smlstep = 0.0
cpu_mixing = 0.0
cpu_filter = 0.0
cpu_cloud = 0.0
cpu_boundary = 0.0
cpu_copy = 0.0
cpu_init0 = 0.0
cpu_usrout = 0.0
cpu_regrid = 0.0
cpu_bndexch = 0.0
cpu_bndcint = 0.0
cpu_update = 0.0
cpu_pack = 0.0
cpu_unpack = 0.0
cpu_simulation = 0.0
!-----------------------------------------------------------------------
! Flag=1, write out cpu information
!-----------------------------------------------------------------------
ELSE
cpu_solver = cpu_advect+cpu_smlstep+cpu_mixing+cpu_cloud &
+ cpu_boundary+cpu_copy+cpu_main+cpu_filter
cpu_interface = cpu_simulation - cpu_solver - cpu_usrout &
- cpu_init0
WRITE(UNIT,999)
WRITE(UNIT,101) 'ADAPTIVE MESH CLOUD MODEL CPU STATISTICS'
WRITE(UNIT,999)
WRITE(UNIT,101) 'Total CPU for SIMULATION is ',cpu_simulation
WRITE(UNIT,999)
WRITE(UNIT,101) 'Total CPU for INTERFACE is ',cpu_interface
WRITE(UNIT,101) 'Total CPU for REGRID is ',cpu_regrid
WRITE(UNIT,101) 'Total CPU for EXCHBC is ',cpu_bndexch
WRITE(UNIT,101) 'Total CPU for UPDBC is ',cpu_bndcint
WRITE(UNIT,101) 'Total CPU for UPDATE is ',cpu_update
WRITE(UNIT,101) 'Total CPU for PACKING is ',cpu_pack
WRITE(UNIT,101) 'Total CPU for UNPACKING is ',cpu_unpack
WRITE(UNIT,101) 'Total CPU for INIT is ',cpu_init0
WRITE(UNIT,101) 'Total CPU for USROUT is ',cpu_usrout
WRITE(UNIT,999)
WRITE(UNIT,101) 'Total CPU for SOLVER is ',cpu_solver
WRITE(UNIT,101) 'Total CPU for CLOUD3D is ',cpu_main
WRITE(UNIT,101) 'Total CPU for SUB SMLSTEP is ',cpu_smlstep
WRITE(UNIT,101) 'Total CPU for SUB ADVECT is ',cpu_advect
WRITE(UNIT,101) 'Total CPU for SUB CLOUD is ',cpu_cloud
WRITE(UNIT,101) 'Total CPU for SUB MIXING is ',cpu_mixing
WRITE(UNIT,101) 'Total CPU for SUB FILTER is ',cpu_filter
WRITE(UNIT,101) 'Total CPU for SUB BOUNDS is ',cpu_boundary
WRITE(UNIT,101) 'Total CPU for SUB COPY is ',cpu_copy
WRITE(UNIT,999)
101 FORMAT(1X,a,f15.5)
999 FORMAT(/79('-')/)
END IF
RETURN
END SUBROUTINE prtcpu
SUBROUTINE writint( icnst,ncnst , UNIT)
INTEGER :: ncnst , UNIT
INTEGER :: icnst(ncnst)
DO i=1,ncnst
WRITE(UNIT, '(1x,2i10)') i, icnst(i)
END DO
RETURN
END SUBROUTINE writint
SUBROUTINE readint( icnst,ncnst , UNIT)
INTEGER :: ncnst , UNIT
INTEGER :: icnst(ncnst)
DO i=1,ncnst
READ(UNIT, '(1x,2i10)') ii, icnst(i)
WRITE(6, '(1x,2(a,i10))') 'Integer No. ',i,'=',icnst(i)
END DO
RETURN
END SUBROUTINE readint