c
c
c                MISCELLANEOUS SUBROUTINES (CHARACTER PROCESSING)
c
c                       Richard Carpenter, Univ. of Okla.
c
c                                  August 1991
c
c
c
c     SUBROUTINE  DESCRIPTION
c     ----------  -----------
c     Getnum1        : Convert a string of numbers into integers
c     Getposn        : Find the location of a string of numbers
c     Getdate        : Get the date and time (Cray)
c     Chardate        : Convert a numerical date obtained with Getdate into character
c     Chrdate2        : Convert a numerical date obtained with Getdate into character
c   F Fnblnk        : Location of first non-blank
c   F Lnblnk        : Location of last non-blank
c     Lwrc        : Convert a string to lowercase
c     Uprc        : Convert a string to uppercase
c   F Rindex        : Finds the right-most location of a string
c     Parse        : Find the words in a character string
c     Ljust        : Left-justify a character string
c     Pslab        : Print an array 
c     Chkexist        : See whether a file exists
c     Csqueeze        : Remove all blanks from a string
c     Csqueeze2        : Remove all consecutive blanks from a string
c
c
c
c
c
c                   ########################################
c                   ########################################
c                   ########################################
c                   ########                        ########
c                   ########        GETNUM1         ########
c                   ########                        ########
c                   ########################################
c                   ########################################
c                   ########################################
c
c
c

      Subroutine Getnum1 (name, ipos1, ipos2, number)
      Implicit None
      Integer ipos1, ipos2, number, iten, i
      Character*(*) name
c
c     Convert the  Name(Ipos1:Ipos2)  into  Number
c     Note that '0' is ASCII 48.
c
      number         = 0
      iten        = 1
      Do 1000        i=ipos2,ipos1,-1
      number        = number + ( Ichar (name(i:i)) - 48 ) * iten
      iten        = iten * 10
 1000 Continue
      End
c
c
c
c
c                    ########################################
c                    ########################################
c                    ########################################
c                    ########                        ########
c                    ########         GETPOSN        ########
c                    ########                        ########
c                    ########################################
c                    ########################################
c                    ########################################
c
c

      Subroutine Getposn (dumpfile, ipos1, ipos2)
      Implicit None
      Integer        ipos1, ipos2, jchar, i
      Character*(*) dumpfile
c
c     Find the location of the number of the file, Dumpfile(Ipos1:Ipos2)
c
c     Note that 'index' is an m4 command
c     Ipos2     = old Lendmpfl = length of filename and location of last char
c     Ipos1     = leading char of the digit of the filename (after the H or R)
c
      ipos2     = Index (dumpfile,' ') - 1
c      
      Do 100    i=ipos2-1,1,-1
c     jchar     = Ichar (dumpfile(i:i))
c     If (jchar.LT.48 .OR. jchar.GT.57) Go To 101
      If (dumpfile(i:i).LT.'0' .OR. dumpfile(i:i).GT.'9') Goto 101
 100  Continue
 101  Continue
      ipos1     = i + 1
c
      End
c
c
c
c
c                    ########################################
c                    ########################################
c                    ########################################
c                    ########                        ########
c                    ########         GETDATE        ########
c                    ########                        ########
c                    ########################################
c                    ########################################
c                    ########################################
c
c

      Subroutine Getdate (idate) 
      Implicit None
      Integer idate(7)
!      Character*9 char
      CHARACTER*10  datestr, timestr, zonestr
c     External Date, Clock
c
c     Get date and time from Cray
c
c     idate(1) : Day of the week
c     idate(2) : Day of the month
c     idate(3) : Month
c     idate(4) : Year
c     idate(5) : Hour
c     idate(6) : Minute
c     idate(7) : Second
c
!      Call Date (char)                ! returns date in the form "10/26/90"
!      Read (char, 9901) idate(3), idate(2), idate(4)
!      !Call Clock (char)                ! returns time in the form "10:26:00"
!      Call Time (char)                ! returns time in the form "10:26:00"
!      Read (char, 9901) idate(5), idate(6), idate(7)
!      idate(1)        = 0
!      idate(4)        = idate(4) + 1900
! 9901 Format (3(i2,1x))
!  
      idate(1) = 0
      CALL DATE_AND_TIME(datestr,timestr,zonestr)
      READ(datestr,9901) idate(4),idate(2),idate(3)
      READ(timestr,9902) idate(5),idate(6),idate(7)
 9901 FORMAT(i4,1x,2(i2,1x))
 9902 FORMAT(3(i2,1x))

      END
c
c
c
c
c                    ########################################
c                    ########################################
c                    ########################################
c                    ########                        ########
c                    ########        CHARDATE        ########
c                    ########                        ########
c                    ########################################
c                    ########################################
c                    ########################################
c
c

      Subroutine Chardate (idate, cdate) 
      Implicit None
      Integer idate(7), i, j, k
      Character*24 cdate, wkday, month*39
      Data wkday /'   SunMonTueWedThuFriSat'/, 
     >     month /'   JanFebMarAprMayJunJulAugSepOctNovDec'/
c
c     Convert integer date and time into character form.
c        Mon 29-Oct-1990 08:36:00
c        123456789012345678901234
c
      j                = 3 * idate(1)
      k                = 3 * idate(3)
      Write (cdate, 9901) wkday(j+1:j+3), idate(2), month(k+1:k+3), 
     >                           (idate(i),i=4,7)
 9901 Format (a3, i3.2, '-', a3, '-', i4, i3.2, ':', i2.2, ':', i2.2)
c
      End
c
c
c
c
c                    ########################################
c                    ########################################
c                    ########################################
c                    ########                            ########
c                    ########        CHRDATE2        ########
c                    ########                            ########
c                    ########################################
c                    ########################################
c                    ########################################
c
c

      Subroutine Chrdate2 (idate, cdate) 
      Implicit None
      Integer idate(7), i, j, k
      Character*(*) cdate
c
c     Convert integer date and time into character form.
c        10/29/90 08:36:00
c        123456789012345678901234
c
      j                = 3 * idate(1)
      k                = 3 * idate(3)
      Write(cdate, 9901)idate(3),idate(2),idate(4)-1900,(idate(i),i=5,7)
 9901 Format (i2.2,2('/',i2.2),1x, i2.2,2(':',i2.2))
c
      End
c
c
c
c
c                   ########################################
c                   ########################################
c                   ########################################
c                   ########                        ########
c                   ########         LNBLNK         ########
c                   ########                        ########
c                   ########################################
c                   ########################################
c                   ########################################
c
c

      Integer Function Lnblnk (string),4
      Implicit None
c
c     This routine is identical to the Alliant routine having the same name.
c     Returns 0 if strings is all blanks or uninitialized (all 0's).
c
      Character*(*) string
      Integer        i
c
      Lnblnk        = 0
      If (Ichar(string(1:1)).EQ.0) Return
c
      Do i=Len(string),1,-1
        If (string(i:i).NE.' ') Then
          Lnblnk    = i
          Return
        End If
      End Do
c
c
      End
c
c
c
c
c
c
c
c
c                   ########################################
c                   ########################################
c                   ########################################
c                   ########                        ########
c                   ########         FNBLNK         ########
c                   ########                        ########
c                   ########################################
c                   ########################################
c                   ########################################
c
c

      Integer Function Fnblnk (string)
      Implicit None
c
c     Finds the first non-blank character.
c     Returns 0 if strings is all blanks or uninitialized (all 0's).
c
      Character*(*) string
      Integer        i
c
      Fnblnk        = 0
      If (Ichar(string(1:1)).EQ.0) Return
c
      Do i=1,Len(string)
        If (string(i:i).NE.' ') Then
          Fnblnk    = i
          Return
        End If
      End Do
c
c
      End
c
c
c
c
c                   ########################################
c                   ########################################
c                   ########################################
c                   ########                        ########
c                   ########          LWRC          ########
c                   ########                        ########
c                   ########################################
c                   ########################################
c                   ########################################
c
c

      Subroutine Lwrc (line)
      Implicit None
c
c     Convert a string to lowercase.
c
      Character*(*) line
      Integer        i, ichr
c
      Do  i=1,Len(line)
      ichr        = Ichar (line(i:i))
      If (ichr.GE.65 .AND. ichr.LE.90)  line(i:i) = Char (ichr+32)
      End Do
      End
c
c
c
c
c                   ########################################
c                   ########################################
c                   ########################################
c                   ########                        ########
c                   ########          UPRC          ########
c                   ########                        ########
c                   ########################################
c                   ########################################
c                   ########################################
c
c

      Subroutine Uprc (line) 4
      Implicit None
c
c     Convert a string to uppercase.
c
      Character*(*) line
      Integer        i, ichr
c
      Do  i=1,Len(line)
      ichr        = Ichar (line(i:i))
      If (ichr.GE.97 .AND. ichr.LE.122)  line(i:i) = Char (ichr-32)
      End Do
      End
c
c
c
c
c                   ########################################
c                   ########################################
c                   ########################################
c                   ########                        ########
c                   ########         RINDEX         ########
c                   ########                        ########
c                   ########################################
c                   ########################################
c                   ########################################
c
c

      Integer Function IndexR (s1, s2)
      Implicit None
c
c     Note: Apparently RINDEX is the name of some mysterious AIX function.
c
c     This function works much like the Index function, except it finds the
c     _last_ occurance of string s2 within string s1. Returns 0 if substring
c     not found. 
c
      Character*(*) s1, s2
      Integer        j
c
      IndexR        = 0
c
      Do j=Len(s1),1,-1
      If (Index(s1(j:),s2) .NE. 0) Then
        IndexR        = j
        Return
      End If
      End Do
c
      End
c
c
c
c
c                   ########################################
c                   ########################################
c                   ########################################
c                   ########                        ########
c                   ########         PARSE          ########
c                   ########                        ########
c                   ########################################
c                   ########################################
c                   ########################################
c
c

      Subroutine Parse (strng, words, nwords, nwmax) 1,3
      Implicit None
      Integer nwords, nwmax, j, j0, nw, indx
      Character*(*) strng, words(nwmax)
      Character*256 string
c
c
c     strng        = Input string
c     words        = Returns an array of of left-justified words
c     nwords        = Number of words detected
c     nwmax        = Dimension of words.
c
c
c
      If (Len(strng).GT.Len(string)) Then
        Print '(a,i4,a)', '% Parse: only the first', Len(string), 
     >                    ' characters of input string will be checked.'
      End If
c
c  Store string in temp var, left-justify, squeeze out multiple blanks.
c
      string        = strng
      Call Ljust (string)
      Call Csqueeze2 (string)
c
c
c     indx        = first occurance of whitespace.
c
c
c
c     Print '(1x,2a)', 'Parse: string:<', string
      indx        = Index (string,' ')
      If (indx.EQ.0) Then        ! all one long word
        nwords        = 1
        words(nwords) = string
        Return
      End If
c
c     Print '(1x,2a)', 'Parse: string:<', string
c
c
c     Generate left-justified words.
c
c
c     j0        = First letter of next word
c
      j0        = 1
      Do nw=1,nwmax
      indx        = Index (string,' ')
      If (indx.LE.1) Then        !THIS DOESN'T ALLOW FOR MULTIPLE BLANKS
        nwords        = nw - 1
c       Print *, 'nwords = ', nwords
        Return
      End If
      words(nw)        = string(:indx-1)
c     Print *, 'Parse: nw,j0,indx-1,words(nw): ', nw,j0,indx-1,words(nw)
      If (indx.LE.1) Then
        nwords        = nw - 1
c       Print *, 'nwords = ', nwords
        Return
      End If
c
c
c     Get ready for next time through
c
      string        = string(indx+1:)
      Call Ljust (string)
      End Do

c
      nwords        = nw - 1
c
      End
c
c
c
c
c                   ########################################
c                   ########################################
c                   ########################################
c                   ########                        ########
c                   ########         LJUST          ########
c                   ########                        ########
c                   ########################################
c                   ########################################
c                   ########################################
c
c
c        This routine returns a left-justified string.  All whitespace up to
c        the first letter is removed.  If the string is blank, a null string
c        will be returned.  
c        Note: Tabs not handled properly yet.
c

      Subroutine Ljust (string) 2
      Implicit None
      Character*(*) string
      Integer        Fnblnk        
c
      string        = string(Max(1,Fnblnk(string)):)
c
      End
c
c
c
c
c                   ########################################
c                   ########################################
c                   ########################################
c                   ########                        ########
c                   ########       CHECKEXIST       ########
c                   ########                        ########
c                   ########################################
c                   ########################################
c                   ########################################
c
c

      Subroutine CheckExist (file)
      Implicit None
      Character*(*) file
      Logical   exist
c
      Inquire (File=file, exist=exist)
      If (.NOT. exist) Then
        Print *, '*** File does not exist: ', file
        Stop
      End If
      End
c
c
c
c
c                   ########################################
c                   ########################################
c                   ########################################
c                   ########                        ########
c                   ########        CHKEXIST        ########
c                   ########                        ########
c                   ########################################
c                   ########################################
c                   ########################################
c
c

      Subroutine Chkexist (file,string) 1
      Implicit None
      Character*(*) file
      Logical   exist
      Character*(*) string
c
      Inquire (File=file, exist=exist)
      If (.NOT. exist) Then
      Print *, string, 'File does not exist: ', file
      Stop
      End If
      End
c
c
c
c
c                   ########################################
c                   ########################################
c                   ########################################
c                   ########                        ########
c                   ########        CSQUEEZE        ########
c                   ########                        ########
c                   ########################################
c                   ########################################
c                   ########################################
c
c

      Subroutine Csqueeze (string)
      Implicit None
      Integer        i, Lnblnk
      Character*(*) string
c
c  Removes all blanks from a string
c
      i                = 1
c
      Do While (i.LT.Lnblnk(string))
      If (string(i:i).EQ.' ') Then
        string(i:) = string(i+1:)
      Else
        i        = i + 1
      End If
      End Do
c
c
      End
c
c
c
c
c                   ########################################
c                   ########################################
c                   ########################################
c                   ########                        ########
c                   ########        CSQUEEZE2       ########
c                   ########                        ########
c                   ########################################
c                   ########################################
c                   ########################################
c
c

      Subroutine Csqueeze2 (string) 1
      Implicit None
      Integer        i, Lnblnk
      Character*(*) string
c
c  Removes consequtive blanks from a string.
c
      i                = 1
c
      Do While (i.LT.Lnblnk(string))
      If (string(i:i+1).EQ.'  ') Then
        string(i:) = string(i+1:)
      Else
        i        = i + 1
      End If
      End Do
c
c
      End
c
c
c
c
c                   ########################################
c                   ########################################
c                   ########################################
c                   ########                        ########
c                   ########          PSLAB         ########
c                   ########                        ########
c                   ########################################
c                   ########################################
c                   ########################################
c
c        Print a 2-d array, or XZ slabs of a 3-d array, to an output file
c        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

      Subroutine Pslab (a,file,string,n132,
     >   nx1,nx2, ny1,ny2, nz1,nz2, i1,i2, j1,j2, k1,k2)
      Implicit None
c
c%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%-
c
c  INPUT:
c     a                = Array
c     file        = Output filename ('-' for output to screen)
c     string        = String written to output file
c     n132        = +-132 for 132-column output (12 or 10 cols of data);
c                  +-80 otherwise (7 or 6 cols of data);
c                  printed format is f10.5 if n132>=0; 1p,e12.4 otherwise.
c     nx1...nz2        = Upper & lower dimensions of A
c     i1...k2        = Portion of the array to print
c
c  OUTPUT: Formatted output is sent to file.
c
c  NOTES:
c     - To print a 2-d array, set k1=k2; a single XY slab will be printed.
c     - The parameter n132 controls both the width of the output (80/132)
c        as well as the format (f10.5 if n132>=0, 1p,e12.4 otherwise).
c     - 6 or 10 columns of data will be printed, depending on n132.
c
c%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%-
c
      Integer nx1,nx2,ny1,ny2,nz1,nz2,i1, i2, j1, j2, k1, k2, lu,
     >  i,j,k,n132,ncols,i3,i4,nformat
      Real a(nx1:nx2,ny1:ny2,nz1:nz2)
      Character*(*) file,string
c
c----------------------------------------------------------------------=
c
      If (file.EQ.'-' .OR. file.EQ.' ') Then
        Print *, '% Pslab: printing to screen'
        lu        = 6
      Else
        lu        = 11
        Print *, '% Pslab: ', file
        Open (Unit=lu, File=file, Status='Unknown')
      End If
      Write(lu,*) string
      Write(lu,9100) 'Array dimensions: (', nx1,nx2,ny1,ny2,nz1,nz2,file
      Write(lu,9100) 'Printed region:   (', i1, i2, j1, j2, k1, k2
 9100 Format (1x,a,2(i3,':',i3,','),i3,':',i3,')', :,'   File: ',a)
      Write(lu,*)
c
      nformat        = 10        !width of format field
      If (n132.LT.0) nformat = 12
      ncols        = 76/nformat
      If (Abs(n132).EQ.132) Then
      nformat        = 12
      ncols        = 128/nformat
      End If
c
c
c     XZ slabs of 3-d array
c
      If (k1.NE.k2) Then
      Do i3=i1,i2,ncols
      i4        = Min(i2,i3+ncols-1)
      Do j=j1,j2
      If (n132.GE.0) Then
        Write(lu,1000) 'j=', j, (i,i=i3,i4)
      Else
        Write(lu,1012) 'j=', j, (i,i=i3,i4)
      End If
      Do k=k2,k1,-1
      If (n132.GE.0) Then
        Write(lu,3000) k, (a(i,j,k),i=i3,i4)
      Else
        Write(lu,4000) k, (a(i,j,k),i=i3,i4)
      End If
      End Do
      Write(lu,*)
      End Do
      End Do
c
c
c     XY slab of 2-d array
c
      Else
      Do i3=i1,i2,ncols
      i4        = Min(i2,i3+ncols-1)
      Do k=k1,k2
      If (n132.GE.0) Then
        Write(lu,2000) (i,i=i3,i4)
      Else
        Write(lu,2012) (i,i=i3,i4)
      End If
      Do j=j2,j1,-1
      If (n132.GE.0) Then 
        Write(lu,3000) j, (a(i,j,k),i=i3,i4)
      Else
        Write(lu,4000) j, (a(i,j,k),i=i3,i4)
      End If
      End Do
      Write(lu,*)
      End Do
      End Do
      End If
c
      If (lu.NE.6) Close (lu)
 1000 Format (a,i3,i8,20i10)                !top row of integers: 3-d, 10x format
 1012 Format (a,i3,i8,20i12)                !top row of integers: 3-d, 12x format
 2000 Format (2x,20i10)                        !top row of integers: 2-d, 10x format
 2012 Format (2x,20i12)                        !top row of integers: 2-d, 12x format
 3000 Format (i3,2x,20f10.5)                !f10.5
 4000 Format (i3,2x,1p,20e12.4)                !e12.4
c
      Return
      End
c
c
c
c
c                   ########################################
c                   ########################################
c                   ########################################
c                   ########                        ########
c                   ########         PSLABF         ########
c                   ########                        ########
c                   ########################################
c                   ########################################
c                   ########################################
c
c        Print a 2-d array, or XZ slabs of a 3-d array, to an output file
c        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

      SUBROUTINE Pslabf (a,file,string,nwid,format,
     >   nx1,nx2, ny1,ny2, nz1,nz2, i1,i2, j1,j2, k1,k2)
      IMPLICIT NONE
c
c%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%-
c
c  INPUT:
c     a                = Array
c     file        = Output filename ('-' for output to screen)
c     string        = String written to output file
c     nwid        = max number of cols for output, usu 80 or 132.
c     format        = format string
c     nx1...nz2        = Upper & lower dimensions of A
c     i1...k2        = Portion of the array to print
c
c  OUTPUT: FORMATted output is sent to file.
c
c  NOTES:
c     - To print a 2-d array, set k1=k2; a single XY slab will be printed.
c     - The parameter n132 controls both the width of the output (80/132)
c        as well as the format (f10.5 if n132>=0, 1p,e12.4 otherwise).
c     - 6 or 10 columns of data will be printed, depending on n132.
c
c%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%-
c
      INTEGER nx1,nx2,ny1,ny2,nz1,nz2,i1, i2, j1, j2, k1, k2, lu,
     >  i,j,k,n132,ncols,j3,j4,i3,i4,nformat, Lnblnk, nwid, jf1,jf2
      REAL a(nx1:nx2,ny1:ny2,nz1:nz2)
      CHARACTER*(*) file,string,format, fmt*40, hfmt*40
c
c----------------------------------------------------------------------=
c
c
      IF (file.EQ.'-' .OR. file.EQ.' ') THEN
c       PRINT *, '% Pslabf: printing to screen'
        lu        = 6
      ELSE
        lu        = 11
        PRINT *, '% Pslabf: ', file
        OPEN (UNIT=lu, FILE=file, STATUS='UNKNOWN')
      END IF
      WRITE(lu,*) string
      WRITE(lu,9100) 'Array dimensions: (', nx1,nx2,ny1,ny2,nz1,nz2,file
      WRITE(lu,9100) 'Printed region:   (', i1, i2, j1, j2, k1, k2
 9100 FORMAT (1x,a,2(i3,':',i3,','),i3,':',i3,')', :,'   File: ',a)
      WRITE(lu,*)
c
c
c  The format MUST have the form  (F8.2), (E8.2), or (G8.2).  IF a G format,
c  then the 1P scale factor will be used.
c  
c
      IF (nwid.LE.0) nwid = 80
c
c     format        = '(F8.2)'
      jf1        = 3        !Index(format,',')
      jf2        = Index(format,'.') - 1
      jf2        = Min(jf2,jf1+1)
      IF (jf2-jf1.LT.0) THEN
        PRINT *, '% Pslabf: unable to parse format'
        PRINT *, '% Pslabf: ', jf1,jf2, format
      END IF
!     print *, 'reading from <', format(jf1:jf2), '> ', jf1, jf2
      IF (jf2.EQ.jf1) THEN
        READ (format(jf1:jf2), Fmt='(I1)') nformat
      ELSE
        READ (format(jf1:jf2), Fmt='(I2)') nformat
      END IF
      IF (nformat.LT.5 .AND. nformat.GT.18) THEN
        PRINT *, '% Pslabf: unable to parse format'
        PRINT *, '% Pslabf: ', nformat, format
        STOP
      END IF
c
      ncols        = (nwid-4)/nformat                ! number of cols of data
      fmt        = '(I3,2X,40' // format(:Lnblnk(format)) // ')'
      IF (Index(format,'G').GT.0)
     >  fmt        = '(I3,2X,1P,40' // format(:Lnblnk(format)) // ')'
      hfmt        = '(A,I3,40I' // format(jf1:jf2) // ')'
      IF (k1.EQ.k2)
     >hfmt        = '(2X,40I' // format(jf1:jf2) // ')'
      PRINT *, '% Pslabf: Fmt=  ', fmt
      PRINT *, '% Pslabf: Fmt=  ', hfmt
c
c
c     XZ slabs of 3-d array
c
      IF (k1.NE.k2) THEN
c
c...XZ slabs of 3-d array
c
      IF (j1.EQ.j2) THEN
      DO i3=i1,i2,ncols
      i4        = Min(i2,i3+ncols-1)
      DO j=j1,j2
        WRITE(lu,Fmt=hfmt) 'j=', j, (i,i=i3,i4)
      DO k=k2,k1,-1
        WRITE(lu,Fmt=fmt) k, (a(i,j,k),i=i3,i4)
      END DO
      WRITE(lu,*)
      END DO
      END DO
c
c
c...YZ slabs of 3-d array
c
      ELSE
      DO j3=j1,j2,ncols
      j4        = Min(j2,j3+ncols-1)
      DO i=i1,i2
        WRITE(lu,Fmt=hfmt) 'i=', i, (j,j=j3,j4)
      DO k=k2,k1,-1
        WRITE(lu,Fmt=fmt) k, (a(i,j,k),j=j3,j4)
      END DO
      WRITE(lu,*)
      END DO
      END DO
      END IF
c
c
c     XY slab of 2-d array
c
      ELSE
      DO i3=i1,i2,ncols
      i4        = Min(i2,i3+ncols-1)
      DO k=k1,k2
        WRITE(lu,Fmt=hfmt) (i,i=i3,i4)
      DO j=j2,j1,-1
        WRITE(lu,Fmt=fmt) j, (a(i,j,k),i=i3,i4)
      END DO
      WRITE(lu,*)
      END DO
      END DO
      END IF
c
      IF (lu.NE.6) CLOSE (lu)
c
c
      END
c
c
c
c
c                   ########################################
c                   ########################################
c                   ########################################
c                   ########                        ########
c                   ########        PARSENUM        ########
c                   ########                        ########
c                   ########################################
c                   ########################################
c                   ########################################
c
c

      Subroutine ParseNum (string, numtraj, ntraj),2
      Implicit None
      Character*(*) string
      Character*8 format
      Integer        ntraj,numtraj(ntraj)
      Integer        lnb,jj,kk,itraj,itraj1,itraj2,Lnblnk, ipunct,jpunct
c
c...Setup
c
      ntraj        = 0
      lnb        = Lnblnk(string)
      jj        = 1
c
c...Check for comma(44), dash(45)
c
 1000 Continue
c
      Call Punct (string,jj,jpunct,ipunct)
      kk        = jpunct - 1
c     print *, 'jj,kk,lnb:', jj,kk,lnb
c
      If (lnb.LT.kk) Return
c
c...Read single traj (n,) or first element of list (n-)
c
      Write (format,'(a,i1,a)') '(I', kk-jj+1, ')'
      Read (string(jj:kk),Fmt=format) itraj1
cprint *, itraj1
      ntraj        = ntraj + 1
      numtraj(ntraj) = itraj1
c
c
c...Parse to dash
c
      If (ipunct.EQ.45) Then
c     print *, 'dash'
        jj        = kk + 2
        Call Punct (string,jj,jpunct,ipunct)
        kk        = jpunct - 1
c     print *, 'jj,kk,lnb:', jj,kk,lnb
        Write (format,'(a,i1,a)') '(I', kk-jj+1, ')'
        Read (string(jj:kk),Fmt=format) itraj2
        Do itraj=itraj1+1,itraj2
c  print *, itraj
          ntraj        = ntraj + 1
          numtraj(ntraj) = itraj
        End Do
      End If
c
c
      jj        = kk + 2
      If (jj.LE.lnb) Go To 1000
c
      End
c
c
c
c
c                   ########################################
c                   ########################################
c                   ########################################
c                   ########                        ########
c                   ########          PUNCT         ########
c                   ########                        ########
c                   ########################################
c                   ########################################
c                   ########################################
c
c

      Subroutine Punct (string,j1,jpunct,ipunct) 2
      Implicit None
      Character*(*) string
      Character*1 TAB
      Integer        j1,jpunct,ipunct,jblank,jcomma,jdash,jdot,jtab,Lnblnk
c
c...Find the location of the next punctuation
c   This doesn't account for the last character being non-punctuation
c   (non-blank).
c
c  string        = string to be parsed (input)
c  j1                = index of first character to be scanned (input)
c  j2                = index of first punctuation (output)
c  ipunct        = ASCII code of punctuation (output)
c
c
      TAB        = Char(9)
      jpunct        = Len(string) + 1
c
      jblank        = Index (string(j1:),' ') + j1 - 1
      jcomma        = Index (string(j1:),',') + j1 - 1
      jdash        = Index (string(j1:),'-') + j1 - 1
      jdot        = Index (string(j1:),'.') + j1 - 1
      jtab        = Index (string(j1:),TAB) + j1 - 1
c
      If (jblank.LT.j1) jblank = 9999
      If (jcomma.LT.j1) jcomma = 9999
      If (jdash.LT.j1)        jdash = 9999
      If (jdot.LT.j1)        jdot = 9999
      If (jtab.LT.j1)        jtab = 9999
c
      jpunct        = Min(jblank,jpunct)
      jpunct        = Min(jcomma,jpunct)
      jpunct        = Min(jdash,jpunct)
      jpunct        = Min(jdot,jpunct)
      jpunct        = Min(jtab,jpunct)
c
      ipunct        = Ichar (string(jpunct:jpunct))
c
c     Print *, 'jpunct,ipunct: ', jpunct,ipunct
c
      End