Preconditioner Routines for Banded Problems
The following pair of subroutines – banja and banps – provides a general-purpose
banded preconditioner matrix for use with the DASKR solver, with the Krylov linear system
method. When using DASKR to solve a problem , whose iteration matrix
(Jacobian) , where is a scalar, is either banded or
approximately equal to a banded matrix, these routines can be used to generate a banded
approximation to as the preconditioner and to solve the resulting banded linear system,
in conjunction with the Krylov method option (info(12) = 1
) in DASKR.
Other than the user-supplied residual routine res
defining , the only other
inputs required by these routines are the half-bandwidth parameters and
of the approximate banded Jacobian. If the system size is ,
the half-bandwidths are defined as integers between 0 and such that only
elements with indices satisfying are
to be retained in the preconditioner. For example, if , a
diagonal matrix will be generated as the preconditioner. The banded preconditioner is
obtained by difference quotient approximations. If the true problem Jacobian is not banded
but is approximately equal to a matrix that is banded, the procedure used here will have the
effect of lumping the elements outside of the band onto the elements within the band.
To use these routines in conjunction with DASKR, the user's calling program should include the following, in addition to setting the other DASKR input parameters:
Dimension the array ipar
to have length at least 2, and load the half-bandwidths into
ipar
as ipar(1) = ml
and ipar(2) = mu
. Array ipar
is used to communicate these
parameters to banja and banps. If the user program also uses ipar
for communication
with res
, that data should be located beyond the first 2 positions.
Import this module. Set info(15) = 1
to indicate that a jac
routine exists. Then in the
call to DASKR, pass the procedure names banja
and banps
as the arguments jac
and
psol
, respectively.
The DASKR work arrays rwork
and iwork
must include segments wp
and iwp
for use
by banja and banps. The lengths of these arrays depend on the problem size and
half-bandwidths, as follows:
lwp = length of rwork segment wp = (2*ml + mu + 1)*neq + 2*((neq/(ml + mu + 1)) + 1)
liwp = length of iwork segment iwp = neq
Note the integer divide in lwp
. Load these lengths in iwork
as iwork(27) = lwp
and
iwork(28) = liwp
, and include these values in the declared size of rwork
and iwork
.
The banja and banps routines generate and solve the banded preconditioner matrix
within the preconditioned Krylov algorithm used by DASKR when info(12) = 1
.
is generated and LU-factored periodically during the integration, and the factors are used to
solve systems as needed.
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.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
real | :: | res | ||||
integer, | intent(inout) | :: | ires |
Output flag set by |
||
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 |
||
real(kind=rk), | intent(in) | :: | wk(*) |
Real work space of length |
||
real(kind=rk), | intent(in) | :: | h |
Current step size. |
||
real(kind=rk), | intent(in) | :: | cj |
Scalar proportional to |
||
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: |
||
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. |
This subroutine uses the factors produced by banja to solve linear systems for the banded preconditioner , given a vector . It calls the LINPACK routine dgbsl for this.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
integer, | intent(in) | :: | neq |
Problem size. |
||
real(kind=rk), | intent(in) | :: | t |
Independent variable (not used). |
||
real(kind=rk), | intent(in) | :: | y(*) |
Current dependent variables (not used). |
||
real(kind=rk), | intent(in) | :: | yprime(*) |
Current derivatives of dependent variables (not used). |
||
real(kind=rk), | intent(in) | :: | savr(*) |
Current residual evaluated at |
||
real(kind=rk), | intent(in) | :: | wk(*) |
Real work space of length |
||
real(kind=rk), | intent(in) | :: | cj |
Scalar proportional to |
||
real(kind=rk), | intent(in) | :: | wght(*) |
Error weights for computing norms (not used). |
||
real(kind=rk), | intent(inout) | :: | wp(*) |
Real work array containing the LU decomposition of P. |
||
integer, | intent(inout) | :: | iwp(*) |
Integer array containing matrix pivot information. |
||
real(kind=rk), | intent(inout) | :: | b(*) |
Right-hand side vector on input; solution on output. |
||
real(kind=rk), | intent(in) | :: | eplin |
Tolerance for linear system (not used). |
||
integer, | intent(inout) | :: | ier |
Output error flag (not used; assumed 0 on input). |
||
real(kind=rk), | intent(inout) | :: | rpar(*) |
Real array used for communication between the calling program and external user routines (not used). |
||
integer, | intent(inout) | :: | ipar(*) |
Integer array used for communication between the calling program and external user
routines (not used). |