dpcg Subroutine

subroutine dpcg(Neq, Tn, Y, Savf, R, Wght, N, Maxl, Delta, Hl0, Jpre, Mnewt, f, psol, Npsl, X, P, W, Z, Lpcg, Wp, Iwp, Wk, Iflag)

This routine computes the solution to the system A*x = b using a preconditioned version of the Conjugate Gradient algorithm. It is assumed here that the matrix A and the preconditioner matrix M are symmetric positive definite or nearly so.

On entry

NEQ

problem size, passed to F and PSOL (NEQ(1) = N).

TN

current value of t.

Y

array containing current dependent variable vector.

SAVF

array containing current value of f(t,y).

R

the right hand side of the system A*x = b.

WGHT

array of length N containing scale factors. 1/WGHT(i) are the diagonal elements of the diagonal scaling matrix D.

N

the order of the matrix A, and the lengths of the vectors Y, SAVF, R, WGHT, P, W, Z, WK, and X.

MAXL

the maximum allowable number of iterates.

DELTA

tolerance on residuals b - A*x in weighted RMS-norm.

HL0

current value of (step size h) * (coefficient l0).

JPRE

preconditioner type flag.

MNEWT

Newton iteration counter (.ge. 0).

WK

real work array used by routine DATP.

WP

real work array used by preconditioner PSOL.

IWP

integer work array used by preconditioner PSOL.

On return

X

the final computed approximation to the solution of the system A*x = b.

LPCG

the number of iterations performed, and current order of the upper Hessenberg matrix HES.

NPSL

the number of calls to PSOL.

IFLAG

integer error flag:

        0 means convergence in LPCG iterations, LPCG .le. MAXL.
        1 means the convergence test did not pass in MAXL
          iterations, but the residual norm is .lt. 1,
          or .lt. norm(b) if MNEWT = 0, and so X is computed.
        2 means the convergence test did not pass in MAXL
          iterations, residual .gt. 1, and X is undefined.
        3 means there was a recoverable error in PSOL
          caused by the preconditioner being out of date.
        4 means there was a zero denominator in the algorithm.
          The system matrix or preconditioner matrix is not
          sufficiently close to being symmetric pos. definite.
       -1 means there was a nonrecoverable error in PSOL.

Arguments

Type IntentOptional Attributes Name
integer :: Neq(*)
real(kind=dp) :: Tn
real(kind=dp) :: Y(*)
real(kind=dp) :: Savf(*)
real(kind=dp) :: R(*)
real(kind=dp) :: Wght(*)
integer :: N
integer, intent(in) :: Maxl
real(kind=dp), intent(in) :: Delta
real(kind=dp) :: Hl0
integer, intent(in) :: Jpre
integer, intent(in) :: Mnewt
real :: f
real :: psol
integer, intent(out) :: Npsl
real(kind=dp), intent(inout) :: X(*)
real(kind=dp), intent(inout) :: P(*)
real(kind=dp), intent(inout) :: W(*)
real(kind=dp), intent(inout) :: Z(*)
integer, intent(out) :: Lpcg
real(kind=dp), intent(inout) :: Wp(*)
integer :: Iwp(*)
real(kind=dp), intent(inout) :: Wk(*)
integer, intent(out) :: Iflag

Calls

proc~~dpcg~~CallsGraph proc~dpcg dpcg.inc::dpcg datp datp proc~dpcg->datp daxpy daxpy proc~dpcg->daxpy ddot ddot proc~dpcg->ddot dvnorm dvnorm proc~dpcg->dvnorm

Variables

Type Visibility Attributes Name Initial
real(kind=dp), public :: alpha
real(kind=dp), public :: beta
real(kind=dp), public :: bnrm
integer, public :: i
integer, public :: ier
real(kind=dp), public :: ptw
real(kind=dp), public :: rnrm
real(kind=dp), public :: ztr
real(kind=dp), public :: ztr0

Source Code

subroutine dpcg(Neq,Tn,Y,Savf,R,Wght,N,Maxl,Delta,Hl0,Jpre,Mnewt,f,psol,Npsl,X,P,W,Z,Lpcg,Wp,Iwp,Wk,Iflag)
!
integer                      :: Neq(*)
real(kind=dp)                :: Tn
real(kind=dp)                :: Y(*)
real(kind=dp)                :: Savf(*)
real(kind=dp)                :: R(*)
real(kind=dp)                :: Wght(*)
integer                      :: N
integer,intent(in)           :: Maxl
real(kind=dp),intent(in)     :: Delta
real(kind=dp)                :: Hl0
integer,intent(in)           :: Jpre
integer,intent(in)           :: Mnewt
external                     :: f
external                     :: psol
integer,intent(out)          :: Npsl
real(kind=dp),intent(inout)  :: X(*)
real(kind=dp),intent(inout)  :: P(*)
real(kind=dp),intent(inout)  :: W(*)
real(kind=dp),intent(inout)  :: Z(*)
integer,intent(out)          :: Lpcg
real(kind=dp),intent(inout)  :: Wp(*)
integer                      :: Iwp(*)
real(kind=dp),intent(inout)  :: Wk(*)
integer,intent(out)          :: Iflag
!
real(kind=dp) :: alpha , beta , bnrm , ptw , rnrm , ztr , ztr0
integer :: i , ier
   !
   Iflag = 0
   Npsl = 0
   Lpcg = 0
   do i = 1 , N
      X(i) = 0.0D0
   enddo
   bnrm = dvnorm(N,R,Wght)
   !  Test for immediate return with X = 0 or X = b. -----------------------
   if ( bnrm>Delta ) then
   !
      ztr = 0.0D0
   else
      if ( Mnewt>0 ) return
      !X!call dcopy(N,R,1,X,1)
      X(1:N) = R(1:N)!X!
      return
   endif
   !  Loop point for PCG iterations. ---------------------------------------
   INFINITE: do
      Lpcg = Lpcg + 1
      !X!call dcopy(N,R,1,Z,1)
      Z(1:N) = R(1:N)!X!
      ier = 0
      if ( Jpre/=0 ) then
         call psol(Neq,Tn,Y,Savf,Wk,Hl0,Wp,Iwp,Z,3,ier)
         Npsl = Npsl + 1
         if ( ier/=0 ) then
      !-----------------------------------------------------------------------
      !  This block handles error returns from PSOL.
      !-----------------------------------------------------------------------
            if ( ier<0 ) Iflag = -1
            if ( ier>0 ) Iflag = 3
            return
         endif
      endif
      ztr0 = ztr
      ztr = ddot(N,Z,1,R,1)
      if ( Lpcg==1 ) then
         !X!call dcopy(N,Z,1,P,1)
         P(1:N) = Z(1:N)!X!
      elseif ( ztr0==0.0D0 ) then
      !-----------------------------------------------------------------------
      !  This block handles division by zero errors.
      !-----------------------------------------------------------------------
         Iflag = 4
         return
      else
         beta = ztr/ztr0
         do i = 1 , N
            P(i) = Z(i) + beta*P(i)
         enddo
      endif
      !-----------------------------------------------------------------------
      !   Call DATP to compute A*p and return the answer in W.
      !-----------------------------------------------------------------------
      call datp(Neq,Y,Savf,P,Wght,Hl0,Wk,f,W)
      !
      ptw = ddot(N,P,1,W,1)
      if ( ptw==0.0D0 ) then
         Iflag = 4
         exit INFINITE
      else
         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<=Delta ) return
         if ( Lpcg<Maxl ) cycle INFINITE
         Iflag = 2
         if ( rnrm<=1.0D0 ) Iflag = 1
         if ( rnrm<=bnrm .and. Mnewt==0 ) Iflag = 1
         exit INFINITE
      endif
   enddo INFINITE
end subroutine dpcg