*     F02FJF Example Program Text
*     Mark 20 Revised. NAG Copyright 2001.
*     .. Parameters ..
      INTEGER          NMAX, LA, LRWORK, KMAX, LWORK, LIWORK, NRX
      PARAMETER        (NMAX=16,LA=10*NMAX,LRWORK=1,KMAX=6,
     +                 LWORK=5*KMAX+2*NMAX,LIWORK=2*LA+7*NMAX+1,
     +                 NRX=NMAX)
      INTEGER          NIN, NOUT
      PARAMETER        (NIN=5,NOUT=6)
*     .. Scalars in Common ..
      INTEGER          NNZ
*     .. Arrays in Common ..
      DOUBLE PRECISION A(LA)
      INTEGER          ICOL(LA), IPIV(NMAX), IROW(LA), ISTR(NMAX+1)
*     .. Local Scalars ..
      DOUBLE PRECISION DSCALE, DTOL, TOL
      INTEGER          I, IFAIL, J, K, L, LFILL, M, N, NNZC, NOITS,
     +                 NOVECS, NPIVM
      CHARACTER        MIC, PSTRAT
*     .. Local Arrays ..
      DOUBLE PRECISION D(NMAX), RWORK(LRWORK), WORK(LWORK), X(NRX,KMAX)
      INTEGER          IWORK(LIWORK)
*     .. External Functions ..
      DOUBLE PRECISION DOT
      EXTERNAL         DOT
*     .. External Subroutines ..
      EXTERNAL         F02FJF, F02FJZ, F11JAF, IMAGE
*     .. Common blocks ..
      COMMON           /BLOCK1/A, IROW, ICOL, IPIV, ISTR, NNZ
*     .. Executable Statements ..
      WRITE (NOUT,*) 'F02FJF Example Program Results'
*     Skip heading in data file
      READ (NIN,*)
      READ (NIN,*) N, M, K, TOL
      WRITE (NOUT,*)
      IF (N.LT.5 .OR. N.GT.16) THEN
         WRITE (NOUT,99999) 'N is out of range.  N =', N
      ELSE IF (M.LT.1 .OR. M.GE.K .OR. K.GT.KMAX) THEN
         WRITE (NOUT,99999) 'M or K out of range.  M =', M, '   K =', K
      ELSE
*
*        Set up the sparse symmetric coefficient matrix A.
*
         L = 0
         DO 20 I = 1, N
            IF (I.GE.5) THEN
               L = L + 1
               A(L) = -0.25D0
               IROW(L) = I
               ICOL(L) = I - 4
            END IF
            IF (I.GE.2) THEN
               L = L + 1
               A(L) = -0.25D0
               IROW(L) = I
               ICOL(L) = I - 1
            END IF
            L = L + 1
            A(L) = 1.0D0
            IROW(L) = I
            ICOL(L) = I
   20    CONTINUE
         NNZ = L
*
*        Call F11JAF to find an incomplete Cholesky factorisation of A.
*
         LFILL = 2
         DTOL = 0.0D0
         MIC = 'M'
         DSCALE = 0.0D0
         PSTRAT = 'M'
         IFAIL = 1
*
         CALL F11JAF(N,NNZ,A,LA,IROW,ICOL,LFILL,DTOL,MIC,DSCALE,PSTRAT,
     +               IPIV,ISTR,NNZC,NPIVM,IWORK,LIWORK,IFAIL)
*
         IF (IFAIL.NE.0) THEN
            WRITE (NOUT,99999) 'F11JAF fails. IFAIL =', IFAIL
         ELSE
*
*           Call F02FJF to find eigenvalues and eigenvectors.
            IFAIL = 1
*           * To obtain monitoring information from the supplied
*           subroutine MONIT, replace the name F02FJZ by MONIT in
*           the next statement, and declare MONIT as external *
*
            NOITS = 1000
            NOVECS = 0
*
            CALL F02FJF(N,M,K,NOITS,TOL,DOT,IMAGE,F02FJZ,NOVECS,X,NRX,D,
     +                  WORK,LWORK,RWORK,LRWORK,IWORK,LIWORK,IFAIL)
*
            IF (IFAIL.NE.0) THEN
               WRITE (NOUT,99999) 'Warning - F02FJF returns IFAIL =',
     +           IFAIL
            END IF
            IF (IFAIL.GE.0 .AND. IFAIL.NE.1 .AND. IFAIL.LE.4 .AND. M.GE.
     +          1) THEN
               DO 40 I = 1, M
                  D(I) = 1.0D0/D(I)
   40          CONTINUE
               WRITE (NOUT,*) 'Final results'
               WRITE (NOUT,*)
               WRITE (NOUT,*) '  Eigenvalues'
               WRITE (NOUT,99998) (D(I),I=1,M)
               WRITE (NOUT,*)
               WRITE (NOUT,*) '  Eigenvectors'
               WRITE (NOUT,99998) ((X(I,J),J=1,M),I=1,N)
            END IF
         END IF
      END IF
      STOP
*
99999 FORMAT (1X,A,I5,A,I5)
99998 FORMAT (1X,1P,4D12.3)
      END
*
      DOUBLE PRECISION FUNCTION DOT(IFLAG,N,Z,W,RWORK,LRWORK,IWORK,
     +                              LIWORK)
*     This function implements the dot product - transpose(W)*B*Z.
*     DOT assumes that N is at least 3.
*     .. Scalar Arguments ..
      INTEGER                       IFLAG, LIWORK, LRWORK, N
*     .. Array Arguments ..
      DOUBLE PRECISION              RWORK(LRWORK), W(N), Z(N)
      INTEGER                       IWORK(LIWORK)
*     .. Local Scalars ..
      DOUBLE PRECISION              S
      INTEGER                       I
*     .. Executable Statements ..
      S = 0.0D0
      S = S + (Z(1)-0.5D0*Z(2))*W(1)
      S = S + (-0.5D0*Z(N-1)+Z(N))*W(N)
      DO 20 I = 2, N - 1
         S = S + (-0.5D0*Z(I-1)+Z(I)-0.5D0*Z(I+1))*W(I)
   20 CONTINUE
      DOT = S
      RETURN
      END
*
      SUBROUTINE IMAGE(IFLAG,N,Z,W,RWORK,LRWORK,IWORK,LIWORK)
*     This routine solves  A*W = B*Z  for W.
*     The routine assumes that N is at least 3.
*     A, IROW, ICOL, IPIV, ISTR and NNZ must be as returned by routine
*     F11JAF.
*     .. Parameters ..
      INTEGER          NMAX, LA, LWORK
      PARAMETER        (NMAX=16,LA=10*NMAX,LWORK=6*NMAX+120)
*     .. Scalar Arguments ..
      INTEGER          IFLAG, LIWORK, LRWORK, N
*     .. Array Arguments ..
      DOUBLE PRECISION RWORK(LRWORK), W(N), Z(N)
      INTEGER          IWORK(LIWORK)
*     .. Scalars in Common ..
      INTEGER          NNZ
*     .. Arrays in Common ..
      DOUBLE PRECISION A(LA)
      INTEGER          ICOL(LA), IPIV(NMAX), IROW(LA), ISTR(NMAX+1)
*     .. Local Scalars ..
      DOUBLE PRECISION RNORM, TOL
      INTEGER          IFAIL, ITN, J, MAXITN
      CHARACTER*2      METHOD
*     .. Local Arrays ..
      DOUBLE PRECISION RHS(NMAX), WORK(LWORK)
*     .. External Functions ..
      DOUBLE PRECISION X02AJF
      EXTERNAL         X02AJF
*     .. External Subroutines ..
      EXTERNAL         F11JCF
*     .. Common blocks ..
*
*     Form B*Z in RHS and initialize W to zero.
*
      COMMON           /BLOCK1/A, IROW, ICOL, IPIV, ISTR, NNZ
*     .. Executable Statements ..
      RHS(1) = Z(1) - 0.5D0*Z(2)
      W(1) = 0.0D0
      RHS(N) = -0.5D0*Z(N-1) + Z(N)
      W(N) = 0.0D0
      DO 20 J = 2, N - 1
         RHS(J) = -0.5D0*Z(J-1) + Z(J) - 0.5D0*Z(J+1)
         W(J) = 0.0D0
   20 CONTINUE
*
*     Call F11JCF to solve the equations  A*W = B*Z.
*
      METHOD = 'CG'
      TOL = X02AJF()
      MAXITN = 100
      IFAIL = 1
*
      CALL F11JCF(METHOD,N,NNZ,A,LA,IROW,ICOL,IPIV,ISTR,RHS,TOL,MAXITN,
     +            W,RNORM,ITN,WORK,LWORK,IFAIL)
*
      IF (IFAIL.GT.0) IFLAG = -IFAIL
      RETURN
      END
*
      SUBROUTINE MONIT(ISTATE,NEXTIT,NEVALS,NEVECS,K,F,D)
*     Monitoring routine for F02FJF.
*     .. Parameters ..
      INTEGER          NOUT
      PARAMETER        (NOUT=6)
*     .. Scalar Arguments ..
      INTEGER          ISTATE, K, NEVALS, NEVECS, NEXTIT
*     .. Array Arguments ..
      DOUBLE PRECISION D(K), F(K)
*     .. Local Scalars ..
      INTEGER          I
*     .. Executable Statements ..
      IF (ISTATE.NE.0) THEN
         WRITE (NOUT,*)
         WRITE (NOUT,99999) '  ISTATE = ', ISTATE, ' NEXTIT = ', NEXTIT
         WRITE (NOUT,99999) '  NEVALS = ', NEVALS, ' NEVECS = ', NEVECS
         WRITE (NOUT,*) '       F           D'
         WRITE (NOUT,99998) (F(I),D(I),I=1,K)
      END IF
      RETURN
*
99999 FORMAT (1X,A,I4,A,I4)
99998 FORMAT (1X,1P,D11.3,3X,D11.3)
      END
