banja Subroutine

public subroutine banja(res, ires, neq, t, y, yprime, rewt, savr, wk, h, cj, wp, iwp, ier, rpar, ipar)

This subroutine generates a banded preconditioner matrix that approximates the iteration matrix , where the DAE system is . The band matrix has half-bandwidths and . It is computed by making calls to the user's res routine and forming difference quotients, exactly as in the banded direct method option of DASKR. banja calls the LINPACK routine dgbfa to do an LU factorization of this matrix.

Arguments

Type IntentOptional Attributes Name
real :: res
integer, intent(inout) :: ires

Output flag set by res. See res description in DASKR.

integer, intent(in) :: neq

Problem size.

real(kind=rk), intent(in) :: t

Independent variable.

real(kind=rk), intent(inout) :: y(*)

Current dependent variables.

real(kind=rk), intent(inout) :: yprime(*)

Current derivatives of dependent variables.

real(kind=rk), intent(in) :: rewt(*)

Vector of reciprocal error weights, used here for computing increments.

real(kind=rk), intent(in) :: savr(*)

Current residual evaluated at (t, y, yprime).

real(kind=rk), intent(in) :: wk(*)

Real work space of length neq.

real(kind=rk), intent(in) :: h

Current step size.

real(kind=rk), intent(in) :: cj

Scalar proportional to 1/h.

real(kind=rk), intent(inout) :: wp(*)

Real work array for P, etc. On output, it contains the LU decomposition of the banded approximation P.

integer, intent(inout) :: iwp(*)

Integer work space for matrix pivot information.

integer, intent(inout) :: ier

Output flag: ier > 0 if P is singular, and ier = 0 otherwise.

real(kind=rk), intent(inout) :: rpar(*)

Real array used for communication between the calling program and external user routines.

integer, intent(inout) :: ipar(*)

Integer array used for communication between the calling program and external user routines. ipar(1) and ipar(2) must contain ml and mu, respectively.


Calls

proc~~banja~~CallsGraph proc~banja banja d1mach d1mach proc~banja->d1mach dgbfa dgbfa proc~banja->dgbfa

Variables

Type Visibility Attributes Name Initial
real(kind=rk), public :: del
real(kind=rk), public :: delinv
real(kind=rk), public :: squr
real(kind=rk), public :: uround
integer, public :: i
integer, public :: i1
integer, public :: i2
integer, public :: ii
integer, public :: ipsave
integer, public :: isave
integer, public :: j
integer, public :: k
integer, public :: lenp
integer, public :: mba
integer, public :: mband
integer, public :: meb1
integer, public :: meband
integer, public :: ml
integer, public :: msave
integer, public :: mu
integer, public :: n

Source Code

   subroutine banja(res, ires, neq, t, y, yprime, rewt, savr, wk, h, cj, wp, iwp, ier, rpar, ipar)
   !! This subroutine generates a banded preconditioner matrix \(P\) that approximates the
   !! iteration matrix \(J = dG/dy + c_j dG/dy'\), where the DAE system is \(G(t,y,y') = 0\). 
   !! The band matrix \(P\) has half-bandwidths \(\mathrm{ml}\) and \(\mathrm{mu}\). It is computed
   !! by making \(\mathrm{ml} + \mathrm{mu} + 1\) calls to the user's `res` routine and forming
   !! difference quotients, exactly as in the banded direct method option of [[daskr]]. 
   !! [[banja]] calls the LINPACK routine [[DGBFA]] to do an LU factorization of this matrix.
      external :: res
      integer, intent(inout) :: ires
        !! Output flag set by `res`. See `res` description in [[daskr]].
      integer, intent(in) :: neq
        !! Problem size.
      real(rk), intent(in) :: t
        !! Independent variable.
      real(rk), intent(inout) :: y(*)
        !! Current dependent variables.
      real(rk), intent(inout) :: yprime(*)
        !! Current derivatives of dependent variables.
      real(rk), intent(in) :: rewt(*)
        !! Vector of reciprocal error weights, used here for computing increments.
      real(rk), intent(in) :: savr(*)
        !! Current residual evaluated at `(t, y, yprime)`.
      real(rk), intent(in) :: wk(*)
        !! Real work space of length `neq`.
      real(rk), intent(in) :: h
        !! Current step size.
      real(rk), intent(in) :: cj
        !! Scalar proportional to `1/h`.
      real(rk), intent(inout) :: wp(*)
        !! Real work array for P, etc. On output, it contains the LU decomposition of the banded
        !! approximation P.
      integer, intent(inout) :: iwp(*)
        !! Integer work space for matrix pivot information.
      integer, intent(inout) :: ier
        !! Output flag: `ier > 0` if P is singular, and `ier = 0` otherwise.
      real(rk), intent(inout) :: rpar(*)
        !! Real array used for communication between the calling program and external user
        !! routines.
      integer, intent(inout) :: ipar(*)
        !! Integer array used for communication between the calling program and external user
        !! routines. `ipar(1)` and `ipar(2)` must contain `ml` and `mu`, respectively.

      external :: dgbfa, d1mach

      real(rk) :: del, delinv, squr, uround, d1mach
      integer :: i, i1, i2, ii, ipsave, isave, j, k, lenp, mba, mband, meb1, meband, ml, &
                 msave, mu, n

      ! Set band parameters.
      ml = ipar(1)
      mu = ipar(2)
      mband = ml + mu + 1
      mba = min(mband, neq)
      meband = mband + ml
      meb1 = meband - 1

      ! Set the machine unit roundoff UROUND and SQRT(UROUND), used to set increments in the
      ! difference quotient procedure.
      uround = d1mach(4)
      squr = sqrt(uround)

      ! Set pointers into WP. LENP is the length of the segment for P.
      ! Following that are two segments of size (NEQ/MBAND), with offsets
      ! ISAVE and IPSAVE, for temporary storage of Y and YPRIME elements.
      lenp = (2*ml + mu + 1)*neq
      msave = (neq/mband) + 1
      isave = lenp
      ipsave = isave + msave

      ! Initialize error flags.
      ier = 0
      ires = 0

      ! Generate the banded approximate iteration matrix P using difference quotients on the
      ! results of calls to RES.
      do j = 1, mba

         do n = j, neq, mband
            k = (n - j)/mband + 1
            wp(isave + k) = y(n)
            wp(ipsave + k) = yprime(n)
            del = squr*max(abs(y(n)), abs(h*yprime(n)), abs(one/rewt(n)))
            del = sign(del, h*yprime(n))
            del = (y(n) + del) - y(n)
            y(n) = y(n) + del
            yprime(n) = yprime(n) + cj*del
         end do
         
         call res(t, y, yprime, cj, wk, ires, rpar, ipar)
         
         if (ires < 0) return
         
         do n = j, neq, mband
            k = (n - j)/mband + 1
            y(n) = wp(isave + k)
            yprime(n) = wp(ipsave + k)
            del = squr*max(abs(y(n)), abs(h*yprime(n)), abs(one/rewt(n)))
            del = sign(del, h*yprime(n))
            del = (y(n) + del) - y(n)
            delinv = one/del
            i1 = max(1, n - mu)
            i2 = min(neq, n + ml)
            ii = n*meb1 - ml
            do i = i1, i2
               wp(ii + i) = (wk(i) - savr(i))*delinv
            end do
         end do
      
      end do

      ! Do LU decomposition of the band matrix P.
      call dgbfa(wp, meband, neq, ml, mu, iwp, ier)

   end subroutine banja