C                                                            <HTML><PRE>
C Program SMEIGEN to read a symetric matrix SM1 and to compute general
C matrix GM1 of its eigenvectors and diagonal matrix DM1 of its
C eigenvalues.
C
C Version: 5.50
C Date: 2001, May 29
C
C Coded by Petr Bulant
C     Department of Geophysics, Charles University Prague,
C     Ke Karlovu 3, 121 16 Praha 2, Czech Republic,
C     E-mail: bulant@seis.karlov.mff.cuni.cz
C
C.......................................................................
C                                                    <A NAME="data"></A>
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                                                     <A NAME="SEP"></A>
C Input data file 'SEP':
C     File 'SEP' has the form of the <A HREF="../forms/sep.htm">SEP</A>
C     parameter file.  The parameters, which do not differ from their
C     defaults, need not be specified in file 'SEP'.
C Data specifying dimensions of the matrices:
C     M1='string'... Name of the file containing a single integer number
C             specifying the number of rows (and columns) of
C             matrices SM1, GM1, and DM1.
C             Default: M1=' ' means that the number is 1.
C Filenames of the files with the matrices:
C     SM1='string' ... Name of the file containing the input matrix.
C             No default, 'SM1' must be specified and cannot be blank.
C     GM1='string' ... Name of the file containing general
C             matrix of eigenvectors of matrix SM1 (output).
C             Default: GM1=' ' (the matrix is not written).
C     DM1='string' ... Name of the file containing diagonal
C             matrix of eigenvalues of matrix SM1 (output).
C             Default: DM1=' ' (the matrix is not written).
C     If both GM1 and DM1 equal ' ', the program is stopped.
C     For general description of the files with matrices refer to file
C     <A HREF="../forms/forms.htm#MAT">forms.htm</A>.
C Form of the files with matrices:
C     FORMM='string' ... Form of the files with matrices. Allowed values
C             are FORMM='formatted' and FORMM='unformatted'. If the form
C             differs for input and for output files, FORMMR and FORMMW
C             should be used instead of FORMM.
C             Default: FORMM='formatted'
C     FORMMR='string' ... Form of the files with matrices to be read.
C             Default: FORMMR=FORMM
C     FORMMW='string' ... Form of the files with matrices to be written.
C             Default: FORMMW=FORMM
C
C-----------------------------------------------------------------------
C Subroutines and external functions required:
      EXTERNAL SMEIG,SMBLO,EIGEN,ERROR,RSEP1,RSEP3T,RMAT,WMAT
C     SMEIG,SMBLO ... This file.
C     EIGEN ... File <A HREF="../forms/eigennr.for">eigennr.for</A>.
C     ERROR ... File <A HREF="../forms/error.for">error.for</A>.
C     RSEP1,RSEP3T ... File <A HREF="../forms/sep.for">sep.for</A>.
C     RMAT,WMAT ... File <A HREF="../forms/forms.for">forms.for</A>.
C
C Common block /RAMC/:
      INCLUDE 'ram.inc'
C     <A HREF="ram.inc">ram.inc</A>
      INTEGER IRAM(MRAM)
      EQUIVALENCE (IRAM,RAM)
C
      EXTERNAL IND,INDG
      INTEGER IND,INDG
C
      CHARACTER*80 FILSEP,FILE1,FILE2,FILE3
      INTEGER M1,N,NN,NB,LU1,I1,I2,I3,I4,IBMI,IBMA,J2,J3
      PARAMETER (LU1=1)
C
C-----------------------------------------------------------------------
C
C     Reading the name of the file with the input data:
      WRITE(*,'(A)') '+SMEIGEN: Enter input filename: '
      FILSEP=' '
      READ(*,*) FILSEP
C
C     Reading all the data from the SEP file into the memory:
      IF (FILSEP.NE.' ') THEN
        CALL RSEP1(LU1,FILSEP)
      ELSE
C       <A NAME="error01"></A><FONT COLOR="RED">SMEIGEN-01</FONT>
        CALL ERROR('SMEIGEN-01: SEP file not given')
      ENDIF
C
C     Reading the dimension of the matrices:
      CALL RSEP3T('M1',FILE1,' ')
      IF (FILE1.EQ.' ') THEN
        M1=1
      ELSE
        OPEN(LU1,FILE=FILE1,STATUS='OLD')
        READ(LU1,*) M1
        CLOSE(LU1)
      ENDIF
      N=M1
      NN=M1*(M1+1)/2
      MAXRAM=MRAM-2*N
      IF (2*NN+2*N*N+N+N+1+N+N.GT.MRAM) THEN
C       <A NAME="error02"></A><FONT COLOR="RED">SMEIGEN-02</FONT>
        CALL ERROR('SMEIGEN-02: Small dimension MRAM of array RAM')
C       If possible, enlarge the dimension MRAM of array RAM in include
C       file <A HREF="ram.inc">ram.inc</A>.
      END IF
C
C     Reading the names of the files with the matrices:
      CALL RSEP3T('SM1',FILE1,' ')
      CALL RSEP3T('GM1',FILE2,' ')
      CALL RSEP3T('DM1',FILE3,' ')
      IF (FILE1.EQ.' ') THEN
C       <A NAME="error03"></A><FONT COLOR="RED">SMEIGEN-03</FONT>
        CALL ERROR('SMEIGEN-03: Input file with matrix SM1 not given')
      ENDIF
      IF ((FILE2.EQ.' ').AND.(FILE3.EQ.' ')) THEN
C       <A NAME="error04"></A><FONT COLOR="RED">SMEIGEN-04</FONT>
        CALL
     *  ERROR('SMEIGEN-04: None of the output files GM1 or DM1 given')
      ENDIF
C
C     Reading input matrix:
      CALL RMAT(LU1,FILE1,M1,0,RAM(MAXRAM-NN+1))
C
      WRITE(*,'(A)') '+SMEIGEN: Working...            '
C
C     Identification of blocks:
      CALL SMBLO(RAM(MAXRAM-NN+1),N,NN,NB,IRAM(MAXRAM-NN-N))
C
C     Preparing array for results:
      DO 5, I1=MAXRAM-NN-N-1-N*N-N+1,MAXRAM-NN-N-1
        RAM(I1)=0.
   5  CONTINUE
C
C     Computing the eigenvalues and the eigenvectors:
      DO 20, I1=1,NB
C       Current block:
        IBMI=IRAM(MAXRAM-NN-N+I1-1)+1
        IBMA=IRAM(MAXRAM-NN-N+I1)
C       Moving the block to RAM(1):
        I4=0
        DO 10, I2=IBMI,IBMA
          DO 8, I3=IBMI,I2
            I4=I4+1
            RAM(I4)=RAM(MAXRAM-NN+IND(I3,I2))
   8      CONTINUE
  10    CONTINUE
        J2=IBMA-IBMI+1
        J3=I2*(I2+1)/2
C       Computing the eigenvalues and the eigenvectors:
        CALL SMEIG(RAM,J2,J3)
C       Moving the eigenvectors to RAM(MAXRAM-NN-N-1-N*N+1):
        I4=0
        DO 14, I2=IBMI,IBMA
          DO 12, I3=IBMI,IBMA
            I4=I4+1
            RAM(MAXRAM-NN-N-1-N*N+INDG(I3,I2,N))=RAM(J3+I4)
  12      CONTINUE
  14    CONTINUE
C       Moving the eigenvalues to RAM(MAXRAM-NN-N-1-N*N-N+1):
        DO 16, I4=1,J2
          RAM(MAXRAM-NN-N-1-N*N-N+IBMI-1+I4)=RAM(J3+J2*J2+I4)
  16    CONTINUE
  20  CONTINUE
C
C     Writing output matrix GM1:
      IF (FILE2.NE.' ') THEN
        CALL WMAT(LU1,FILE2,M1,M1,RAM(MAXRAM-NN-N-1-N*N+1))
      ENDIF
C     Writing output matrix DM1:
      IF (FILE3.NE.' ') THEN
        CALL WMAT(LU1,FILE3,M1,1,RAM(MAXRAM-NN-N-1-N*N-N+1))
      ENDIF
      WRITE(*,'(A)') '+SMEIGEN: Done.                 '
C
      STOP
      END
C
C=======================================================================
C
      SUBROUTINE SMEIG(SM,N,NN)
C
C=======================================================================
C     Computes the eigenvectors and eigenvalues of symmetric matrix SM.
      INTEGER N,NN
      REAL SM(NN+N*N+N)
C     Input: SM ... input symmetric matrix
C            N  ... number of rows (and columns) of the matrix
C            NN ... N*(N+1)/2
C     Output: SM(NN+1) ... eigenvectors of the input matrix
C             SM(NN+N*N+1) ... eigenvalues of the input matrix
      INTEGER I
C-----------------------------------------------------------------------
      CALL EIGEN(SM,SM(NN+1),N,0)
      DO 21 I=1,N
        SM(NN+N*N+I)=SM(I*(I+1)/2)
   21 CONTINUE
      RETURN
      END
C
C=======================================================================
C
      SUBROUTINE SMBLO(SM,N,NN,NB,IB)
C
C=======================================================================
C     Subroutine to find blocks of a symmetric matrix
      INTEGER N,NN,NB,IB(0:N)
      REAL SM(NN)
C     Input: SM ... symmetric matrix
C            N  ... number of rows (and columns) of the matrix
C            NN ... N*(N+1)/2
C     Output: NB ... number of blocks of the matrix
C             IB ... array with numbers of lines (and rows), at which
C                    the blocks finish
      INTEGER I1,I2
      EXTERNAL IND
      INTEGER IND
C-----------------------------------------------------------------------
C     Initiating first block:
      NB=1
      IB(0)=0
      IB(1)=1
      I1=0
  10  CONTINUE
C       Loop for lines of the matrix:
        I1=I1+1
        DO 20, I2=N,IB(NB)+1,-1
C         Loop for rows of the line I1:
          IF (SM(IND(I1,I2)).NE.0.) THEN
C           The block is larger:
            IB(NB)=I2
            GOTO 21
          ENDIF
  20    CONTINUE
  21    CONTINUE
        IF (IB(NB).EQ.N) THEN
C         End of the search for blocks.
          RETURN
        ENDIF
        IF (IB(NB).EQ.I1) THEN
C         Block finished, continuing with the next block.
          NB=NB+1
          IB(NB)=I1+1
        ENDIF
      GOTO 10
      END
C=======================================================================
      INTEGER FUNCTION IND(I,J)
      INTEGER I,J
C     I ... Index of a line.
C     J ... Index of a row.
      IND=J*(J-1)/2+I
      RETURN
      END
C=======================================================================
      INTEGER FUNCTION INDG(I,J,K)
      INTEGER I,J,K
C     I ... Index of a line.
C     J ... Index of a row.
C     K ... Number of lines.
      INDG=K*(J-1)+I
      RETURN
      END
C
C=======================================================================
C
      INCLUDE 'forms.for'
C     <A HREF="../forms/forms.for">forms.for</A>
      INCLUDE 'error.for'
C     <A HREF="../forms/error.for">error.for</A>
      INCLUDE 'length.for'
C     <A HREF="../forms/length.for">length.for</A>
      INCLUDE 'sep.for'
C     <A HREF="../forms/sep.for">sep.for</A>
      INCLUDE 'eigennr.for'
C     <A HREF="../forms/eigennr.for">eigennr.for</A>
      INCLUDE 'indexx.for'
C     <A HREF="../nr/indexx.for">indexx.for</A>
      INCLUDE 'tred2.for'
C     <A HREF="../nr/tred2.for">tred2.for</A>
      INCLUDE 'tqli.for'
C     <A HREF="../nr/tqli.for">tqli.for</A>
      INCLUDE 'pythag.for'
C     <A HREF="../nr/pythag.for">pythag.for</A>
C
C=======================================================================
C                                                                 </PRE>
