*DECK DPCGS
      SUBROUTINE DPCGS (NEQ, TN, Y, SAVF, R, WGHT, N, MAXL, DELTA, HL0,
     1 JPRE, MNEWT, F, PSOL, NPSL, X, P, W, Z, LPCG, WP, IWP, WK, IFLAG)
      EXTERNAL F, PSOL
      INTEGER NEQ, N, MAXL, JPRE, MNEWT, NPSL, LPCG, IWP, IFLAG
      DOUBLE PRECISION TN,Y,SAVF,R,WGHT,DELTA,HL0,X,P,W,Z,WP,WK
      DIMENSION NEQ(*), Y(*), SAVF(*), R(*), WGHT(*), X(*), P(*), W(*),
     1   Z(*), WP(*), IWP(*), WK(*)
C-----------------------------------------------------------------------
C This routine computes the solution to the system A*x = b using a
C scaled preconditioned version of the Conjugate Gradient algorithm.
C It is assumed here that the scaled matrix D**-1 * A * D and the
C scaled preconditioner D**-1 * M * D are close to being
C symmetric positive definite.
C-----------------------------------------------------------------------
C
C      On entry
C
C          NEQ = problem size, passed to F and PSOL (NEQ(1) = N).
C
C           TN = current value of t.
C
C            Y = array containing current dependent variable vector.
C
C         SAVF = array containing current value of f(t,y).
C
C            R = the right hand side of the system A*x = b.
C
C         WGHT = array of length N containing scale factors.
C                1/WGHT(i) are the diagonal elements of the diagonal
C                scaling matrix D.
C
C            N = the order of the matrix A, and the lengths
C                of the vectors Y, SAVF, R, WGHT, P, W, Z, WK, and X.
C
C         MAXL = the maximum allowable number of iterates.
C
C        DELTA = tolerance on residuals b - A*x in weighted RMS-norm.
C
C          HL0 = current value of (step size h) * (coefficient l0).
C
C         JPRE = preconditioner type flag.
C
C        MNEWT = Newton iteration counter (.ge. 0).
C
C           WK = real work array used by routine DATP.
C
C           WP = real work array used by preconditioner PSOL.
C
C          IWP = integer work array used by preconditioner PSOL.
C
C      On return
C
C         X    = the final computed approximation to the solution
C                of the system A*x = b.
C
C         LPCG = the number of iterations performed, and current
C                order of the upper Hessenberg matrix HES.
C
C         NPSL = the number of calls to PSOL.
C
C        IFLAG = integer error flag:
C                0 means convergence in LPCG iterations, LPCG .le. MAXL.
C                1 means the convergence test did not pass in MAXL
C                  iterations, but the residual norm is .lt. 1,
C                  or .lt. norm(b) if MNEWT = 0, and so X is computed.
C                2 means the convergence test did not pass in MAXL
C                  iterations, residual .gt. 1, and X is undefined.
C                3 means there was a recoverable error in PSOL
C                  caused by the preconditioner being out of date.
C                4 means there was a zero denominator in the algorithm.
C                  the scaled matrix or scaled preconditioner is not
C                  sufficiently close to being symmetric pos. definite.
C               -1 means there was a nonrecoverable error in PSOL.
C
C-----------------------------------------------------------------------
      INTEGER I, IER
      DOUBLE PRECISION ALPHA, BETA, BNRM, PTW, RNRM, DVNORM, ZTR, ZTR0
C
      IFLAG = 0
      NPSL = 0
      LPCG = 0
      DO 10 I = 1,N
 10     X(I) = 0.0D0
      BNRM = DVNORM (N, R, WGHT)
C Test for immediate return with X = 0 or X = b. -----------------------
      IF (BNRM .GT. DELTA) GO TO 20
      IF (MNEWT .GT. 0) RETURN
      CALL DCOPY (N, R, 1, X, 1)
      RETURN
C
 20   ZTR = 0.0D0
C Loop point for PCG iterations. ---------------------------------------
 30   CONTINUE
      LPCG = LPCG + 1
      CALL DCOPY (N, R, 1, Z, 1)
      IER = 0
      IF (JPRE .EQ. 0) GO TO 40
      CALL PSOL (NEQ, TN, Y, SAVF, WK, HL0, WP, IWP, Z, 3, IER)
      NPSL = NPSL + 1
      IF (IER .NE. 0) GO TO 100
 40   CONTINUE
      ZTR0 = ZTR
      ZTR = 0.0D0
      DO 45 I = 1,N
 45     ZTR = ZTR + Z(I)*R(I)*WGHT(I)**2
      IF (LPCG .NE. 1) GO TO 50
      CALL DCOPY (N, Z, 1, P, 1)
      GO TO 70
 50   CONTINUE
      IF (ZTR0 .EQ. 0.0D0) GO TO 200
      BETA = ZTR/ZTR0
      DO 60 I = 1,N
 60     P(I) = Z(I) + BETA*P(I)
 70   CONTINUE
C-----------------------------------------------------------------------
C  Call DATP to compute A*p and return the answer in W.
C-----------------------------------------------------------------------
      CALL DATP (NEQ, Y, SAVF, P, WGHT, HL0, WK, F, W)
C
      PTW = 0.0D0
      DO 80 I = 1,N
 80     PTW = PTW + P(I)*W(I)*WGHT(I)**2
      IF (PTW .EQ. 0.0D0) GO TO 200
      ALPHA = ZTR/PTW
      CALL DAXPY (N, ALPHA, P, 1, X, 1)
      ALPHA = -ALPHA
      CALL DAXPY (N, ALPHA, W, 1, R, 1)
      RNRM = DVNORM (N, R, WGHT)
      IF (RNRM .LE. DELTA) RETURN
      IF (LPCG .LT. MAXL) GO TO 30
      IFLAG = 2
      IF (RNRM .LE. 1.0D0) IFLAG = 1
      IF (RNRM .LE. BNRM .AND. MNEWT .EQ. 0) IFLAG = 1
      RETURN
C-----------------------------------------------------------------------
C This block handles error returns from PSOL.
C-----------------------------------------------------------------------
 100  CONTINUE
      IF (IER .LT. 0) IFLAG = -1
      IF (IER .GT. 0) IFLAG = 3
      RETURN
C-----------------------------------------------------------------------
C This block handles division by zero errors.
C-----------------------------------------------------------------------
 200  CONTINUE
      IFLAG = 4
      RETURN
C----------------------- End of Subroutine DPCGS -----------------------
      END