C
C Program GRDFD to calculate gradient of the grid values by means of the
C the second-order finite differences
C
C Version: 5.20
C Date: 1998, November 6
C
C Coded by: Ludek Klimes
C     Department of Geophysics, Charles University Prague,
C     Ke Karlovu 3, 121 16 Praha 2, Czech Republic,
C     E-mail: klimes@seis.karlov.mff.cuni.cz
C
C.......................................................................
C
C                                                    
C Description of the data files:
C
C The data are read in by the list directed input (free format).
C In the description of data files, each numbered paragraph indicates
C the beginning of a new input operation (new READ statement).
C If the symbolic name of the input variable is enclosed in apostrophes,
C the corresponding value in input data is of the type CHARACTER, i.e.
C it should be a character string enclosed in apostrophes.  If the first
C letter of the symbolic name is I-N, the corresponding value is of the
C type INTEGER.  Otherwise, the input parameter is of the type REAL and
C may or may not contain a decimal point.
C
C Input data read from the * external unit:
C     The interactive * external unit may also be redirected to the file
C     containing the relevant data.
C (1) 'SEP','GRD','GRD1','GRD2','GRD3',/
C     'SEP'...String in apostrophes containing the name of the input
C             file with the data specifying dimensions of the input
C             grid.
C     'GRD'...String in apostrophes containing the name of the input
C             ASCII files with the grid values.
C     'GRD1','GRD2','GRD3',... Strings in apostrophes containing the
C             names of the output ASCII files containing the first
C             partial derivatives in the respective directions.
C             Derivatives corresponding to a blank filename are not
C             evaluated.
C     /...    Input data line must be terminated by a slash.
C     Default: 'SEP'='grd.h', 'GRD'='grd.out', 'GRD1'=' ',
C             'GRD2'=' ', 'GRD3'=' '.
C
C                                                     
C Data file SEP has the form of the SEP (Stanford Exploration Project)
C parameter file:
C     All the data are specified in the form of PARAMETER=VALUE, e.g.
C     N1=50, with PARAMETER directly preceding = without intervening
C     spaces and with VALUE directly following = without intervening
C     spaces.  The PARAMETER=VALUE couple must be delimited by a space
C     or comma from both sides.
C     The PARAMETER string is not case-sensitive.
C     PARAMETER= followed by a space resets the default parameter value.
C     All other text in the input files is ignored.  The file thus may
C     contain unused data or comments without leading comment character.
C     Everything between comment character # and the end of the
C     respective line is ignored, too.
C     The PARAMETER=VALUE couples may be specified in any order.
C     The last appearance takes precedence.
C Data specifying grid dimensions:
C     N1=positive integer... Number of gridpoints along the X1 axis.
C             Default: N1=1
C     N2=positive integer... Number of gridpoints along the X2 axis.
C             Default: N2=1
C     N3=positive integer... Number of gridpoints along the X3 axis.
C             Default: N3=1
C     N4=positive integer... Number of time slices.
C             Default: N4=1
C     D1=real... Grid interval in the direction of the first coordinate
C             axis.
C             Default: D1=1.
C     D2=real... Grid interval in the direction of the second coordinate
C             axis.
C             Default: D2=1.
C     D3=real... Grid interval in the direction of the third coordinate
C             axis.
C             Default: D3=1.
C Data specific to this program:
C     NORDER=even positive integer... Order of finite diference scheme.
C             Only NORDER=2 is now coded.
C             Default: NORDER=2
C     NHALF=integer... Kind of finite diference scheme:
C             NHALF=0: Ordinary centred 1-D scheme.  Output grids have
C                      the same dimensions as the input grid.
C                      Differences at boundaries and in the vicinity of
C                      undefined values are approximated by single-sided
C                      differences.
C                      Error of derivative F1 for NORDER=2:
C                        Err(F1)=4*F111*D1**2/24
C             NHALF=1: Half-interval 1-D scheme.  Output grids have
C                      dimensions: 'GRD1': (N1-1)*N2*N3
C                                  'GRD2': N1*(N2-1)*N3
C                                  'GRD3': N1*N2*(N3-1)
C                      Error of derivative F1 for NORDER=2:
C                        Err(F1)=  F111*D1**2/24
C             NHALF=2: Averaged half-interval 1-D schemes.  Output grids
C                      have dimensions (N1-1)*(N2-1)*(N3-1) gridpoints
C                      if N1, N2 and N3 are greater than 1.
C                      Naturally, any dimension Ni=1 is not changed.
C                      Error of derivative F1 for NORDER=2:
C                        Err(F1)=(F111*D1**2+F122*D2**2+F122*D2**2)/24
C             Default: NHALF=0
C
C=======================================================================
C
C Common block /RAMC/:
      INCLUDE 'ram.inc'
C     ram.inc
C
C.......................................................................
C
C     Filenames and parameters:
      CHARACTER*80 FILE1,FILE2,FILE3,FILE4,FILE5
      INTEGER LU1,LU2,LU3,LU4
      REAL UNDEF
      PARAMETER (LU1=1,LU2=2,LU3=3,LU4=4,UNDEF=-999999.)
C     Input data:
      INTEGER N1,N2,N3,N4
      REAL D1,D2,D3
C     Other variables:
      INTEGER N12,N123,N1234,I1,I2,I3,I4,I
      REAL D,DD,F1,F2,F3
C
C.......................................................................
C
C     Reading main input data:
      FILE1='grd.h'
      FILE2='grd.out'
      FILE3=' '
      FILE4=' '
      FILE5=' '
      WRITE(*,'(2A)') '+GRDFD: Enter 5 filenames ',
     *                     '[''grd.h'',''grd.out'','' '','' '','' '']: '
      READ(*,*) FILE1,FILE2,FILE3,FILE4,FILE5
      WRITE(*,'(A)')
     *  '+GRDFD: Reading, calculating, writing...                      '
C
C     Reading grid dimensions:
C     Original grid:
      CALL RSEP1(LU1,FILE1)
      CALL RSEP3I('N1',N1,1)
      CALL RSEP3I('N2',N2,1)
      CALL RSEP3I('N3',N3,1)
      CALL RSEP3I('N4',N4,1)
      CALL RSEP3R('D1',D1,1.)
      CALL RSEP3R('D2',D2,1.)
      CALL RSEP3R('D3',D3,1.)
      N12  =N1*N2
      N123 =N1*N2*N3
C4    N1234=N1*N2*N3*N4
      N1234=N1*N2*N3
      IF(2*N1234.GT.MRAM) THEN
C       GRDFD-01
        CALL ERROR('GRDFD-01: Too small array RAM(MRAM)')
C       Too small array RAM(MRAM) to allocate both input and output
C       grid values.  If possible, increase dimension MRAM in include
C       file ram.inc.
      END IF
C
C     Reading parameters of FD scheme:
      CALL RSEP3I('NORDER',NORDER,2)
      IF(NORDER.EQ.2) THEN
        CONTINUE
      ELSE
C       GRDFD-02
        CALL ERROR('GRDFD-02: Incorrect value of NORDER')
C       Allowed values of input parameter NORDER: 2.
C       See the description of input data SEP.
      END IF
      CALL RSEP3I('NHALF',NHALF,0)
      IF(NHALF.EQ.0) THEN
        CONTINUE
ccc   ELSE IF(NHALF.EQ.1) THEN
ccc     CONTINUE
ccc   ELSE IF(NHALF.EQ.2) THEN
ccc     CONTINUE
      ELSE
C       GRDFD-03
        CALL ERROR('GRDFD-03: Incorrect value of NHALF')
C       Allowed values of input parameter NHALF: 0.
C       See the description of input data SEP.
      END IF
C
C     Reading input grid values:
      OPEN(LU1,FILE=FILE2,FORM='FORMATTED',STATUS='OLD')
      IF(FILE3.NE.' ') THEN
        OPEN(LU2,FILE=FILE3,FORM='FORMATTED')
      END IF
      IF(FILE4.NE.' ') THEN
        OPEN(LU3,FILE=FILE4,FORM='FORMATTED')
      END IF
      IF(FILE5.NE.' ') THEN
        OPEN(LU4,FILE=FILE5,FORM='FORMATTED')
      END IF
C
C     Loop over time levels:
      DO 34 I4=0,N4-1
        CALL RARRAY(LU1,' ','FORMATTED',.TRUE.,UNDEF,N1234,RAM)
C
C       Calculating X1 derivatives:
        IF(FILE3.NE.' ') THEN
          IF(N1.LE.1) THEN
C           GRDFD-04
            CALL ERROR('GRDFD-04: N1 is less than 2')
          END IF
          D=D1
          DD=2.*D
          I=0
          J=N1234
          DO 13 I3=1,N3
            DO 12 I2=1,N2
              I=I+1
              J=J+1
              F2=RAM(I)
              F3=RAM(I+1)
              IF(F2.NE.UNDEF.AND.F3.NE.UNDEF) THEN
                RAM(J)=(F3-F2)/D
              ELSE
                RAM(J)=UNDEF
              END IF
              DO 11 I1=2,N1-1
                I=I+1
                J=J+1
                F1=F2
                F2=F3
                F3=RAM(I+1)
                IF(F1.NE.UNDEF.AND.F3.NE.UNDEF) THEN
                  RAM(J)=(F3-F1)/DD
                ELSE IF(F1.NE.UNDEF.AND.F2.NE.UNDEF) THEN
                  RAM(J)=(F2-F1)/D
                ELSE IF(F2.NE.UNDEF.AND.F3.NE.UNDEF) THEN
                  RAM(J)=(F3-F2)/D
                ELSE
                  RAM(J)=UNDEF
                END IF
   11         CONTINUE
              I=I+1
              J=J+1
              IF(F2.NE.UNDEF.AND.F3.NE.UNDEF) THEN
                RAM(J)=(F3-F2)/D
              ELSE
                RAM(J)=UNDEF
              END IF
   12       CONTINUE
   13     CONTINUE
C         Writing output grid values:
          CALL WARRAY(LU2,' ','FORMATTED',.TRUE.,UNDEF,.FALSE.,0.,
     *                                               N1234,RAM(N1234+1))
        END IF
C
C       Calculating X2 derivatives:
        IF(FILE4.NE.' ') THEN
          IF(N2.LE.1) THEN
C           GRDFD-05
            CALL ERROR('GRDFD-05: N2 is less than 2')
          END IF
          D=D2
          DD=2.*D
          DO 23 I3=0,N3-1
            DO 22 I1=1,N1
              I=I3*N12+I1
              J=N1234+I
              F2=RAM(I)
              F3=RAM(I+N1)
              IF(F2.NE.UNDEF.AND.F3.NE.UNDEF) THEN
                RAM(J)=(F3-F2)/D
              ELSE
                RAM(J)=UNDEF
              END IF
              DO 21 I2=1,N2-2
                I=I+N1
                J=J+N1
                F1=F2
                F2=F3
                F3=RAM(I+N1)
                IF(F1.NE.UNDEF.AND.F3.NE.UNDEF) THEN
                  RAM(J)=(F3-F1)/DD
                ELSE IF(F1.NE.UNDEF.AND.F2.NE.UNDEF) THEN
                  RAM(J)=(F2-F1)/D
                ELSE IF(F2.NE.UNDEF.AND.F3.NE.UNDEF) THEN
                  RAM(J)=(F3-F2)/D
                ELSE
                  RAM(J)=UNDEF
                END IF
   21         CONTINUE
              I=I+N1
              J=J+N1
              IF(F2.NE.UNDEF.AND.F3.NE.UNDEF) THEN
                RAM(J)=(F3-F2)/D
              ELSE
                RAM(J)=UNDEF
              END IF
   22       CONTINUE
   23     CONTINUE
C         Writing output grid values:
          CALL WARRAY(LU3,' ','FORMATTED',.TRUE.,UNDEF,.FALSE.,0.,
     *                                               N1234,RAM(N1234+1))
        END IF
C
C       Calculating X3 derivatives:
        IF(FILE5.NE.' ') THEN
          IF(N3.LE.1) THEN
C           GRDFD-06
            CALL ERROR('GRDFD-06: N3 is less than 2')
          END IF
          D=D3
          DD=2.*D
          DO 33 I2=0,N2-1
            DO 32 I1=1,N1
              I=I2*N1+I1
              J=N1234+I
              F2=RAM(I)
              F3=RAM(I+N12)
              IF(F2.NE.UNDEF.AND.F3.NE.UNDEF) THEN
                RAM(J)=(F3-F2)/D
              ELSE
                RAM(J)=UNDEF
              END IF
              DO 31 I3=1,N3-2
                I=I+N12
                J=J+N12
                F1=F2
                F2=F3
                F3=RAM(I+N12)
                IF(F1.NE.UNDEF.AND.F3.NE.UNDEF) THEN
                  RAM(J)=(F3-F1)/DD
                ELSE IF(F1.NE.UNDEF.AND.F2.NE.UNDEF) THEN
                  RAM(J)=(F2-F1)/D
                ELSE IF(F2.NE.UNDEF.AND.F3.NE.UNDEF) THEN
                  RAM(J)=(F3-F2)/D
                ELSE
                  RAM(J)=UNDEF
                END IF
   31         CONTINUE
              I=I+N12
              J=J+N12
              IF(F2.NE.UNDEF.AND.F3.NE.UNDEF) THEN
                RAM(J)=(F3-F2)/D
              ELSE
                RAM(J)=UNDEF
              END IF
   32       CONTINUE
   33     CONTINUE
C         Writing output grid values:
          CALL WARRAY(LU4,' ','FORMATTED',.TRUE.,UNDEF,.FALSE.,0.,
     *                                               N1234,RAM(N1234+1))
        END IF
C
   34 CONTINUE
      CLOSE(LU1)
      IF(FILE3.NE.' ') THEN
        CLOSE(LU2)
      END IF
      IF(FILE4.NE.' ') THEN
        CLOSE(LU3)
      END IF
      IF(FILE5.NE.' ') THEN
        CLOSE(LU4)
      END IF
      WRITE(*,'(A)')
     *  '+GRDFD: Done.                                                 '
      STOP
      END
C
C=======================================================================
C
      INCLUDE 'error.for'
C     length.for
      INCLUDE 'sep.for'
C     sep.for
      INCLUDE 'forms.for'
C     forms.for
      INCLUDE 'length.for'
C     length.for
C
C=======================================================================
C