C
C Program GRDFD to calculate gradient of the grid values by means of the
C second-order finite differences
C
C Version: 5.40
C Date: 2000, January 22
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 Description of data files:
C
C Input data read from the standard input device (*):
C     The data are read by the list directed input (free format) and
C     consist of a single string 'SEP':
C     'SEP'...String in apostrophes containing the name of the input
C             SEP parameter or history file with the input data.
C     No default, 'SEP' must be specified and cannot be blank.
C
C                                                     
C Input data file 'SEP':
C     File 'SEP' has the form of the SEP
C     parameter file.  The parameters, which do not differ from their
C     defaults, need not be specified in file 'SEP'.
C Names of the input and output files:
C     GRD='string'...Name of the input ASCII file with the grid values.
C             Default: GRD='grd.out'
C     GRD1='string', GRD2='string', GRD3='string'... The names
C             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             Default: GRD1=' ', GRD2=' ', GRD3=' '
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 difference scheme.
C             Only NORDER=2 is now coded.
C             Default: NORDER=2
C     NHALF=integer... Kind of finite difference 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 name of SEP file with input data:
      WRITE(*,'(A)') '+GRDFD: Enter input filename: '
      FILE1=' '
      READ(*,*) FILE1
      WRITE(*,'(A)') '+GRDFD: Working ...           '
C
C     Reading all data from the SEP file into the memory:
      IF (FILE1.NE.' ') THEN
        CALL RSEP1(LU1,FILE1)
      ELSE
C       GRDFD-07
        CALL ERROR('GRDFD-07: SEP file not given')
C       Input file in the form of the SEP (Stanford Exploration Project)
C       parameter or history file must be specified.
C       There is no default filename.
      ENDIF
C
C     Reading input parameters from the SEP file:
      CALL RSEP3T('GRD',FILE2,'grd.out')
      CALL RSEP3T('GRD1',FILE3,' ')
      CALL RSEP3T('GRD2',FILE4,' ')
      CALL RSEP3T('GRD3',FILE5,' ')
C
C     Reading grid dimensions:
C     Original grid:
      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