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