datv.inc Source File


Source Code

!----------------------------------------------------------------------------------------------------------------------------------!
!()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()!
!----------------------------------------------------------------------------------------------------------------------------------!
!>
!! This routine computes the product
!!
!!      (D-inverse)*(P1-inverse)*(I - hl0*df/dy)*(P2-inverse)*(D*v)
!!
!! where D is a diagonal scaling matrix, and P1 and P2 are the
!! left and right preconditioning matrices, respectively.
!!
!! v is assumed to have WRMS norm equal to 1.
!! The product is stored in z.  This is computed by a
!! difference quotient, a call to F, and two calls to PSOL.
!!
!!### On entry
!!
!! NEQ
!!
!! : problem size, passed to F and PSOL (NEQ(1) = N).
!!
!! Y
!!
!! : array containing current dependent variable vector.
!!
!! SAVF
!!
!! : array containing current value of f(t,y).
!!
!! V
!!
!! : real array of length N (can be the same array as Z).
!!
!! WGHT
!!
!! : array of length N containing scale factors.
!! 1/WGHT(i) are the diagonal elements of the matrix D.
!!
!! FTEM
!!
!! : work array of length N.
!!
!! VTEM
!!
!! : work array of length N used to store the
!! unscaled version of V.
!!
!! WP
!!
!! : real work array used by preconditioner PSOL.
!!
!! IWP
!!
!! : integer work array used by preconditioner PSOL.
!!
!! HL0
!!
!! : current value of (step size h) * (coefficient l0).
!!
!! JPRE
!!
!! : preconditioner type flag.
!!
!!### On return
!!
!! Z
!!
!! : array of length N containing desired scaled
!! matrix-vector product.
!!
!! IER
!!
!! : error flag from PSOL.
!!
!! NPSL
!!
!! : the number of calls to PSOL.
!!
!! In addition, this routine uses the Common variables TN, N, NFE.
!-----------------------------------------------------------------------
subroutine datv(Neq,Y,Savf,V,Wght,Ftem,f,psol,Z,Vtem,Wp,Iwp,Hl0,Jpre,Ier,Npsl)

integer                     :: Neq(*)
real(kind=dp)               :: Y(*)
real(kind=dp)               :: Savf(*)
real(kind=dp),intent(in)    :: V(*)
real(kind=dp),intent(in)    :: Wght(*)
real(kind=dp)               :: Ftem(*)
external                    :: f
external                    :: psol
real(kind=dp),intent(inout) :: Z(*)
real(kind=dp),intent(inout) :: Vtem(*)
real(kind=dp),intent(inout) :: Wp(*)
integer                     :: Iwp(*)
real(kind=dp)               :: Hl0
integer, intent(inout)      :: Jpre
integer, intent(inout)      :: Ier
integer, intent(inout)      :: Npsl

real(kind=dp) :: fac, rnorm, tempn
integer :: i

   !  Set VTEM = D * V.
   do i = 1, dls1%n
      Vtem(i) = V(i)/Wght(i)
   enddo

   Ier = 0

   if ( Jpre>=2 ) then

      !  JPRE = 2 or 3.  Apply inverse of right preconditioner to VTEM.
      call psol(Neq,dls1%tn,Y,Savf,Ftem,Hl0,Wp,Iwp,Vtem,2,Ier)
      Npsl = Npsl + 1

      if ( Ier/=0 ) return

      !  Calculate L-2 norm of (D-inverse) * VTEM.
      do i = 1, dls1%n
         Z(i) = Vtem(i)*Wght(i)
      enddo

      tempn = dnrm2(dls1%n,Z,1)
      rnorm = 1.0D0/tempn

      !  Save Y in Z and increment Y by VTEM/norm.
      !X!call dcopy(dls1%n,Y,1,Z,1)
      Z(1:dls1%n)=Y(1:dls1%n)!X!

      do i = 1, dls1%n
         Y(i) = Z(i) + Vtem(i)*rnorm
      enddo

      fac = Hl0*tempn
   else

      !  JPRE = 0 or 1.  Save Y in Z and increment Y by VTEM.
      !X!call dcopy(dls1%n,Y,1,Z,1)
      Z(1:dls1%n)=Y(1:dls1%n)!X!

      do i = 1, dls1%n
         Y(i) = Z(i) + Vtem(i)
      enddo

      fac = Hl0
   endif

   !  For all JPRE, call F with incremented Y argument, and restore Y.
   call f(Neq,dls1%tn,Y,Ftem)
   dls1%nfe = dls1%nfe + 1
   !X!call dcopy(dls1%n,Z,1,Y,1)
   Y(1:dls1%n)=Z(1:dls1%n)!X!

   !  Set Z = (identity - hl0*Jacobian) * VTEM, using difference quotient.
   do i = 1, dls1%n
      Z(i) = Ftem(i) - Savf(i)
   enddo
   do i = 1, dls1%n
      Z(i) = Vtem(i) - fac*Z(i)
   enddo

   !  Apply inverse of left preconditioner to Z, if nontrivial.
   if ( Jpre/=0 .and. Jpre/=2 ) then
      call psol(Neq,dls1%tn,Y,Savf,Ftem,Hl0,Wp,Iwp,Z,1,Ier)
      Npsl = Npsl + 1
      if ( Ier/=0 ) return
   endif

   !  Apply D-inverse to Z and return.
   do i = 1, dls1%n
      Z(i) = Z(i)*Wght(i)
   enddo

end subroutine datv