cantera/ext/math/ddaspk.f
2003-04-14 17:57:48 +00:00

6612 lines
245 KiB
Fortran
Executable file

SUBROUTINE DDASPK (RES, NEQ, T, Y, YPRIME, TOUT, INFO, RTOL, ATOL,
* IDID, RWORK, LRW, IWORK, LIW, RPAR, IPAR, JAC, PSOL)
C
C***BEGIN PROLOGUE DDASPK
C***DATE WRITTEN 890101 (YYMMDD)
C***REVISION DATE 910624 (Added HMAX test at 525 in main driver.)
C***REVISION DATE 920929 (CJ in RES call, RES counter fix.)
C***REVISION DATE 921215 (Warnings on poor iteration performance)
C***REVISION DATE 921216 (NRMAX as optional input)
C***REVISION DATE 930315 (Name change: DDINI to DDINIT)
C***REVISION DATE 940822 (Replaced initial condition calculation)
C***REVISION DATE 941101 (Added linesearch in I.C. calculations)
C***REVISION DATE 941220 (Misc. corrections throughout)
C***REVISION DATE 950125 (Added DINVWT routine)
C***REVISION DATE 950714 (Misc. corrections throughout)
C***REVISION DATE 950802 (Default NRMAX = 5, based on tests.)
C***REVISION DATE 950808 (Optional error test added.)
C***REVISION DATE 950814 (Added I.C. constraints and INFO(14))
C***REVISION DATE 950828 (Various minor corrections.)
C***REVISION DATE 951006 (Corrected WT scaling in DFNRMK.)
C***REVISION DATE 951030 (Corrected history update at end of DDASTP.)
C***REVISION DATE 960129 (Corrected RL bug in DLINSD, DLINSK.)
C***REVISION DATE 960301 (Added NONNEG to SAVE statement.)
C***REVISION DATE 000512 (Removed copyright notices.)
C***REVISION DATE 000622 (Corrected LWM value using NCPHI.)
C***REVISION DATE 000628 (Corrected I.C. stopping tests when index = 0.)
C***REVISION DATE 000628 (Fixed alpha test in I.C. calc., Krylov case.)
C***REVISION DATE 000628 (Improved restart in I.C. calc., Krylov case.)
C***REVISION DATE 000628 (Minor corrections throughout.)
C***REVISION DATE 000711 (Fixed Newton convergence test in DNSD, DNSK.)
C***REVISION DATE 000712 (Fixed tests on TN - TOUT below 420 and 440.)
C***CATEGORY NO. I1A2
C***KEYWORDS DIFFERENTIAL/ALGEBRAIC, BACKWARD DIFFERENTIATION FORMULAS,
C IMPLICIT DIFFERENTIAL SYSTEMS, KRYLOV ITERATION
C***AUTHORS Linda R. Petzold, Peter N. Brown, Alan C. Hindmarsh, and
C Clement W. Ulrich
C Center for Computational Sciences & Engineering, L-316
C Lawrence Livermore National Laboratory
C P.O. Box 808,
C Livermore, CA 94551
C***PURPOSE This code solves a system of differential/algebraic
C equations of the form
C G(t,y,y') = 0 ,
C using a combination of Backward Differentiation Formula
C (BDF) methods and a choice of two linear system solution
C methods: direct (dense or band) or Krylov (iterative).
C This version is in double precision.
C-----------------------------------------------------------------------
C***DESCRIPTION
C
C *Usage:
C
C IMPLICIT DOUBLE PRECISION(A-H,O-Z)
C INTEGER NEQ, INFO(N), IDID, LRW, LIW, IWORK(LIW), IPAR(*)
C DOUBLE PRECISION T, Y(*), YPRIME(*), TOUT, RTOL(*), ATOL(*),
C RWORK(LRW), RPAR(*)
C EXTERNAL RES, JAC, PSOL
C
C CALL DDASPK (RES, NEQ, T, Y, YPRIME, TOUT, INFO, RTOL, ATOL,
C * IDID, RWORK, LRW, IWORK, LIW, RPAR, IPAR, JAC, PSOL)
C
C Quantities which may be altered by the code are:
C T, Y(*), YPRIME(*), INFO(1), RTOL, ATOL, IDID, RWORK(*), IWORK(*)
C
C
C *Arguments:
C
C RES:EXT This is the name of a subroutine which you
C provide to define the residual function G(t,y,y')
C of the differential/algebraic system.
C
C NEQ:IN This is the number of equations in the system.
C
C T:INOUT This is the current value of the independent
C variable.
C
C Y(*):INOUT This array contains the solution components at T.
C
C YPRIME(*):INOUT This array contains the derivatives of the solution
C components at T.
C
C TOUT:IN This is a point at which a solution is desired.
C
C INFO(N):IN This is an integer array used to communicate details
C of how the solution is to be carried out, such as
C tolerance type, matrix structure, step size and
C order limits, and choice of nonlinear system method.
C N must be at least 20.
C
C RTOL,ATOL:INOUT These quantities represent absolute and relative
C error tolerances (on local error) which you provide
C to indicate how accurately you wish the solution to
C be computed. You may choose them to be both scalars
C or else both arrays of length NEQ.
C
C IDID:OUT This integer scalar is an indicator reporting what
C the code did. You must monitor this variable to
C decide what action to take next.
C
C RWORK:WORK A real work array of length LRW which provides the
C code with needed storage space.
C
C LRW:IN The length of RWORK.
C
C IWORK:WORK An integer work array of length LIW which provides
C the code with needed storage space.
C
C LIW:IN The length of IWORK.
C
C RPAR,IPAR:IN These are real and integer parameter arrays which
C you can use for communication between your calling
C program and the RES, JAC, and PSOL subroutines.
C
C JAC:EXT This is the name of a subroutine which you may
C provide (optionally) for calculating Jacobian
C (partial derivative) data involved in solving linear
C systems within DDASPK.
C
C PSOL:EXT This is the name of a subroutine which you must
C provide for solving linear systems if you selected
C a Krylov method. The purpose of PSOL is to solve
C linear systems involving a left preconditioner P.
C
C *Overview
C
C The DDASPK solver uses the backward differentiation formulas of
C orders one through five to solve a system of the form G(t,y,y') = 0
C for y = Y and y' = YPRIME. Values for Y and YPRIME at the initial
C time must be given as input. These values should be consistent,
C that is, if T, Y, YPRIME are the given initial values, they should
C satisfy G(T,Y,YPRIME) = 0. However, if consistent values are not
C known, in many cases you can have DDASPK solve for them -- see INFO(11).
C (This and other options are described in more detail below.)
C
C Normally, DDASPK solves the system from T to TOUT. It is easy to
C continue the solution to get results at additional TOUT. This is
C the interval mode of operation. Intermediate results can also be
C obtained easily by specifying INFO(3).
C
C On each step taken by DDASPK, a sequence of nonlinear algebraic
C systems arises. These are solved by one of two types of
C methods:
C * a Newton iteration with a direct method for the linear
C systems involved (INFO(12) = 0), or
C * a Newton iteration with a preconditioned Krylov iterative
C method for the linear systems involved (INFO(12) = 1).
C
C The direct method choices are dense and band matrix solvers,
C with either a user-supplied or an internal difference quotient
C Jacobian matrix, as specified by INFO(5) and INFO(6).
C In the band case, INFO(6) = 1, you must supply half-bandwidths
C in IWORK(1) and IWORK(2).
C
C The Krylov method is the Generalized Minimum Residual (GMRES)
C method, in either complete or incomplete form, and with
C scaling and preconditioning. The method is implemented
C in an algorithm called SPIGMR. Certain options in the Krylov
C method case are specified by INFO(13) and INFO(15).
C
C If the Krylov method is chosen, you may supply a pair of routines,
C JAC and PSOL, to apply preconditioning to the linear system.
C If the system is A*x = b, the matrix is A = dG/dY + CJ*dG/dYPRIME
C (of order NEQ). This system can then be preconditioned in the form
C (P-inverse)*A*x = (P-inverse)*b, with left preconditioner P.
C (DDASPK does not allow right preconditioning.)
C Then the Krylov method is applied to this altered, but equivalent,
C linear system, hopefully with much better performance than without
C preconditioning. (In addition, a diagonal scaling matrix based on
C the tolerances is also introduced into the altered system.)
C
C The JAC routine evaluates any data needed for solving systems
C with coefficient matrix P, and PSOL carries out that solution.
C In any case, in order to improve convergence, you should try to
C make P approximate the matrix A as much as possible, while keeping
C the system P*x = b reasonably easy and inexpensive to solve for x,
C given a vector b.
C
C
C *Description
C
C------INPUT - WHAT TO DO ON THE FIRST CALL TO DDASPK-------------------
C
C
C The first call of the code is defined to be the start of each new
C problem. Read through the descriptions of all the following items,
C provide sufficient storage space for designated arrays, set
C appropriate variables for the initialization of the problem, and
C give information about how you want the problem to be solved.
C
C
C RES -- Provide a subroutine of the form
C
C SUBROUTINE RES (T, Y, YPRIME, CJ, DELTA, IRES, RPAR, IPAR)
C
C to define the system of differential/algebraic
C equations which is to be solved. For the given values
C of T, Y and YPRIME, the subroutine should return
C the residual of the differential/algebraic system
C DELTA = G(T,Y,YPRIME)
C DELTA is a vector of length NEQ which is output from RES.
C
C Subroutine RES must not alter T, Y, YPRIME, or CJ.
C You must declare the name RES in an EXTERNAL
C statement in your program that calls DDASPK.
C You must dimension Y, YPRIME, and DELTA in RES.
C
C The input argument CJ can be ignored, or used to rescale
C constraint equations in the system (see Ref. 2, p. 145).
C Note: In this respect, DDASPK is not downward-compatible
C with DDASSL, which does not have the RES argument CJ.
C
C IRES is an integer flag which is always equal to zero
C on input. Subroutine RES should alter IRES only if it
C encounters an illegal value of Y or a stop condition.
C Set IRES = -1 if an input value is illegal, and DDASPK
C will try to solve the problem without getting IRES = -1.
C If IRES = -2, DDASPK will return control to the calling
C program with IDID = -11.
C
C RPAR and IPAR are real and integer parameter arrays which
C you can use for communication between your calling program
C and subroutine RES. They are not altered by DDASPK. If you
C do not need RPAR or IPAR, ignore these parameters by treat-
C ing them as dummy arguments. If you do choose to use them,
C dimension them in your calling program and in RES as arrays
C of appropriate length.
C
C NEQ -- Set it to the number of equations in the system (NEQ .GE. 1).
C
C T -- Set it to the initial point of the integration. (T must be
C a variable.)
C
C Y(*) -- Set this array to the initial values of the NEQ solution
C components at the initial point. You must dimension Y of
C length at least NEQ in your calling program.
C
C YPRIME(*) -- Set this array to the initial values of the NEQ first
C derivatives of the solution components at the initial
C point. You must dimension YPRIME at least NEQ in your
C calling program.
C
C TOUT - Set it to the first point at which a solution is desired.
C You cannot take TOUT = T. Integration either forward in T
C (TOUT .GT. T) or backward in T (TOUT .LT. T) is permitted.
C
C The code advances the solution from T to TOUT using step
C sizes which are automatically selected so as to achieve the
C desired accuracy. If you wish, the code will return with the
C solution and its derivative at intermediate steps (the
C intermediate-output mode) so that you can monitor them,
C but you still must provide TOUT in accord with the basic
C aim of the code.
C
C The first step taken by the code is a critical one because
C it must reflect how fast the solution changes near the
C initial point. The code automatically selects an initial
C step size which is practically always suitable for the
C problem. By using the fact that the code will not step past
C TOUT in the first step, you could, if necessary, restrict the
C length of the initial step.
C
C For some problems it may not be permissible to integrate
C past a point TSTOP, because a discontinuity occurs there
C or the solution or its derivative is not defined beyond
C TSTOP. When you have declared a TSTOP point (see INFO(4)
C and RWORK(1)), you have told the code not to integrate past
C TSTOP. In this case any tout beyond TSTOP is invalid input.
C
C INFO(*) - Use the INFO array to give the code more details about
C how you want your problem solved. This array should be
C dimensioned of length 20, though DDASPK uses only the
C first 15 entries. You must respond to all of the following
C items, which are arranged as questions. The simplest use
C of DDASPK corresponds to setting all entries of INFO to 0.
C
C INFO(1) - This parameter enables the code to initialize itself.
C You must set it to indicate the start of every new
C problem.
C
C **** Is this the first call for this problem ...
C yes - set INFO(1) = 0
C no - not applicable here.
C See below for continuation calls. ****
C
C INFO(2) - How much accuracy you want of your solution
C is specified by the error tolerances RTOL and ATOL.
C The simplest use is to take them both to be scalars.
C To obtain more flexibility, they can both be arrays.
C The code must be told your choice.
C
C **** Are both error tolerances RTOL, ATOL scalars ...
C yes - set INFO(2) = 0
C and input scalars for both RTOL and ATOL
C no - set INFO(2) = 1
C and input arrays for both RTOL and ATOL ****
C
C INFO(3) - The code integrates from T in the direction of TOUT
C by steps. If you wish, it will return the computed
C solution and derivative at the next intermediate step
C (the intermediate-output mode) or TOUT, whichever comes
C first. This is a good way to proceed if you want to
C see the behavior of the solution. If you must have
C solutions at a great many specific TOUT points, this
C code will compute them efficiently.
C
C **** Do you want the solution only at
C TOUT (and not at the next intermediate step) ...
C yes - set INFO(3) = 0
C no - set INFO(3) = 1 ****
C
C INFO(4) - To handle solutions at a great many specific
C values TOUT efficiently, this code may integrate past
C TOUT and interpolate to obtain the result at TOUT.
C Sometimes it is not possible to integrate beyond some
C point TSTOP because the equation changes there or it is
C not defined past TSTOP. Then you must tell the code
C this stop condition.
C
C **** Can the integration be carried out without any
C restrictions on the independent variable T ...
C yes - set INFO(4) = 0
C no - set INFO(4) = 1
C and define the stopping point TSTOP by
C setting RWORK(1) = TSTOP ****
C
C INFO(5) - used only when INFO(12) = 0 (direct methods).
C To solve differential/algebraic systems you may wish
C to use a matrix of partial derivatives of the
C system of differential equations. If you do not
C provide a subroutine to evaluate it analytically (see
C description of the item JAC in the call list), it will
C be approximated by numerical differencing in this code.
C Although it is less trouble for you to have the code
C compute partial derivatives by numerical differencing,
C the solution will be more reliable if you provide the
C derivatives via JAC. Usually numerical differencing is
C more costly than evaluating derivatives in JAC, but
C sometimes it is not - this depends on your problem.
C
C **** Do you want the code to evaluate the partial deriv-
C atives automatically by numerical differences ...
C yes - set INFO(5) = 0
C no - set INFO(5) = 1
C and provide subroutine JAC for evaluating the
C matrix of partial derivatives ****
C
C INFO(6) - used only when INFO(12) = 0 (direct methods).
C DDASPK will perform much better if the matrix of
C partial derivatives, dG/dY + CJ*dG/dYPRIME (here CJ is
C a scalar determined by DDASPK), is banded and the code
C is told this. In this case, the storage needed will be
C greatly reduced, numerical differencing will be performed
C much cheaper, and a number of important algorithms will
C execute much faster. The differential equation is said
C to have half-bandwidths ML (lower) and MU (upper) if
C equation i involves only unknowns Y(j) with
C i-ML .le. j .le. i+MU .
C For all i=1,2,...,NEQ. Thus, ML and MU are the widths
C of the lower and upper parts of the band, respectively,
C with the main diagonal being excluded. If you do not
C indicate that the equation has a banded matrix of partial
C derivatives the code works with a full matrix of NEQ**2
C elements (stored in the conventional way). Computations
C with banded matrices cost less time and storage than with
C full matrices if 2*ML+MU .lt. NEQ. If you tell the
C code that the matrix of partial derivatives has a banded
C structure and you want to provide subroutine JAC to
C compute the partial derivatives, then you must be careful
C to store the elements of the matrix in the special form
C indicated in the description of JAC.
C
C **** Do you want to solve the problem using a full (dense)
C matrix (and not a special banded structure) ...
C yes - set INFO(6) = 0
C no - set INFO(6) = 1
C and provide the lower (ML) and upper (MU)
C bandwidths by setting
C IWORK(1)=ML
C IWORK(2)=MU ****
C
C INFO(7) - You can specify a maximum (absolute value of)
C stepsize, so that the code will avoid passing over very
C large regions.
C
C **** Do you want the code to decide on its own the maximum
C stepsize ...
C yes - set INFO(7) = 0
C no - set INFO(7) = 1
C and define HMAX by setting
C RWORK(2) = HMAX ****
C
C INFO(8) - Differential/algebraic problems may occasionally
C suffer from severe scaling difficulties on the first
C step. If you know a great deal about the scaling of
C your problem, you can help to alleviate this problem
C by specifying an initial stepsize H0.
C
C **** Do you want the code to define its own initial
C stepsize ...
C yes - set INFO(8) = 0
C no - set INFO(8) = 1
C and define H0 by setting
C RWORK(3) = H0 ****
C
C INFO(9) - If storage is a severe problem, you can save some
C storage by restricting the maximum method order MAXORD.
C The default value is 5. For each order decrease below 5,
C the code requires NEQ fewer locations, but it is likely
C to be slower. In any case, you must have
C 1 .le. MAXORD .le. 5.
C **** Do you want the maximum order to default to 5 ...
C yes - set INFO(9) = 0
C no - set INFO(9) = 1
C and define MAXORD by setting
C IWORK(3) = MAXORD ****
C
C INFO(10) - If you know that certain components of the
C solutions to your equations are always nonnegative
C (or nonpositive), it may help to set this
C parameter. There are three options that are
C available:
C 1. To have constraint checking only in the initial
C condition calculation.
C 2. To enforce nonnegativity in Y during the integration.
C 3. To enforce both options 1 and 2.
C
C When selecting option 2 or 3, it is probably best to try the
C code without using this option first, and only use
C this option if that does not work very well.
C
C **** Do you want the code to solve the problem without
C invoking any special inequality constraints ...
C yes - set INFO(10) = 0
C no - set INFO(10) = 1 to have option 1 enforced
C no - set INFO(10) = 2 to have option 2 enforced
C no - set INFO(10) = 3 to have option 3 enforced ****
C
C If you have specified INFO(10) = 1 or 3, then you
C will also need to identify how each component of Y
C in the initial condition calculation is constrained.
C You must set:
C IWORK(40+I) = +1 if Y(I) must be .GE. 0,
C IWORK(40+I) = +2 if Y(I) must be .GT. 0,
C IWORK(40+I) = -1 if Y(I) must be .LE. 0, while
C IWORK(40+I) = -2 if Y(I) must be .LT. 0, while
C IWORK(40+I) = 0 if Y(I) is not constrained.
C
C INFO(11) - DDASPK normally requires the initial T, Y, and
C YPRIME to be consistent. That is, you must have
C G(T,Y,YPRIME) = 0 at the initial T. If you do not know
C the initial conditions precisely, in some cases
C DDASPK may be able to compute it.
C
C Denoting the differential variables in Y by Y_d
C and the algebraic variables by Y_a, DDASPK can solve
C one of two initialization problems:
C 1. Given Y_d, calculate Y_a and Y'_d, or
C 2. Given Y', calculate Y.
C In either case, initial values for the given
C components are input, and initial guesses for
C the unknown components must also be provided as input.
C
C **** Are the initial T, Y, YPRIME consistent ...
C
C yes - set INFO(11) = 0
C no - set INFO(11) = 1 to calculate option 1 above,
C or set INFO(11) = 2 to calculate option 2 ****
C
C If you have specified INFO(11) = 1, then you
C will also need to identify which are the
C differential and which are the algebraic
C components (algebraic components are components
C whose derivatives do not appear explicitly
C in the function G(T,Y,YPRIME)). You must set:
C IWORK(LID+I) = +1 if Y(I) is a differential variable
C IWORK(LID+I) = -1 if Y(I) is an algebraic variable,
C where LID = 40 if INFO(10) = 0 or 2 and LID = 40+NEQ
C if INFO(10) = 1 or 3.
C
C INFO(12) - Except for the addition of the RES argument CJ,
C DDASPK by default is downward-compatible with DDASSL,
C which uses only direct (dense or band) methods to solve
C the linear systems involved. You must set INFO(12) to
C indicate whether you want the direct methods or the
C Krylov iterative method.
C **** Do you want DDASPK to use standard direct methods
C (dense or band) or the Krylov (iterative) method ...
C direct methods - set INFO(12) = 0.
C Krylov method - set INFO(12) = 1,
C and check the settings of INFO(13) and INFO(15).
C
C INFO(13) - used when INFO(12) = 1 (Krylov methods).
C DDASPK uses scalars MAXL, KMP, NRMAX, and EPLI for the
C iterative solution of linear systems. INFO(13) allows
C you to override the default values of these parameters.
C These parameters and their defaults are as follows:
C MAXL = maximum number of iterations in the SPIGMR
C algorithm (MAXL .le. NEQ). The default is
C MAXL = MIN(5,NEQ).
C KMP = number of vectors on which orthogonalization is
C done in the SPIGMR algorithm. The default is
C KMP = MAXL, which corresponds to complete GMRES
C iteration, as opposed to the incomplete form.
C NRMAX = maximum number of restarts of the SPIGMR
C algorithm per nonlinear iteration. The default is
C NRMAX = 5.
C EPLI = convergence test constant in SPIGMR algorithm.
C The default is EPLI = 0.05.
C Note that the length of RWORK depends on both MAXL
C and KMP. See the definition of LRW below.
C **** Are MAXL, KMP, and EPLI to be given their
C default values ...
C yes - set INFO(13) = 0
C no - set INFO(13) = 1,
C and set all of the following:
C IWORK(24) = MAXL (1 .le. MAXL .le. NEQ)
C IWORK(25) = KMP (1 .le. KMP .le. MAXL)
C IWORK(26) = NRMAX (NRMAX .ge. 0)
C RWORK(10) = EPLI (0 .lt. EPLI .lt. 1.0) ****
C
C INFO(14) - used with INFO(11) > 0 (initial condition
C calculation is requested). In this case, you may
C request control to be returned to the calling program
C immediately after the initial condition calculation,
C before proceeding to the integration of the system
C (e.g. to examine the computed Y and YPRIME).
C If this is done, and if the initialization succeeded
C (IDID = 4), you should reset INFO(11) to 0 for the
C next call, to prevent the solver from repeating the
C initialization (and to avoid an infinite loop).
C **** Do you want to proceed to the integration after
C the initial condition calculation is done ...
C yes - set INFO(14) = 0
C no - set INFO(14) = 1 ****
C
C INFO(15) - used when INFO(12) = 1 (Krylov methods).
C When using preconditioning in the Krylov method,
C you must supply a subroutine, PSOL, which solves the
C associated linear systems using P.
C The usage of DDASPK is simpler if PSOL can carry out
C the solution without any prior calculation of data.
C However, if some partial derivative data is to be
C calculated in advance and used repeatedly in PSOL,
C then you must supply a JAC routine to do this,
C and set INFO(15) to indicate that JAC is to be called
C for this purpose. For example, P might be an
C approximation to a part of the matrix A which can be
C calculated and LU-factored for repeated solutions of
C the preconditioner system. The arrays WP and IWP
C (described under JAC and PSOL) can be used to
C communicate data between JAC and PSOL.
C **** Does PSOL operate with no prior preparation ...
C yes - set INFO(15) = 0 (no JAC routine)
C no - set INFO(15) = 1
C and supply a JAC routine to evaluate and
C preprocess any required Jacobian data. ****
C
C INFO(16) - option to exclude algebraic variables from
C the error test.
C **** Do you wish to control errors locally on
C all the variables...
C yes - set INFO(16) = 0
C no - set INFO(16) = 1
C If you have specified INFO(16) = 1, then you
C will also need to identify which are the
C differential and which are the algebraic
C components (algebraic components are components
C whose derivatives do not appear explicitly
C in the function G(T,Y,YPRIME)). You must set:
C IWORK(LID+I) = +1 if Y(I) is a differential
C variable, and
C IWORK(LID+I) = -1 if Y(I) is an algebraic
C variable,
C where LID = 40 if INFO(10) = 0 or 2 and
C LID = 40 + NEQ if INFO(10) = 1 or 3.
C
C INFO(17) - used when INFO(11) > 0 (DDASPK is to do an
C initial condition calculation).
C DDASPK uses several heuristic control quantities in the
C initial condition calculation. They have default values,
C but can also be set by the user using INFO(17).
C These parameters and their defaults are as follows:
C MXNIT = maximum number of Newton iterations
C per Jacobian or preconditioner evaluation.
C The default is:
C MXNIT = 5 in the direct case (INFO(12) = 0), and
C MXNIT = 15 in the Krylov case (INFO(12) = 1).
C MXNJ = maximum number of Jacobian or preconditioner
C evaluations. The default is:
C MXNJ = 6 in the direct case (INFO(12) = 0), and
C MXNJ = 2 in the Krylov case (INFO(12) = 1).
C MXNH = maximum number of values of the artificial
C stepsize parameter H to be tried if INFO(11) = 1.
C The default is MXNH = 5.
C NOTE: the maximum number of Newton iterations
C allowed in all is MXNIT*MXNJ*MXNH if INFO(11) = 1,
C and MXNIT*MXNJ if INFO(11) = 2.
C LSOFF = flag to turn off the linesearch algorithm
C (LSOFF = 0 means linesearch is on, LSOFF = 1 means
C it is turned off). The default is LSOFF = 0.
C STPTOL = minimum scaled step in linesearch algorithm.
C The default is STPTOL = (unit roundoff)**(2/3).
C EPINIT = swing factor in the Newton iteration convergence
C test. The test is applied to the residual vector,
C premultiplied by the approximate Jacobian (in the
C direct case) or the preconditioner (in the Krylov
C case). For convergence, the weighted RMS norm of
C this vector (scaled by the error weights) must be
C less than EPINIT*EPCON, where EPCON = .33 is the
C analogous test constant used in the time steps.
C The default is EPINIT = .01.
C **** Are the initial condition heuristic controls to be
C given their default values...
C yes - set INFO(17) = 0
C no - set INFO(17) = 1,
C and set all of the following:
C IWORK(32) = MXNIT (.GT. 0)
C IWORK(33) = MXNJ (.GT. 0)
C IWORK(34) = MXNH (.GT. 0)
C IWORK(35) = LSOFF ( = 0 or 1)
C RWORK(14) = STPTOL (.GT. 0.0)
C RWORK(15) = EPINIT (.GT. 0.0) ****
C
C INFO(18) - option to get extra printing in initial condition
C calculation.
C **** Do you wish to have extra printing...
C no - set INFO(18) = 0
C yes - set INFO(18) = 1 for minimal printing, or
C set INFO(18) = 2 for full printing.
C If you have specified INFO(18) .ge. 1, data
C will be printed with the error handler routines.
C To print to a non-default unit number L, include
C the line CALL XSETUN(L) in your program. ****
C
C RTOL, ATOL -- You must assign relative (RTOL) and absolute (ATOL)
C error tolerances to tell the code how accurately you
C want the solution to be computed. They must be defined
C as variables because the code may change them.
C you have two choices --
C Both RTOL and ATOL are scalars (INFO(2) = 0), or
C both RTOL and ATOL are vectors (INFO(2) = 1).
C In either case all components must be non-negative.
C
C The tolerances are used by the code in a local error
C test at each step which requires roughly that
C abs(local error in Y(i)) .le. EWT(i) ,
C where EWT(i) = RTOL*abs(Y(i)) + ATOL is an error weight
C quantity, for each vector component.
C (More specifically, a root-mean-square norm is used to
C measure the size of vectors, and the error test uses the
C magnitude of the solution at the beginning of the step.)
C
C The true (global) error is the difference between the
C true solution of the initial value problem and the
C computed approximation. Practically all present day
C codes, including this one, control the local error at
C each step and do not even attempt to control the global
C error directly.
C
C Usually, but not always, the true accuracy of
C the computed Y is comparable to the error tolerances.
C This code will usually, but not always, deliver a more
C accurate solution if you reduce the tolerances and
C integrate again. By comparing two such solutions you
C can get a fairly reliable idea of the true error in the
C solution at the larger tolerances.
C
C Setting ATOL = 0. results in a pure relative error test
C on that component. Setting RTOL = 0. results in a pure
C absolute error test on that component. A mixed test
C with non-zero RTOL and ATOL corresponds roughly to a
C relative error test when the solution component is
C much bigger than ATOL and to an absolute error test
C when the solution component is smaller than the
C threshold ATOL.
C
C The code will not attempt to compute a solution at an
C accuracy unreasonable for the machine being used. It
C will advise you if you ask for too much accuracy and
C inform you as to the maximum accuracy it believes
C possible.
C
C RWORK(*) -- a real work array, which should be dimensioned in your
C calling program with a length equal to the value of
C LRW (or greater).
C
C LRW -- Set it to the declared length of the RWORK array. The
C minimum length depends on the options you have selected,
C given by a base value plus additional storage as described
C below.
C
C If INFO(12) = 0 (standard direct method), the base value is
C base = 50 + max(MAXORD+4,7)*NEQ.
C The default value is MAXORD = 5 (see INFO(9)). With the
C default MAXORD, base = 50 + 9*NEQ.
C Additional storage must be added to the base value for
C any or all of the following options:
C if INFO(6) = 0 (dense matrix), add NEQ**2
C if INFO(6) = 1 (banded matrix), then
C if INFO(5) = 0, add (2*ML+MU+1)*NEQ + 2*(NEQ/(ML+MU+1)+1),
C if INFO(5) = 1, add (2*ML+MU+1)*NEQ,
C if INFO(16) = 1, add NEQ.
C
C If INFO(12) = 1 (Krylov method), the base value is
C base = 50 + (MAXORD+5)*NEQ + (MAXL+3+MIN0(1,MAXL-KMP))*NEQ +
C + (MAXL+3)*MAXL + 1 + LENWP.
C See PSOL for description of LENWP. The default values are:
C MAXORD = 5 (see INFO(9)), MAXL = min(5,NEQ) and KMP = MAXL
C (see INFO(13)).
C With the default values for MAXORD, MAXL and KMP,
C base = 91 + 18*NEQ + LENWP.
C Additional storage must be added to the base value for
C any or all of the following options:
C if INFO(16) = 1, add NEQ.
C
C
C IWORK(*) -- an integer work array, which should be dimensioned in
C your calling program with a length equal to the value
C of LIW (or greater).
C
C LIW -- Set it to the declared length of the IWORK array. The
C minimum length depends on the options you have selected,
C given by a base value plus additional storage as described
C below.
C
C If INFO(12) = 0 (standard direct method), the base value is
C base = 40 + NEQ.
C IF INFO(10) = 1 or 3, add NEQ to the base value.
C If INFO(11) = 1 or INFO(16) =1, add NEQ to the base value.
C
C If INFO(12) = 1 (Krylov method), the base value is
C base = 40 + LENIWP.
C See PSOL for description of LENIWP.
C IF INFO(10) = 1 or 3, add NEQ to the base value.
C If INFO(11) = 1 or INFO(16) = 1, add NEQ to the base value.
C
C
C RPAR, IPAR -- These are arrays of double precision and integer type,
C respectively, which are available for you to use
C for communication between your program that calls
C DDASPK and the RES subroutine (and the JAC and PSOL
C subroutines). They are not altered by DDASPK.
C If you do not need RPAR or IPAR, ignore these
C parameters by treating them as dummy arguments.
C If you do choose to use them, dimension them in
C your calling program and in RES (and in JAC and PSOL)
C as arrays of appropriate length.
C
C JAC -- This is the name of a routine that you may supply
C (optionally) that relates to the Jacobian matrix of the
C nonlinear system that the code must solve at each T step.
C The role of JAC (and its call sequence) depends on whether
C a direct (INFO(12) = 0) or Krylov (INFO(12) = 1) method
C is selected.
C
C **** INFO(12) = 0 (direct methods):
C If you are letting the code generate partial derivatives
C numerically (INFO(5) = 0), then JAC can be absent
C (or perhaps a dummy routine to satisfy the loader).
C Otherwise you must supply a JAC routine to compute
C the matrix A = dG/dY + CJ*dG/dYPRIME. It must have
C the form
C
C SUBROUTINE JAC (T, Y, YPRIME, PD, CJ, RPAR, IPAR)
C
C The JAC routine must dimension Y, YPRIME, and PD (and RPAR
C and IPAR if used). CJ is a scalar which is input to JAC.
C For the given values of T, Y, and YPRIME, the JAC routine
C must evaluate the nonzero elements of the matrix A, and
C store these values in the array PD. The elements of PD are
C set to zero before each call to JAC, so that only nonzero
C elements need to be defined.
C The way you store the elements into the PD array depends
C on the structure of the matrix indicated by INFO(6).
C *** INFO(6) = 0 (full or dense matrix) ***
C Give PD a first dimension of NEQ. When you evaluate the
C nonzero partial derivatives of equation i (i.e. of G(i))
C with respect to component j (of Y and YPRIME), you must
C store the element in PD according to
C PD(i,j) = dG(i)/dY(j) + CJ*dG(i)/dYPRIME(j).
C *** INFO(6) = 1 (banded matrix with half-bandwidths ML, MU
C as described under INFO(6)) ***
C Give PD a first dimension of 2*ML+MU+1. When you
C evaluate the nonzero partial derivatives of equation i
C (i.e. of G(i)) with respect to component j (of Y and
C YPRIME), you must store the element in PD according to
C IROW = i - j + ML + MU + 1
C PD(IROW,j) = dG(i)/dY(j) + CJ*dG(i)/dYPRIME(j).
C
C **** INFO(12) = 1 (Krylov method):
C If you are not calculating Jacobian data in advance for use
C in PSOL (INFO(15) = 0), JAC can be absent (or perhaps a
C dummy routine to satisfy the loader). Otherwise, you may
C supply a JAC routine to compute and preprocess any parts of
C of the Jacobian matrix A = dG/dY + CJ*dG/dYPRIME that are
C involved in the preconditioner matrix P.
C It is to have the form
C
C SUBROUTINE JAC (RES, IRES, NEQ, T, Y, YPRIME, REWT, SAVR,
C WK, H, CJ, WP, IWP, IER, RPAR, IPAR)
C
C The JAC routine must dimension Y, YPRIME, REWT, SAVR, WK,
C and (if used) WP, IWP, RPAR, and IPAR.
C The Y, YPRIME, and SAVR arrays contain the current values
C of Y, YPRIME, and the residual G, respectively.
C The array WK is work space of length NEQ.
C H is the step size. CJ is a scalar, input to JAC, that is
C normally proportional to 1/H. REWT is an array of
C reciprocal error weights, 1/EWT(i), where EWT(i) is
C RTOL*abs(Y(i)) + ATOL (unless you supplied routine DDAWTS
C instead), for use in JAC if needed. For example, if JAC
C computes difference quotient approximations to partial
C derivatives, the REWT array may be useful in setting the
C increments used. The JAC routine should do any
C factorization operations called for, in preparation for
C solving linear systems in PSOL. The matrix P should
C be an approximation to the Jacobian,
C A = dG/dY + CJ*dG/dYPRIME.
C
C WP and IWP are real and integer work arrays which you may
C use for communication between your JAC routine and your
C PSOL routine. These may be used to store elements of the
C preconditioner P, or related matrix data (such as factored
C forms). They are not altered by DDASPK.
C If you do not need WP or IWP, ignore these parameters by
C treating them as dummy arguments. If you do use them,
C dimension them appropriately in your JAC and PSOL routines.
C See the PSOL description for instructions on setting
C the lengths of WP and IWP.
C
C On return, JAC should set the error flag IER as follows..
C IER = 0 if JAC was successful,
C IER .ne. 0 if JAC was unsuccessful (e.g. if Y or YPRIME
C was illegal, or a singular matrix is found).
C (If IER .ne. 0, a smaller stepsize will be tried.)
C IER = 0 on entry to JAC, so need be reset only on a failure.
C If RES is used within JAC, then a nonzero value of IRES will
C override any nonzero value of IER (see the RES description).
C
C Regardless of the method type, subroutine JAC must not
C alter T, Y(*), YPRIME(*), H, CJ, or REWT(*).
C You must declare the name JAC in an EXTERNAL statement in
C your program that calls DDASPK.
C
C PSOL -- This is the name of a routine you must supply if you have
C selected a Krylov method (INFO(12) = 1) with preconditioning.
C In the direct case (INFO(12) = 0), PSOL can be absent
C (a dummy routine may have to be supplied to satisfy the
C loader). Otherwise, you must provide a PSOL routine to
C solve linear systems arising from preconditioning.
C When supplied with INFO(12) = 1, the PSOL routine is to
C have the form
C
C SUBROUTINE PSOL (NEQ, T, Y, YPRIME, SAVR, WK, CJ, WGHT,
C WP, IWP, B, EPLIN, IER, RPAR, IPAR)
C
C The PSOL routine must solve linear systems of the form
C P*x = b where P is the left preconditioner matrix.
C
C The right-hand side vector b is in the B array on input, and
C PSOL must return the solution vector x in B.
C The Y, YPRIME, and SAVR arrays contain the current values
C of Y, YPRIME, and the residual G, respectively.
C
C Work space required by JAC and/or PSOL, and space for data to
C be communicated from JAC to PSOL is made available in the form
C of arrays WP and IWP, which are parts of the RWORK and IWORK
C arrays, respectively. The lengths of these real and integer
C work spaces WP and IWP must be supplied in LENWP and LENIWP,
C respectively, as follows..
C IWORK(27) = LENWP = length of real work space WP
C IWORK(28) = LENIWP = length of integer work space IWP.
C
C WK is a work array of length NEQ for use by PSOL.
C CJ is a scalar, input to PSOL, that is normally proportional
C to 1/H (H = stepsize). If the old value of CJ
C (at the time of the last JAC call) is needed, it must have
C been saved by JAC in WP.
C
C WGHT is an array of weights, to be used if PSOL uses an
C iterative method and performs a convergence test. (In terms
C of the argument REWT to JAC, WGHT is REWT/sqrt(NEQ).)
C If PSOL uses an iterative method, it should use EPLIN
C (a heuristic parameter) as the bound on the weighted norm of
C the residual for the computed solution. Specifically, the
C residual vector R should satisfy
C SQRT (SUM ( (R(i)*WGHT(i))**2 ) ) .le. EPLIN
C
C PSOL must not alter NEQ, T, Y, YPRIME, SAVR, CJ, WGHT, EPLIN.
C
C On return, PSOL should set the error flag IER as follows..
C IER = 0 if PSOL was successful,
C IER .lt. 0 if an unrecoverable error occurred, meaning
C control will be passed to the calling routine,
C IER .gt. 0 if a recoverable error occurred, meaning that
C the step will be retried with the same step size
C but with a call to JAC to update necessary data,
C unless the Jacobian data is current, in which case
C the step will be retried with a smaller step size.
C IER = 0 on entry to PSOL so need be reset only on a failure.
C
C You must declare the name PSOL in an EXTERNAL statement in
C your program that calls DDASPK.
C
C
C OPTIONALLY REPLACEABLE SUBROUTINE:
C
C DDASPK uses a weighted root-mean-square norm to measure the
C size of various error vectors. The weights used in this norm
C are set in the following subroutine:
C
C SUBROUTINE DDAWTS (NEQ, IWT, RTOL, ATOL, Y, EWT, RPAR, IPAR)
C DIMENSION RTOL(*), ATOL(*), Y(*), EWT(*), RPAR(*), IPAR(*)
C
C A DDAWTS routine has been included with DDASPK which sets the
C weights according to
C EWT(I) = RTOL*ABS(Y(I)) + ATOL
C in the case of scalar tolerances (IWT = 0) or
C EWT(I) = RTOL(I)*ABS(Y(I)) + ATOL(I)
C in the case of array tolerances (IWT = 1). (IWT is INFO(2).)
C In some special cases, it may be appropriate for you to define
C your own error weights by writing a subroutine DDAWTS to be
C called instead of the version supplied. However, this should
C be attempted only after careful thought and consideration.
C If you supply this routine, you may use the tolerances and Y
C as appropriate, but do not overwrite these variables. You
C may also use RPAR and IPAR to communicate data as appropriate.
C ***Note: Aside from the values of the weights, the choice of
C norm used in DDASPK (weighted root-mean-square) is not subject
C to replacement by the user. In this respect, DDASPK is not
C downward-compatible with the original DDASSL solver (in which
C the norm routine was optionally user-replaceable).
C
C
C------OUTPUT - AFTER ANY RETURN FROM DDASPK----------------------------
C
C The principal aim of the code is to return a computed solution at
C T = TOUT, although it is also possible to obtain intermediate
C results along the way. To find out whether the code achieved its
C goal or if the integration process was interrupted before the task
C was completed, you must check the IDID parameter.
C
C
C T -- The output value of T is the point to which the solution
C was successfully advanced.
C
C Y(*) -- contains the computed solution approximation at T.
C
C YPRIME(*) -- contains the computed derivative approximation at T.
C
C IDID -- reports what the code did, described as follows:
C
C *** TASK COMPLETED ***
C Reported by positive values of IDID
C
C IDID = 1 -- a step was successfully taken in the
C intermediate-output mode. The code has not
C yet reached TOUT.
C
C IDID = 2 -- the integration to TSTOP was successfully
C completed (T = TSTOP) by stepping exactly to TSTOP.
C
C IDID = 3 -- the integration to TOUT was successfully
C completed (T = TOUT) by stepping past TOUT.
C Y(*) and YPRIME(*) are obtained by interpolation.
C
C IDID = 4 -- the initial condition calculation, with
C INFO(11) > 0, was successful, and INFO(14) = 1.
C No integration steps were taken, and the solution
C is not considered to have been started.
C
C *** TASK INTERRUPTED ***
C Reported by negative values of IDID
C
C IDID = -1 -- a large amount of work has been expended
C (about 500 steps).
C
C IDID = -2 -- the error tolerances are too stringent.
C
C IDID = -3 -- the local error test cannot be satisfied
C because you specified a zero component in ATOL
C and the corresponding computed solution component
C is zero. Thus, a pure relative error test is
C impossible for this component.
C
C IDID = -5 -- there were repeated failures in the evaluation
C or processing of the preconditioner (in JAC).
C
C IDID = -6 -- DDASPK had repeated error test failures on the
C last attempted step.
C
C IDID = -7 -- the nonlinear system solver in the time integration
C could not converge.
C
C IDID = -8 -- the matrix of partial derivatives appears
C to be singular (direct method).
C
C IDID = -9 -- the nonlinear system solver in the time integration
C failed to achieve convergence, and there were repeated
C error test failures in this step.
C
C IDID =-10 -- the nonlinear system solver in the time integration
C failed to achieve convergence because IRES was equal
C to -1.
C
C IDID =-11 -- IRES = -2 was encountered and control is
C being returned to the calling program.
C
C IDID =-12 -- DDASPK failed to compute the initial Y, YPRIME.
C
C IDID =-13 -- unrecoverable error encountered inside user's
C PSOL routine, and control is being returned to
C the calling program.
C
C IDID =-14 -- the Krylov linear system solver could not
C achieve convergence.
C
C IDID =-15,..,-32 -- Not applicable for this code.
C
C *** TASK TERMINATED ***
C reported by the value of IDID=-33
C
C IDID = -33 -- the code has encountered trouble from which
C it cannot recover. A message is printed
C explaining the trouble and control is returned
C to the calling program. For example, this occurs
C when invalid input is detected.
C
C RTOL, ATOL -- these quantities remain unchanged except when
C IDID = -2. In this case, the error tolerances have been
C increased by the code to values which are estimated to
C be appropriate for continuing the integration. However,
C the reported solution at T was obtained using the input
C values of RTOL and ATOL.
C
C RWORK, IWORK -- contain information which is usually of no interest
C to the user but necessary for subsequent calls.
C However, you may be interested in the performance data
C listed below. These quantities are accessed in RWORK
C and IWORK but have internal mnemonic names, as follows..
C
C RWORK(3)--contains H, the step size h to be attempted
C on the next step.
C
C RWORK(4)--contains TN, the current value of the
C independent variable, i.e. the farthest point
C integration has reached. This will differ
C from T if interpolation has been performed
C (IDID = 3).
C
C RWORK(7)--contains HOLD, the stepsize used on the last
C successful step. If INFO(11) = INFO(14) = 1,
C this contains the value of H used in the
C initial condition calculation.
C
C IWORK(7)--contains K, the order of the method to be
C attempted on the next step.
C
C IWORK(8)--contains KOLD, the order of the method used
C on the last step.
C
C IWORK(11)--contains NST, the number of steps (in T)
C taken so far.
C
C IWORK(12)--contains NRE, the number of calls to RES
C so far.
C
C IWORK(13)--contains NJE, the number of calls to JAC so
C far (Jacobian or preconditioner evaluations).
C
C IWORK(14)--contains NETF, the total number of error test
C failures so far.
C
C IWORK(15)--contains NCFN, the total number of nonlinear
C convergence failures so far (includes counts
C of singular iteration matrix or singular
C preconditioners).
C
C IWORK(16)--contains NCFL, the number of convergence
C failures of the linear iteration so far.
C
C IWORK(17)--contains LENIW, the length of IWORK actually
C required. This is defined on normal returns
C and on an illegal input return for
C insufficient storage.
C
C IWORK(18)--contains LENRW, the length of RWORK actually
C required. This is defined on normal returns
C and on an illegal input return for
C insufficient storage.
C
C IWORK(19)--contains NNI, the total number of nonlinear
C iterations so far (each of which calls a
C linear solver).
C
C IWORK(20)--contains NLI, the total number of linear
C (Krylov) iterations so far.
C
C IWORK(21)--contains NPS, the number of PSOL calls so
C far, for preconditioning solve operations or
C for solutions with the user-supplied method.
C
C Note: The various counters in IWORK do not include
C counts during a call made with INFO(11) > 0 and
C INFO(14) = 1.
C
C
C------INPUT - WHAT TO DO TO CONTINUE THE INTEGRATION -----------------
C (CALLS AFTER THE FIRST)
C
C This code is organized so that subsequent calls to continue the
C integration involve little (if any) additional effort on your
C part. You must monitor the IDID parameter in order to determine
C what to do next.
C
C Recalling that the principal task of the code is to integrate
C from T to TOUT (the interval mode), usually all you will need
C to do is specify a new TOUT upon reaching the current TOUT.
C
C Do not alter any quantity not specifically permitted below. In
C particular do not alter NEQ, T, Y(*), YPRIME(*), RWORK(*),
C IWORK(*), or the differential equation in subroutine RES. Any
C such alteration constitutes a new problem and must be treated
C as such, i.e. you must start afresh.
C
C You cannot change from array to scalar error control or vice
C versa (INFO(2)), but you can change the size of the entries of
C RTOL or ATOL. Increasing a tolerance makes the equation easier
C to integrate. Decreasing a tolerance will make the equation
C harder to integrate and should generally be avoided.
C
C You can switch from the intermediate-output mode to the
C interval mode (INFO(3)) or vice versa at any time.
C
C If it has been necessary to prevent the integration from going
C past a point TSTOP (INFO(4), RWORK(1)), keep in mind that the
C code will not integrate to any TOUT beyond the currently
C specified TSTOP. Once TSTOP has been reached, you must change
C the value of TSTOP or set INFO(4) = 0. You may change INFO(4)
C or TSTOP at any time but you must supply the value of TSTOP in
C RWORK(1) whenever you set INFO(4) = 1.
C
C Do not change INFO(5), INFO(6), INFO(12-17) or their associated
C IWORK/RWORK locations unless you are going to restart the code.
C
C *** FOLLOWING A COMPLETED TASK ***
C
C If..
C IDID = 1, call the code again to continue the integration
C another step in the direction of TOUT.
C
C IDID = 2 or 3, define a new TOUT and call the code again.
C TOUT must be different from T. You cannot change
C the direction of integration without restarting.
C
C IDID = 4, reset INFO(11) = 0 and call the code again to begin
C the integration. (If you leave INFO(11) > 0 and
C INFO(14) = 1, you may generate an infinite loop.)
C In this situation, the next call to DASPK is
C considered to be the first call for the problem,
C in that all initializations are done.
C
C *** FOLLOWING AN INTERRUPTED TASK ***
C
C To show the code that you realize the task was interrupted and
C that you want to continue, you must take appropriate action and
C set INFO(1) = 1.
C
C If..
C IDID = -1, the code has taken about 500 steps. If you want to
C continue, set INFO(1) = 1 and call the code again.
C An additional 500 steps will be allowed.
C
C
C IDID = -2, the error tolerances RTOL, ATOL have been increased
C to values the code estimates appropriate for
C continuing. You may want to change them yourself.
C If you are sure you want to continue with relaxed
C error tolerances, set INFO(1) = 1 and call the code
C again.
C
C IDID = -3, a solution component is zero and you set the
C corresponding component of ATOL to zero. If you
C are sure you want to continue, you must first alter
C the error criterion to use positive values of ATOL
C for those components corresponding to zero solution
C components, then set INFO(1) = 1 and call the code
C again.
C
C IDID = -4 --- cannot occur with this code.
C
C IDID = -5, your JAC routine failed with the Krylov method. Check
C for errors in JAC and restart the integration.
C
C IDID = -6, repeated error test failures occurred on the last
C attempted step in DDASPK. A singularity in the
C solution may be present. If you are absolutely
C certain you want to continue, you should restart
C the integration. (Provide initial values of Y and
C YPRIME which are consistent.)
C
C IDID = -7, repeated convergence test failures occurred on the last
C attempted step in DDASPK. An inaccurate or ill-
C conditioned Jacobian or preconditioner may be the
C problem. If you are absolutely certain you want
C to continue, you should restart the integration.
C
C
C IDID = -8, the matrix of partial derivatives is singular, with
C the use of direct methods. Some of your equations
C may be redundant. DDASPK cannot solve the problem
C as stated. It is possible that the redundant
C equations could be removed, and then DDASPK could
C solve the problem. It is also possible that a
C solution to your problem either does not exist
C or is not unique.
C
C IDID = -9, DDASPK had multiple convergence test failures, preceded
C by multiple error test failures, on the last
C attempted step. It is possible that your problem is
C ill-posed and cannot be solved using this code. Or,
C there may be a discontinuity or a singularity in the
C solution. If you are absolutely certain you want to
C continue, you should restart the integration.
C
C IDID = -10, DDASPK had multiple convergence test failures
C because IRES was equal to -1. If you are
C absolutely certain you want to continue, you
C should restart the integration.
C
C IDID = -11, there was an unrecoverable error (IRES = -2) from RES
C inside the nonlinear system solver. Determine the
C cause before trying again.
C
C IDID = -12, DDASPK failed to compute the initial Y and YPRIME
C vectors. This could happen because the initial
C approximation to Y or YPRIME was not very good, or
C because no consistent values of these vectors exist.
C The problem could also be caused by an inaccurate or
C singular iteration matrix, or a poor preconditioner.
C
C IDID = -13, there was an unrecoverable error encountered inside
C your PSOL routine. Determine the cause before
C trying again.
C
C IDID = -14, the Krylov linear system solver failed to achieve
C convergence. This may be due to ill-conditioning
C in the iteration matrix, or a singularity in the
C preconditioner (if one is being used).
C Another possibility is that there is a better
C choice of Krylov parameters (see INFO(13)).
C Possibly the failure is caused by redundant equations
C in the system, or by inconsistent equations.
C In that case, reformulate the system to make it
C consistent and non-redundant.
C
C IDID = -15,..,-32 --- Cannot occur with this code.
C
C *** FOLLOWING A TERMINATED TASK ***
C
C If IDID = -33, you cannot continue the solution of this problem.
C An attempt to do so will result in your run being
C terminated.
C
C ---------------------------------------------------------------------
C
C***REFERENCES
C 1. L. R. Petzold, A Description of DASSL: A Differential/Algebraic
C System Solver, in Scientific Computing, R. S. Stepleman et al.
C (Eds.), North-Holland, Amsterdam, 1983, pp. 65-68.
C 2. K. E. Brenan, S. L. Campbell, and L. R. Petzold, Numerical
C Solution of Initial-Value Problems in Differential-Algebraic
C Equations, Elsevier, New York, 1989.
C 3. P. N. Brown and A. C. Hindmarsh, Reduced Storage Matrix Methods
C in Stiff ODE Systems, J. Applied Mathematics and Computation,
C 31 (1989), pp. 40-91.
C 4. P. N. Brown, A. C. Hindmarsh, and L. R. Petzold, Using Krylov
C Methods in the Solution of Large-Scale Differential-Algebraic
C Systems, SIAM J. Sci. Comp., 15 (1994), pp. 1467-1488.
C 5. P. N. Brown, A. C. Hindmarsh, and L. R. Petzold, Consistent
C Initial Condition Calculation for Differential-Algebraic
C Systems, SIAM J. Sci. Comp. 19 (1998), pp. 1495-1512.
C
C***ROUTINES CALLED
C
C The following are all the subordinate routines used by DDASPK.
C
C DDASIC computes consistent initial conditions.
C DYYPNW updates Y and YPRIME in linesearch for initial condition
C calculation.
C DDSTP carries out one step of the integration.
C DCNSTR/DCNST0 check the current solution for constraint violations.
C DDAWTS sets error weight quantities.
C DINVWT tests and inverts the error weights.
C DDATRP performs interpolation to get an output solution.
C DDWNRM computes the weighted root-mean-square norm of a vector.
C D1MACH provides the unit roundoff of the computer.
C XERRWD/XSETF/XSETUN/IXSAV is a package to handle error messages.
C DDASID nonlinear equation driver to initialize Y and YPRIME using
C direct linear system solver methods. Interfaces to Newton
C solver (direct case).
C DNSID solves the nonlinear system for unknown initial values by
C modified Newton iteration and direct linear system methods.
C DLINSD carries out linesearch algorithm for initial condition
C calculation (direct case).
C DFNRMD calculates weighted norm of preconditioned residual in
C initial condition calculation (direct case).
C DNEDD nonlinear equation driver for direct linear system solver
C methods. Interfaces to Newton solver (direct case).
C DMATD assembles the iteration matrix (direct case).
C DNSD solves the associated nonlinear system by modified
C Newton iteration and direct linear system methods.
C DSLVD interfaces to linear system solver (direct case).
C DDASIK nonlinear equation driver to initialize Y and YPRIME using
C Krylov iterative linear system methods. Interfaces to
C Newton solver (Krylov case).
C DNSIK solves the nonlinear system for unknown initial values by
C Newton iteration and Krylov iterative linear system methods.
C DLINSK carries out linesearch algorithm for initial condition
C calculation (Krylov case).
C DFNRMK calculates weighted norm of preconditioned residual in
C initial condition calculation (Krylov case).
C DNEDK nonlinear equation driver for iterative linear system solver
C methods. Interfaces to Newton solver (Krylov case).
C DNSK solves the associated nonlinear system by Inexact Newton
C iteration and (linear) Krylov iteration.
C DSLVK interfaces to linear system solver (Krylov case).
C DSPIGM solves a linear system by SPIGMR algorithm.
C DATV computes matrix-vector product in Krylov algorithm.
C DORTH performs orthogonalization of Krylov basis vectors.
C DHEQR performs QR factorization of Hessenberg matrix.
C DHELS finds least-squares solution of Hessenberg linear system.
C DGEFA, DGESL, DGBFA, DGBSL are LINPACK routines for solving
C linear systems (dense or band direct methods).
C DAXPY, DCOPY, DDOT, DNRM2, DSCAL are Basic Linear Algebra (BLAS)
C routines.
C
C The routines called directly by DDASPK are:
C DCNST0, DDAWTS, DINVWT, D1MACH, DDWNRM, DDASIC, DDATRP, DDSTP,
C XERRWD
C
C***END PROLOGUE DDASPK
C
C
IMPLICIT DOUBLE PRECISION(A-H,O-Z)
LOGICAL DONE, LAVL, LCFN, LCFL, LWARN
DIMENSION Y(*),YPRIME(*)
DIMENSION INFO(20)
DIMENSION RWORK(LRW),IWORK(LIW)
DIMENSION RTOL(*),ATOL(*)
DIMENSION RPAR(*),IPAR(*)
CHARACTER MSG*80
EXTERNAL RES, JAC, PSOL, DDASID, DDASIK, DNEDD, DNEDK
C
C Set pointers into IWORK.
C
PARAMETER (LML=1, LMU=2, LMTYPE=4,
* LIWM=1, LMXORD=3, LJCALC=5, LPHASE=6, LK=7, LKOLD=8,
* LNS=9, LNSTL=10, LNST=11, LNRE=12, LNJE=13, LETF=14, LNCFN=15,
* LNCFL=16, LNIW=17, LNRW=18, LNNI=19, LNLI=20, LNPS=21,
* LNPD=22, LMITER=23, LMAXL=24, LKMP=25, LNRMAX=26, LLNWP=27,
* LLNIWP=28, LLOCWP=29, LLCIWP=30, LKPRIN=31,
* LMXNIT=32, LMXNJ=33, LMXNH=34, LLSOFF=35, LICNS=41)
C
C Set pointers into RWORK.
C
PARAMETER (LTSTOP=1, LHMAX=2, LH=3, LTN=4, LCJ=5, LCJOLD=6,
* LHOLD=7, LS=8, LROUND=9, LEPLI=10, LSQRN=11, LRSQRN=12,
* LEPCON=13, LSTOL=14, LEPIN=15,
* LALPHA=21, LBETA=27, LGAMMA=33, LPSI=39, LSIGMA=45, LDELTA=51)
C
SAVE LID, LENID, NONNEG, NCPHI
C
C
C***FIRST EXECUTABLE STATEMENT DDASPK
C
C
IF(INFO(1).NE.0) GO TO 100
C
C-----------------------------------------------------------------------
C This block is executed for the initial call only.
C It contains checking of inputs and initializations.
C-----------------------------------------------------------------------
C
C First check INFO array to make sure all elements of INFO
C Are within the proper range. (INFO(1) is checked later, because
C it must be tested on every call.) ITEMP holds the location
C within INFO which may be out of range.
C
DO 10 I=2,9
ITEMP = I
IF (INFO(I) .NE. 0 .AND. INFO(I) .NE. 1) GO TO 701
10 CONTINUE
ITEMP = 10
IF(INFO(10).LT.0 .OR. INFO(10).GT.3) GO TO 701
ITEMP = 11
IF(INFO(11).LT.0 .OR. INFO(11).GT.2) GO TO 701
DO 15 I=12,17
ITEMP = I
IF (INFO(I) .NE. 0 .AND. INFO(I) .NE. 1) GO TO 701
15 CONTINUE
ITEMP = 18
IF(INFO(18).LT.0 .OR. INFO(18).GT.2) GO TO 701
C
C Check NEQ to see if it is positive.
C
IF (NEQ .LE. 0) GO TO 702
C
C Check and compute maximum order.
C
MXORD=5
IF (INFO(9) .NE. 0) THEN
MXORD=IWORK(LMXORD)
IF (MXORD .LT. 1 .OR. MXORD .GT. 5) GO TO 703
ENDIF
IWORK(LMXORD)=MXORD
C
C Set and/or check inputs for constraint checking (INFO(10) .NE. 0).
C Set values for ICNFLG, NONNEG, and pointer LID.
C
ICNFLG = 0
NONNEG = 0
LID = LICNS
IF (INFO(10) .EQ. 0) GO TO 20
IF (INFO(10) .EQ. 1) THEN
ICNFLG = 1
NONNEG = 0
LID = LICNS + NEQ
ELSEIF (INFO(10) .EQ. 2) THEN
ICNFLG = 0
NONNEG = 1
ELSE
ICNFLG = 1
NONNEG = 1
LID = LICNS + NEQ
ENDIF
C
20 CONTINUE
C
C Set and/or check inputs for Krylov solver (INFO(12) .NE. 0).
C If indicated, set default values for MAXL, KMP, NRMAX, and EPLI.
C Otherwise, verify inputs required for iterative solver.
C
IF (INFO(12) .EQ. 0) GO TO 25
C
IWORK(LMITER) = INFO(12)
IF (INFO(13) .EQ. 0) THEN
IWORK(LMAXL) = MIN(5,NEQ)
IWORK(LKMP) = IWORK(LMAXL)
IWORK(LNRMAX) = 5
RWORK(LEPLI) = 0.05D0
ELSE
IF(IWORK(LMAXL) .LT. 1 .OR. IWORK(LMAXL) .GT. NEQ) GO TO 720
IF(IWORK(LKMP) .LT. 1 .OR. IWORK(LKMP) .GT. IWORK(LMAXL))
1 GO TO 721
IF(IWORK(LNRMAX) .LT. 0) GO TO 722
IF(RWORK(LEPLI).LE.0.0D0 .OR. RWORK(LEPLI).GE.1.0D0)GO TO 723
ENDIF
C
25 CONTINUE
C
C Set and/or check controls for the initial condition calculation
C (INFO(11) .GT. 0). If indicated, set default values.
C Otherwise, verify inputs required for iterative solver.
C
IF (INFO(11) .EQ. 0) GO TO 30
IF (INFO(17) .EQ. 0) THEN
IWORK(LMXNIT) = 5
IF (INFO(12) .GT. 0) IWORK(LMXNIT) = 15
IWORK(LMXNJ) = 6
IF (INFO(12) .GT. 0) IWORK(LMXNJ) = 2
IWORK(LMXNH) = 5
IWORK(LLSOFF) = 0
RWORK(LEPIN) = 0.01D0
ELSE
IF (IWORK(LMXNIT) .LE. 0) GO TO 725
IF (IWORK(LMXNJ) .LE. 0) GO TO 725
IF (IWORK(LMXNH) .LE. 0) GO TO 725
LSOFF = IWORK(LLSOFF)
IF (LSOFF .LT. 0 .OR. LSOFF .GT. 1) GO TO 725
IF (RWORK(LEPIN) .LE. 0.0D0) GO TO 725
ENDIF
C
30 CONTINUE
C
C Below is the computation and checking of the work array lengths
C LENIW and LENRW, using direct methods (INFO(12) = 0) or
C the Krylov methods (INFO(12) = 1).
C
LENIC = 0
IF (INFO(10) .EQ. 1 .OR. INFO(10) .EQ. 3) LENIC = NEQ
LENID = 0
IF (INFO(11) .EQ. 1 .OR. INFO(16) .EQ. 1) LENID = NEQ
IF (INFO(12) .EQ. 0) THEN
C
C Compute MTYPE, etc. Check ML and MU.
C
NCPHI = MAX(MXORD + 1, 4)
IF(INFO(6).EQ.0) THEN
LENPD = NEQ**2
LENRW = 50 + (NCPHI+3)*NEQ + LENPD
IF(INFO(5).EQ.0) THEN
IWORK(LMTYPE)=2
ELSE
IWORK(LMTYPE)=1
ENDIF
ELSE
IF(IWORK(LML).LT.0.OR.IWORK(LML).GE.NEQ)GO TO 717
IF(IWORK(LMU).LT.0.OR.IWORK(LMU).GE.NEQ)GO TO 718
LENPD=(2*IWORK(LML)+IWORK(LMU)+1)*NEQ
IF(INFO(5).EQ.0) THEN
IWORK(LMTYPE)=5
MBAND=IWORK(LML)+IWORK(LMU)+1
MSAVE=(NEQ/MBAND)+1
LENRW = 50 + (NCPHI+3)*NEQ + LENPD + 2*MSAVE
ELSE
IWORK(LMTYPE)=4
LENRW = 50 + (NCPHI+3)*NEQ + LENPD
ENDIF
ENDIF
C
C Compute LENIW, LENWP, LENIWP.
C
LENIW = 40 + LENIC + LENID + NEQ
LENWP = 0
LENIWP = 0
C
ELSE IF (INFO(12) .EQ. 1) THEN
NCPHI = MXORD + 1
MAXL = IWORK(LMAXL)
LENWP = IWORK(LLNWP)
LENIWP = IWORK(LLNIWP)
LENPD = (MAXL+3+MIN0(1,MAXL-IWORK(LKMP)))*NEQ
1 + (MAXL+3)*MAXL + 1 + LENWP
LENRW = 50 + (MXORD+5)*NEQ + LENPD
LENIW = 40 + LENIC + LENID + LENIWP
C
ENDIF
IF(INFO(16) .NE. 0) LENRW = LENRW + NEQ
C
C Check lengths of RWORK and IWORK.
C
IWORK(LNIW)=LENIW
IWORK(LNRW)=LENRW
IWORK(LNPD)=LENPD
IWORK(LLOCWP) = LENPD-LENWP+1
IF(LRW.LT.LENRW)GO TO 704
IF(LIW.LT.LENIW)GO TO 705
C
C Check ICNSTR for legality.
C
IF (LENIC .GT. 0) THEN
DO 40 I = 1,NEQ
ICI = IWORK(LICNS-1+I)
IF (ICI .LT. -2 .OR. ICI .GT. 2) GO TO 726
40 CONTINUE
ENDIF
C
C Check Y for consistency with constraints.
C
IF (LENIC .GT. 0) THEN
CALL DCNST0(NEQ,Y,IWORK(LICNS),IRET)
IF (IRET .NE. 0) GO TO 727
ENDIF
C
C Check ID for legality and set INDEX = 0 or 1.
C
INDEX = 1
IF (LENID .GT. 0) THEN
INDEX = 0
DO 50 I = 1,NEQ
IDI = IWORK(LID-1+I)
IF (IDI .NE. 1 .AND. IDI .NE. -1) GO TO 724
IF (IDI .EQ. -1) INDEX = 1
50 CONTINUE
ENDIF
C
C Check to see that TOUT is different from T.
C
IF(TOUT .EQ. T)GO TO 719
C
C Check HMAX.
C
IF(INFO(7) .NE. 0) THEN
HMAX = RWORK(LHMAX)
IF (HMAX .LE. 0.0D0) GO TO 710
ENDIF
C
C Initialize counters and other flags.
C
IWORK(LNST)=0
IWORK(LNRE)=0
IWORK(LNJE)=0
IWORK(LETF)=0
IWORK(LNCFN)=0
IWORK(LNNI)=0
IWORK(LNLI)=0
IWORK(LNPS)=0
IWORK(LNCFL)=0
IWORK(LKPRIN)=INFO(18)
IDID=1
GO TO 200
C
C-----------------------------------------------------------------------
C This block is for continuation calls only.
C Here we check INFO(1), and if the last step was interrupted,
C we check whether appropriate action was taken.
C-----------------------------------------------------------------------
C
100 CONTINUE
IF(INFO(1).EQ.1)GO TO 110
ITEMP = 1
IF(INFO(1).NE.-1)GO TO 701
C
C If we are here, the last step was interrupted by an error
C condition from DDSTP, and appropriate action was not taken.
C This is a fatal error.
C
MSG = 'DASPK-- THE LAST STEP TERMINATED WITH A NEGATIVE'
CALL XERRWD(MSG,49,201,0,0,0,0,0,0.0D0,0.0D0)
MSG = 'DASPK-- VALUE (=I1) OF IDID AND NO APPROPRIATE'
CALL XERRWD(MSG,47,202,0,1,IDID,0,0,0.0D0,0.0D0)
MSG = 'DASPK-- ACTION WAS TAKEN. RUN TERMINATED'
CALL XERRWD(MSG,41,203,1,0,0,0,0,0.0D0,0.0D0)
RETURN
110 CONTINUE
C
C-----------------------------------------------------------------------
C This block is executed on all calls.
C
C Counters are saved for later checks of performance.
C Then the error tolerance parameters are checked, and the
C work array pointers are set.
C-----------------------------------------------------------------------
C
200 CONTINUE
C
C Save counters for use later.
C
IWORK(LNSTL)=IWORK(LNST)
NLI0 = IWORK(LNLI)
NNI0 = IWORK(LNNI)
NCFN0 = IWORK(LNCFN)
NCFL0 = IWORK(LNCFL)
NWARN = 0
C
C Check RTOL and ATOL.
C
NZFLG = 0
RTOLI = RTOL(1)
ATOLI = ATOL(1)
DO 210 I=1,NEQ
IF (INFO(2) .EQ. 1) RTOLI = RTOL(I)
IF (INFO(2) .EQ. 1) ATOLI = ATOL(I)
IF (RTOLI .GT. 0.0D0 .OR. ATOLI .GT. 0.0D0) NZFLG = 1
IF (RTOLI .LT. 0.0D0) GO TO 706
IF (ATOLI .LT. 0.0D0) GO TO 707
210 CONTINUE
IF (NZFLG .EQ. 0) GO TO 708
C
C Set pointers to RWORK and IWORK segments.
C For direct methods, SAVR is not used.
C
IWORK(LLCIWP) = LID + LENID
LSAVR = LDELTA
IF (INFO(12) .NE. 0) LSAVR = LDELTA + NEQ
LE = LSAVR + NEQ
LWT = LE + NEQ
LVT = LWT
IF (INFO(16) .NE. 0) LVT = LWT + NEQ
LPHI = LVT + NEQ
LWM = LPHI + NCPHI*NEQ
IF (INFO(1) .EQ. 1) GO TO 400
C
C-----------------------------------------------------------------------
C This block is executed on the initial call only.
C Set the initial step size, the error weight vector, and PHI.
C Compute unknown initial components of Y and YPRIME, if requested.
C-----------------------------------------------------------------------
C
300 CONTINUE
TN=T
IDID=1
C
C Set error weight array WT and altered weight array VT.
C
CALL DDAWTS(NEQ,INFO(2),RTOL,ATOL,Y,RWORK(LWT),RPAR,IPAR)
CALL DINVWT(NEQ,RWORK(LWT),IER)
IF (IER .NE. 0) GO TO 713
IF (INFO(16) .NE. 0) THEN
DO 305 I = 1, NEQ
305 RWORK(LVT+I-1) = MAX(IWORK(LID+I-1),0)*RWORK(LWT+I-1)
ENDIF
C
C Compute unit roundoff and HMIN.
C
UROUND = D1MACH(4)
RWORK(LROUND) = UROUND
HMIN = 4.0D0*UROUND*MAX(ABS(T),ABS(TOUT))
C
C Set/check STPTOL control for initial condition calculation.
C
IF (INFO(11) .NE. 0) THEN
IF( INFO(17) .EQ. 0) THEN
RWORK(LSTOL) = UROUND**.6667D0
ELSE
IF (RWORK(LSTOL) .LE. 0.0D0) GO TO 725
ENDIF
ENDIF
C
C Compute EPCON and square root of NEQ and its reciprocal, used
C inside iterative solver.
C
RWORK(LEPCON) = 0.33D0
FLOATN = NEQ
RWORK(LSQRN) = SQRT(FLOATN)
RWORK(LRSQRN) = 1.D0/RWORK(LSQRN)
C
C Check initial interval to see that it is long enough.
C
TDIST = ABS(TOUT - T)
IF(TDIST .LT. HMIN) GO TO 714
C
C Check H0, if this was input.
C
IF (INFO(8) .EQ. 0) GO TO 310
H0 = RWORK(LH)
IF ((TOUT - T)*H0 .LT. 0.0D0) GO TO 711
IF (H0 .EQ. 0.0D0) GO TO 712
GO TO 320
310 CONTINUE
C
C Compute initial stepsize, to be used by either
C DDSTP or DDASIC, depending on INFO(11).
C
H0 = 0.001D0*TDIST
YPNORM = DDWNRM(NEQ,YPRIME,RWORK(LVT),RPAR,IPAR)
IF (YPNORM .GT. 0.5D0/H0) H0 = 0.5D0/YPNORM
H0 = SIGN(H0,TOUT-T)
C
C Adjust H0 if necessary to meet HMAX bound.
C
320 IF (INFO(7) .EQ. 0) GO TO 330
RH = ABS(H0)/RWORK(LHMAX)
IF (RH .GT. 1.0D0) H0 = H0/RH
C
C Check against TSTOP, if applicable.
C
330 IF (INFO(4) .EQ. 0) GO TO 340
TSTOP = RWORK(LTSTOP)
write(*,*) 'tstop = ',tstop
IF ((TSTOP - T)*H0 .LT. 0.0D0) GO TO 715
IF ((T + H0 - TSTOP)*H0 .GT. 0.0D0) H0 = TSTOP - T
IF ((TSTOP - TOUT)*H0 .LT. 0.0D0) GO TO 709
C
340 IF (INFO(11) .EQ. 0) GO TO 370
C
C Compute unknown components of initial Y and YPRIME, depending
C on INFO(11) and INFO(12). INFO(12) represents the nonlinear
C solver type (direct/Krylov). Pass the name of the specific
C nonlinear solver, depending on INFO(12). The location of the work
C arrays SAVR, YIC, YPIC, PWK also differ in the two cases.
C For use in stopping tests, pass TSCALE = TDIST if INDEX = 0.
C
NWT = 1
EPCONI = RWORK(LEPIN)*RWORK(LEPCON)
TSCALE = 0.0D0
IF (INDEX .EQ. 0) TSCALE = TDIST
350 IF (INFO(12) .EQ. 0) THEN
LYIC = LPHI + 2*NEQ
LYPIC = LYIC + NEQ
LPWK = LYPIC
CALL DDASIC(TN,Y,YPRIME,NEQ,INFO(11),IWORK(LID),
* RES,JAC,PSOL,H0,TSCALE,RWORK(LWT),NWT,IDID,RPAR,IPAR,
* RWORK(LPHI),RWORK(LSAVR),RWORK(LDELTA),RWORK(LE),
* RWORK(LYIC),RWORK(LYPIC),RWORK(LPWK),RWORK(LWM),IWORK(LIWM),
* RWORK(LROUND),RWORK(LEPLI),RWORK(LSQRN),RWORK(LRSQRN),
* EPCONI,RWORK(LSTOL),INFO(15),ICNFLG,IWORK(LICNS),DDASID)
ELSE IF (INFO(12) .EQ. 1) THEN
LYIC = LWM
LYPIC = LYIC + NEQ
LPWK = LYPIC + NEQ
CALL DDASIC(TN,Y,YPRIME,NEQ,INFO(11),IWORK(LID),
* RES,JAC,PSOL,H0,TSCALE,RWORK(LWT),NWT,IDID,RPAR,IPAR,
* RWORK(LPHI),RWORK(LSAVR),RWORK(LDELTA),RWORK(LE),
* RWORK(LYIC),RWORK(LYPIC),RWORK(LPWK),RWORK(LWM),IWORK(LIWM),
* RWORK(LROUND),RWORK(LEPLI),RWORK(LSQRN),RWORK(LRSQRN),
* EPCONI,RWORK(LSTOL),INFO(15),ICNFLG,IWORK(LICNS),DDASIK)
ENDIF
C
IF (IDID .LT. 0) GO TO 600
C
C DDASIC was successful. If this was the first call to DDASIC,
C update the WT array (with the current Y) and call it again.
C
IF (NWT .EQ. 2) GO TO 355
NWT = 2
CALL DDAWTS(NEQ,INFO(2),RTOL,ATOL,Y,RWORK(LWT),RPAR,IPAR)
CALL DINVWT(NEQ,RWORK(LWT),IER)
IF (IER .NE. 0) GO TO 713
GO TO 350
C
C If INFO(14) = 1, return now with IDID = 4.
C
355 IF (INFO(14) .EQ. 1) THEN
IDID = 4
H = H0
IF (INFO(11) .EQ. 1) RWORK(LHOLD) = H0
GO TO 590
ENDIF
C
C Update the WT and VT arrays one more time, with the new Y.
C
CALL DDAWTS(NEQ,INFO(2),RTOL,ATOL,Y,RWORK(LWT),RPAR,IPAR)
CALL DINVWT(NEQ,RWORK(LWT),IER)
IF (IER .NE. 0) GO TO 713
IF (INFO(16) .NE. 0) THEN
DO 357 I = 1, NEQ
357 RWORK(LVT+I-1) = MAX(IWORK(LID+I-1),0)*RWORK(LWT+I-1)
ENDIF
C
C Reset the initial stepsize to be used by DDSTP.
C Use H0, if this was input. Otherwise, recompute H0,
C and adjust it if necessary to meet HMAX bound.
C
IF (INFO(8) .NE. 0) THEN
H0 = RWORK(LH)
GO TO 360
ENDIF
C
H0 = 0.001D0*TDIST
YPNORM = DDWNRM(NEQ,YPRIME,RWORK(LVT),RPAR,IPAR)
IF (YPNORM .GT. 0.5D0/H0) H0 = 0.5D0/YPNORM
H0 = SIGN(H0,TOUT-T)
C
360 IF (INFO(7) .NE. 0) THEN
RH = ABS(H0)/RWORK(LHMAX)
IF (RH .GT. 1.0D0) H0 = H0/RH
ENDIF
C
C Check against TSTOP, if applicable.
C
IF (INFO(4) .NE. 0) THEN
TSTOP = RWORK(LTSTOP)
write(*,*) 'tstop = ',tstop
IF ((T + H0 - TSTOP)*H0 .GT. 0.0D0) H0 = TSTOP - T
ENDIF
C
C Load H and RWORK(LH) with H0.
C
370 H = H0
RWORK(LH) = H
C
C Load Y and H*YPRIME into PHI(*,1) and PHI(*,2).
C
ITEMP = LPHI + NEQ
DO 380 I = 1,NEQ
RWORK(LPHI + I - 1) = Y(I)
380 RWORK(ITEMP + I - 1) = H*YPRIME(I)
C
GO TO 500
C
C-----------------------------------------------------------------------
C This block is for continuation calls only.
C Its purpose is to check stop conditions before taking a step.
C Adjust H if necessary to meet HMAX bound.
C-----------------------------------------------------------------------
C
400 CONTINUE
UROUND=RWORK(LROUND)
DONE = .FALSE.
TN=RWORK(LTN)
H=RWORK(LH)
IF(INFO(7) .EQ. 0) GO TO 410
RH = ABS(H)/RWORK(LHMAX)
IF(RH .GT. 1.0D0) H = H/RH
410 CONTINUE
IF(T .EQ. TOUT) GO TO 719
IF((T - TOUT)*H .GT. 0.0D0) GO TO 711
IF(INFO(4) .EQ. 1) GO TO 430
IF(INFO(3) .EQ. 1) GO TO 420
IF((TN-TOUT)*H.LT.0.0D0)GO TO 490
CALL DDATRP(TN,TOUT,Y,YPRIME,NEQ,IWORK(LKOLD),
* RWORK(LPHI),RWORK(LPSI))
T=TOUT
IDID = 3
DONE = .TRUE.
GO TO 490
420 IF((TN-T)*H .LE. 0.0D0) GO TO 490
IF((TN - TOUT)*H .GE. 0.0D0) GO TO 425
CALL DDATRP(TN,TN,Y,YPRIME,NEQ,IWORK(LKOLD),
* RWORK(LPHI),RWORK(LPSI))
T = TN
IDID = 1
DONE = .TRUE.
GO TO 490
425 CONTINUE
CALL DDATRP(TN,TOUT,Y,YPRIME,NEQ,IWORK(LKOLD),
* RWORK(LPHI),RWORK(LPSI))
T = TOUT
IDID = 3
DONE = .TRUE.
GO TO 490
430 IF(INFO(3) .EQ. 1) GO TO 440
TSTOP=RWORK(LTSTOP)
write(*,*) 'tstop = ',tstop
IF((TN-TSTOP)*H.GT.0.0D0) GO TO 715
IF((TSTOP-TOUT)*H.LT.0.0D0)GO TO 709
IF((TN-TOUT)*H.LT.0.0D0)GO TO 450
CALL DDATRP(TN,TOUT,Y,YPRIME,NEQ,IWORK(LKOLD),
* RWORK(LPHI),RWORK(LPSI))
T=TOUT
IDID = 3
DONE = .TRUE.
GO TO 490
440 TSTOP = RWORK(LTSTOP)
write(*,*) 'tstop = ',tstop
IF((TN-TSTOP)*H .GT. 0.0D0) GO TO 715
IF((TSTOP-TOUT)*H .LT. 0.0D0) GO TO 709
IF((TN-T)*H .LE. 0.0D0) GO TO 450
IF((TN - TOUT)*H .GE. 0.0D0) GO TO 445
CALL DDATRP(TN,TN,Y,YPRIME,NEQ,IWORK(LKOLD),
* RWORK(LPHI),RWORK(LPSI))
T = TN
IDID = 1
DONE = .TRUE.
GO TO 490
445 CONTINUE
CALL DDATRP(TN,TOUT,Y,YPRIME,NEQ,IWORK(LKOLD),
* RWORK(LPHI),RWORK(LPSI))
T = TOUT
IDID = 3
DONE = .TRUE.
GO TO 490
450 CONTINUE
C
C Check whether we are within roundoff of TSTOP.
C
IF(ABS(TN-TSTOP).GT.100.0D0*UROUND*
* (ABS(TN)+ABS(H)))GO TO 460
CALL DDATRP(TN,TSTOP,Y,YPRIME,NEQ,IWORK(LKOLD),
* RWORK(LPHI),RWORK(LPSI))
IDID=2
T=TSTOP
DONE = .TRUE.
GO TO 490
460 TNEXT=TN+H
IF((TNEXT-TSTOP)*H.LE.0.0D0)GO TO 490
H=TSTOP-TN
RWORK(LH)=H
C
490 IF (DONE) GO TO 590
C
C-----------------------------------------------------------------------
C The next block contains the call to the one-step integrator DDSTP.
C This is a looping point for the integration steps.
C Check for too many steps.
C Check for poor Newton/Krylov performance.
C Update WT. Check for too much accuracy requested.
C Compute minimum stepsize.
C-----------------------------------------------------------------------
C
500 CONTINUE
C
C Check for too many steps.
C
IF((IWORK(LNST)-IWORK(LNSTL)).LT.500) GO TO 505
IDID=-1
GO TO 527
C
C Check for poor Newton/Krylov performance.
C
505 IF (INFO(12) .EQ. 0) GO TO 510
NSTD = IWORK(LNST) - IWORK(LNSTL)
NNID = IWORK(LNNI) - NNI0
IF (NSTD .LT. 10 .OR. NNID .EQ. 0) GO TO 510
AVLIN = REAL(IWORK(LNLI) - NLI0)/REAL(NNID)
RCFN = REAL(IWORK(LNCFN) - NCFN0)/REAL(NSTD)
RCFL = REAL(IWORK(LNCFL) - NCFL0)/REAL(NNID)
FMAXL = IWORK(LMAXL)
LAVL = AVLIN .GT. FMAXL
LCFN = RCFN .GT. 0.9D0
LCFL = RCFL .GT. 0.9D0
LWARN = LAVL .OR. LCFN .OR. LCFL
IF (.NOT.LWARN) GO TO 510
NWARN = NWARN + 1
IF (NWARN .GT. 10) GO TO 510
IF (LAVL) THEN
MSG = 'DASPK-- Warning. Poor iterative algorithm performance '
CALL XERRWD (MSG, 56, 501, 0, 0, 0, 0, 0, 0.0D0, 0.0D0)
MSG = ' at T = R1. Average no. of linear iterations = R2 '
CALL XERRWD (MSG, 56, 501, 0, 0, 0, 0, 2, TN, AVLIN)
ENDIF
IF (LCFN) THEN
MSG = 'DASPK-- Warning. Poor iterative algorithm performance '
CALL XERRWD (MSG, 56, 502, 0, 0, 0, 0, 0, 0.0D0, 0.0D0)
MSG = ' at T = R1. Nonlinear convergence failure rate = R2'
CALL XERRWD (MSG, 56, 502, 0, 0, 0, 0, 2, TN, RCFN)
ENDIF
IF (LCFL) THEN
MSG = 'DASPK-- Warning. Poor iterative algorithm performance '
CALL XERRWD (MSG, 56, 503, 0, 0, 0, 0, 0, 0.0D0, 0.0D0)
MSG = ' at T = R1. Linear convergence failure rate = R2 '
CALL XERRWD (MSG, 56, 503, 0, 0, 0, 0, 2, TN, RCFL)
ENDIF
C
C Update WT and VT, if this is not the first call.
C
510 CALL DDAWTS(NEQ,INFO(2),RTOL,ATOL,RWORK(LPHI),RWORK(LWT),
* RPAR,IPAR)
CALL DINVWT(NEQ,RWORK(LWT),IER)
IF (IER .NE. 0) THEN
IDID = -3
GO TO 527
ENDIF
IF (INFO(16) .NE. 0) THEN
DO 515 I = 1, NEQ
515 RWORK(LVT+I-1) = MAX(IWORK(LID+I-1),0)*RWORK(LWT+I-1)
ENDIF
C
C Test for too much accuracy requested.
C
R = DDWNRM(NEQ,RWORK(LPHI),RWORK(LWT),RPAR,IPAR)*100.0D0*UROUND
IF (R .LE. 1.0D0) GO TO 525
C
C Multiply RTOL and ATOL by R and return.
C
IF(INFO(2).EQ.1)GO TO 523
RTOL(1)=R*RTOL(1)
ATOL(1)=R*ATOL(1)
IDID=-2
GO TO 527
523 DO 524 I=1,NEQ
RTOL(I)=R*RTOL(I)
524 ATOL(I)=R*ATOL(I)
IDID=-2
GO TO 527
525 CONTINUE
C
C Compute minimum stepsize.
C
HMIN=4.0D0*UROUND*MAX(ABS(TN),ABS(TOUT))
C
C Test H vs. HMAX
IF (INFO(7) .NE. 0) THEN
RH = ABS(H)/RWORK(LHMAX)
IF (RH .GT. 1.0D0) H = H/RH
ENDIF
C
C Call the one-step integrator.
C Note that INFO(12) represents the nonlinear solver type.
C Pass the required nonlinear solver, depending upon INFO(12).
C
IF (INFO(12) .EQ. 0) THEN
CALL DDSTP(TN,Y,YPRIME,NEQ,
* RES,JAC,PSOL,H,RWORK(LWT),RWORK(LVT),INFO(1),IDID,RPAR,IPAR,
* RWORK(LPHI),RWORK(LSAVR),RWORK(LDELTA),RWORK(LE),
* RWORK(LWM),IWORK(LIWM),
* RWORK(LALPHA),RWORK(LBETA),RWORK(LGAMMA),
* RWORK(LPSI),RWORK(LSIGMA),
* RWORK(LCJ),RWORK(LCJOLD),RWORK(LHOLD),RWORK(LS),HMIN,
* RWORK(LROUND), RWORK(LEPLI),RWORK(LSQRN),RWORK(LRSQRN),
* RWORK(LEPCON), IWORK(LPHASE),IWORK(LJCALC),INFO(15),
* IWORK(LK), IWORK(LKOLD),IWORK(LNS),NONNEG,INFO(12),
* DNEDD)
ELSE IF (INFO(12) .EQ. 1) THEN
CALL DDSTP(TN,Y,YPRIME,NEQ,
* RES,JAC,PSOL,H,RWORK(LWT),RWORK(LVT),INFO(1),IDID,RPAR,IPAR,
* RWORK(LPHI),RWORK(LSAVR),RWORK(LDELTA),RWORK(LE),
* RWORK(LWM),IWORK(LIWM),
* RWORK(LALPHA),RWORK(LBETA),RWORK(LGAMMA),
* RWORK(LPSI),RWORK(LSIGMA),
* RWORK(LCJ),RWORK(LCJOLD),RWORK(LHOLD),RWORK(LS),HMIN,
* RWORK(LROUND), RWORK(LEPLI),RWORK(LSQRN),RWORK(LRSQRN),
* RWORK(LEPCON), IWORK(LPHASE),IWORK(LJCALC),INFO(15),
* IWORK(LK), IWORK(LKOLD),IWORK(LNS),NONNEG,INFO(12),
* DNEDK)
ENDIF
C
527 IF(IDID.LT.0)GO TO 600
C
C-----------------------------------------------------------------------
C This block handles the case of a successful return from DDSTP
C (IDID=1). Test for stop conditions.
C-----------------------------------------------------------------------
C
IF(INFO(4).NE.0)GO TO 540
IF(INFO(3).NE.0)GO TO 530
IF((TN-TOUT)*H.LT.0.0D0)GO TO 500
CALL DDATRP(TN,TOUT,Y,YPRIME,NEQ,
* IWORK(LKOLD),RWORK(LPHI),RWORK(LPSI))
IDID=3
T=TOUT
GO TO 580
530 IF((TN-TOUT)*H.GE.0.0D0)GO TO 535
T=TN
IDID=1
GO TO 580
535 CALL DDATRP(TN,TOUT,Y,YPRIME,NEQ,
* IWORK(LKOLD),RWORK(LPHI),RWORK(LPSI))
IDID=3
T=TOUT
GO TO 580
540 IF(INFO(3).NE.0)GO TO 550
IF((TN-TOUT)*H.LT.0.0D0)GO TO 542
CALL DDATRP(TN,TOUT,Y,YPRIME,NEQ,
* IWORK(LKOLD),RWORK(LPHI),RWORK(LPSI))
T=TOUT
IDID=3
GO TO 580
542 IF(ABS(TN-TSTOP).LE.100.0D0*UROUND*
* (ABS(TN)+ABS(H)))GO TO 545
TNEXT=TN+H
IF((TNEXT-TSTOP)*H.LE.0.0D0)GO TO 500
H=TSTOP-TN
GO TO 500
545 CALL DDATRP(TN,TSTOP,Y,YPRIME,NEQ,
* IWORK(LKOLD),RWORK(LPHI),RWORK(LPSI))
IDID=2
T=TSTOP
GO TO 580
550 IF((TN-TOUT)*H.GE.0.0D0)GO TO 555
IF(ABS(TN-TSTOP).LE.100.0D0*UROUND*(ABS(TN)+ABS(H)))GO TO 552
T=TN
IDID=1
GO TO 580
552 CALL DDATRP(TN,TSTOP,Y,YPRIME,NEQ,
* IWORK(LKOLD),RWORK(LPHI),RWORK(LPSI))
IDID=2
T=TSTOP
GO TO 580
555 CALL DDATRP(TN,TOUT,Y,YPRIME,NEQ,
* IWORK(LKOLD),RWORK(LPHI),RWORK(LPSI))
T=TOUT
IDID=3
580 CONTINUE
C
C-----------------------------------------------------------------------
C All successful returns from DDASPK are made from this block.
C-----------------------------------------------------------------------
C
590 CONTINUE
RWORK(LTN)=TN
RWORK(LH)=H
RETURN
C
C-----------------------------------------------------------------------
C This block handles all unsuccessful returns other than for
C illegal input.
C-----------------------------------------------------------------------
C
600 CONTINUE
ITEMP = -IDID
GO TO (610,620,630,700,655,640,650,660,670,675,
* 680,685,690,695), ITEMP
C
C The maximum number of steps was taken before
C reaching tout.
C
610 MSG = 'DASPK-- AT CURRENT T (=R1) 500 STEPS'
CALL XERRWD(MSG,38,610,0,0,0,0,1,TN,0.0D0)
MSG = 'DASPK-- TAKEN ON THIS CALL BEFORE REACHING TOUT'
CALL XERRWD(MSG,48,611,0,0,0,0,0,0.0D0,0.0D0)
GO TO 700
C
C Too much accuracy for machine precision.
C
620 MSG = 'DASPK-- AT T (=R1) TOO MUCH ACCURACY REQUESTED'
CALL XERRWD(MSG,47,620,0,0,0,0,1,TN,0.0D0)
MSG = 'DASPK-- FOR PRECISION OF MACHINE. RTOL AND ATOL'
CALL XERRWD(MSG,48,621,0,0,0,0,0,0.0D0,0.0D0)
MSG = 'DASPK-- WERE INCREASED TO APPROPRIATE VALUES'
CALL XERRWD(MSG,45,622,0,0,0,0,0,0.0D0,0.0D0)
GO TO 700
C
C WT(I) .LE. 0.0D0 for some I (not at start of problem).
C
630 MSG = 'DASPK-- AT T (=R1) SOME ELEMENT OF WT'
CALL XERRWD(MSG,38,630,0,0,0,0,1,TN,0.0D0)
MSG = 'DASPK-- HAS BECOME .LE. 0.0'
CALL XERRWD(MSG,28,631,0,0,0,0,0,0.0D0,0.0D0)
GO TO 700
C
C Error test failed repeatedly or with H=HMIN.
C
640 MSG = 'DASPK-- AT T (=R1) AND STEPSIZE H (=R2) THE'
CALL XERRWD(MSG,44,640,0,0,0,0,2,TN,H)
MSG='DASPK-- ERROR TEST FAILED REPEATEDLY OR WITH ABS(H)=HMIN'
CALL XERRWD(MSG,57,641,0,0,0,0,0,0.0D0,0.0D0)
GO TO 700
C
C Nonlinear solver failed to converge repeatedly or with H=HMIN.
C
650 MSG = 'DASPK-- AT T (=R1) AND STEPSIZE H (=R2) THE'
CALL XERRWD(MSG,44,650,0,0,0,0,2,TN,H)
MSG = 'DASPK-- NONLINEAR SOLVER FAILED TO CONVERGE'
CALL XERRWD(MSG,44,651,0,0,0,0,0,0.0D0,0.0D0)
MSG = 'DASPK-- REPEATEDLY OR WITH ABS(H)=HMIN'
CALL XERRWD(MSG,40,652,0,0,0,0,0,0.0D0,0.0D0)
GO TO 700
C
C The preconditioner had repeated failures.
C
655 MSG = 'DASPK-- AT T (=R1) AND STEPSIZE H (=R2) THE'
CALL XERRWD(MSG,44,655,0,0,0,0,2,TN,H)
MSG = 'DASPK-- PRECONDITIONER HAD REPEATED FAILURES.'
CALL XERRWD(MSG,46,656,0,0,0,0,0,0.0D0,0.0D0)
GO TO 700
C
C The iteration matrix is singular.
C
660 MSG = 'DASPK-- AT T (=R1) AND STEPSIZE H (=R2) THE'
CALL XERRWD(MSG,44,660,0,0,0,0,2,TN,H)
MSG = 'DASPK-- ITERATION MATRIX IS SINGULAR.'
CALL XERRWD(MSG,38,661,0,0,0,0,0,0.0D0,0.0D0)
GO TO 700
C
C Nonlinear system failure preceded by error test failures.
C
670 MSG = 'DASPK-- AT T (=R1) AND STEPSIZE H (=R2) THE'
CALL XERRWD(MSG,44,670,0,0,0,0,2,TN,H)
MSG = 'DASPK-- NONLINEAR SOLVER COULD NOT CONVERGE.'
CALL XERRWD(MSG,45,671,0,0,0,0,0,0.0D0,0.0D0)
MSG = 'DASPK-- ALSO, THE ERROR TEST FAILED REPEATEDLY.'
CALL XERRWD(MSG,49,672,0,0,0,0,0,0.0D0,0.0D0)
GO TO 700
C
C Nonlinear system failure because IRES = -1.
C
675 MSG = 'DASPK-- AT T (=R1) AND STEPSIZE H (=R2) THE'
CALL XERRWD(MSG,44,675,0,0,0,0,2,TN,H)
MSG = 'DASPK-- NONLINEAR SYSTEM SOLVER COULD NOT CONVERGE'
CALL XERRWD(MSG,51,676,0,0,0,0,0,0.0D0,0.0D0)
MSG = 'DASPK-- BECAUSE IRES WAS EQUAL TO MINUS ONE'
CALL XERRWD(MSG,44,677,0,0,0,0,0,0.0D0,0.0D0)
GO TO 700
C
C Failure because IRES = -2.
C
680 MSG = 'DASPK-- AT T (=R1) AND STEPSIZE H (=R2)'
CALL XERRWD(MSG,40,680,0,0,0,0,2,TN,H)
MSG = 'DASPK-- IRES WAS EQUAL TO MINUS TWO'
CALL XERRWD(MSG,36,681,0,0,0,0,0,0.0D0,0.0D0)
GO TO 700
C
C Failed to compute initial YPRIME.
C
685 MSG = 'DASPK-- AT T (=R1) AND STEPSIZE H (=R2) THE'
CALL XERRWD(MSG,44,685,0,0,0,0,0,0.0D0,0.0D0)
MSG = 'DASPK-- INITIAL (Y,YPRIME) COULD NOT BE COMPUTED'
CALL XERRWD(MSG,49,686,0,0,0,0,2,TN,H0)
GO TO 700
C
C Failure because IER was negative from PSOL.
C
690 MSG = 'DASPK-- AT T (=R1) AND STEPSIZE H (=R2)'
CALL XERRWD(MSG,40,690,0,0,0,0,2,TN,H)
MSG = 'DASPK-- IER WAS NEGATIVE FROM PSOL'
CALL XERRWD(MSG,35,691,0,0,0,0,0,0.0D0,0.0D0)
GO TO 700
C
C Failure because the linear system solver could not converge.
C
695 MSG = 'DASPK-- AT T (=R1) AND STEPSIZE H (=R2) THE'
CALL XERRWD(MSG,44,695,0,0,0,0,2,TN,H)
MSG = 'DASPK-- LINEAR SYSTEM SOLVER COULD NOT CONVERGE.'
CALL XERRWD(MSG,50,696,0,0,0,0,0,0.0D0,0.0D0)
GO TO 700
C
C
700 CONTINUE
INFO(1)=-1
T=TN
RWORK(LTN)=TN
RWORK(LH)=H
RETURN
C
C-----------------------------------------------------------------------
C This block handles all error returns due to illegal input,
C as detected before calling DDSTP.
C First the error message routine is called. If this happens
C twice in succession, execution is terminated.
C-----------------------------------------------------------------------
C
701 MSG = 'DASPK-- ELEMENT (=I1) OF INFO VECTOR IS NOT VALID'
CALL XERRWD(MSG,50,1,0,1,ITEMP,0,0,0.0D0,0.0D0)
GO TO 750
702 MSG = 'DASPK-- NEQ (=I1) .LE. 0'
CALL XERRWD(MSG,25,2,0,1,NEQ,0,0,0.0D0,0.0D0)
GO TO 750
703 MSG = 'DASPK-- MAXORD (=I1) NOT IN RANGE'
CALL XERRWD(MSG,34,3,0,1,MXORD,0,0,0.0D0,0.0D0)
GO TO 750
704 MSG='DASPK-- RWORK LENGTH NEEDED, LENRW (=I1), EXCEEDS LRW (=I2)'
CALL XERRWD(MSG,60,4,0,2,LENRW,LRW,0,0.0D0,0.0D0)
GO TO 750
705 MSG='DASPK-- IWORK LENGTH NEEDED, LENIW (=I1), EXCEEDS LIW (=I2)'
CALL XERRWD(MSG,60,5,0,2,LENIW,LIW,0,0.0D0,0.0D0)
GO TO 750
706 MSG = 'DASPK-- SOME ELEMENT OF RTOL IS .LT. 0'
CALL XERRWD(MSG,39,6,0,0,0,0,0,0.0D0,0.0D0)
GO TO 750
707 MSG = 'DASPK-- SOME ELEMENT OF ATOL IS .LT. 0'
CALL XERRWD(MSG,39,7,0,0,0,0,0,0.0D0,0.0D0)
GO TO 750
708 MSG = 'DASPK-- ALL ELEMENTS OF RTOL AND ATOL ARE ZERO'
CALL XERRWD(MSG,47,8,0,0,0,0,0,0.0D0,0.0D0)
GO TO 750
709 MSG='DASPK-- INFO(4) = 1 AND TSTOP (=R1) BEHIND TOUT (=R2)'
CALL XERRWD(MSG,54,9,0,0,0,0,2,TSTOP,TOUT)
GO TO 750
710 MSG = 'DASPK-- HMAX (=R1) .LT. 0.0'
CALL XERRWD(MSG,28,10,0,0,0,0,1,HMAX,0.0D0)
GO TO 750
711 MSG = 'DASPK-- TOUT (=R1) BEHIND T (=R2)'
CALL XERRWD(MSG,34,11,0,0,0,0,2,TOUT,T)
GO TO 750
712 MSG = 'DASPK-- INFO(8)=1 AND H0=0.0'
CALL XERRWD(MSG,29,12,0,0,0,0,0,0.0D0,0.0D0)
GO TO 750
713 MSG = 'DASPK-- SOME ELEMENT OF WT IS .LE. 0.0'
CALL XERRWD(MSG,39,13,0,0,0,0,0,0.0D0,0.0D0)
GO TO 750
714 MSG='DASPK-- TOUT (=R1) TOO CLOSE TO T (=R2) TO START INTEGRATION'
CALL XERRWD(MSG,60,14,0,0,0,0,2,TOUT,T)
GO TO 750
715 MSG = 'DASPK-- INFO(4)=1 AND TSTOP (=R1) BEHIND T (=R2)'
CALL XERRWD(MSG,49,15,0,0,0,0,2,TSTOP,T)
GO TO 750
717 MSG = 'DASPK-- ML (=I1) ILLEGAL. EITHER .LT. 0 OR .GT. NEQ'
CALL XERRWD(MSG,52,17,0,1,IWORK(LML),0,0,0.0D0,0.0D0)
GO TO 750
718 MSG = 'DASPK-- MU (=I1) ILLEGAL. EITHER .LT. 0 OR .GT. NEQ'
CALL XERRWD(MSG,52,18,0,1,IWORK(LMU),0,0,0.0D0,0.0D0)
GO TO 750
719 MSG = 'DASPK-- TOUT (=R1) IS EQUAL TO T (=R2)'
CALL XERRWD(MSG,39,19,0,0,0,0,2,TOUT,T)
GO TO 750
720 MSG = 'DASPK-- MAXL (=I1) ILLEGAL. EITHER .LT. 1 OR .GT. NEQ'
CALL XERRWD(MSG,54,20,0,1,IWORK(LMAXL),0,0,0.0D0,0.0D0)
GO TO 750
721 MSG = 'DASPK-- KMP (=I1) ILLEGAL. EITHER .LT. 1 OR .GT. MAXL'
CALL XERRWD(MSG,54,21,0,1,IWORK(LKMP),0,0,0.0D0,0.0D0)
GO TO 750
722 MSG = 'DASPK-- NRMAX (=I1) ILLEGAL. .LT. 0'
CALL XERRWD(MSG,36,22,0,1,IWORK(LNRMAX),0,0,0.0D0,0.0D0)
GO TO 750
723 MSG = 'DASPK-- EPLI (=R1) ILLEGAL. EITHER .LE. 0.D0 OR .GE. 1.D0'
CALL XERRWD(MSG,58,23,0,0,0,0,1,RWORK(LEPLI),0.0D0)
GO TO 750
724 MSG = 'DASPK-- ILLEGAL IWORK VALUE FOR INFO(11) .NE. 0'
CALL XERRWD(MSG,48,24,0,0,0,0,0,0.0D0,0.0D0)
GO TO 750
725 MSG = 'DASPK-- ONE OF THE INPUTS FOR INFO(17) = 1 IS ILLEGAL'
CALL XERRWD(MSG,54,25,0,0,0,0,0,0.0D0,0.0D0)
GO TO 750
726 MSG = 'DASPK-- ILLEGAL IWORK VALUE FOR INFO(10) .NE. 0'
CALL XERRWD(MSG,48,26,0,0,0,0,0,0.0D0,0.0D0)
GO TO 750
727 MSG = 'DASPK-- Y(I) AND IWORK(40+I) (I=I1) INCONSISTENT'
CALL XERRWD(MSG,49,27,0,1,IRET,0,0,0.0D0,0.0D0)
GO TO 750
750 IF(INFO(1).EQ.-1) GO TO 760
INFO(1)=-1
IDID=-33
RETURN
760 MSG = 'DASPK-- REPEATED OCCURRENCES OF ILLEGAL INPUT'
CALL XERRWD(MSG,46,701,0,0,0,0,0,0.0D0,0.0D0)
770 MSG = 'DASPK-- RUN TERMINATED. APPARENT INFINITE LOOP'
CALL XERRWD(MSG,47,702,1,0,0,0,0,0.0D0,0.0D0)
RETURN
C
C------END OF SUBROUTINE DDASPK-----------------------------------------
END
SUBROUTINE DDASIC (X, Y, YPRIME, NEQ, ICOPT, ID, RES, JAC, PSOL,
* H, TSCALE, WT, NIC, IDID, RPAR, IPAR, PHI, SAVR, DELTA, E,
* YIC, YPIC, PWK, WM, IWM, UROUND, EPLI, SQRTN, RSQRTN,
* EPCONI, STPTOL, JFLG, ICNFLG, ICNSTR, NLSIC)
C
C***BEGIN PROLOGUE DDASIC
C***REFER TO DDASPK
C***DATE WRITTEN 940628 (YYMMDD)
C***REVISION DATE 941206 (YYMMDD)
C***REVISION DATE 950714 (YYMMDD)
C***REVISION DATE 000628 TSCALE argument added.
C
C-----------------------------------------------------------------------
C***DESCRIPTION
C
C DDASIC is a driver routine to compute consistent initial values
C for Y and YPRIME. There are two different options:
C Denoting the differential variables in Y by Y_d, and
C the algebraic variables by Y_a, the problem solved is either:
C 1. Given Y_d, calculate Y_a and Y_d', or
C 2. Given Y', calculate Y.
C In either case, initial values for the given components
C are input, and initial guesses for the unknown components
C must also be provided as input.
C
C The external routine NLSIC solves the resulting nonlinear system.
C
C The parameters represent
C
C X -- Independent variable.
C Y -- Solution vector at X.
C YPRIME -- Derivative of solution vector.
C NEQ -- Number of equations to be integrated.
C ICOPT -- Flag indicating initial condition option chosen.
C ICOPT = 1 for option 1 above.
C ICOPT = 2 for option 2.
C ID -- Array of dimension NEQ, which must be initialized
C if option 1 is chosen.
C ID(i) = +1 if Y_i is a differential variable,
C ID(i) = -1 if Y_i is an algebraic variable.
C RES -- External user-supplied subroutine to evaluate the
C residual. See RES description in DDASPK prologue.
C JAC -- External user-supplied routine to update Jacobian
C or preconditioner information in the nonlinear solver
C (optional). See JAC description in DDASPK prologue.
C PSOL -- External user-supplied routine to solve
C a linear system using preconditioning.
C See PSOL in DDASPK prologue.
C H -- Scaling factor in iteration matrix. DDASIC may
C reduce H to achieve convergence.
C TSCALE -- Scale factor in T, used for stopping tests if nonzero.
C WT -- Vector of weights for error criterion.
C NIC -- Input number of initial condition calculation call
C (= 1 or 2).
C IDID -- Completion code. See IDID in DDASPK prologue.
C RPAR,IPAR -- Real and integer parameter arrays that
C are used for communication between the
C calling program and external user routines.
C They are not altered by DNSK
C PHI -- Work space for DDASIC of length at least 2*NEQ.
C SAVR -- Work vector for DDASIC of length NEQ.
C DELTA -- Work vector for DDASIC of length NEQ.
C E -- Work vector for DDASIC of length NEQ.
C YIC,YPIC -- Work vectors for DDASIC, each of length NEQ.
C PWK -- Work vector for DDASIC of length NEQ.
C WM,IWM -- Real and integer arrays storing
C information required by the linear solver.
C EPCONI -- Test constant for Newton iteration convergence.
C ICNFLG -- Flag showing whether constraints on Y are to apply.
C ICNSTR -- Integer array of length NEQ with constraint types.
C
C The other parameters are for use internally by DDASIC.
C
C-----------------------------------------------------------------------
C***ROUTINES CALLED
C DCOPY, NLSIC
C
C***END PROLOGUE DDASIC
C
C
IMPLICIT DOUBLE PRECISION(A-H,O-Z)
DIMENSION Y(*),YPRIME(*),ID(*),WT(*),PHI(NEQ,*)
DIMENSION SAVR(*),DELTA(*),E(*),YIC(*),YPIC(*),PWK(*)
DIMENSION WM(*),IWM(*), RPAR(*),IPAR(*), ICNSTR(*)
EXTERNAL RES, JAC, PSOL, NLSIC
C
PARAMETER (LCFN=15)
PARAMETER (LMXNH=34)
C
C The following parameters are data-loaded here:
C RHCUT = factor by which H is reduced on retry of Newton solve.
C RATEMX = maximum convergence rate for which Newton iteration
C is considered converging.
C
SAVE RHCUT, RATEMX
DATA RHCUT/0.1D0/, RATEMX/0.8D0/
C
C
C-----------------------------------------------------------------------
C BLOCK 1.
C Initializations.
C JSKIP is a flag set to 1 when NIC = 2 and NH = 1, to signal that
C the initial call to the JAC routine is to be skipped then.
C Save Y and YPRIME in PHI. Initialize IDID, NH, and CJ.
C-----------------------------------------------------------------------
C
MXNH = IWM(LMXNH)
IDID = 1
NH = 1
JSKIP = 0
IF (NIC .EQ. 2) JSKIP = 1
CALL DCOPY (NEQ, Y, 1, PHI(1,1), 1)
CALL DCOPY (NEQ, YPRIME, 1, PHI(1,2), 1)
C
IF (ICOPT .EQ. 2) THEN
CJ = 0.0D0
ELSE
CJ = 1.0D0/H
ENDIF
C
C-----------------------------------------------------------------------
C BLOCK 2
C Call the nonlinear system solver to obtain
C consistent initial values for Y and YPRIME.
C-----------------------------------------------------------------------
C
200 CONTINUE
CALL NLSIC(X,Y,YPRIME,NEQ,ICOPT,ID,RES,JAC,PSOL,H,TSCALE,WT,
* JSKIP,RPAR,IPAR,SAVR,DELTA,E,YIC,YPIC,PWK,WM,IWM,CJ,UROUND,
* EPLI,SQRTN,RSQRTN,EPCONI,RATEMX,STPTOL,JFLG,ICNFLG,ICNSTR,
* IERNLS)
C
IF (IERNLS .EQ. 0) RETURN
C
C-----------------------------------------------------------------------
C BLOCK 3
C The nonlinear solver was unsuccessful. Increment NCFN.
C Return with IDID = -12 if either
C IERNLS = -1: error is considered unrecoverable,
C ICOPT = 2: we are doing initialization problem type 2, or
C NH = MXNH: the maximum number of H values has been tried.
C Otherwise (problem 1 with IERNLS .GE. 1), reduce H and try again.
C If IERNLS > 1, restore Y and YPRIME to their original values.
C-----------------------------------------------------------------------
C
IWM(LCFN) = IWM(LCFN) + 1
JSKIP = 0
C
IF (IERNLS .EQ. -1) GO TO 350
IF (ICOPT .EQ. 2) GO TO 350
IF (NH .EQ. MXNH) GO TO 350
C
NH = NH + 1
H = H*RHCUT
CJ = 1.0D0/H
C
IF (IERNLS .EQ. 1) GO TO 200
C
CALL DCOPY (NEQ, PHI(1,1), 1, Y, 1)
CALL DCOPY (NEQ, PHI(1,2), 1, YPRIME, 1)
GO TO 200
C
350 IDID = -12
RETURN
C
C------END OF SUBROUTINE DDASIC-----------------------------------------
END
SUBROUTINE DYYPNW (NEQ, Y, YPRIME, CJ, RL, P, ICOPT, ID,
* YNEW, YPNEW)
C
C***BEGIN PROLOGUE DYYPNW
C***REFER TO DLINSK
C***DATE WRITTEN 940830 (YYMMDD)
C
C
C-----------------------------------------------------------------------
C***DESCRIPTION
C
C DYYPNW calculates the new (Y,YPRIME) pair needed in the
C linesearch algorithm based on the current lambda value. It is
C called by DLINSK and DLINSD. Based on the ICOPT and ID values,
C the corresponding entry in Y or YPRIME is updated.
C
C In addition to the parameters described in the calling programs,
C the parameters represent
C
C P -- Array of length NEQ that contains the current
C approximate Newton step.
C RL -- Scalar containing the current lambda value.
C YNEW -- Array of length NEQ containing the updated Y vector.
C YPNEW -- Array of length NEQ containing the updated YPRIME
C vector.
C-----------------------------------------------------------------------
C
C***ROUTINES CALLED (NONE)
C
C***END PROLOGUE DYYPNW
C
C
IMPLICIT DOUBLE PRECISION (A-H,O-Z)
DIMENSION Y(*), YPRIME(*), YNEW(*), YPNEW(*), ID(*), P(*)
C
IF (ICOPT .EQ. 1) THEN
DO 10 I=1,NEQ
IF(ID(I) .LT. 0) THEN
YNEW(I) = Y(I) - RL*P(I)
YPNEW(I) = YPRIME(I)
ELSE
YNEW(I) = Y(I)
YPNEW(I) = YPRIME(I) - RL*CJ*P(I)
ENDIF
10 CONTINUE
ELSE
DO 20 I = 1,NEQ
YNEW(I) = Y(I) - RL*P(I)
YPNEW(I) = YPRIME(I)
20 CONTINUE
ENDIF
RETURN
C----------------------- END OF SUBROUTINE DYYPNW ----------------------
END
SUBROUTINE DDSTP(X,Y,YPRIME,NEQ,RES,JAC,PSOL,H,WT,VT,
* JSTART,IDID,RPAR,IPAR,PHI,SAVR,DELTA,E,WM,IWM,
* ALPHA,BETA,GAMMA,PSI,SIGMA,CJ,CJOLD,HOLD,S,HMIN,UROUND,
* EPLI,SQRTN,RSQRTN,EPCON,IPHASE,JCALC,JFLG,K,KOLD,NS,NONNEG,
* NTYPE,NLS)
C
C***BEGIN PROLOGUE DDSTP
C***REFER TO DDASPK
C***DATE WRITTEN 890101 (YYMMDD)
C***REVISION DATE 900926 (YYMMDD)
C***REVISION DATE 940909 (YYMMDD) (Reset PSI(1), PHI(*,2) at 690)
C
C
C-----------------------------------------------------------------------
C***DESCRIPTION
C
C DDSTP solves a system of differential/algebraic equations of
C the form G(X,Y,YPRIME) = 0, for one step (normally from X to X+H).
C
C The methods used are modified divided difference, fixed leading
C coefficient forms of backward differentiation formulas.
C The code adjusts the stepsize and order to control the local error
C per step.
C
C
C The parameters represent
C X -- Independent variable.
C Y -- Solution vector at X.
C YPRIME -- Derivative of solution vector
C after successful step.
C NEQ -- Number of equations to be integrated.
C RES -- External user-supplied subroutine
C to evaluate the residual. See RES description
C in DDASPK prologue.
C JAC -- External user-supplied routine to update
C Jacobian or preconditioner information in the
C nonlinear solver. See JAC description in DDASPK
C prologue.
C PSOL -- External user-supplied routine to solve
C a linear system using preconditioning.
C (This is optional). See PSOL in DDASPK prologue.
C H -- Appropriate step size for next step.
C Normally determined by the code.
C WT -- Vector of weights for error criterion used in Newton test.
C VT -- Masked vector of weights used in error test.
C JSTART -- Integer variable set 0 for
C first step, 1 otherwise.
C IDID -- Completion code returned from the nonlinear solver.
C See IDID description in DDASPK prologue.
C RPAR,IPAR -- Real and integer parameter arrays that
C are used for communication between the
C calling program and external user routines.
C They are not altered by DNSK
C PHI -- Array of divided differences used by
C DDSTP. The length is NEQ*(K+1), where
C K is the maximum order.
C SAVR -- Work vector for DDSTP of length NEQ.
C DELTA,E -- Work vectors for DDSTP of length NEQ.
C WM,IWM -- Real and integer arrays storing
C information required by the linear solver.
C
C The other parameters are information
C which is needed internally by DDSTP to
C continue from step to step.
C
C-----------------------------------------------------------------------
C***ROUTINES CALLED
C NLS, DDWNRM, DDATRP
C
C***END PROLOGUE DDSTP
C
C
IMPLICIT DOUBLE PRECISION(A-H,O-Z)
DIMENSION Y(*),YPRIME(*),WT(*),VT(*)
DIMENSION PHI(NEQ,*),SAVR(*),DELTA(*),E(*)
DIMENSION WM(*),IWM(*)
DIMENSION PSI(*),ALPHA(*),BETA(*),GAMMA(*),SIGMA(*)
DIMENSION RPAR(*),IPAR(*)
EXTERNAL RES, JAC, PSOL, NLS
C
PARAMETER (LMXORD=3)
PARAMETER (LNST=11, LETF=14, LCFN=15)
C
C
C-----------------------------------------------------------------------
C BLOCK 1.
C Initialize. On the first call, set
C the order to 1 and initialize
C other variables.
C-----------------------------------------------------------------------
C
C Initializations for all calls
C
XOLD=X
NCF=0
NEF=0
IF(JSTART .NE. 0) GO TO 120
C
C If this is the first step, perform
C other initializations
C
K=1
KOLD=0
HOLD=0.0D0
PSI(1)=H
CJ = 1.D0/H
IPHASE = 0
NS=0
120 CONTINUE
C
C
C
C
C
C-----------------------------------------------------------------------
C BLOCK 2
C Compute coefficients of formulas for
C this step.
C-----------------------------------------------------------------------
200 CONTINUE
KP1=K+1
KP2=K+2
KM1=K-1
IF(H.NE.HOLD.OR.K .NE. KOLD) NS = 0
NS=MIN0(NS+1,KOLD+2)
NSP1=NS+1
IF(KP1 .LT. NS)GO TO 230
C
BETA(1)=1.0D0
ALPHA(1)=1.0D0
TEMP1=H
GAMMA(1)=0.0D0
SIGMA(1)=1.0D0
DO 210 I=2,KP1
TEMP2=PSI(I-1)
PSI(I-1)=TEMP1
BETA(I)=BETA(I-1)*PSI(I-1)/TEMP2
TEMP1=TEMP2+H
ALPHA(I)=H/TEMP1
SIGMA(I)=(I-1)*SIGMA(I-1)*ALPHA(I)
GAMMA(I)=GAMMA(I-1)+ALPHA(I-1)/H
210 CONTINUE
PSI(KP1)=TEMP1
230 CONTINUE
C
C Compute ALPHAS, ALPHA0
C
ALPHAS = 0.0D0
ALPHA0 = 0.0D0
DO 240 I = 1,K
ALPHAS = ALPHAS - 1.0D0/I
ALPHA0 = ALPHA0 - ALPHA(I)
240 CONTINUE
C
C Compute leading coefficient CJ
C
CJLAST = CJ
CJ = -ALPHAS/H
C
C Compute variable stepsize error coefficient CK
C
CK = ABS(ALPHA(KP1) + ALPHAS - ALPHA0)
CK = MAX(CK,ALPHA(KP1))
C
C Change PHI to PHI STAR
C
IF(KP1 .LT. NSP1) GO TO 280
DO 270 J=NSP1,KP1
DO 260 I=1,NEQ
260 PHI(I,J)=BETA(J)*PHI(I,J)
270 CONTINUE
280 CONTINUE
C
C Update time
C
X=X+H
C
C Initialize IDID to 1
C
IDID = 1
C
C
C
C
C
C-----------------------------------------------------------------------
C BLOCK 3
C Call the nonlinear system solver to obtain the solution and
C derivative.
C-----------------------------------------------------------------------
C
CALL NLS(X,Y,YPRIME,NEQ,
* RES,JAC,PSOL,H,WT,JSTART,IDID,RPAR,IPAR,PHI,GAMMA,
* SAVR,DELTA,E,WM,IWM,CJ,CJOLD,CJLAST,S,
* UROUND,EPLI,SQRTN,RSQRTN,EPCON,JCALC,JFLG,KP1,
* NONNEG,NTYPE,IERNLS)
C
IF(IERNLS .NE. 0)GO TO 600
C
C
C
C
C
C-----------------------------------------------------------------------
C BLOCK 4
C Estimate the errors at orders K,K-1,K-2
C as if constant stepsize was used. Estimate
C the local error at order K and test
C whether the current step is successful.
C-----------------------------------------------------------------------
C
C Estimate errors at orders K,K-1,K-2
C
ENORM = DDWNRM(NEQ,E,VT,RPAR,IPAR)
ERK = SIGMA(K+1)*ENORM
TERK = (K+1)*ERK
EST = ERK
KNEW=K
IF(K .EQ. 1)GO TO 430
DO 405 I = 1,NEQ
405 DELTA(I) = PHI(I,KP1) + E(I)
ERKM1=SIGMA(K)*DDWNRM(NEQ,DELTA,VT,RPAR,IPAR)
TERKM1 = K*ERKM1
IF(K .GT. 2)GO TO 410
IF(TERKM1 .LE. 0.5*TERK)GO TO 420
GO TO 430
410 CONTINUE
DO 415 I = 1,NEQ
415 DELTA(I) = PHI(I,K) + DELTA(I)
ERKM2=SIGMA(K-1)*DDWNRM(NEQ,DELTA,VT,RPAR,IPAR)
TERKM2 = (K-1)*ERKM2
IF(MAX(TERKM1,TERKM2).GT.TERK)GO TO 430
C
C Lower the order
C
420 CONTINUE
KNEW=K-1
EST = ERKM1
C
C
C Calculate the local error for the current step
C to see if the step was successful
C
430 CONTINUE
ERR = CK * ENORM
IF(ERR .GT. 1.0D0)GO TO 600
C
C
C
C
C
C-----------------------------------------------------------------------
C BLOCK 5
C The step is successful. Determine
C the best order and stepsize for
C the next step. Update the differences
C for the next step.
C-----------------------------------------------------------------------
IDID=1
IWM(LNST)=IWM(LNST)+1
KDIFF=K-KOLD
KOLD=K
HOLD=H
C
C
C Estimate the error at order K+1 unless
C already decided to lower order, or
C already using maximum order, or
C stepsize not constant, or
C order raised in previous step
C
IF(KNEW.EQ.KM1.OR.K.EQ.IWM(LMXORD))IPHASE=1
IF(IPHASE .EQ. 0)GO TO 545
IF(KNEW.EQ.KM1)GO TO 540
IF(K.EQ.IWM(LMXORD)) GO TO 550
IF(KP1.GE.NS.OR.KDIFF.EQ.1)GO TO 550
DO 510 I=1,NEQ
510 DELTA(I)=E(I)-PHI(I,KP2)
ERKP1 = (1.0D0/(K+2))*DDWNRM(NEQ,DELTA,VT,RPAR,IPAR)
TERKP1 = (K+2)*ERKP1
IF(K.GT.1)GO TO 520
IF(TERKP1.GE.0.5D0*TERK)GO TO 550
GO TO 530
520 IF(TERKM1.LE.MIN(TERK,TERKP1))GO TO 540
IF(TERKP1.GE.TERK.OR.K.EQ.IWM(LMXORD))GO TO 550
C
C Raise order
C
530 K=KP1
EST = ERKP1
GO TO 550
C
C Lower order
C
540 K=KM1
EST = ERKM1
GO TO 550
C
C If IPHASE = 0, increase order by one and multiply stepsize by
C factor two
C
545 K = KP1
HNEW = H*2.0D0
H = HNEW
GO TO 575
C
C
C Determine the appropriate stepsize for
C the next step.
C
550 HNEW=H
TEMP2=K+1
R=(2.0D0*EST+0.0001D0)**(-1.0D0/TEMP2)
IF(R .LT. 2.0D0) GO TO 555
HNEW = 2.0D0*H
GO TO 560
555 IF(R .GT. 1.0D0) GO TO 560
R = MAX(0.5D0,MIN(0.9D0,R))
HNEW = H*R
560 H=HNEW
C
C
C Update differences for next step
C
575 CONTINUE
IF(KOLD.EQ.IWM(LMXORD))GO TO 585
DO 580 I=1,NEQ
580 PHI(I,KP2)=E(I)
585 CONTINUE
DO 590 I=1,NEQ
590 PHI(I,KP1)=PHI(I,KP1)+E(I)
DO 595 J1=2,KP1
J=KP1-J1+1
DO 595 I=1,NEQ
595 PHI(I,J)=PHI(I,J)+PHI(I,J+1)
JSTART = 1
RETURN
C
C
C
C
C
C-----------------------------------------------------------------------
C BLOCK 6
C The step is unsuccessful. Restore X,PSI,PHI
C Determine appropriate stepsize for
C continuing the integration, or exit with
C an error flag if there have been many
C failures.
C-----------------------------------------------------------------------
600 IPHASE = 1
C
C Restore X,PHI,PSI
C
X=XOLD
IF(KP1.LT.NSP1)GO TO 630
DO 620 J=NSP1,KP1
TEMP1=1.0D0/BETA(J)
DO 610 I=1,NEQ
610 PHI(I,J)=TEMP1*PHI(I,J)
620 CONTINUE
630 CONTINUE
DO 640 I=2,KP1
640 PSI(I-1)=PSI(I)-H
C
C
C Test whether failure is due to nonlinear solver
C or error test
C
IF(IERNLS .EQ. 0)GO TO 660
IWM(LCFN)=IWM(LCFN)+1
C
C
C The nonlinear solver failed to converge.
C Determine the cause of the failure and take appropriate action.
C If IERNLS .LT. 0, then return. Otherwise, reduce the stepsize
C and try again, unless too many failures have occurred.
C
IF (IERNLS .LT. 0) GO TO 675
NCF = NCF + 1
R = 0.25D0
H = H*R
IF (NCF .LT. 10 .AND. ABS(H) .GE. HMIN) GO TO 690
IF (IDID .EQ. 1) IDID = -7
IF (NEF .GE. 3) IDID = -9
GO TO 675
C
C
C The nonlinear solver converged, and the cause
C of the failure was the error estimate
C exceeding the tolerance.
C
660 NEF=NEF+1
IWM(LETF)=IWM(LETF)+1
IF (NEF .GT. 1) GO TO 665
C
C On first error test failure, keep current order or lower
C order by one. Compute new stepsize based on differences
C of the solution.
C
K = KNEW
TEMP2 = K + 1
R = 0.90D0*(2.0D0*EST+0.0001D0)**(-1.0D0/TEMP2)
R = MAX(0.25D0,MIN(0.9D0,R))
H = H*R
IF (ABS(H) .GE. HMIN) GO TO 690
IDID = -6
GO TO 675
C
C On second error test failure, use the current order or
C decrease order by one. Reduce the stepsize by a factor of
C one quarter.
C
665 IF (NEF .GT. 2) GO TO 670
K = KNEW
R = 0.25D0
H = R*H
IF (ABS(H) .GE. HMIN) GO TO 690
IDID = -6
GO TO 675
C
C On third and subsequent error test failures, set the order to
C one, and reduce the stepsize by a factor of one quarter.
C
670 K = 1
R = 0.25D0
H = R*H
IF (ABS(H) .GE. HMIN) GO TO 690
IDID = -6
GO TO 675
C
C
C
C
C For all crashes, restore Y to its last value,
C interpolate to find YPRIME at last X, and return.
C
C Before returning, verify that the user has not set
C IDID to a nonnegative value. If the user has set IDID
C to a nonnegative value, then reset IDID to be -7, indicating
C a failure in the nonlinear system solver.
C
675 CONTINUE
CALL DDATRP(X,X,Y,YPRIME,NEQ,K,PHI,PSI)
JSTART = 1
IF (IDID .GE. 0) IDID = -7
RETURN
C
C
C Go back and try this step again.
C If this is the first step, reset PSI(1) and rescale PHI(*,2).
C
690 IF (KOLD .EQ. 0) THEN
PSI(1) = H
DO 695 I = 1,NEQ
695 PHI(I,2) = R*PHI(I,2)
ENDIF
GO TO 200
C
C------END OF SUBROUTINE DDSTP------------------------------------------
END
SUBROUTINE DCNSTR (NEQ, Y, YNEW, ICNSTR, TAU, RLX, IRET, IVAR)
C
C***BEGIN PROLOGUE DCNSTR
C***DATE WRITTEN 950808 (YYMMDD)
C***REVISION DATE 950814 (YYMMDD)
C
C
C-----------------------------------------------------------------------
C***DESCRIPTION
C
C This subroutine checks for constraint violations in the proposed
C new approximate solution YNEW.
C If a constraint violation occurs, then a new step length, TAU,
C is calculated, and this value is to be given to the linesearch routine
C to calculate a new approximate solution YNEW.
C
C On entry:
C
C NEQ -- size of the nonlinear system, and the length of arrays
C Y, YNEW and ICNSTR.
C
C Y -- real array containing the current approximate y.
C
C YNEW -- real array containing the new approximate y.
C
C ICNSTR -- INTEGER array of length NEQ containing flags indicating
C which entries in YNEW are to be constrained.
C if ICNSTR(I) = 2, then YNEW(I) must be .GT. 0,
C if ICNSTR(I) = 1, then YNEW(I) must be .GE. 0,
C if ICNSTR(I) = -1, then YNEW(I) must be .LE. 0, while
C if ICNSTR(I) = -2, then YNEW(I) must be .LT. 0, while
C if ICNSTR(I) = 0, then YNEW(I) is not constrained.
C
C RLX -- real scalar restricting update, if ICNSTR(I) = 2 or -2,
C to ABS( (YNEW-Y)/Y ) < FAC2*RLX in component I.
C
C TAU -- the current size of the step length for the linesearch.
C
C On return
C
C TAU -- the adjusted size of the step length if a constraint
C violation occurred (otherwise, it is unchanged). it is
C the step length to give to the linesearch routine.
C
C IRET -- output flag.
C IRET=0 means that YNEW satisfied all constraints.
C IRET=1 means that YNEW failed to satisfy all the
C constraints, and a new linesearch step
C must be computed.
C
C IVAR -- index of variable causing constraint to be violated.
C
C-----------------------------------------------------------------------
IMPLICIT DOUBLE PRECISION(A-H,O-Z)
DIMENSION Y(NEQ), YNEW(NEQ), ICNSTR(NEQ)
SAVE FAC, FAC2, ZERO
DATA FAC /0.6D0/, FAC2 /0.9D0/, ZERO/0.0D0/
C-----------------------------------------------------------------------
C Check constraints for proposed new step YNEW. If a constraint has
C been violated, then calculate a new step length, TAU, to be
C used in the linesearch routine.
C-----------------------------------------------------------------------
IRET = 0
RDYMX = ZERO
IVAR = 0
DO 100 I = 1,NEQ
C
IF (ICNSTR(I) .EQ. 2) THEN
RDY = ABS( (YNEW(I)-Y(I))/Y(I) )
IF (RDY .GT. RDYMX) THEN
RDYMX = RDY
IVAR = I
ENDIF
IF (YNEW(I) .LE. ZERO) THEN
TAU = FAC*TAU
IVAR = I
IRET = 1
RETURN
ENDIF
C
ELSEIF (ICNSTR(I) .EQ. 1) THEN
IF (YNEW(I) .LT. ZERO) THEN
TAU = FAC*TAU
IVAR = I
IRET = 1
RETURN
ENDIF
C
ELSEIF (ICNSTR(I) .EQ. -1) THEN
IF (YNEW(I) .GT. ZERO) THEN
TAU = FAC*TAU
IVAR = I
IRET = 1
RETURN
ENDIF
C
ELSEIF (ICNSTR(I) .EQ. -2) THEN
RDY = ABS( (YNEW(I)-Y(I))/Y(I) )
IF (RDY .GT. RDYMX) THEN
RDYMX = RDY
IVAR = I
ENDIF
IF (YNEW(I) .GE. ZERO) THEN
TAU = FAC*TAU
IVAR = I
IRET = 1
RETURN
ENDIF
C
ENDIF
100 CONTINUE
IF(RDYMX .GE. RLX) THEN
TAU = FAC2*TAU*RLX/RDYMX
IRET = 1
ENDIF
C
RETURN
C----------------------- END OF SUBROUTINE DCNSTR ----------------------
END
SUBROUTINE DCNST0 (NEQ, Y, ICNSTR, IRET)
C
C***BEGIN PROLOGUE DCNST0
C***DATE WRITTEN 950808 (YYMMDD)
C***REVISION DATE 950808 (YYMMDD)
C
C
C-----------------------------------------------------------------------
C***DESCRIPTION
C
C This subroutine checks for constraint violations in the initial
C approximate solution u.
C
C On entry
C
C NEQ -- size of the nonlinear system, and the length of arrays
C Y and ICNSTR.
C
C Y -- real array containing the initial approximate root.
C
C ICNSTR -- INTEGER array of length NEQ containing flags indicating
C which entries in Y are to be constrained.
C if ICNSTR(I) = 2, then Y(I) must be .GT. 0,
C if ICNSTR(I) = 1, then Y(I) must be .GE. 0,
C if ICNSTR(I) = -1, then Y(I) must be .LE. 0, while
C if ICNSTR(I) = -2, then Y(I) must be .LT. 0, while
C if ICNSTR(I) = 0, then Y(I) is not constrained.
C
C On return
C
C IRET -- output flag.
C IRET=0 means that u satisfied all constraints.
C IRET.NE.0 means that Y(IRET) failed to satisfy its
C constraint.
C
C-----------------------------------------------------------------------
IMPLICIT DOUBLE PRECISION(A-H,O-Z)
DIMENSION Y(NEQ), ICNSTR(NEQ)
SAVE ZERO
DATA ZERO/0.D0/
C-----------------------------------------------------------------------
C Check constraints for initial Y. If a constraint has been violated,
C set IRET = I to signal an error return to calling routine.
C-----------------------------------------------------------------------
IRET = 0
DO 100 I = 1,NEQ
IF (ICNSTR(I) .EQ. 2) THEN
IF (Y(I) .LE. ZERO) THEN
IRET = I
RETURN
ENDIF
ELSEIF (ICNSTR(I) .EQ. 1) THEN
IF (Y(I) .LT. ZERO) THEN
IRET = I
RETURN
ENDIF
ELSEIF (ICNSTR(I) .EQ. -1) THEN
IF (Y(I) .GT. ZERO) THEN
IRET = I
RETURN
ENDIF
ELSEIF (ICNSTR(I) .EQ. -2) THEN
IF (Y(I) .GE. ZERO) THEN
IRET = I
RETURN
ENDIF
ENDIF
100 CONTINUE
RETURN
C----------------------- END OF SUBROUTINE DCNST0 ----------------------
END
SUBROUTINE DDAWTS(NEQ,IWT,RTOL,ATOL,Y,WT,RPAR,IPAR)
C
C***BEGIN PROLOGUE DDAWTS
C***REFER TO DDASPK
C***ROUTINES CALLED (NONE)
C***DATE WRITTEN 890101 (YYMMDD)
C***REVISION DATE 900926 (YYMMDD)
C***END PROLOGUE DDAWTS
C-----------------------------------------------------------------------
C This subroutine sets the error weight vector,
C WT, according to WT(I)=RTOL(I)*ABS(Y(I))+ATOL(I),
C I = 1 to NEQ.
C RTOL and ATOL are scalars if IWT = 0,
C and vectors if IWT = 1.
C-----------------------------------------------------------------------
C
IMPLICIT DOUBLE PRECISION(A-H,O-Z)
DIMENSION RTOL(*),ATOL(*),Y(*),WT(*)
DIMENSION RPAR(*),IPAR(*)
RTOLI=RTOL(1)
ATOLI=ATOL(1)
DO 20 I=1,NEQ
IF (IWT .EQ.0) GO TO 10
RTOLI=RTOL(I)
ATOLI=ATOL(I)
10 WT(I)=RTOLI*ABS(Y(I))+ATOLI
20 CONTINUE
RETURN
C
C------END OF SUBROUTINE DDAWTS-----------------------------------------
END
SUBROUTINE DINVWT(NEQ,WT,IER)
C
C***BEGIN PROLOGUE DINVWT
C***REFER TO DDASPK
C***ROUTINES CALLED (NONE)
C***DATE WRITTEN 950125 (YYMMDD)
C***END PROLOGUE DINVWT
C-----------------------------------------------------------------------
C This subroutine checks the error weight vector WT, of length NEQ,
C for components that are .le. 0, and if none are found, it
C inverts the WT(I) in place. This replaces division operations
C with multiplications in all norm evaluations.
C IER is returned as 0 if all WT(I) were found positive,
C and the first I with WT(I) .le. 0.0 otherwise.
C-----------------------------------------------------------------------
C
IMPLICIT DOUBLE PRECISION(A-H,O-Z)
DIMENSION WT(*)
C
DO 10 I = 1,NEQ
IF (WT(I) .LE. 0.0D0) GO TO 30
10 CONTINUE
DO 20 I = 1,NEQ
20 WT(I) = 1.0D0/WT(I)
IER = 0
RETURN
C
30 IER = I
RETURN
C
C------END OF SUBROUTINE DINVWT-----------------------------------------
END
SUBROUTINE DDATRP(X,XOUT,YOUT,YPOUT,NEQ,KOLD,PHI,PSI)
C
C***BEGIN PROLOGUE DDATRP
C***REFER TO DDASPK
C***ROUTINES CALLED (NONE)
C***DATE WRITTEN 890101 (YYMMDD)
C***REVISION DATE 900926 (YYMMDD)
C***END PROLOGUE DDATRP
C
C-----------------------------------------------------------------------
C The methods in subroutine DDSTP use polynomials
C to approximate the solution. DDATRP approximates the
C solution and its derivative at time XOUT by evaluating
C one of these polynomials, and its derivative, there.
C Information defining this polynomial is passed from
C DDSTP, so DDATRP cannot be used alone.
C
C The parameters are
C
C X The current time in the integration.
C XOUT The time at which the solution is desired.
C YOUT The interpolated approximation to Y at XOUT.
C (This is output.)
C YPOUT The interpolated approximation to YPRIME at XOUT.
C (This is output.)
C NEQ Number of equations.
C KOLD Order used on last successful step.
C PHI Array of scaled divided differences of Y.
C PSI Array of past stepsize history.
C-----------------------------------------------------------------------
C
IMPLICIT DOUBLE PRECISION(A-H,O-Z)
DIMENSION YOUT(*),YPOUT(*)
DIMENSION PHI(NEQ,*),PSI(*)
KOLDP1=KOLD+1
TEMP1=XOUT-X
DO 10 I=1,NEQ
YOUT(I)=PHI(I,1)
10 YPOUT(I)=0.0D0
C=1.0D0
D=0.0D0
GAMMA=TEMP1/PSI(1)
DO 30 J=2,KOLDP1
D=D*GAMMA+C/PSI(J-1)
C=C*GAMMA
GAMMA=(TEMP1+PSI(J-1))/PSI(J)
DO 20 I=1,NEQ
YOUT(I)=YOUT(I)+C*PHI(I,J)
20 YPOUT(I)=YPOUT(I)+D*PHI(I,J)
30 CONTINUE
RETURN
C
C------END OF SUBROUTINE DDATRP-----------------------------------------
END
DOUBLE PRECISION FUNCTION DDWNRM(NEQ,V,RWT,RPAR,IPAR)
C
C***BEGIN PROLOGUE DDWNRM
C***ROUTINES CALLED (NONE)
C***DATE WRITTEN 890101 (YYMMDD)
C***REVISION DATE 900926 (YYMMDD)
C***END PROLOGUE DDWNRM
C-----------------------------------------------------------------------
C This function routine computes the weighted
C root-mean-square norm of the vector of length
C NEQ contained in the array V, with reciprocal weights
C contained in the array RWT of length NEQ.
C DDWNRM=SQRT((1/NEQ)*SUM(V(I)*RWT(I))**2)
C-----------------------------------------------------------------------
C
IMPLICIT DOUBLE PRECISION(A-H,O-Z)
DIMENSION V(*),RWT(*)
DIMENSION RPAR(*),IPAR(*)
DDWNRM = 0.0D0
VMAX = 0.0D0
DO 10 I = 1,NEQ
IF(ABS(V(I)*RWT(I)) .GT. VMAX) VMAX = ABS(V(I)*RWT(I))
10 CONTINUE
IF(VMAX .LE. 0.0D0) GO TO 30
SUM = 0.0D0
DO 20 I = 1,NEQ
20 SUM = SUM + ((V(I)*RWT(I))/VMAX)**2
DDWNRM = VMAX*SQRT(SUM/NEQ)
30 CONTINUE
RETURN
C
C------END OF FUNCTION DDWNRM-------------------------------------------
END
SUBROUTINE DDASID(X,Y,YPRIME,NEQ,ICOPT,ID,RES,JACD,PDUM,H,TSCALE,
* WT,JSDUM,RPAR,IPAR,DUMSVR,DELTA,R,YIC,YPIC,DUMPWK,WM,IWM,CJ,
* UROUND,DUME,DUMS,DUMR,EPCON,RATEMX,STPTOL,JFDUM,
* ICNFLG,ICNSTR,IERNLS)
C
C***BEGIN PROLOGUE DDASID
C***REFER TO DDASPK
C***DATE WRITTEN 940701 (YYMMDD)
C***REVISION DATE 950808 (YYMMDD)
C***REVISION DATE 951110 Removed unreachable block 390.
C***REVISION DATE 000628 TSCALE argument added.
C
C
C-----------------------------------------------------------------------
C***DESCRIPTION
C
C
C DDASID solves a nonlinear system of algebraic equations of the
C form G(X,Y,YPRIME) = 0 for the unknown parts of Y and YPRIME in
C the initial conditions.
C
C The method used is a modified Newton scheme.
C
C The parameters represent
C
C X -- Independent variable.
C Y -- Solution vector.
C YPRIME -- Derivative of solution vector.
C NEQ -- Number of unknowns.
C ICOPT -- Initial condition option chosen (1 or 2).
C ID -- Array of dimension NEQ, which must be initialized
C if ICOPT = 1. See DDASIC.
C RES -- External user-supplied subroutine to evaluate the
C residual. See RES description in DDASPK prologue.
C JACD -- External user-supplied routine to evaluate the
C Jacobian. See JAC description for the case
C INFO(12) = 0 in the DDASPK prologue.
C PDUM -- Dummy argument.
C H -- Scaling factor for this initial condition calc.
C TSCALE -- Scale factor in T, used for stopping tests if nonzero.
C WT -- Vector of weights for error criterion.
C JSDUM -- Dummy argument.
C RPAR,IPAR -- Real and integer arrays used for communication
C between the calling program and external user
C routines. They are not altered within DASPK.
C DUMSVR -- Dummy argument.
C DELTA -- Work vector for NLS of length NEQ.
C R -- Work vector for NLS of length NEQ.
C YIC,YPIC -- Work vectors for NLS, each of length NEQ.
C DUMPWK -- Dummy argument.
C WM,IWM -- Real and integer arrays storing matrix information
C such as the matrix of partial derivatives,
C permutation vector, and various other information.
C CJ -- Matrix parameter = 1/H (ICOPT = 1) or 0 (ICOPT = 2).
C UROUND -- Unit roundoff.
C DUME -- Dummy argument.
C DUMS -- Dummy argument.
C DUMR -- Dummy argument.
C EPCON -- Tolerance to test for convergence of the Newton
C iteration.
C RATEMX -- Maximum convergence rate for which Newton iteration
C is considered converging.
C JFDUM -- Dummy argument.
C STPTOL -- Tolerance used in calculating the minimum lambda
C value allowed.
C ICNFLG -- Integer scalar. If nonzero, then constraint
C violations in the proposed new approximate solution
C will be checked for, and the maximum step length
C will be adjusted accordingly.
C ICNSTR -- Integer array of length NEQ containing flags for
C checking constraints.
C IERNLS -- Error flag for nonlinear solver.
C 0 ==> nonlinear solver converged.
C 1,2 ==> recoverable error inside nonlinear solver.
C 1 => retry with current Y, YPRIME
C 2 => retry with original Y, YPRIME
C -1 ==> unrecoverable error in nonlinear solver.
C
C All variables with "DUM" in their names are dummy variables
C which are not used in this routine.
C
C-----------------------------------------------------------------------
C
C***ROUTINES CALLED
C RES, DMATD, DNSID
C
C***END PROLOGUE DDASID
C
C
IMPLICIT DOUBLE PRECISION(A-H,O-Z)
DIMENSION Y(*),YPRIME(*),ID(*),WT(*),ICNSTR(*)
DIMENSION DELTA(*),R(*),YIC(*),YPIC(*)
DIMENSION WM(*),IWM(*), RPAR(*),IPAR(*)
EXTERNAL RES, JACD
C
PARAMETER (LNRE=12, LNJE=13, LMXNIT=32, LMXNJ=33)
C
C
C Perform initializations.
C
MXNIT = IWM(LMXNIT)
MXNJ = IWM(LMXNJ)
IERNLS = 0
NJ = 0
C
C Call RES to initialize DELTA.
C
IRES = 0
IWM(LNRE) = IWM(LNRE) + 1
CALL RES(X,Y,YPRIME,CJ,DELTA,IRES,RPAR,IPAR)
IF (IRES .LT. 0) GO TO 370
C
C Looping point for updating the Jacobian.
C
300 CONTINUE
C
C Initialize all error flags to zero.
C
IERJ = 0
IRES = 0
IERNEW = 0
C
C Reevaluate the iteration matrix, J = dG/dY + CJ*dG/dYPRIME,
C where G(X,Y,YPRIME) = 0.
C
NJ = NJ + 1
IWM(LNJE)=IWM(LNJE)+1
CALL DMATD(NEQ,X,Y,YPRIME,DELTA,CJ,H,IERJ,WT,R,
* WM,IWM,RES,IRES,UROUND,JACD,RPAR,IPAR)
IF (IRES .LT. 0 .OR. IERJ .NE. 0) GO TO 370
C
C Call the nonlinear Newton solver for up to MXNIT iterations.
C
CALL DNSID(X,Y,YPRIME,NEQ,ICOPT,ID,RES,WT,RPAR,IPAR,DELTA,R,
* YIC,YPIC,WM,IWM,CJ,TSCALE,EPCON,RATEMX,MXNIT,STPTOL,
* ICNFLG,ICNSTR,IERNEW)
C
IF (IERNEW .EQ. 1 .AND. NJ .LT. MXNJ) THEN
C
C MXNIT iterations were done, the convergence rate is < 1,
C and the number of Jacobian evaluations is less than MXNJ.
C Call RES, reevaluate the Jacobian, and try again.
C
IWM(LNRE)=IWM(LNRE)+1
CALL RES(X,Y,YPRIME,CJ,DELTA,IRES,RPAR,IPAR)
IF (IRES .LT. 0) GO TO 370
GO TO 300
ENDIF
C
IF (IERNEW .NE. 0) GO TO 380
RETURN
C
C
C Unsuccessful exits from nonlinear solver.
C Compute IERNLS accordingly.
C
370 IERNLS = 2
IF (IRES .LE. -2) IERNLS = -1
RETURN
C
380 IERNLS = MIN(IERNEW,2)
RETURN
C
C------END OF SUBROUTINE DDASID-----------------------------------------
END
SUBROUTINE DNSID(X,Y,YPRIME,NEQ,ICOPT,ID,RES,WT,RPAR,IPAR,
* DELTA,R,YIC,YPIC,WM,IWM,CJ,TSCALE,EPCON,RATEMX,MAXIT,STPTOL,
* ICNFLG,ICNSTR,IERNEW)
C
C***BEGIN PROLOGUE DNSID
C***REFER TO DDASPK
C***DATE WRITTEN 940701 (YYMMDD)
C***REVISION DATE 950713 (YYMMDD)
C***REVISION DATE 000628 TSCALE argument added.
C
C
C-----------------------------------------------------------------------
C***DESCRIPTION
C
C DNSID solves a nonlinear system of algebraic equations of the
C form G(X,Y,YPRIME) = 0 for the unknown parts of Y and YPRIME
C in the initial conditions.
C
C The method used is a modified Newton scheme.
C
C The parameters represent
C
C X -- Independent variable.
C Y -- Solution vector.
C YPRIME -- Derivative of solution vector.
C NEQ -- Number of unknowns.
C ICOPT -- Initial condition option chosen (1 or 2).
C ID -- Array of dimension NEQ, which must be initialized
C if ICOPT = 1. See DDASIC.
C RES -- External user-supplied subroutine to evaluate the
C residual. See RES description in DDASPK prologue.
C WT -- Vector of weights for error criterion.
C RPAR,IPAR -- Real and integer arrays used for communication
C between the calling program and external user
C routines. They are not altered within DASPK.
C DELTA -- Residual vector on entry, and work vector of
C length NEQ for DNSID.
C WM,IWM -- Real and integer arrays storing matrix information
C such as the matrix of partial derivatives,
C permutation vector, and various other information.
C CJ -- Matrix parameter = 1/H (ICOPT = 1) or 0 (ICOPT = 2).
C TSCALE -- Scale factor in T, used for stopping tests if nonzero.
C R -- Array of length NEQ used as workspace by the
C linesearch routine DLINSD.
C YIC,YPIC -- Work vectors for DLINSD, each of length NEQ.
C EPCON -- Tolerance to test for convergence of the Newton
C iteration.
C RATEMX -- Maximum convergence rate for which Newton iteration
C is considered converging.
C MAXIT -- Maximum allowed number of Newton iterations.
C STPTOL -- Tolerance used in calculating the minimum lambda
C value allowed.
C ICNFLG -- Integer scalar. If nonzero, then constraint
C violations in the proposed new approximate solution
C will be checked for, and the maximum step length
C will be adjusted accordingly.
C ICNSTR -- Integer array of length NEQ containing flags for
C checking constraints.
C IERNEW -- Error flag for Newton iteration.
C 0 ==> Newton iteration converged.
C 1 ==> failed to converge, but RATE .le. RATEMX.
C 2 ==> failed to converge, RATE .gt. RATEMX.
C 3 ==> other recoverable error (IRES = -1, or
C linesearch failed).
C -1 ==> unrecoverable error (IRES = -2).
C
C-----------------------------------------------------------------------
C
C***ROUTINES CALLED
C DSLVD, DDWNRM, DLINSD, DCOPY
C
C***END PROLOGUE DNSID
C
C
IMPLICIT DOUBLE PRECISION(A-H,O-Z)
DIMENSION Y(*),YPRIME(*),WT(*),R(*)
DIMENSION ID(*),DELTA(*), YIC(*), YPIC(*)
DIMENSION WM(*),IWM(*), RPAR(*),IPAR(*)
DIMENSION ICNSTR(*)
EXTERNAL RES
C
PARAMETER (LNNI=19, LLSOFF=35)
C
C
C Initializations. M is the Newton iteration counter.
C
LSOFF = IWM(LLSOFF)
M = 0
RATE = 1.0D0
RLX = 0.4D0
C
C Compute a new step vector DELTA by back-substitution.
C
CALL DSLVD (NEQ, DELTA, WM, IWM)
C
C Get norm of DELTA. Return now if norm(DELTA) .le. EPCON.
C
DELNRM = DDWNRM(NEQ,DELTA,WT,RPAR,IPAR)
FNRM = DELNRM
IF (TSCALE .GT. 0.0D0) FNRM = FNRM*TSCALE*ABS(CJ)
IF (FNRM .LE. EPCON) RETURN
C
C Newton iteration loop.
C
300 CONTINUE
IWM(LNNI) = IWM(LNNI) + 1
C
C Call linesearch routine for global strategy and set RATE
C
OLDFNM = FNRM
C
CALL DLINSD (NEQ, Y, X, YPRIME, CJ, TSCALE, DELTA, DELNRM, WT,
* LSOFF, STPTOL, IRET, RES, IRES, WM, IWM, FNRM, ICOPT,
* ID, R, YIC, YPIC, ICNFLG, ICNSTR, RLX, RPAR, IPAR)
C
RATE = FNRM/OLDFNM
C
C Check for error condition from linesearch.
IF (IRET .NE. 0) GO TO 390
C
C Test for convergence of the iteration, and return or loop.
C
IF (FNRM .LE. EPCON) RETURN
C
C The iteration has not yet converged. Update M.
C Test whether the maximum number of iterations have been tried.
C
M = M + 1
IF (M .GE. MAXIT) GO TO 380
C
C Copy the residual to DELTA and its norm to DELNRM, and loop for
C another iteration.
C
CALL DCOPY (NEQ, R, 1, DELTA, 1)
DELNRM = FNRM
GO TO 300
C
C The maximum number of iterations was done. Set IERNEW and return.
C
380 IF (RATE .LE. RATEMX) THEN
IERNEW = 1
ELSE
IERNEW = 2
ENDIF
RETURN
C
390 IF (IRES .LE. -2) THEN
IERNEW = -1
ELSE
IERNEW = 3
ENDIF
RETURN
C
C
C------END OF SUBROUTINE DNSID------------------------------------------
END
SUBROUTINE DLINSD (NEQ, Y, T, YPRIME, CJ, TSCALE, P, PNRM, WT,
* LSOFF, STPTOL, IRET, RES, IRES, WM, IWM,
* FNRM, ICOPT, ID, R, YNEW, YPNEW, ICNFLG,
* ICNSTR, RLX, RPAR, IPAR)
C
C***BEGIN PROLOGUE DLINSD
C***REFER TO DNSID
C***DATE WRITTEN 941025 (YYMMDD)
C***REVISION DATE 941215 (YYMMDD)
C***REVISION DATE 960129 Moved line RL = ONE to top block.
C***REVISION DATE 000628 TSCALE argument added.
C
C
C-----------------------------------------------------------------------
C***DESCRIPTION
C
C DLINSD uses a linesearch algorithm to calculate a new (Y,YPRIME)
C pair (YNEW,YPNEW) such that
C
C f(YNEW,YPNEW) .le. (1 - 2*ALPHA*RL)*f(Y,YPRIME) ,
C
C where 0 < RL <= 1. Here, f(y,y') is defined as
C
C f(y,y') = (1/2)*norm( (J-inverse)*G(t,y,y') )**2 ,
C
C where norm() is the weighted RMS vector norm, G is the DAE
C system residual function, and J is the system iteration matrix
C (Jacobian).
C
C In addition to the parameters defined elsewhere, we have
C
C TSCALE -- Scale factor in T, used for stopping tests if nonzero.
C P -- Approximate Newton step used in backtracking.
C PNRM -- Weighted RMS norm of P.
C LSOFF -- Flag showing whether the linesearch algorithm is
C to be invoked. 0 means do the linesearch, and
C 1 means turn off linesearch.
C STPTOL -- Tolerance used in calculating the minimum lambda
C value allowed.
C ICNFLG -- Integer scalar. If nonzero, then constraint violations
C in the proposed new approximate solution will be
C checked for, and the maximum step length will be
C adjusted accordingly.
C ICNSTR -- Integer array of length NEQ containing flags for
C checking constraints.
C RLX -- Real scalar restricting update size in DCNSTR.
C YNEW -- Array of length NEQ used to hold the new Y in
C performing the linesearch.
C YPNEW -- Array of length NEQ used to hold the new YPRIME in
C performing the linesearch.
C Y -- Array of length NEQ containing the new Y (i.e.,=YNEW).
C YPRIME -- Array of length NEQ containing the new YPRIME
C (i.e.,=YPNEW).
C FNRM -- Real scalar containing SQRT(2*f(Y,YPRIME)) for the
C current (Y,YPRIME) on input and output.
C R -- Work array of length NEQ, containing the scaled
C residual (J-inverse)*G(t,y,y') on return.
C IRET -- Return flag.
C IRET=0 means that a satisfactory (Y,YPRIME) was found.
C IRET=1 means that the routine failed to find a new
C (Y,YPRIME) that was sufficiently distinct from
C the current (Y,YPRIME) pair.
C IRET=2 means IRES .ne. 0 from RES.
C-----------------------------------------------------------------------
C
C***ROUTINES CALLED
C DFNRMD, DYYPNW, DCNSTR, DCOPY, XERRWD
C
C***END PROLOGUE DLINSD
C
IMPLICIT DOUBLE PRECISION(A-H,O-Z)
EXTERNAL RES
DIMENSION Y(*), YPRIME(*), WT(*), R(*), ID(*)
DIMENSION WM(*), IWM(*)
DIMENSION YNEW(*), YPNEW(*), P(*), ICNSTR(*)
DIMENSION RPAR(*), IPAR(*)
CHARACTER MSG*80
C
PARAMETER (LNRE=12, LKPRIN=31)
C
SAVE ALPHA, ONE, TWO
DATA ALPHA/1.0D-4/, ONE/1.0D0/, TWO/2.0D0/
C
KPRIN=IWM(LKPRIN)
C
F1NRM = (FNRM*FNRM)/TWO
RATIO = ONE
IF (KPRIN .GE. 2) THEN
MSG = '------ IN ROUTINE DLINSD-- PNRM = (R1)'
CALL XERRWD(MSG, 38, 901, 0, 0, 0, 0, 1, PNRM, 0.0D0)
ENDIF
TAU = PNRM
RL = ONE
C-----------------------------------------------------------------------
C Check for violations of the constraints, if any are imposed.
C If any violations are found, the step vector P is rescaled, and the
C constraint check is repeated, until no violations are found.
C-----------------------------------------------------------------------
IF (ICNFLG .NE. 0) THEN
10 CONTINUE
CALL DYYPNW (NEQ,Y,YPRIME,CJ,RL,P,ICOPT,ID,YNEW,YPNEW)
CALL DCNSTR (NEQ, Y, YNEW, ICNSTR, TAU, RLX, IRET, IVAR)
IF (IRET .EQ. 1) THEN
RATIO1 = TAU/PNRM
RATIO = RATIO*RATIO1
DO 20 I = 1,NEQ
20 P(I) = P(I)*RATIO1
PNRM = TAU
IF (KPRIN .GE. 2) THEN
MSG = '------ CONSTRAINT VIOL., PNRM = (R1), INDEX = (I1)'
CALL XERRWD(MSG, 50, 902, 0, 1, IVAR, 0, 1, PNRM, 0.0D0)
ENDIF
IF (PNRM .LE. STPTOL) THEN
IRET = 1
RETURN
ENDIF
GO TO 10
ENDIF
ENDIF
C
SLPI = (-TWO*F1NRM)*RATIO
RLMIN = STPTOL/PNRM
IF (LSOFF .EQ. 0 .AND. KPRIN .GE. 2) THEN
MSG = '------ MIN. LAMBDA = (R1)'
CALL XERRWD(MSG, 25, 903, 0, 0, 0, 0, 1, RLMIN, 0.0D0)
ENDIF
C-----------------------------------------------------------------------
C Begin iteration to find RL value satisfying alpha-condition.
C If RL becomes less than RLMIN, then terminate with IRET = 1.
C-----------------------------------------------------------------------
100 CONTINUE
CALL DYYPNW (NEQ,Y,YPRIME,CJ,RL,P,ICOPT,ID,YNEW,YPNEW)
CALL DFNRMD (NEQ, YNEW, T, YPNEW, R, CJ, TSCALE, WT, RES, IRES,
* FNRMP, WM, IWM, RPAR, IPAR)
IWM(LNRE) = IWM(LNRE) + 1
IF (IRES .NE. 0) THEN
IRET = 2
RETURN
ENDIF
IF (LSOFF .EQ. 1) GO TO 150
C
F1NRMP = FNRMP*FNRMP/TWO
IF (KPRIN .GE. 2) THEN
MSG = '------ LAMBDA = (R1)'
CALL XERRWD(MSG, 20, 904, 0, 0, 0, 0, 1, RL, 0.0D0)
MSG = '------ NORM(F1) = (R1), NORM(F1NEW) = (R2)'
CALL XERRWD(MSG, 43, 905, 0, 0, 0, 0, 2, F1NRM, F1NRMP)
ENDIF
IF (F1NRMP .GT. F1NRM + ALPHA*SLPI*RL) GO TO 200
C-----------------------------------------------------------------------
C Alpha-condition is satisfied, or linesearch is turned off.
C Copy YNEW,YPNEW to Y,YPRIME and return.
C-----------------------------------------------------------------------
150 IRET = 0
CALL DCOPY (NEQ, YNEW, 1, Y, 1)
CALL DCOPY (NEQ, YPNEW, 1, YPRIME, 1)
FNRM = FNRMP
IF (KPRIN .GE. 1) THEN
MSG = '------ LEAVING ROUTINE DLINSD, FNRM = (R1)'
CALL XERRWD(MSG, 42, 906, 0, 0, 0, 0, 1, FNRM, 0.0D0)
ENDIF
RETURN
C-----------------------------------------------------------------------
C Alpha-condition not satisfied. Perform backtrack to compute new RL
C value. If no satisfactory YNEW,YPNEW can be found sufficiently
C distinct from Y,YPRIME, then return IRET = 1.
C-----------------------------------------------------------------------
200 CONTINUE
IF (RL .LT. RLMIN) THEN
IRET = 1
RETURN
ENDIF
C
RL = RL/TWO
GO TO 100
C
C----------------------- END OF SUBROUTINE DLINSD ----------------------
END
SUBROUTINE DFNRMD (NEQ, Y, T, YPRIME, R, CJ, TSCALE, WT,
* RES, IRES, FNORM, WM, IWM, RPAR, IPAR)
C
C***BEGIN PROLOGUE DFNRMD
C***REFER TO DLINSD
C***DATE WRITTEN 941025 (YYMMDD)
C***REVISION DATE 000628 TSCALE argument added.
C
C
C-----------------------------------------------------------------------
C***DESCRIPTION
C
C DFNRMD calculates the scaled preconditioned norm of the nonlinear
C function used in the nonlinear iteration for obtaining consistent
C initial conditions. Specifically, DFNRMD calculates the weighted
C root-mean-square norm of the vector (J-inverse)*G(T,Y,YPRIME),
C where J is the Jacobian matrix.
C
C In addition to the parameters described in the calling program
C DLINSD, the parameters represent
C
C R -- Array of length NEQ that contains
C (J-inverse)*G(T,Y,YPRIME) on return.
C TSCALE -- Scale factor in T, used for stopping tests if nonzero.
C FNORM -- Scalar containing the weighted norm of R on return.
C-----------------------------------------------------------------------
C
C***ROUTINES CALLED
C RES, DSLVD, DDWNRM
C
C***END PROLOGUE DFNRMD
C
C
IMPLICIT DOUBLE PRECISION (A-H,O-Z)
EXTERNAL RES
DIMENSION Y(*), YPRIME(*), WT(*), R(*)
DIMENSION WM(*),IWM(*), RPAR(*),IPAR(*)
C-----------------------------------------------------------------------
C Call RES routine.
C-----------------------------------------------------------------------
IRES = 0
CALL RES(T,Y,YPRIME,CJ,R,IRES,RPAR,IPAR)
IF (IRES .LT. 0) RETURN
C-----------------------------------------------------------------------
C Apply inverse of Jacobian to vector R.
C-----------------------------------------------------------------------
CALL DSLVD(NEQ,R,WM,IWM)
C-----------------------------------------------------------------------
C Calculate norm of R.
C-----------------------------------------------------------------------
FNORM = DDWNRM(NEQ,R,WT,RPAR,IPAR)
IF (TSCALE .GT. 0.0D0) FNORM = FNORM*TSCALE*ABS(CJ)
C
RETURN
C----------------------- END OF SUBROUTINE DFNRMD ----------------------
END
SUBROUTINE DNEDD(X,Y,YPRIME,NEQ,RES,JACD,PDUM,H,WT,
* JSTART,IDID,RPAR,IPAR,PHI,GAMMA,DUMSVR,DELTA,E,
* WM,IWM,CJ,CJOLD,CJLAST,S,UROUND,DUME,DUMS,DUMR,
* EPCON,JCALC,JFDUM,KP1,NONNEG,NTYPE,IERNLS)
C
C***BEGIN PROLOGUE DNEDD
C***REFER TO DDASPK
C***DATE WRITTEN 891219 (YYMMDD)
C***REVISION DATE 900926 (YYMMDD)
C
C
C-----------------------------------------------------------------------
C***DESCRIPTION
C
C DNEDD solves a nonlinear system of
C algebraic equations of the form
C G(X,Y,YPRIME) = 0 for the unknown Y.
C
C The method used is a modified Newton scheme.
C
C The parameters represent
C
C X -- Independent variable.
C Y -- Solution vector.
C YPRIME -- Derivative of solution vector.
C NEQ -- Number of unknowns.
C RES -- External user-supplied subroutine
C to evaluate the residual. See RES description
C in DDASPK prologue.
C JACD -- External user-supplied routine to evaluate the
C Jacobian. See JAC description for the case
C INFO(12) = 0 in the DDASPK prologue.
C PDUM -- Dummy argument.
C H -- Appropriate step size for next step.
C WT -- Vector of weights for error criterion.
C JSTART -- Indicates first call to this routine.
C If JSTART = 0, then this is the first call,
C otherwise it is not.
C IDID -- Completion flag, output by DNEDD.
C See IDID description in DDASPK prologue.
C RPAR,IPAR -- Real and integer arrays used for communication
C between the calling program and external user
C routines. They are not altered within DASPK.
C PHI -- Array of divided differences used by
C DNEDD. The length is NEQ*(K+1),where
C K is the maximum order.
C GAMMA -- Array used to predict Y and YPRIME. The length
C is MAXORD+1 where MAXORD is the maximum order.
C DUMSVR -- Dummy argument.
C DELTA -- Work vector for NLS of length NEQ.
C E -- Error accumulation vector for NLS of length NEQ.
C WM,IWM -- Real and integer arrays storing
C matrix information such as the matrix
C of partial derivatives, permutation
C vector, and various other information.
C CJ -- Parameter always proportional to 1/H.
C CJOLD -- Saves the value of CJ as of the last call to DMATD.
C Accounts for changes in CJ needed to
C decide whether to call DMATD.
C CJLAST -- Previous value of CJ.
C S -- A scalar determined by the approximate rate
C of convergence of the Newton iteration and used
C in the convergence test for the Newton iteration.
C
C If RATE is defined to be an estimate of the
C rate of convergence of the Newton iteration,
C then S = RATE/(1.D0-RATE).
C
C The closer RATE is to 0., the faster the Newton
C iteration is converging; the closer RATE is to 1.,
C the slower the Newton iteration is converging.
C
C On the first Newton iteration with an up-dated
C preconditioner S = 100.D0, Thus the initial
C RATE of convergence is approximately 1.
C
C S is preserved from call to call so that the rate
C estimate from a previous step can be applied to
C the current step.
C UROUND -- Unit roundoff.
C DUME -- Dummy argument.
C DUMS -- Dummy argument.
C DUMR -- Dummy argument.
C EPCON -- Tolerance to test for convergence of the Newton
C iteration.
C JCALC -- Flag used to determine when to update
C the Jacobian matrix. In general:
C
C JCALC = -1 ==> Call the DMATD routine to update
C the Jacobian matrix.
C JCALC = 0 ==> Jacobian matrix is up-to-date.
C JCALC = 1 ==> Jacobian matrix is out-dated,
C but DMATD will not be called unless
C JCALC is set to -1.
C JFDUM -- Dummy argument.
C KP1 -- The current order(K) + 1; updated across calls.
C NONNEG -- Flag to determine nonnegativity constraints.
C NTYPE -- Identification code for the NLS routine.
C 0 ==> modified Newton; direct solver.
C IERNLS -- Error flag for nonlinear solver.
C 0 ==> nonlinear solver converged.
C 1 ==> recoverable error inside nonlinear solver.
C -1 ==> unrecoverable error inside nonlinear solver.
C
C All variables with "DUM" in their names are dummy variables
C which are not used in this routine.
C
C Following is a list and description of local variables which
C may not have an obvious usage. They are listed in roughly the
C order they occur in this subroutine.
C
C The following group of variables are passed as arguments to
C the Newton iteration solver. They are explained in greater detail
C in DNSD:
C TOLNEW, MULDEL, MAXIT, IERNEW
C
C IERTYP -- Flag which tells whether this subroutine is correct.
C 0 ==> correct subroutine.
C 1 ==> incorrect subroutine.
C
C-----------------------------------------------------------------------
C***ROUTINES CALLED
C DDWNRM, RES, DMATD, DNSD
C
C***END PROLOGUE DNEDD
C
C
IMPLICIT DOUBLE PRECISION(A-H,O-Z)
DIMENSION Y(*),YPRIME(*),WT(*)
DIMENSION DELTA(*),E(*)
DIMENSION WM(*),IWM(*), RPAR(*),IPAR(*)
DIMENSION PHI(NEQ,*),GAMMA(*)
EXTERNAL RES, JACD
C
PARAMETER (LNRE=12, LNJE=13)
C
SAVE MULDEL, MAXIT, XRATE
DATA MULDEL/1/, MAXIT/4/, XRATE/0.25D0/
C
C Verify that this is the correct subroutine.
C
IERTYP = 0
IF (NTYPE .NE. 0) THEN
IERTYP = 1
GO TO 380
ENDIF
C
C If this is the first step, perform initializations.
C
IF (JSTART .EQ. 0) THEN
CJOLD = CJ
JCALC = -1
ENDIF
C
C Perform all other initializations.
C
IERNLS = 0
C
C Decide whether new Jacobian is needed.
C
TEMP1 = (1.0D0 - XRATE)/(1.0D0 + XRATE)
TEMP2 = 1.0D0/TEMP1
IF (CJ/CJOLD .LT. TEMP1 .OR. CJ/CJOLD .GT. TEMP2) JCALC = -1
IF (CJ .NE. CJLAST) S = 100.D0
C
C-----------------------------------------------------------------------
C Entry point for updating the Jacobian with current
C stepsize.
C-----------------------------------------------------------------------
300 CONTINUE
C
C Initialize all error flags to zero.
C
IERJ = 0
IRES = 0
IERNEW = 0
C
C Predict the solution and derivative and compute the tolerance
C for the Newton iteration.
C
DO 310 I=1,NEQ
Y(I)=PHI(I,1)
310 YPRIME(I)=0.0D0
DO 330 J=2,KP1
DO 320 I=1,NEQ
Y(I)=Y(I)+PHI(I,J)
320 YPRIME(I)=YPRIME(I)+GAMMA(J)*PHI(I,J)
330 CONTINUE
PNORM = DDWNRM (NEQ,Y,WT,RPAR,IPAR)
TOLNEW = 100.D0*UROUND*PNORM
C
C Call RES to initialize DELTA.
C
IWM(LNRE)=IWM(LNRE)+1
CALL RES(X,Y,YPRIME,CJ,DELTA,IRES,RPAR,IPAR)
IF (IRES .LT. 0) GO TO 380
C
C If indicated, reevaluate the iteration matrix
C J = dG/dY + CJ*dG/dYPRIME (where G(X,Y,YPRIME)=0).
C Set JCALC to 0 as an indicator that this has been done.
C
IF(JCALC .EQ. -1) THEN
IWM(LNJE)=IWM(LNJE)+1
JCALC=0
CALL DMATD(NEQ,X,Y,YPRIME,DELTA,CJ,H,IERJ,WT,E,WM,IWM,
* RES,IRES,UROUND,JACD,RPAR,IPAR)
CJOLD=CJ
S = 100.D0
IF (IRES .LT. 0) GO TO 380
IF(IERJ .NE. 0)GO TO 380
ENDIF
C
C Call the nonlinear Newton solver.
C
TEMP1 = 2.0D0/(1.0D0 + CJ/CJOLD)
CALL DNSD(X,Y,YPRIME,NEQ,RES,PDUM,WT,RPAR,IPAR,DUMSVR,
* DELTA,E,WM,IWM,CJ,DUMS,DUMR,DUME,EPCON,S,TEMP1,
* TOLNEW,MULDEL,MAXIT,IRES,IDUM,IERNEW)
C
IF (IERNEW .GT. 0 .AND. JCALC .NE. 0) THEN
C
C The Newton iteration had a recoverable failure with an old
C iteration matrix. Retry the step with a new iteration matrix.
C
JCALC = -1
GO TO 300
ENDIF
C
IF (IERNEW .NE. 0) GO TO 380
C
C The Newton iteration has converged. If nonnegativity of
C solution is required, set the solution nonnegative, if the
C perturbation to do it is small enough. If the change is too
C large, then consider the corrector iteration to have failed.
C
375 IF(NONNEG .EQ. 0) GO TO 390
DO 377 I = 1,NEQ
377 DELTA(I) = MIN(Y(I),0.0D0)
DELNRM = DDWNRM(NEQ,DELTA,WT,RPAR,IPAR)
IF(DELNRM .GT. EPCON) GO TO 380
DO 378 I = 1,NEQ
378 E(I) = E(I) - DELTA(I)
GO TO 390
C
C
C Exits from nonlinear solver.
C No convergence with current iteration
C matrix, or singular iteration matrix.
C Compute IERNLS and IDID accordingly.
C
380 CONTINUE
IF (IRES .LE. -2 .OR. IERTYP .NE. 0) THEN
IERNLS = -1
IF (IRES .LE. -2) IDID = -11
IF (IERTYP .NE. 0) IDID = -15
ELSE
IERNLS = 1
IF (IRES .LT. 0) IDID = -10
IF (IERJ .NE. 0) IDID = -8
ENDIF
C
390 JCALC = 1
RETURN
C
C------END OF SUBROUTINE DNEDD------------------------------------------
END
SUBROUTINE DNSD(X,Y,YPRIME,NEQ,RES,PDUM,WT,RPAR,IPAR,
* DUMSVR,DELTA,E,WM,IWM,CJ,DUMS,DUMR,DUME,EPCON,
* S,CONFAC,TOLNEW,MULDEL,MAXIT,IRES,IDUM,IERNEW)
C
C***BEGIN PROLOGUE DNSD
C***REFER TO DDASPK
C***DATE WRITTEN 891219 (YYMMDD)
C***REVISION DATE 900926 (YYMMDD)
C***REVISION DATE 950126 (YYMMDD)
C***REVISION DATE 000711 (YYMMDD)
C
C
C-----------------------------------------------------------------------
C***DESCRIPTION
C
C DNSD solves a nonlinear system of
C algebraic equations of the form
C G(X,Y,YPRIME) = 0 for the unknown Y.
C
C The method used is a modified Newton scheme.
C
C The parameters represent
C
C X -- Independent variable.
C Y -- Solution vector.
C YPRIME -- Derivative of solution vector.
C NEQ -- Number of unknowns.
C RES -- External user-supplied subroutine
C to evaluate the residual. See RES description
C in DDASPK prologue.
C PDUM -- Dummy argument.
C WT -- Vector of weights for error criterion.
C RPAR,IPAR -- Real and integer arrays used for communication
C between the calling program and external user
C routines. They are not altered within DASPK.
C DUMSVR -- Dummy argument.
C DELTA -- Work vector for DNSD of length NEQ.
C E -- Error accumulation vector for DNSD of length NEQ.
C WM,IWM -- Real and integer arrays storing
C matrix information such as the matrix
C of partial derivatives, permutation
C vector, and various other information.
C CJ -- Parameter always proportional to 1/H (step size).
C DUMS -- Dummy argument.
C DUMR -- Dummy argument.
C DUME -- Dummy argument.
C EPCON -- Tolerance to test for convergence of the Newton
C iteration.
C S -- Used for error convergence tests.
C In the Newton iteration: S = RATE/(1 - RATE),
C where RATE is the estimated rate of convergence
C of the Newton iteration.
C The calling routine passes the initial value
C of S to the Newton iteration.
C CONFAC -- A residual scale factor to improve convergence.
C TOLNEW -- Tolerance on the norm of Newton correction in
C alternative Newton convergence test.
C MULDEL -- A flag indicating whether or not to multiply
C DELTA by CONFAC.
C 0 ==> do not scale DELTA by CONFAC.
C 1 ==> scale DELTA by CONFAC.
C MAXIT -- Maximum allowed number of Newton iterations.
C IRES -- Error flag returned from RES. See RES description
C in DDASPK prologue. If IRES = -1, then IERNEW
C will be set to 1.
C If IRES < -1, then IERNEW will be set to -1.
C IDUM -- Dummy argument.
C IERNEW -- Error flag for Newton iteration.
C 0 ==> Newton iteration converged.
C 1 ==> recoverable error inside Newton iteration.
C -1 ==> unrecoverable error inside Newton iteration.
C
C All arguments with "DUM" in their names are dummy arguments
C which are not used in this routine.
C-----------------------------------------------------------------------
C
C***ROUTINES CALLED
C DSLVD, DDWNRM, RES
C
C***END PROLOGUE DNSD
C
C
IMPLICIT DOUBLE PRECISION(A-H,O-Z)
DIMENSION Y(*),YPRIME(*),WT(*),DELTA(*),E(*)
DIMENSION WM(*),IWM(*), RPAR(*),IPAR(*)
EXTERNAL RES
C
PARAMETER (LNRE=12, LNNI=19)
C
C Initialize Newton counter M and accumulation vector E.
C
M = 0
DO 100 I=1,NEQ
100 E(I)=0.0D0
C
C Corrector loop.
C
300 CONTINUE
IWM(LNNI) = IWM(LNNI) + 1
C
C If necessary, multiply residual by convergence factor.
C
IF (MULDEL .EQ. 1) THEN
DO 320 I = 1,NEQ
320 DELTA(I) = DELTA(I) * CONFAC
ENDIF
C
C Compute a new iterate (back-substitution).
C Store the correction in DELTA.
C
CALL DSLVD(NEQ,DELTA,WM,IWM)
C
C Update Y, E, and YPRIME.
C
DO 340 I=1,NEQ
Y(I)=Y(I)-DELTA(I)
E(I)=E(I)-DELTA(I)
340 YPRIME(I)=YPRIME(I)-CJ*DELTA(I)
C
C Test for convergence of the iteration.
C
DELNRM=DDWNRM(NEQ,DELTA,WT,RPAR,IPAR)
IF (M .EQ. 0) THEN
OLDNRM = DELNRM
IF (DELNRM .LE. TOLNEW) GO TO 370
ELSE
RATE = (DELNRM/OLDNRM)**(1.0D0/M)
IF (RATE .GT. 0.9D0) GO TO 380
S = RATE/(1.0D0 - RATE)
ENDIF
IF (S*DELNRM .LE. EPCON) GO TO 370
C
C The corrector has not yet converged.
C Update M and test whether the
C maximum number of iterations have
C been tried.
C
M=M+1
IF(M.GE.MAXIT) GO TO 380
C
C Evaluate the residual,
C and go back to do another iteration.
C
IWM(LNRE)=IWM(LNRE)+1
CALL RES(X,Y,YPRIME,CJ,DELTA,IRES,RPAR,IPAR)
IF (IRES .LT. 0) GO TO 380
GO TO 300
C
C The iteration has converged.
C
370 RETURN
C
C The iteration has not converged. Set IERNEW appropriately.
C
380 CONTINUE
IF (IRES .LE. -2 ) THEN
IERNEW = -1
ELSE
IERNEW = 1
ENDIF
RETURN
C
C
C------END OF SUBROUTINE DNSD-------------------------------------------
END
SUBROUTINE DMATD(NEQ,X,Y,YPRIME,DELTA,CJ,H,IER,EWT,E,
* WM,IWM,RES,IRES,UROUND,JACD,RPAR,IPAR)
C
C***BEGIN PROLOGUE DMATD
C***REFER TO DDASPK
C***DATE WRITTEN 890101 (YYMMDD)
C***REVISION DATE 900926 (YYMMDD)
C***REVISION DATE 940701 (YYMMDD) (new LIPVT)
C
C-----------------------------------------------------------------------
C***DESCRIPTION
C
C This routine computes the iteration matrix
C J = dG/dY+CJ*dG/dYPRIME (where G(X,Y,YPRIME)=0).
C Here J is computed by:
C the user-supplied routine JACD if IWM(MTYPE) is 1 or 4, or
C by numerical difference quotients if IWM(MTYPE) is 2 or 5.
C
C The parameters have the following meanings.
C X = Independent variable.
C Y = Array containing predicted values.
C YPRIME = Array containing predicted derivatives.
C DELTA = Residual evaluated at (X,Y,YPRIME).
C (Used only if IWM(MTYPE)=2 or 5).
C CJ = Scalar parameter defining iteration matrix.
C H = Current stepsize in integration.
C IER = Variable which is .NE. 0 if iteration matrix
C is singular, and 0 otherwise.
C EWT = Vector of error weights for computing norms.
C E = Work space (temporary) of length NEQ.
C WM = Real work space for matrices. On output
C it contains the LU decomposition
C of the iteration matrix.
C IWM = Integer work space containing
C matrix information.
C RES = External user-supplied subroutine
C to evaluate the residual. See RES description
C in DDASPK prologue.
C IRES = Flag which is equal to zero if no illegal values
C in RES, and less than zero otherwise. (If IRES
C is less than zero, the matrix was not completed).
C In this case (if IRES .LT. 0), then IER = 0.
C UROUND = The unit roundoff error of the machine being used.
C JACD = Name of the external user-supplied routine
C to evaluate the iteration matrix. (This routine
C is only used if IWM(MTYPE) is 1 or 4)
C See JAC description for the case INFO(12) = 0
C in DDASPK prologue.
C RPAR,IPAR= Real and integer parameter arrays that
C are used for communication between the
C calling program and external user routines.
C They are not altered by DMATD.
C-----------------------------------------------------------------------
C***ROUTINES CALLED
C JACD, RES, DGEFA, DGBFA
C
C***END PROLOGUE DMATD
C
C
IMPLICIT DOUBLE PRECISION(A-H,O-Z)
DIMENSION Y(*),YPRIME(*),DELTA(*),EWT(*),E(*)
DIMENSION WM(*),IWM(*), RPAR(*),IPAR(*)
EXTERNAL RES, JACD
C
PARAMETER (LML=1, LMU=2, LMTYPE=4, LNRE=12, LNPD=22, LLCIWP=30)
C
LIPVT = IWM(LLCIWP)
IER = 0
MTYPE=IWM(LMTYPE)
GO TO (100,200,300,400,500),MTYPE
C
C
C Dense user-supplied matrix.
C
100 LENPD=IWM(LNPD)
DO 110 I=1,LENPD
110 WM(I)=0.0D0
CALL JACD(X,Y,YPRIME,WM,CJ,RPAR,IPAR)
GO TO 230
C
C
C Dense finite-difference-generated matrix.
C
200 IRES=0
NROW=0
SQUR = SQRT(UROUND)
DO 210 I=1,NEQ
DEL=SQUR*MAX(ABS(Y(I)),ABS(H*YPRIME(I)),
* ABS(1.D0/EWT(I)))
DEL=SIGN(DEL,H*YPRIME(I))
DEL=(Y(I)+DEL)-Y(I)
YSAVE=Y(I)
YPSAVE=YPRIME(I)
Y(I)=Y(I)+DEL
YPRIME(I)=YPRIME(I)+CJ*DEL
IWM(LNRE)=IWM(LNRE)+1
CALL RES(X,Y,YPRIME,CJ,E,IRES,RPAR,IPAR)
IF (IRES .LT. 0) RETURN
DELINV=1.0D0/DEL
DO 220 L=1,NEQ
220 WM(NROW+L)=(E(L)-DELTA(L))*DELINV
NROW=NROW+NEQ
Y(I)=YSAVE
YPRIME(I)=YPSAVE
210 CONTINUE
C
C
C Do dense-matrix LU decomposition on J.
C
230 CALL DGEFA(WM,NEQ,NEQ,IWM(LIPVT),IER)
RETURN
C
C
C Dummy section for IWM(MTYPE)=3.
C
300 RETURN
C
C
C Banded user-supplied matrix.
C
400 LENPD=IWM(LNPD)
DO 410 I=1,LENPD
410 WM(I)=0.0D0
CALL JACD(X,Y,YPRIME,WM,CJ,RPAR,IPAR)
MEBAND=2*IWM(LML)+IWM(LMU)+1
GO TO 550
C
C
C Banded finite-difference-generated matrix.
C
500 MBAND=IWM(LML)+IWM(LMU)+1
MBA=MIN0(MBAND,NEQ)
MEBAND=MBAND+IWM(LML)
MEB1=MEBAND-1
MSAVE=(NEQ/MBAND)+1
ISAVE=IWM(LNPD)
IPSAVE=ISAVE+MSAVE
IRES=0
SQUR=SQRT(UROUND)
DO 540 J=1,MBA
DO 510 N=J,NEQ,MBAND
K= (N-J)/MBAND + 1
WM(ISAVE+K)=Y(N)
WM(IPSAVE+K)=YPRIME(N)
DEL=SQUR*MAX(ABS(Y(N)),ABS(H*YPRIME(N)),
* ABS(1.D0/EWT(N)))
DEL=SIGN(DEL,H*YPRIME(N))
DEL=(Y(N)+DEL)-Y(N)
Y(N)=Y(N)+DEL
510 YPRIME(N)=YPRIME(N)+CJ*DEL
IWM(LNRE)=IWM(LNRE)+1
CALL RES(X,Y,YPRIME,CJ,E,IRES,RPAR,IPAR)
IF (IRES .LT. 0) RETURN
DO 530 N=J,NEQ,MBAND
K= (N-J)/MBAND + 1
Y(N)=WM(ISAVE+K)
YPRIME(N)=WM(IPSAVE+K)
DEL=SQUR*MAX(ABS(Y(N)),ABS(H*YPRIME(N)),
* ABS(1.D0/EWT(N)))
DEL=SIGN(DEL,H*YPRIME(N))
DEL=(Y(N)+DEL)-Y(N)
DELINV=1.0D0/DEL
I1=MAX0(1,(N-IWM(LMU)))
I2=MIN0(NEQ,(N+IWM(LML)))
II=N*MEB1-IWM(LML)
DO 520 I=I1,I2
520 WM(II+I)=(E(I)-DELTA(I))*DELINV
530 CONTINUE
540 CONTINUE
C
C
C Do LU decomposition of banded J.
C
550 CALL DGBFA (WM,MEBAND,NEQ,IWM(LML),IWM(LMU),IWM(LIPVT),IER)
RETURN
C
C------END OF SUBROUTINE DMATD------------------------------------------
END
SUBROUTINE DSLVD(NEQ,DELTA,WM,IWM)
C
C***BEGIN PROLOGUE DSLVD
C***REFER TO DDASPK
C***DATE WRITTEN 890101 (YYMMDD)
C***REVISION DATE 900926 (YYMMDD)
C***REVISION DATE 940701 (YYMMDD) (new LIPVT)
C
C-----------------------------------------------------------------------
C***DESCRIPTION
C
C This routine manages the solution of the linear
C system arising in the Newton iteration.
C Real matrix information and real temporary storage
C is stored in the array WM.
C Integer matrix information is stored in the array IWM.
C For a dense matrix, the LINPACK routine DGESL is called.
C For a banded matrix, the LINPACK routine DGBSL is called.
C-----------------------------------------------------------------------
C***ROUTINES CALLED
C DGESL, DGBSL
C
C***END PROLOGUE DSLVD
C
C
IMPLICIT DOUBLE PRECISION(A-H,O-Z)
DIMENSION DELTA(*),WM(*),IWM(*)
C
PARAMETER (LML=1, LMU=2, LMTYPE=4, LLCIWP=30)
C
LIPVT = IWM(LLCIWP)
MTYPE=IWM(LMTYPE)
GO TO(100,100,300,400,400),MTYPE
C
C Dense matrix.
C
100 CALL DGESL(WM,NEQ,NEQ,IWM(LIPVT),DELTA,0)
RETURN
C
C Dummy section for MTYPE=3.
C
300 CONTINUE
RETURN
C
C Banded matrix.
C
400 MEBAND=2*IWM(LML)+IWM(LMU)+1
CALL DGBSL(WM,MEBAND,NEQ,IWM(LML),
* IWM(LMU),IWM(LIPVT),DELTA,0)
RETURN
C
C------END OF SUBROUTINE DSLVD------------------------------------------
END
SUBROUTINE DDASIK(X,Y,YPRIME,NEQ,ICOPT,ID,RES,JACK,PSOL,H,TSCALE,
* WT,JSKIP,RPAR,IPAR,SAVR,DELTA,R,YIC,YPIC,PWK,WM,IWM,CJ,UROUND,
* EPLI,SQRTN,RSQRTN,EPCON,RATEMX,STPTOL,JFLG,
* ICNFLG,ICNSTR,IERNLS)
C
C***BEGIN PROLOGUE DDASIK
C***REFER TO DDASPK
C***DATE WRITTEN 941026 (YYMMDD)
C***REVISION DATE 950808 (YYMMDD)
C***REVISION DATE 951110 Removed unreachable block 390.
C***REVISION DATE 000628 TSCALE argument added.
C
C
C-----------------------------------------------------------------------
C***DESCRIPTION
C
C
C DDASIK solves a nonlinear system of algebraic equations of the
C form G(X,Y,YPRIME) = 0 for the unknown parts of Y and YPRIME in
C the initial conditions.
C
C An initial value for Y and initial guess for YPRIME are input.
C
C The method used is a Newton scheme with Krylov iteration and a
C linesearch algorithm.
C
C The parameters represent
C
C X -- Independent variable.
C Y -- Solution vector at x.
C YPRIME -- Derivative of solution vector.
C NEQ -- Number of equations to be integrated.
C ICOPT -- Initial condition option chosen (1 or 2).
C ID -- Array of dimension NEQ, which must be initialized
C if ICOPT = 1. See DDASIC.
C RES -- External user-supplied subroutine
C to evaluate the residual. See RES description
C in DDASPK prologue.
C JACK -- External user-supplied routine to update
C the preconditioner. (This is optional).
C See JAC description for the case
C INFO(12) = 1 in the DDASPK prologue.
C PSOL -- External user-supplied routine to solve
C a linear system using preconditioning.
C (This is optional). See explanation inside DDASPK.
C H -- Scaling factor for this initial condition calc.
C TSCALE -- Scale factor in T, used for stopping tests if nonzero.
C WT -- Vector of weights for error criterion.
C JSKIP -- input flag to signal if initial JAC call is to be
C skipped. 1 => skip the call, 0 => do not skip call.
C RPAR,IPAR -- Real and integer arrays used for communication
C between the calling program and external user
C routines. They are not altered within DASPK.
C SAVR -- Work vector for DDASIK of length NEQ.
C DELTA -- Work vector for DDASIK of length NEQ.
C R -- Work vector for DDASIK of length NEQ.
C YIC,YPIC -- Work vectors for DDASIK, each of length NEQ.
C PWK -- Work vector for DDASIK of length NEQ.
C WM,IWM -- Real and integer arrays storing
C matrix information for linear system
C solvers, and various other information.
C CJ -- Matrix parameter = 1/H (ICOPT = 1) or 0 (ICOPT = 2).
C UROUND -- Unit roundoff. Not used here.
C EPLI -- convergence test constant.
C See DDASPK prologue for more details.
C SQRTN -- Square root of NEQ.
C RSQRTN -- reciprical of square root of NEQ.
C EPCON -- Tolerance to test for convergence of the Newton
C iteration.
C RATEMX -- Maximum convergence rate for which Newton iteration
C is considered converging.
C JFLG -- Flag showing whether a Jacobian routine is supplied.
C ICNFLG -- Integer scalar. If nonzero, then constraint
C violations in the proposed new approximate solution
C will be checked for, and the maximum step length
C will be adjusted accordingly.
C ICNSTR -- Integer array of length NEQ containing flags for
C checking constraints.
C IERNLS -- Error flag for nonlinear solver.
C 0 ==> nonlinear solver converged.
C 1,2 ==> recoverable error inside nonlinear solver.
C 1 => retry with current Y, YPRIME
C 2 => retry with original Y, YPRIME
C -1 ==> unrecoverable error in nonlinear solver.
C
C-----------------------------------------------------------------------
C
C***ROUTINES CALLED
C RES, JACK, DNSIK, DCOPY
C
C***END PROLOGUE DDASIK
C
C
IMPLICIT DOUBLE PRECISION(A-H,O-Z)
DIMENSION Y(*),YPRIME(*),ID(*),WT(*),ICNSTR(*)
DIMENSION SAVR(*),DELTA(*),R(*),YIC(*),YPIC(*),PWK(*)
DIMENSION WM(*),IWM(*), RPAR(*),IPAR(*)
EXTERNAL RES, JACK, PSOL
C
PARAMETER (LNRE=12, LNJE=13, LLOCWP=29, LLCIWP=30)
PARAMETER (LMXNIT=32, LMXNJ=33)
C
C
C Perform initializations.
C
LWP = IWM(LLOCWP)
LIWP = IWM(LLCIWP)
MXNIT = IWM(LMXNIT)
MXNJ = IWM(LMXNJ)
IERNLS = 0
NJ = 0
EPLIN = EPLI*EPCON
C
C Call RES to initialize DELTA.
C
IRES = 0
IWM(LNRE) = IWM(LNRE) + 1
CALL RES(X,Y,YPRIME,CJ,DELTA,IRES,RPAR,IPAR)
IF (IRES .LT. 0) GO TO 370
C
C Looping point for updating the preconditioner.
C
300 CONTINUE
C
C Initialize all error flags to zero.
C
IERPJ = 0
IRES = 0
IERNEW = 0
C
C If a Jacobian routine was supplied, call it.
C
IF (JFLG .EQ. 1 .AND. JSKIP .EQ. 0) THEN
NJ = NJ + 1
IWM(LNJE)=IWM(LNJE)+1
CALL JACK (RES, IRES, NEQ, X, Y, YPRIME, WT, DELTA, R, H, CJ,
* WM(LWP), IWM(LIWP), IERPJ, RPAR, IPAR)
IF (IRES .LT. 0 .OR. IERPJ .NE. 0) GO TO 370
ENDIF
JSKIP = 0
C
C Call the nonlinear Newton solver for up to MXNIT iterations.
C
CALL DNSIK(X,Y,YPRIME,NEQ,ICOPT,ID,RES,PSOL,WT,RPAR,IPAR,
* SAVR,DELTA,R,YIC,YPIC,PWK,WM,IWM,CJ,TSCALE,SQRTN,RSQRTN,
* EPLIN,EPCON,RATEMX,MXNIT,STPTOL,ICNFLG,ICNSTR,IERNEW)
C
IF (IERNEW .EQ. 1 .AND. NJ .LT. MXNJ .AND. JFLG .EQ. 1) THEN
C
C Up to MXNIT iterations were done, the convergence rate is < 1,
C a Jacobian routine is supplied, and the number of JACK calls
C is less than MXNJ.
C Copy the residual SAVR to DELTA, call JACK, and try again.
C
CALL DCOPY (NEQ, SAVR, 1, DELTA, 1)
GO TO 300
ENDIF
C
IF (IERNEW .NE. 0) GO TO 380
RETURN
C
C
C Unsuccessful exits from nonlinear solver.
C Set IERNLS accordingly.
C
370 IERNLS = 2
IF (IRES .LE. -2) IERNLS = -1
RETURN
C
380 IERNLS = MIN(IERNEW,2)
RETURN
C
C----------------------- END OF SUBROUTINE DDASIK-----------------------
END
SUBROUTINE DNSIK(X,Y,YPRIME,NEQ,ICOPT,ID,RES,PSOL,WT,RPAR,IPAR,
* SAVR,DELTA,R,YIC,YPIC,PWK,WM,IWM,CJ,TSCALE,SQRTN,RSQRTN,EPLIN,
* EPCON,RATEMX,MAXIT,STPTOL,ICNFLG,ICNSTR,IERNEW)
C
C***BEGIN PROLOGUE DNSIK
C***REFER TO DDASPK
C***DATE WRITTEN 940701 (YYMMDD)
C***REVISION DATE 950714 (YYMMDD)
C***REVISION DATE 000628 TSCALE argument added.
C***REVISION DATE 000628 Added criterion for IERNEW = 1 return.
C
C
C-----------------------------------------------------------------------
C***DESCRIPTION
C
C DNSIK solves a nonlinear system of algebraic equations of the
C form G(X,Y,YPRIME) = 0 for the unknown parts of Y and YPRIME in
C the initial conditions.
C
C The method used is a Newton scheme combined with a linesearch
C algorithm, using Krylov iterative linear system methods.
C
C The parameters represent
C
C X -- Independent variable.
C Y -- Solution vector.
C YPRIME -- Derivative of solution vector.
C NEQ -- Number of unknowns.
C ICOPT -- Initial condition option chosen (1 or 2).
C ID -- Array of dimension NEQ, which must be initialized
C if ICOPT = 1. See DDASIC.
C RES -- External user-supplied subroutine
C to evaluate the residual. See RES description
C in DDASPK prologue.
C PSOL -- External user-supplied routine to solve
C a linear system using preconditioning.
C See explanation inside DDASPK.
C WT -- Vector of weights for error criterion.
C RPAR,IPAR -- Real and integer arrays used for communication
C between the calling program and external user
C routines. They are not altered within DASPK.
C SAVR -- Work vector for DNSIK of length NEQ.
C DELTA -- Residual vector on entry, and work vector of
C length NEQ for DNSIK.
C R -- Work vector for DNSIK of length NEQ.
C YIC,YPIC -- Work vectors for DNSIK, each of length NEQ.
C PWK -- Work vector for DNSIK of length NEQ.
C WM,IWM -- Real and integer arrays storing
C matrix information such as the matrix
C of partial derivatives, permutation
C vector, and various other information.
C CJ -- Matrix parameter = 1/H (ICOPT = 1) or 0 (ICOPT = 2).
C TSCALE -- Scale factor in T, used for stopping tests if nonzero.
C SQRTN -- Square root of NEQ.
C RSQRTN -- reciprical of square root of NEQ.
C EPLIN -- Tolerance for linear system solver.
C EPCON -- Tolerance to test for convergence of the Newton
C iteration.
C RATEMX -- Maximum convergence rate for which Newton iteration
C is considered converging.
C MAXIT -- Maximum allowed number of Newton iterations.
C STPTOL -- Tolerance used in calculating the minimum lambda
C value allowed.
C ICNFLG -- Integer scalar. If nonzero, then constraint
C violations in the proposed new approximate solution
C will be checked for, and the maximum step length
C will be adjusted accordingly.
C ICNSTR -- Integer array of length NEQ containing flags for
C checking constraints.
C IERNEW -- Error flag for Newton iteration.
C 0 ==> Newton iteration converged.
C 1 ==> failed to converge, but RATE .lt. 1, or the
C residual norm was reduced by a factor of .1.
C 2 ==> failed to converge, RATE .gt. RATEMX.
C 3 ==> other recoverable error.
C -1 ==> unrecoverable error inside Newton iteration.
C-----------------------------------------------------------------------
C
C***ROUTINES CALLED
C DFNRMK, DSLVK, DDWNRM, DLINSK, DCOPY
C
C***END PROLOGUE DNSIK
C
C
IMPLICIT DOUBLE PRECISION(A-H,O-Z)
DIMENSION Y(*),YPRIME(*),WT(*),ID(*),DELTA(*),R(*),SAVR(*)
DIMENSION YIC(*),YPIC(*),PWK(*),WM(*),IWM(*), RPAR(*),IPAR(*)
DIMENSION ICNSTR(*)
EXTERNAL RES, PSOL
C
PARAMETER (LNNI=19, LNPS=21, LLOCWP=29, LLCIWP=30)
PARAMETER (LLSOFF=35, LSTOL=14)
C
C
C Initializations. M is the Newton iteration counter.
C
LSOFF = IWM(LLSOFF)
M = 0
RATE = 1.0D0
LWP = IWM(LLOCWP)
LIWP = IWM(LLCIWP)
RLX = 0.4D0
C
C Save residual in SAVR.
C
CALL DCOPY (NEQ, DELTA, 1, SAVR, 1)
C
C Compute norm of (P-inverse)*(residual).
C
CALL DFNRMK (NEQ, Y, X, YPRIME, SAVR, R, CJ, TSCALE, WT,
* SQRTN, RSQRTN, RES, IRES, PSOL, 1, IER, FNRM, EPLIN,
* WM(LWP), IWM(LIWP), PWK, RPAR, IPAR)
IWM(LNPS) = IWM(LNPS) + 1
IF (IER .NE. 0) THEN
IERNEW = 3
RETURN
ENDIF
C
C Return now if residual norm is .le. EPCON.
C
IF (FNRM .LE. EPCON) RETURN
C
C Newton iteration loop.
C
FNRM0 = FNRM
300 CONTINUE
IWM(LNNI) = IWM(LNNI) + 1
C
C Compute a new step vector DELTA.
C
CALL DSLVK (NEQ, Y, X, YPRIME, SAVR, DELTA, WT, WM, IWM,
* RES, IRES, PSOL, IERSL, CJ, EPLIN, SQRTN, RSQRTN, RHOK,
* RPAR, IPAR)
IF (IRES .NE. 0 .OR. IERSL .NE. 0) GO TO 390
C
C Get norm of DELTA. Return now if DELTA is zero.
C
DELNRM = DDWNRM(NEQ,DELTA,WT,RPAR,IPAR)
IF (DELNRM .EQ. 0.0D0) RETURN
C
C Call linesearch routine for global strategy and set RATE.
C
OLDFNM = FNRM
C
CALL DLINSK (NEQ, Y, X, YPRIME, SAVR, CJ, TSCALE, DELTA, DELNRM,
* WT, SQRTN, RSQRTN, LSOFF, STPTOL, IRET, RES, IRES, PSOL,
* WM, IWM, RHOK, FNRM, ICOPT, ID, WM(LWP), IWM(LIWP), R, EPLIN,
* YIC, YPIC, PWK, ICNFLG, ICNSTR, RLX, RPAR, IPAR)
C
RATE = FNRM/OLDFNM
C
C Check for error condition from linesearch.
IF (IRET .NE. 0) GO TO 390
C
C Test for convergence of the iteration, and return or loop.
C
IF (FNRM .LE. EPCON) RETURN
C
C The iteration has not yet converged. Update M.
C Test whether the maximum number of iterations have been tried.
C
M = M + 1
IF(M .GE. MAXIT) GO TO 380
C
C Copy the residual SAVR to DELTA and loop for another iteration.
C
CALL DCOPY (NEQ, SAVR, 1, DELTA, 1)
GO TO 300
C
C The maximum number of iterations was done. Set IERNEW and return.
C
380 IF (RATE .LE. RATEMX .OR. FNRM .LE. 0.1D0*FNRM0) THEN
IERNEW = 1
ELSE
IERNEW = 2
ENDIF
RETURN
C
390 IF (IRES .LE. -2 .OR. IERSL .LT. 0) THEN
IERNEW = -1
ELSE
IERNEW = 3
IF (IRES .EQ. 0 .AND. IERSL .EQ. 1 .AND. M .GE. 2
1 .AND. RATE .LT. 1.0D0) IERNEW = 1
ENDIF
RETURN
C
C
C----------------------- END OF SUBROUTINE DNSIK------------------------
END
SUBROUTINE DLINSK (NEQ, Y, T, YPRIME, SAVR, CJ, TSCALE, P, PNRM,
* WT, SQRTN, RSQRTN, LSOFF, STPTOL, IRET, RES, IRES, PSOL,
* WM, IWM, RHOK, FNRM, ICOPT, ID, WP, IWP, R, EPLIN, YNEW, YPNEW,
* PWK, ICNFLG, ICNSTR, RLX, RPAR, IPAR)
C
C***BEGIN PROLOGUE DLINSK
C***REFER TO DNSIK
C***DATE WRITTEN 940830 (YYMMDD)
C***REVISION DATE 951006 (Arguments SQRTN, RSQRTN added.)
C***REVISION DATE 960129 Moved line RL = ONE to top block.
C***REVISION DATE 000628 TSCALE argument added.
C***REVISION DATE 000628 RHOK*RHOK term removed in alpha test.
C
C
C-----------------------------------------------------------------------
C***DESCRIPTION
C
C DLINSK uses a linesearch algorithm to calculate a new (Y,YPRIME)
C pair (YNEW,YPNEW) such that
C
C f(YNEW,YPNEW) .le. (1 - 2*ALPHA*RL)*f(Y,YPRIME)
C
C where 0 < RL <= 1, and RHOK is the scaled preconditioned norm of
C the final residual vector in the Krylov iteration.
C Here, f(y,y') is defined as
C
C f(y,y') = (1/2)*norm( (P-inverse)*G(t,y,y') )**2 ,
C
C where norm() is the weighted RMS vector norm, G is the DAE
C system residual function, and P is the preconditioner used
C in the Krylov iteration.
C
C In addition to the parameters defined elsewhere, we have
C
C SAVR -- Work array of length NEQ, containing the residual
C vector G(t,y,y') on return.
C TSCALE -- Scale factor in T, used for stopping tests if nonzero.
C P -- Approximate Newton step used in backtracking.
C PNRM -- Weighted RMS norm of P.
C LSOFF -- Flag showing whether the linesearch algorithm is
C to be invoked. 0 means do the linesearch,
C 1 means turn off linesearch.
C STPTOL -- Tolerance used in calculating the minimum lambda
C value allowed.
C ICNFLG -- Integer scalar. If nonzero, then constraint violations
C in the proposed new approximate solution will be
C checked for, and the maximum step length will be
C adjusted accordingly.
C ICNSTR -- Integer array of length NEQ containing flags for
C checking constraints.
C RHOK -- Weighted norm of preconditioned Krylov residual.
C RLX -- Real scalar restricting update size in DCNSTR.
C YNEW -- Array of length NEQ used to hold the new Y in
C performing the linesearch.
C YPNEW -- Array of length NEQ used to hold the new YPRIME in
C performing the linesearch.
C PWK -- Work vector of length NEQ for use in PSOL.
C Y -- Array of length NEQ containing the new Y (i.e.,=YNEW).
C YPRIME -- Array of length NEQ containing the new YPRIME
C (i.e.,=YPNEW).
C FNRM -- Real scalar containing SQRT(2*f(Y,YPRIME)) for the
C current (Y,YPRIME) on input and output.
C R -- Work space length NEQ for residual vector.
C IRET -- Return flag.
C IRET=0 means that a satisfactory (Y,YPRIME) was found.
C IRET=1 means that the routine failed to find a new
C (Y,YPRIME) that was sufficiently distinct from
C the current (Y,YPRIME) pair.
C IRET=2 means a failure in RES or PSOL.
C-----------------------------------------------------------------------
C
C***ROUTINES CALLED
C DFNRMK, DYYPNW, DCNSTR, DCOPY, XERRWD
C
C***END PROLOGUE DLINSK
C
IMPLICIT DOUBLE PRECISION(A-H,O-Z)
EXTERNAL RES, PSOL
DIMENSION Y(*), YPRIME(*), P(*), WT(*), SAVR(*), R(*), ID(*)
DIMENSION WM(*), IWM(*), YNEW(*), YPNEW(*), PWK(*), ICNSTR(*)
DIMENSION WP(*), IWP(*), RPAR(*), IPAR(*)
CHARACTER MSG*80
C
PARAMETER (LNRE=12, LNPS=21, LKPRIN=31)
C
SAVE ALPHA, ONE, TWO
DATA ALPHA/1.0D-4/, ONE/1.0D0/, TWO/2.0D0/
C
KPRIN=IWM(LKPRIN)
F1NRM = (FNRM*FNRM)/TWO
RATIO = ONE
C
IF (KPRIN .GE. 2) THEN
MSG = '------ IN ROUTINE DLINSK-- PNRM = (R1)'
CALL XERRWD(MSG, 38, 921, 0, 0, 0, 0, 1, PNRM, 0.0D0)
ENDIF
TAU = PNRM
RL = ONE
C-----------------------------------------------------------------------
C Check for violations of the constraints, if any are imposed.
C If any violations are found, the step vector P is rescaled, and the
C constraint check is repeated, until no violations are found.
C-----------------------------------------------------------------------
IF (ICNFLG .NE. 0) THEN
10 CONTINUE
CALL DYYPNW (NEQ,Y,YPRIME,CJ,RL,P,ICOPT,ID,YNEW,YPNEW)
CALL DCNSTR (NEQ, Y, YNEW, ICNSTR, TAU, RLX, IRET, IVAR)
IF (IRET .EQ. 1) THEN
RATIO1 = TAU/PNRM
RATIO = RATIO*RATIO1
DO 20 I = 1,NEQ
20 P(I) = P(I)*RATIO1
PNRM = TAU
IF (KPRIN .GE. 2) THEN
MSG = '------ CONSTRAINT VIOL., PNRM = (R1), INDEX = (I1)'
CALL XERRWD(MSG, 50, 922, 0, 1, IVAR, 0, 1, PNRM, 0.0D0)
ENDIF
IF (PNRM .LE. STPTOL) THEN
IRET = 1
RETURN
ENDIF
GO TO 10
ENDIF
ENDIF
C
SLPI = -TWO*F1NRM*RATIO
RLMIN = STPTOL/PNRM
IF (LSOFF .EQ. 0 .AND. KPRIN .GE. 2) THEN
MSG = '------ MIN. LAMBDA = (R1)'
CALL XERRWD(MSG, 25, 923, 0, 0, 0, 0, 1, RLMIN, 0.0D0)
ENDIF
C-----------------------------------------------------------------------
C Begin iteration to find RL value satisfying alpha-condition.
C Update YNEW and YPNEW, then compute norm of new scaled residual and
C perform alpha condition test.
C-----------------------------------------------------------------------
100 CONTINUE
CALL DYYPNW (NEQ,Y,YPRIME,CJ,RL,P,ICOPT,ID,YNEW,YPNEW)
CALL DFNRMK (NEQ, YNEW, T, YPNEW, SAVR, R, CJ, TSCALE, WT,
* SQRTN, RSQRTN, RES, IRES, PSOL, 0, IER, FNRMP, EPLIN,
* WP, IWP, PWK, RPAR, IPAR)
IWM(LNRE) = IWM(LNRE) + 1
IF (IRES .GE. 0) IWM(LNPS) = IWM(LNPS) + 1
IF (IRES .NE. 0 .OR. IER .NE. 0) THEN
IRET = 2
RETURN
ENDIF
IF (LSOFF .EQ. 1) GO TO 150
C
F1NRMP = FNRMP*FNRMP/TWO
IF (KPRIN .GE. 2) THEN
MSG = '------ LAMBDA = (R1)'
CALL XERRWD(MSG, 20, 924, 0, 0, 0, 0, 1, RL, 0.0D0)
MSG = '------ NORM(F1) = (R1), NORM(F1NEW) = (R2)'
CALL XERRWD(MSG, 43, 925, 0, 0, 0, 0, 2, F1NRM, F1NRMP)
ENDIF
IF (F1NRMP .GT. F1NRM + ALPHA*SLPI*RL) GO TO 200
C-----------------------------------------------------------------------
C Alpha-condition is satisfied, or linesearch is turned off.
C Copy YNEW,YPNEW to Y,YPRIME and return.
C-----------------------------------------------------------------------
150 IRET = 0
CALL DCOPY(NEQ, YNEW, 1, Y, 1)
CALL DCOPY(NEQ, YPNEW, 1, YPRIME, 1)
FNRM = FNRMP
IF (KPRIN .GE. 1) THEN
MSG = '------ LEAVING ROUTINE DLINSK, FNRM = (R1)'
CALL XERRWD(MSG, 42, 926, 0, 0, 0, 0, 1, FNRM, 0.0D0)
ENDIF
RETURN
C-----------------------------------------------------------------------
C Alpha-condition not satisfied. Perform backtrack to compute new RL
C value. If RL is less than RLMIN, i.e. no satisfactory YNEW,YPNEW can
C be found sufficiently distinct from Y,YPRIME, then return IRET = 1.
C-----------------------------------------------------------------------
200 CONTINUE
IF (RL .LT. RLMIN) THEN
IRET = 1
RETURN
ENDIF
C
RL = RL/TWO
GO TO 100
C
C----------------------- END OF SUBROUTINE DLINSK ----------------------
END
SUBROUTINE DFNRMK (NEQ, Y, T, YPRIME, SAVR, R, CJ, TSCALE, WT,
* SQRTN, RSQRTN, RES, IRES, PSOL, IRIN, IER,
* FNORM, EPLIN, WP, IWP, PWK, RPAR, IPAR)
C
C***BEGIN PROLOGUE DFNRMK
C***REFER TO DLINSK
C***DATE WRITTEN 940830 (YYMMDD)
C***REVISION DATE 951006 (SQRTN, RSQRTN, and scaling of WT added.)
C***REVISION DATE 000628 TSCALE argument added.
C
C
C-----------------------------------------------------------------------
C***DESCRIPTION
C
C DFNRMK calculates the scaled preconditioned norm of the nonlinear
C function used in the nonlinear iteration for obtaining consistent
C initial conditions. Specifically, DFNRMK calculates the weighted
C root-mean-square norm of the vector (P-inverse)*G(T,Y,YPRIME),
C where P is the preconditioner matrix.
C
C In addition to the parameters described in the calling program
C DLINSK, the parameters represent
C
C TSCALE -- Scale factor in T, used for stopping tests if nonzero.
C IRIN -- Flag showing whether the current residual vector is
C input in SAVR. 1 means it is, 0 means it is not.
C R -- Array of length NEQ that contains
C (P-inverse)*G(T,Y,YPRIME) on return.
C FNORM -- Scalar containing the weighted norm of R on return.
C-----------------------------------------------------------------------
C
C***ROUTINES CALLED
C RES, DCOPY, DSCAL, PSOL, DDWNRM
C
C***END PROLOGUE DFNRMK
C
C
IMPLICIT DOUBLE PRECISION (A-H,O-Z)
EXTERNAL RES, PSOL
DIMENSION Y(*), YPRIME(*), WT(*), SAVR(*), R(*), PWK(*)
DIMENSION WP(*), IWP(*), RPAR(*), IPAR(*)
C-----------------------------------------------------------------------
C Call RES routine if IRIN = 0.
C-----------------------------------------------------------------------
IF (IRIN .EQ. 0) THEN
IRES = 0
CALL RES (T, Y, YPRIME, CJ, SAVR, IRES, RPAR, IPAR)
IF (IRES .LT. 0) RETURN
ENDIF
C-----------------------------------------------------------------------
C Apply inverse of left preconditioner to vector R.
C First scale WT array by 1/sqrt(N), and undo scaling afterward.
C-----------------------------------------------------------------------
CALL DCOPY(NEQ, SAVR, 1, R, 1)
CALL DSCAL (NEQ, RSQRTN, WT, 1)
IER = 0
CALL PSOL (NEQ, T, Y, YPRIME, SAVR, PWK, CJ, WT, WP, IWP,
* R, EPLIN, IER, RPAR, IPAR)
CALL DSCAL (NEQ, SQRTN, WT, 1)
IF (IER .NE. 0) RETURN
C-----------------------------------------------------------------------
C Calculate norm of R.
C-----------------------------------------------------------------------
FNORM = DDWNRM (NEQ, R, WT, RPAR, IPAR)
IF (TSCALE .GT. 0.0D0) FNORM = FNORM*TSCALE*ABS(CJ)
C
RETURN
C----------------------- END OF SUBROUTINE DFNRMK ----------------------
END
SUBROUTINE DNEDK(X,Y,YPRIME,NEQ,RES,JACK,PSOL,
* H,WT,JSTART,IDID,RPAR,IPAR,PHI,GAMMA,SAVR,DELTA,E,
* WM,IWM,CJ,CJOLD,CJLAST,S,UROUND,EPLI,SQRTN,RSQRTN,
* EPCON,JCALC,JFLG,KP1,NONNEG,NTYPE,IERNLS)
C
C***BEGIN PROLOGUE DNEDK
C***REFER TO DDASPK
C***DATE WRITTEN 891219 (YYMMDD)
C***REVISION DATE 900926 (YYMMDD)
C***REVISION DATE 940701 (YYMMDD)
C
C
C-----------------------------------------------------------------------
C***DESCRIPTION
C
C DNEDK solves a nonlinear system of
C algebraic equations of the form
C G(X,Y,YPRIME) = 0 for the unknown Y.
C
C The method used is a matrix-free Newton scheme.
C
C The parameters represent
C X -- Independent variable.
C Y -- Solution vector at x.
C YPRIME -- Derivative of solution vector
C after successful step.
C NEQ -- Number of equations to be integrated.
C RES -- External user-supplied subroutine
C to evaluate the residual. See RES description
C in DDASPK prologue.
C JACK -- External user-supplied routine to update
C the preconditioner. (This is optional).
C See JAC description for the case
C INFO(12) = 1 in the DDASPK prologue.
C PSOL -- External user-supplied routine to solve
C a linear system using preconditioning.
C (This is optional). See explanation inside DDASPK.
C H -- Appropriate step size for this step.
C WT -- Vector of weights for error criterion.
C JSTART -- Indicates first call to this routine.
C If JSTART = 0, then this is the first call,
C otherwise it is not.
C IDID -- Completion flag, output by DNEDK.
C See IDID description in DDASPK prologue.
C RPAR,IPAR -- Real and integer arrays used for communication
C between the calling program and external user
C routines. They are not altered within DASPK.
C PHI -- Array of divided differences used by
C DNEDK. The length is NEQ*(K+1), where
C K is the maximum order.
C GAMMA -- Array used to predict Y and YPRIME. The length
C is K+1, where K is the maximum order.
C SAVR -- Work vector for DNEDK of length NEQ.
C DELTA -- Work vector for DNEDK of length NEQ.
C E -- Error accumulation vector for DNEDK of length NEQ.
C WM,IWM -- Real and integer arrays storing
C matrix information for linear system
C solvers, and various other information.
C CJ -- Parameter always proportional to 1/H.
C CJOLD -- Saves the value of CJ as of the last call to DITMD.
C Accounts for changes in CJ needed to
C decide whether to call DITMD.
C CJLAST -- Previous value of CJ.
C S -- A scalar determined by the approximate rate
C of convergence of the Newton iteration and used
C in the convergence test for the Newton iteration.
C
C If RATE is defined to be an estimate of the
C rate of convergence of the Newton iteration,
C then S = RATE/(1.D0-RATE).
C
C The closer RATE is to 0., the faster the Newton
C iteration is converging; the closer RATE is to 1.,
C the slower the Newton iteration is converging.
C
C On the first Newton iteration with an up-dated
C preconditioner S = 100.D0, Thus the initial
C RATE of convergence is approximately 1.
C
C S is preserved from call to call so that the rate
C estimate from a previous step can be applied to
C the current step.
C UROUND -- Unit roundoff. Not used here.
C EPLI -- convergence test constant.
C See DDASPK prologue for more details.
C SQRTN -- Square root of NEQ.
C RSQRTN -- reciprical of square root of NEQ.
C EPCON -- Tolerance to test for convergence of the Newton
C iteration.
C JCALC -- Flag used to determine when to update
C the Jacobian matrix. In general:
C
C JCALC = -1 ==> Call the DITMD routine to update
C the Jacobian matrix.
C JCALC = 0 ==> Jacobian matrix is up-to-date.
C JCALC = 1 ==> Jacobian matrix is out-dated,
C but DITMD will not be called unless
C JCALC is set to -1.
C JFLG -- Flag showing whether a Jacobian routine is supplied.
C KP1 -- The current order + 1; updated across calls.
C NONNEG -- Flag to determine nonnegativity constraints.
C NTYPE -- Identification code for the DNEDK routine.
C 1 ==> modified Newton; iterative linear solver.
C 2 ==> modified Newton; user-supplied linear solver.
C IERNLS -- Error flag for nonlinear solver.
C 0 ==> nonlinear solver converged.
C 1 ==> recoverable error inside non-linear solver.
C -1 ==> unrecoverable error inside non-linear solver.
C
C The following group of variables are passed as arguments to
C the Newton iteration solver. They are explained in greater detail
C in DNSK:
C TOLNEW, MULDEL, MAXIT, IERNEW
C
C IERTYP -- Flag which tells whether this subroutine is correct.
C 0 ==> correct subroutine.
C 1 ==> incorrect subroutine.
C
C-----------------------------------------------------------------------
C***ROUTINES CALLED
C RES, JACK, DDWNRM, DNSK
C
C***END PROLOGUE DNEDK
C
C
IMPLICIT DOUBLE PRECISION(A-H,O-Z)
DIMENSION Y(*),YPRIME(*),WT(*)
DIMENSION PHI(NEQ,*),SAVR(*),DELTA(*),E(*)
DIMENSION WM(*),IWM(*)
DIMENSION GAMMA(*),RPAR(*),IPAR(*)
EXTERNAL RES, JACK, PSOL
C
PARAMETER (LNRE=12, LNJE=13, LLOCWP=29, LLCIWP=30)
C
SAVE MULDEL, MAXIT, XRATE
DATA MULDEL/0/, MAXIT/4/, XRATE/0.25D0/
C
C Verify that this is the correct subroutine.
C
IERTYP = 0
IF (NTYPE .NE. 1) THEN
IERTYP = 1
GO TO 380
ENDIF
C
C If this is the first step, perform initializations.
C
IF (JSTART .EQ. 0) THEN
CJOLD = CJ
JCALC = -1
S = 100.D0
ENDIF
C
C Perform all other initializations.
C
IERNLS = 0
LWP = IWM(LLOCWP)
LIWP = IWM(LLCIWP)
C
C Decide whether to update the preconditioner.
C
IF (JFLG .NE. 0) THEN
TEMP1 = (1.0D0 - XRATE)/(1.0D0 + XRATE)
TEMP2 = 1.0D0/TEMP1
IF (CJ/CJOLD .LT. TEMP1 .OR. CJ/CJOLD .GT. TEMP2) JCALC = -1
IF (CJ .NE. CJLAST) S = 100.D0
ELSE
JCALC = 0
ENDIF
C
C Looping point for updating preconditioner with current stepsize.
C
300 CONTINUE
C
C Initialize all error flags to zero.
C
IERPJ = 0
IRES = 0
IERSL = 0
IERNEW = 0
C
C Predict the solution and derivative and compute the tolerance
C for the Newton iteration.
C
DO 310 I=1,NEQ
Y(I)=PHI(I,1)
310 YPRIME(I)=0.0D0
DO 330 J=2,KP1
DO 320 I=1,NEQ
Y(I)=Y(I)+PHI(I,J)
320 YPRIME(I)=YPRIME(I)+GAMMA(J)*PHI(I,J)
330 CONTINUE
EPLIN = EPLI*EPCON
TOLNEW = EPLIN
C
C Call RES to initialize DELTA.
C
IWM(LNRE)=IWM(LNRE)+1
CALL RES(X,Y,YPRIME,CJ,DELTA,IRES,RPAR,IPAR)
IF (IRES .LT. 0) GO TO 380
C
C
C If indicated, update the preconditioner.
C Set JCALC to 0 as an indicator that this has been done.
C
IF(JCALC .EQ. -1)THEN
IWM(LNJE) = IWM(LNJE) + 1
JCALC=0
CALL JACK (RES, IRES, NEQ, X, Y, YPRIME, WT, DELTA, E, H, CJ,
* WM(LWP), IWM(LIWP), IERPJ, RPAR, IPAR)
CJOLD=CJ
S = 100.D0
IF (IRES .LT. 0) GO TO 380
IF (IERPJ .NE. 0) GO TO 380
ENDIF
C
C Call the nonlinear Newton solver.
C
CALL DNSK(X,Y,YPRIME,NEQ,RES,PSOL,WT,RPAR,IPAR,SAVR,
* DELTA,E,WM,IWM,CJ,SQRTN,RSQRTN,EPLIN,EPCON,
* S,TEMP1,TOLNEW,MULDEL,MAXIT,IRES,IERSL,IERNEW)
C
IF (IERNEW .GT. 0 .AND. JCALC .NE. 0) THEN
C
C The Newton iteration had a recoverable failure with an old
C preconditioner. Retry the step with a new preconditioner.
C
JCALC = -1
GO TO 300
ENDIF
C
IF (IERNEW .NE. 0) GO TO 380
C
C The Newton iteration has converged. If nonnegativity of
C solution is required, set the solution nonnegative, if the
C perturbation to do it is small enough. If the change is too
C large, then consider the corrector iteration to have failed.
C
IF(NONNEG .EQ. 0) GO TO 390
DO 360 I = 1,NEQ
360 DELTA(I) = MIN(Y(I),0.0D0)
DELNRM = DDWNRM(NEQ,DELTA,WT,RPAR,IPAR)
IF(DELNRM .GT. EPCON) GO TO 380
DO 370 I = 1,NEQ
370 E(I) = E(I) - DELTA(I)
GO TO 390
C
C
C Exits from nonlinear solver.
C No convergence with current preconditioner.
C Compute IERNLS and IDID accordingly.
C
380 CONTINUE
IF (IRES .LE. -2 .OR. IERSL .LT. 0 .OR. IERTYP .NE. 0) THEN
IERNLS = -1
IF (IRES .LE. -2) IDID = -11
IF (IERSL .LT. 0) IDID = -13
IF (IERTYP .NE. 0) IDID = -15
ELSE
IERNLS = 1
IF (IRES .EQ. -1) IDID = -10
IF (IERPJ .NE. 0) IDID = -5
IF (IERSL .GT. 0) IDID = -14
ENDIF
C
C
390 JCALC = 1
RETURN
C
C------END OF SUBROUTINE DNEDK------------------------------------------
END
SUBROUTINE DNSK(X,Y,YPRIME,NEQ,RES,PSOL,WT,RPAR,IPAR,
* SAVR,DELTA,E,WM,IWM,CJ,SQRTN,RSQRTN,EPLIN,EPCON,
* S,CONFAC,TOLNEW,MULDEL,MAXIT,IRES,IERSL,IERNEW)
C
C***BEGIN PROLOGUE DNSK
C***REFER TO DDASPK
C***DATE WRITTEN 891219 (YYMMDD)
C***REVISION DATE 900926 (YYMMDD)
C***REVISION DATE 950126 (YYMMDD)
C***REVISION DATE 000711 (YYMMDD)
C
C
C-----------------------------------------------------------------------
C***DESCRIPTION
C
C DNSK solves a nonlinear system of
C algebraic equations of the form
C G(X,Y,YPRIME) = 0 for the unknown Y.
C
C The method used is a modified Newton scheme.
C
C The parameters represent
C
C X -- Independent variable.
C Y -- Solution vector.
C YPRIME -- Derivative of solution vector.
C NEQ -- Number of unknowns.
C RES -- External user-supplied subroutine
C to evaluate the residual. See RES description
C in DDASPK prologue.
C PSOL -- External user-supplied routine to solve
C a linear system using preconditioning.
C See explanation inside DDASPK.
C WT -- Vector of weights for error criterion.
C RPAR,IPAR -- Real and integer arrays used for communication
C between the calling program and external user
C routines. They are not altered within DASPK.
C SAVR -- Work vector for DNSK of length NEQ.
C DELTA -- Work vector for DNSK of length NEQ.
C E -- Error accumulation vector for DNSK of length NEQ.
C WM,IWM -- Real and integer arrays storing
C matrix information such as the matrix
C of partial derivatives, permutation
C vector, and various other information.
C CJ -- Parameter always proportional to 1/H (step size).
C SQRTN -- Square root of NEQ.
C RSQRTN -- reciprical of square root of NEQ.
C EPLIN -- Tolerance for linear system solver.
C EPCON -- Tolerance to test for convergence of the Newton
C iteration.
C S -- Used for error convergence tests.
C In the Newton iteration: S = RATE/(1.D0-RATE),
C where RATE is the estimated rate of convergence
C of the Newton iteration.
C
C The closer RATE is to 0., the faster the Newton
C iteration is converging; the closer RATE is to 1.,
C the slower the Newton iteration is converging.
C
C The calling routine sends the initial value
C of S to the Newton iteration.
C CONFAC -- A residual scale factor to improve convergence.
C TOLNEW -- Tolerance on the norm of Newton correction in
C alternative Newton convergence test.
C MULDEL -- A flag indicating whether or not to multiply
C DELTA by CONFAC.
C 0 ==> do not scale DELTA by CONFAC.
C 1 ==> scale DELTA by CONFAC.
C MAXIT -- Maximum allowed number of Newton iterations.
C IRES -- Error flag returned from RES. See RES description
C in DDASPK prologue. If IRES = -1, then IERNEW
C will be set to 1.
C If IRES < -1, then IERNEW will be set to -1.
C IERSL -- Error flag for linear system solver.
C See IERSL description in subroutine DSLVK.
C If IERSL = 1, then IERNEW will be set to 1.
C If IERSL < 0, then IERNEW will be set to -1.
C IERNEW -- Error flag for Newton iteration.
C 0 ==> Newton iteration converged.
C 1 ==> recoverable error inside Newton iteration.
C -1 ==> unrecoverable error inside Newton iteration.
C-----------------------------------------------------------------------
C
C***ROUTINES CALLED
C RES, DSLVK, DDWNRM
C
C***END PROLOGUE DNSK
C
C
IMPLICIT DOUBLE PRECISION(A-H,O-Z)
DIMENSION Y(*),YPRIME(*),WT(*),DELTA(*),E(*),SAVR(*)
DIMENSION WM(*),IWM(*), RPAR(*),IPAR(*)
EXTERNAL RES, PSOL
C
PARAMETER (LNNI=19, LNRE=12)
C
C Initialize Newton counter M and accumulation vector E.
C
M = 0
DO 100 I=1,NEQ
100 E(I) = 0.0D0
C
C Corrector loop.
C
300 CONTINUE
IWM(LNNI) = IWM(LNNI) + 1
C
C If necessary, multiply residual by convergence factor.
C
IF (MULDEL .EQ. 1) THEN
DO 320 I = 1,NEQ
320 DELTA(I) = DELTA(I) * CONFAC
ENDIF
C
C Save residual in SAVR.
C
DO 340 I = 1,NEQ
340 SAVR(I) = DELTA(I)
C
C Compute a new iterate. Store the correction in DELTA.
C
CALL DSLVK (NEQ, Y, X, YPRIME, SAVR, DELTA, WT, WM, IWM,
* RES, IRES, PSOL, IERSL, CJ, EPLIN, SQRTN, RSQRTN, RHOK,
* RPAR, IPAR)
IF (IRES .NE. 0 .OR. IERSL .NE. 0) GO TO 380
C
C Update Y, E, and YPRIME.
C
DO 360 I=1,NEQ
Y(I) = Y(I) - DELTA(I)
E(I) = E(I) - DELTA(I)
360 YPRIME(I) = YPRIME(I) - CJ*DELTA(I)
C
C Test for convergence of the iteration.
C
DELNRM = DDWNRM(NEQ,DELTA,WT,RPAR,IPAR)
IF (M .EQ. 0) THEN
OLDNRM = DELNRM
IF (DELNRM .LE. TOLNEW) GO TO 370
ELSE
RATE = (DELNRM/OLDNRM)**(1.0D0/M)
IF (RATE .GT. 0.9D0) GO TO 380
S = RATE/(1.0D0 - RATE)
ENDIF
IF (S*DELNRM .LE. EPCON) GO TO 370
C
C The corrector has not yet converged. Update M and test whether
C the maximum number of iterations have been tried.
C
M = M + 1
IF (M .GE. MAXIT) GO TO 380
C
C Evaluate the residual, and go back to do another iteration.
C
IWM(LNRE) = IWM(LNRE) + 1
CALL RES(X,Y,YPRIME,CJ,DELTA,IRES,RPAR,IPAR)
IF (IRES .LT. 0) GO TO 380
GO TO 300
C
C The iteration has converged.
C
370 RETURN
C
C The iteration has not converged. Set IERNEW appropriately.
C
380 CONTINUE
IF (IRES .LE. -2 .OR. IERSL .LT. 0) THEN
IERNEW = -1
ELSE
IERNEW = 1
ENDIF
RETURN
C
C
C------END OF SUBROUTINE DNSK-------------------------------------------
END
SUBROUTINE DSLVK (NEQ, Y, TN, YPRIME, SAVR, X, EWT, WM, IWM,
* RES, IRES, PSOL, IERSL, CJ, EPLIN, SQRTN, RSQRTN, RHOK,
* RPAR, IPAR)
C
C***BEGIN PROLOGUE DSLVK
C***REFER TO DDASPK
C***DATE WRITTEN 890101 (YYMMDD)
C***REVISION DATE 900926 (YYMMDD)
C***REVISION DATE 940928 Removed MNEWT and added RHOK in call list.
C
C
C-----------------------------------------------------------------------
C***DESCRIPTION
C
C DSLVK uses a restart algorithm and interfaces to DSPIGM for
C the solution of the linear system arising from a Newton iteration.
C
C In addition to variables described elsewhere,
C communication with DSLVK uses the following variables..
C WM = Real work space containing data for the algorithm
C (Krylov basis vectors, Hessenberg matrix, etc.).
C IWM = Integer work space containing data for the algorithm.
C X = The right-hand side vector on input, and the solution vector
C on output, of length NEQ.
C IRES = Error flag from RES.
C IERSL = Output flag ..
C IERSL = 0 means no trouble occurred (or user RES routine
C returned IRES < 0)
C IERSL = 1 means the iterative method failed to converge
C (DSPIGM returned IFLAG > 0.)
C IERSL = -1 means there was a nonrecoverable error in the
C iterative solver, and an error exit will occur.
C-----------------------------------------------------------------------
C***ROUTINES CALLED
C DSCAL, DCOPY, DSPIGM
C
C***END PROLOGUE DSLVK
C
INTEGER NEQ, IWM, IRES, IERSL, IPAR
DOUBLE PRECISION Y, TN, YPRIME, SAVR, X, EWT, WM, CJ, EPLIN,
1 SQRTN, RSQRTN, RHOK, RPAR
DIMENSION Y(*), YPRIME(*), SAVR(*), X(*), EWT(*),
1 WM(*), IWM(*), RPAR(*), IPAR(*)
C
INTEGER IFLAG, IRST, NRSTS, NRMAX, LR, LDL, LHES, LGMR, LQ, LV,
1 LWK, LZ, MAXLP1, NPSL
INTEGER NLI, NPS, NCFL, NRE, MAXL, KMP, MITER
EXTERNAL RES, PSOL
C
PARAMETER (LNRE=12, LNCFL=16, LNLI=20, LNPS=21)
PARAMETER (LLOCWP=29, LLCIWP=30)
PARAMETER (LMITER=23, LMAXL=24, LKMP=25, LNRMAX=26)
C
C-----------------------------------------------------------------------
C IRST is set to 1, to indicate restarting is in effect.
C NRMAX is the maximum number of restarts.
C-----------------------------------------------------------------------
DATA IRST/1/
C
LIWP = IWM(LLCIWP)
NLI = IWM(LNLI)
NPS = IWM(LNPS)
NCFL = IWM(LNCFL)
NRE = IWM(LNRE)
LWP = IWM(LLOCWP)
MAXL = IWM(LMAXL)
KMP = IWM(LKMP)
NRMAX = IWM(LNRMAX)
MITER = IWM(LMITER)
IERSL = 0
IRES = 0
C-----------------------------------------------------------------------
C Use a restarting strategy to solve the linear system
C P*X = -F. Parse the work vector, and perform initializations.
C Note that zero is the initial guess for X.
C-----------------------------------------------------------------------
MAXLP1 = MAXL + 1
LV = 1
LR = LV + NEQ*MAXL
LHES = LR + NEQ + 1
LQ = LHES + MAXL*MAXLP1
LWK = LQ + 2*MAXL
LDL = LWK + MIN0(1,MAXL-KMP)*NEQ
LZ = LDL + NEQ
CALL DSCAL (NEQ, RSQRTN, EWT, 1)
CALL DCOPY (NEQ, X, 1, WM(LR), 1)
DO 110 I = 1,NEQ
110 X(I) = 0.D0
C-----------------------------------------------------------------------
C Top of loop for the restart algorithm. Initial pass approximates
C X and sets up a transformed system to perform subsequent restarts
C to update X. NRSTS is initialized to -1, because restarting
C does not occur until after the first pass.
C Update NRSTS; conditionally copy DL to R; call the DSPIGM
C algorithm to solve A*Z = R; updated counters; update X with
C the residual solution.
C Note: if convergence is not achieved after NRMAX restarts,
C then the linear solver is considered to have failed.
C-----------------------------------------------------------------------
NRSTS = -1
115 CONTINUE
NRSTS = NRSTS + 1
IF (NRSTS .GT. 0) CALL DCOPY (NEQ, WM(LDL), 1, WM(LR),1)
CALL DSPIGM (NEQ, TN, Y, YPRIME, SAVR, WM(LR), EWT, MAXL, MAXLP1,
1 KMP, EPLIN, CJ, RES, IRES, NRES, PSOL, NPSL, WM(LZ), WM(LV),
2 WM(LHES), WM(LQ), LGMR, WM(LWP), IWM(LIWP), WM(LWK),
3 WM(LDL), RHOK, IFLAG, IRST, NRSTS, RPAR, IPAR)
NLI = NLI + LGMR
NPS = NPS + NPSL
NRE = NRE + NRES
DO 120 I = 1,NEQ
120 X(I) = X(I) + WM(LZ+I-1)
IF ((IFLAG .EQ. 1) .AND. (NRSTS .LT. NRMAX) .AND. (IRES .EQ. 0))
1 GO TO 115
C-----------------------------------------------------------------------
C The restart scheme is finished. Test IRES and IFLAG to see if
C convergence was not achieved, and set flags accordingly.
C-----------------------------------------------------------------------
IF (IRES .LT. 0) THEN
NCFL = NCFL + 1
ELSE IF (IFLAG .NE. 0) THEN
NCFL = NCFL + 1
IF (IFLAG .GT. 0) IERSL = 1
IF (IFLAG .LT. 0) IERSL = -1
ENDIF
C-----------------------------------------------------------------------
C Update IWM with counters, rescale EWT, and return.
C-----------------------------------------------------------------------
IWM(LNLI) = NLI
IWM(LNPS) = NPS
IWM(LNCFL) = NCFL
IWM(LNRE) = NRE
CALL DSCAL (NEQ, SQRTN, EWT, 1)
RETURN
C
C------END OF SUBROUTINE DSLVK------------------------------------------
END
SUBROUTINE DSPIGM (NEQ, TN, Y, YPRIME, SAVR, R, WGHT, MAXL,
* MAXLP1, KMP, EPLIN, CJ, RES, IRES, NRE, PSOL, NPSL, Z, V,
* HES, Q, LGMR, WP, IWP, WK, DL, RHOK, IFLAG, IRST, NRSTS,
* RPAR, IPAR)
C
C***BEGIN PROLOGUE DSPIGM
C***DATE WRITTEN 890101 (YYMMDD)
C***REVISION DATE 900926 (YYMMDD)
C***REVISION DATE 940927 Removed MNEWT and added RHOK in call list.
C
C
C-----------------------------------------------------------------------
C***DESCRIPTION
C
C This routine solves the linear system A * Z = R using a scaled
C preconditioned version of the generalized minimum residual method.
C An initial guess of Z = 0 is assumed.
C
C On entry
C
C NEQ = Problem size, passed to PSOL.
C
C TN = Current Value of T.
C
C Y = Array Containing current dependent variable vector.
C
C YPRIME = Array Containing current first derivative of Y.
C
C SAVR = Array containing current value of G(T,Y,YPRIME).
C
C R = The right hand side of the system A*Z = R.
C R is also used as work space when computing
C the final approximation and will therefore be
C destroyed.
C (R is the same as V(*,MAXL+1) in the call to DSPIGM.)
C
C WGHT = The vector of length NEQ containing the nonzero
C elements of the diagonal scaling matrix.
C
C MAXL = The maximum allowable order of the matrix H.
C
C MAXLP1 = MAXL + 1, used for dynamic dimensioning of HES.
C
C KMP = The number of previous vectors the new vector, VNEW,
C must be made orthogonal to. (KMP .LE. MAXL.)
C
C EPLIN = Tolerance on residuals R-A*Z in weighted rms norm.
C
C CJ = Scalar proportional to current value of
C 1/(step size H).
C
C WK = Real work array used by routine DATV and PSOL.
C
C DL = Real work array used for calculation of the residual
C norm RHO when the method is incomplete (KMP.LT.MAXL)
C and/or when using restarting.
C
C WP = Real work array used by preconditioner PSOL.
C
C IWP = Integer work array used by preconditioner PSOL.
C
C IRST = Method flag indicating if restarting is being
C performed. IRST .GT. 0 means restarting is active,
C while IRST = 0 means restarting is not being used.
C
C NRSTS = Counter for the number of restarts on the current
C call to DSPIGM. If NRSTS .GT. 0, then the residual
C R is already scaled, and so scaling of R is not
C necessary.
C
C
C On Return
C
C Z = The final computed approximation to the solution
C of the system A*Z = R.
C
C LGMR = The number of iterations performed and
C the current order of the upper Hessenberg
C matrix HES.
C
C NRE = The number of calls to RES (i.e. DATV)
C
C NPSL = The number of calls to PSOL.
C
C V = The neq by (LGMR+1) array containing the LGMR
C orthogonal vectors V(*,1) to V(*,LGMR).
C
C HES = The upper triangular factor of the QR decomposition
C of the (LGMR+1) by LGMR upper Hessenberg matrix whose
C entries are the scaled inner-products of A*V(*,I)
C and V(*,K).
C
C Q = Real array of length 2*MAXL containing the components
C of the givens rotations used in the QR decomposition
C of HES. It is loaded in DHEQR and used in DHELS.
C
C IRES = Error flag from RES.
C
C DL = Scaled preconditioned residual,
C (D-inverse)*(P-inverse)*(R-A*Z). Only loaded when
C performing restarts of the Krylov iteration.
C
C RHOK = Weighted norm of final preconditioned residual.
C
C IFLAG = Integer error flag..
C 0 Means convergence in LGMR iterations, LGMR.LE.MAXL.
C 1 Means the convergence test did not pass in MAXL
C iterations, but the new residual norm (RHO) is
C .LT. the old residual norm (RNRM), and so Z is
C computed.
C 2 Means the convergence test did not pass in MAXL
C iterations, new residual norm (RHO) .GE. old residual
C norm (RNRM), and the initial guess, Z = 0, is
C returned.
C 3 Means there was a recoverable error in PSOL
C caused by the preconditioner being out of date.
C -1 Means there was an unrecoverable error in PSOL.
C
C-----------------------------------------------------------------------
C***ROUTINES CALLED
C PSOL, DNRM2, DSCAL, DATV, DORTH, DHEQR, DCOPY, DHELS, DAXPY
C
C***END PROLOGUE DSPIGM
C
INTEGER NEQ,MAXL,MAXLP1,KMP,IRES,NRE,NPSL,LGMR,IWP,
1 IFLAG,IRST,NRSTS,IPAR
DOUBLE PRECISION TN,Y,YPRIME,SAVR,R,WGHT,EPLIN,CJ,Z,V,HES,Q,WP,WK,
1 DL,RHOK,RPAR
DIMENSION Y(*), YPRIME(*), SAVR(*), R(*), WGHT(*), Z(*),
1 V(NEQ,*), HES(MAXLP1,*), Q(*), WP(*), IWP(*), WK(*), DL(*),
2 RPAR(*), IPAR(*)
INTEGER I, IER, INFO, IP1, I2, J, K, LL, LLP1
DOUBLE PRECISION RNRM,C,DLNRM,PROD,RHO,S,SNORMW,DNRM2,TEM
EXTERNAL RES, PSOL
C
IER = 0
IFLAG = 0
LGMR = 0
NPSL = 0
NRE = 0
C-----------------------------------------------------------------------
C The initial guess for Z is 0. The initial residual is therefore
C the vector R. Initialize Z to 0.
C-----------------------------------------------------------------------
DO 10 I = 1,NEQ
10 Z(I) = 0.0D0
C-----------------------------------------------------------------------
C Apply inverse of left preconditioner to vector R if NRSTS .EQ. 0.
C Form V(*,1), the scaled preconditioned right hand side.
C-----------------------------------------------------------------------
IF (NRSTS .EQ. 0) THEN
CALL PSOL (NEQ, TN, Y, YPRIME, SAVR, WK, CJ, WGHT, WP, IWP,
1 R, EPLIN, IER, RPAR, IPAR)
NPSL = 1
IF (IER .NE. 0) GO TO 300
DO 30 I = 1,NEQ
30 V(I,1) = R(I)*WGHT(I)
ELSE
DO 35 I = 1,NEQ
35 V(I,1) = R(I)
ENDIF
C-----------------------------------------------------------------------
C Calculate norm of scaled vector V(*,1) and normalize it
C If, however, the norm of V(*,1) (i.e. the norm of the preconditioned
C residual) is .le. EPLIN, then return with Z=0.
C-----------------------------------------------------------------------
RNRM = DNRM2 (NEQ, V, 1)
IF (RNRM .LE. EPLIN) THEN
RHOK = RNRM
RETURN
ENDIF
TEM = 1.0D0/RNRM
CALL DSCAL (NEQ, TEM, V(1,1), 1)
C-----------------------------------------------------------------------
C Zero out the HES array.
C-----------------------------------------------------------------------
DO 65 J = 1,MAXL
DO 60 I = 1,MAXLP1
60 HES(I,J) = 0.0D0
65 CONTINUE
C-----------------------------------------------------------------------
C Main loop to compute the vectors V(*,2) to V(*,MAXL).
C The running product PROD is needed for the convergence test.
C-----------------------------------------------------------------------
PROD = 1.0D0
DO 90 LL = 1,MAXL
LGMR = LL
C-----------------------------------------------------------------------
C Call routine DATV to compute VNEW = ABAR*V(LL), where ABAR is
C the matrix A with scaling and inverse preconditioner factors applied.
C Call routine DORTH to orthogonalize the new vector VNEW = V(*,LL+1).
C call routine DHEQR to update the factors of HES.
C-----------------------------------------------------------------------
CALL DATV (NEQ, Y, TN, YPRIME, SAVR, V(1,LL), WGHT, Z,
1 RES, IRES, PSOL, V(1,LL+1), WK, WP, IWP, CJ, EPLIN,
1 IER, NRE, NPSL, RPAR, IPAR)
IF (IRES .LT. 0) RETURN
IF (IER .NE. 0) GO TO 300
CALL DORTH (V(1,LL+1), V, HES, NEQ, LL, MAXLP1, KMP, SNORMW)
HES(LL+1,LL) = SNORMW
CALL DHEQR (HES, MAXLP1, LL, Q, INFO, LL)
IF (INFO .EQ. LL) GO TO 120
C-----------------------------------------------------------------------
C Update RHO, the estimate of the norm of the residual R - A*ZL.
C If KMP .LT. MAXL, then the vectors V(*,1),...,V(*,LL+1) are not
C necessarily orthogonal for LL .GT. KMP. The vector DL must then
C be computed, and its norm used in the calculation of RHO.
C-----------------------------------------------------------------------
PROD = PROD*Q(2*LL)
RHO = ABS(PROD*RNRM)
IF ((LL.GT.KMP) .AND. (KMP.LT.MAXL)) THEN
IF (LL .EQ. KMP+1) THEN
CALL DCOPY (NEQ, V(1,1), 1, DL, 1)
DO 75 I = 1,KMP
IP1 = I + 1
I2 = I*2
S = Q(I2)
C = Q(I2-1)
DO 70 K = 1,NEQ
70 DL(K) = S*DL(K) + C*V(K,IP1)
75 CONTINUE
ENDIF
S = Q(2*LL)
C = Q(2*LL-1)/SNORMW
LLP1 = LL + 1
DO 80 K = 1,NEQ
80 DL(K) = S*DL(K) + C*V(K,LLP1)
DLNRM = DNRM2 (NEQ, DL, 1)
RHO = RHO*DLNRM
ENDIF
C-----------------------------------------------------------------------
C Test for convergence. If passed, compute approximation ZL.
C If failed and LL .LT. MAXL, then continue iterating.
C-----------------------------------------------------------------------
IF (RHO .LE. EPLIN) GO TO 200
IF (LL .EQ. MAXL) GO TO 100
C-----------------------------------------------------------------------
C Rescale so that the norm of V(1,LL+1) is one.
C-----------------------------------------------------------------------
TEM = 1.0D0/SNORMW
CALL DSCAL (NEQ, TEM, V(1,LL+1), 1)
90 CONTINUE
100 CONTINUE
IF (RHO .LT. RNRM) GO TO 150
120 CONTINUE
IFLAG = 2
DO 130 I = 1,NEQ
130 Z(I) = 0.D0
RETURN
150 IFLAG = 1
C-----------------------------------------------------------------------
C The tolerance was not met, but the residual norm was reduced.
C If performing restarting (IRST .gt. 0) calculate the residual vector
C RL and store it in the DL array. If the incomplete version is
C being used (KMP .lt. MAXL) then DL has already been calculated.
C-----------------------------------------------------------------------
IF (IRST .GT. 0) THEN
IF (KMP .EQ. MAXL) THEN
C
C Calculate DL from the V(I)'s.
C
CALL DCOPY (NEQ, V(1,1), 1, DL, 1)
MAXLM1 = MAXL - 1
DO 175 I = 1,MAXLM1
IP1 = I + 1
I2 = I*2
S = Q(I2)
C = Q(I2-1)
DO 170 K = 1,NEQ
170 DL(K) = S*DL(K) + C*V(K,IP1)
175 CONTINUE
S = Q(2*MAXL)
C = Q(2*MAXL-1)/SNORMW
DO 180 K = 1,NEQ
180 DL(K) = S*DL(K) + C*V(K,MAXLP1)
ENDIF
C
C Scale DL by RNRM*PROD to obtain the residual RL.
C
TEM = RNRM*PROD
CALL DSCAL(NEQ, TEM, DL, 1)
ENDIF
C-----------------------------------------------------------------------
C Compute the approximation ZL to the solution.
C Since the vector Z was used as work space, and the initial guess
C of the Newton correction is zero, Z must be reset to zero.
C-----------------------------------------------------------------------
200 CONTINUE
LL = LGMR
LLP1 = LL + 1
DO 210 K = 1,LLP1
210 R(K) = 0.0D0
R(1) = RNRM
CALL DHELS (HES, MAXLP1, LL, Q, R)
DO 220 K = 1,NEQ
220 Z(K) = 0.0D0
DO 230 I = 1,LL
CALL DAXPY (NEQ, R(I), V(1,I), 1, Z, 1)
230 CONTINUE
DO 240 I = 1,NEQ
240 Z(I) = Z(I)/WGHT(I)
C Load RHO into RHOK.
RHOK = RHO
RETURN
C-----------------------------------------------------------------------
C This block handles error returns forced by routine PSOL.
C-----------------------------------------------------------------------
300 CONTINUE
IF (IER .LT. 0) IFLAG = -1
IF (IER .GT. 0) IFLAG = 3
C
RETURN
C
C------END OF SUBROUTINE DSPIGM-----------------------------------------
END
SUBROUTINE DATV (NEQ, Y, TN, YPRIME, SAVR, V, WGHT, YPTEM, RES,
* IRES, PSOL, Z, VTEM, WP, IWP, CJ, EPLIN, IER, NRE, NPSL,
* RPAR,IPAR)
C
C***BEGIN PROLOGUE DATV
C***DATE WRITTEN 890101 (YYMMDD)
C***REVISION DATE 900926 (YYMMDD)
C
C
C-----------------------------------------------------------------------
C***DESCRIPTION
C
C This routine computes the product
C
C Z = (D-inverse)*(P-inverse)*(dF/dY)*(D*V),
C
C where F(Y) = G(T, Y, CJ*(Y-A)), CJ is a scalar proportional to 1/H,
C and A involves the past history of Y. The quantity CJ*(Y-A) is
C an approximation to the first derivative of Y and is stored
C in the array YPRIME. Note that dF/dY = dG/dY + CJ*dG/dYPRIME.
C
C D is a diagonal scaling matrix, and P is the left preconditioning
C matrix. V is assumed to have L2 norm equal to 1.
C The product is stored in Z and is computed by means of a
C difference quotient, a call to RES, and one call to PSOL.
C
C On entry
C
C NEQ = Problem size, passed to RES and PSOL.
C
C Y = Array containing current dependent variable vector.
C
C YPRIME = Array containing current first derivative of y.
C
C SAVR = Array containing current value of G(T,Y,YPRIME).
C
C V = Real array of length NEQ (can be the same array as Z).
C
C WGHT = Array of length NEQ containing scale factors.
C 1/WGHT(I) are the diagonal elements of the matrix D.
C
C YPTEM = Work array of length NEQ.
C
C VTEM = Work array of length NEQ used to store the
C unscaled version of V.
C
C WP = Real work array used by preconditioner PSOL.
C
C IWP = Integer work array used by preconditioner PSOL.
C
C CJ = Scalar proportional to current value of
C 1/(step size H).
C
C
C On return
C
C Z = Array of length NEQ containing desired scaled
C matrix-vector product.
C
C IRES = Error flag from RES.
C
C IER = Error flag from PSOL.
C
C NRE = The number of calls to RES.
C
C NPSL = The number of calls to PSOL.
C
C-----------------------------------------------------------------------
C***ROUTINES CALLED
C RES, PSOL
C
C***END PROLOGUE DATV
C
INTEGER NEQ, IRES, IWP, IER, NRE, NPSL, IPAR
DOUBLE PRECISION Y, TN, YPRIME, SAVR, V, WGHT, YPTEM, Z, VTEM,
1 WP, CJ, RPAR
DIMENSION Y(*), YPRIME(*), SAVR(*), V(*), WGHT(*), YPTEM(*),
1 Z(*), VTEM(*), WP(*), IWP(*), RPAR(*), IPAR(*)
INTEGER I
DOUBLE PRECISION EPLIN
EXTERNAL RES, PSOL
C
IRES = 0
C-----------------------------------------------------------------------
C Set VTEM = D * V.
C-----------------------------------------------------------------------
DO 10 I = 1,NEQ
10 VTEM(I) = V(I)/WGHT(I)
IER = 0
C-----------------------------------------------------------------------
C Store Y in Z and increment Z by VTEM.
C Store YPRIME in YPTEM and increment YPTEM by VTEM*CJ.
C-----------------------------------------------------------------------
DO 20 I = 1,NEQ
YPTEM(I) = YPRIME(I) + VTEM(I)*CJ
20 Z(I) = Y(I) + VTEM(I)
C-----------------------------------------------------------------------
C Call RES with incremented Y, YPRIME arguments
C stored in Z, YPTEM. VTEM is overwritten with new residual.
C-----------------------------------------------------------------------
CONTINUE
CALL RES(TN,Z,YPTEM,CJ,VTEM,IRES,RPAR,IPAR)
NRE = NRE + 1
IF (IRES .LT. 0) RETURN
C-----------------------------------------------------------------------
C Set Z = (dF/dY) * VBAR using difference quotient.
C (VBAR is old value of VTEM before calling RES)
C-----------------------------------------------------------------------
DO 70 I = 1,NEQ
70 Z(I) = VTEM(I) - SAVR(I)
C-----------------------------------------------------------------------
C Apply inverse of left preconditioner to Z.
C-----------------------------------------------------------------------
CALL PSOL (NEQ, TN, Y, YPRIME, SAVR, YPTEM, CJ, WGHT, WP, IWP,
1 Z, EPLIN, IER, RPAR, IPAR)
NPSL = NPSL + 1
IF (IER .NE. 0) RETURN
C-----------------------------------------------------------------------
C Apply D-inverse to Z and return.
C-----------------------------------------------------------------------
DO 90 I = 1,NEQ
90 Z(I) = Z(I)*WGHT(I)
RETURN
C
C------END OF SUBROUTINE DATV-------------------------------------------
END
SUBROUTINE DORTH (VNEW, V, HES, N, LL, LDHES, KMP, SNORMW)
C
C***BEGIN PROLOGUE DORTH
C***DATE WRITTEN 890101 (YYMMDD)
C***REVISION DATE 900926 (YYMMDD)
C
C
C-----------------------------------------------------------------------
C***DESCRIPTION
C
C This routine orthogonalizes the vector VNEW against the previous
C KMP vectors in the V array. It uses a modified Gram-Schmidt
C orthogonalization procedure with conditional reorthogonalization.
C
C On entry
C
C VNEW = The vector of length N containing a scaled product
C OF The Jacobian and the vector V(*,LL).
C
C V = The N x LL array containing the previous LL
C orthogonal vectors V(*,1) to V(*,LL).
C
C HES = An LL x LL upper Hessenberg matrix containing,
C in HES(I,K), K.LT.LL, scaled inner products of
C A*V(*,K) and V(*,I).
C
C LDHES = The leading dimension of the HES array.
C
C N = The order of the matrix A, and the length of VNEW.
C
C LL = The current order of the matrix HES.
C
C KMP = The number of previous vectors the new vector VNEW
C must be made orthogonal to (KMP .LE. MAXL).
C
C
C On return
C
C VNEW = The new vector orthogonal to V(*,I0),
C where I0 = MAX(1, LL-KMP+1).
C
C HES = Upper Hessenberg matrix with column LL filled in with
C scaled inner products of A*V(*,LL) and V(*,I).
C
C SNORMW = L-2 norm of VNEW.
C
C-----------------------------------------------------------------------
C***ROUTINES CALLED
C DDOT, DNRM2, DAXPY
C
C***END PROLOGUE DORTH
C
INTEGER N, LL, LDHES, KMP
DOUBLE PRECISION VNEW, V, HES, SNORMW
DIMENSION VNEW(*), V(N,*), HES(LDHES,*)
INTEGER I, I0
DOUBLE PRECISION ARG, DDOT, DNRM2, SUMDSQ, TEM, VNRM
C
C-----------------------------------------------------------------------
C Get norm of unaltered VNEW for later use.
C-----------------------------------------------------------------------
VNRM = DNRM2 (N, VNEW, 1)
C-----------------------------------------------------------------------
C Do Modified Gram-Schmidt on VNEW = A*V(LL).
C Scaled inner products give new column of HES.
C Projections of earlier vectors are subtracted from VNEW.
C-----------------------------------------------------------------------
I0 = MAX0(1,LL-KMP+1)
DO 10 I = I0,LL
HES(I,LL) = DDOT (N, V(1,I), 1, VNEW, 1)
TEM = -HES(I,LL)
CALL DAXPY (N, TEM, V(1,I), 1, VNEW, 1)
10 CONTINUE
C-----------------------------------------------------------------------
C Compute SNORMW = norm of VNEW.
C If VNEW is small compared to its input value (in norm), then
C Reorthogonalize VNEW to V(*,1) through V(*,LL).
C Correct if relative correction exceeds 1000*(unit roundoff).
C Finally, correct SNORMW using the dot products involved.
C-----------------------------------------------------------------------
SNORMW = DNRM2 (N, VNEW, 1)
IF (VNRM + 0.001D0*SNORMW .NE. VNRM) RETURN
SUMDSQ = 0.0D0
DO 30 I = I0,LL
TEM = -DDOT (N, V(1,I), 1, VNEW, 1)
IF (HES(I,LL) + 0.001D0*TEM .EQ. HES(I,LL)) GO TO 30
HES(I,LL) = HES(I,LL) - TEM
CALL DAXPY (N, TEM, V(1,I), 1, VNEW, 1)
SUMDSQ = SUMDSQ + TEM**2
30 CONTINUE
IF (SUMDSQ .EQ. 0.0D0) RETURN
ARG = MAX(0.0D0,SNORMW**2 - SUMDSQ)
SNORMW = SQRT(ARG)
RETURN
C
C------END OF SUBROUTINE DORTH------------------------------------------
END
SUBROUTINE DHEQR (A, LDA, N, Q, INFO, IJOB)
C
C***BEGIN PROLOGUE DHEQR
C***DATE WRITTEN 890101 (YYMMDD)
C***REVISION DATE 900926 (YYMMDD)
C
C-----------------------------------------------------------------------
C***DESCRIPTION
C
C This routine performs a QR decomposition of an upper
C Hessenberg matrix A. There are two options available:
C
C (1) performing a fresh decomposition
C (2) updating the QR factors by adding a row and A
C column to the matrix A.
C
C DHEQR decomposes an upper Hessenberg matrix by using Givens
C rotations.
C
C On entry
C
C A DOUBLE PRECISION(LDA, N)
C The matrix to be decomposed.
C
C LDA INTEGER
C The leading dimension of the array A.
C
C N INTEGER
C A is an (N+1) by N Hessenberg matrix.
C
C IJOB INTEGER
C = 1 Means that a fresh decomposition of the
C matrix A is desired.
C .GE. 2 Means that the current decomposition of A
C will be updated by the addition of a row
C and a column.
C On return
C
C A The upper triangular matrix R.
C The factorization can be written Q*A = R, where
C Q is a product of Givens rotations and R is upper
C triangular.
C
C Q DOUBLE PRECISION(2*N)
C The factors C and S of each Givens rotation used
C in decomposing A.
C
C INFO INTEGER
C = 0 normal value.
C = K If A(K,K) .EQ. 0.0. This is not an error
C condition for this subroutine, but it does
C indicate that DHELS will divide by zero
C if called.
C
C Modification of LINPACK.
C Peter Brown, Lawrence Livermore Natl. Lab.
C
C-----------------------------------------------------------------------
C***ROUTINES CALLED (NONE)
C
C***END PROLOGUE DHEQR
C
INTEGER LDA, N, INFO, IJOB
DOUBLE PRECISION A(LDA,*), Q(*)
INTEGER I, IQ, J, K, KM1, KP1, NM1
DOUBLE PRECISION C, S, T, T1, T2
C
IF (IJOB .GT. 1) GO TO 70
C-----------------------------------------------------------------------
C A new factorization is desired.
C-----------------------------------------------------------------------
C
C QR decomposition without pivoting.
C
INFO = 0
DO 60 K = 1, N
KM1 = K - 1
KP1 = K + 1
C
C Compute Kth column of R.
C First, multiply the Kth column of A by the previous
C K-1 Givens rotations.
C
IF (KM1 .LT. 1) GO TO 20
DO 10 J = 1, KM1
I = 2*(J-1) + 1
T1 = A(J,K)
T2 = A(J+1,K)
C = Q(I)
S = Q(I+1)
A(J,K) = C*T1 - S*T2
A(J+1,K) = S*T1 + C*T2
10 CONTINUE
C
C Compute Givens components C and S.
C
20 CONTINUE
IQ = 2*KM1 + 1
T1 = A(K,K)
T2 = A(KP1,K)
IF (T2 .NE. 0.0D0) GO TO 30
C = 1.0D0
S = 0.0D0
GO TO 50
30 CONTINUE
IF (ABS(T2) .LT. ABS(T1)) GO TO 40
T = T1/T2
S = -1.0D0/SQRT(1.0D0+T*T)
C = -S*T
GO TO 50
40 CONTINUE
T = T2/T1
C = 1.0D0/SQRT(1.0D0+T*T)
S = -C*T
50 CONTINUE
Q(IQ) = C
Q(IQ+1) = S
A(K,K) = C*T1 - S*T2
IF (A(K,K) .EQ. 0.0D0) INFO = K
60 CONTINUE
RETURN
C-----------------------------------------------------------------------
C The old factorization of A will be updated. A row and a column
C has been added to the matrix A.
C N by N-1 is now the old size of the matrix.
C-----------------------------------------------------------------------
70 CONTINUE
NM1 = N - 1
C-----------------------------------------------------------------------
C Multiply the new column by the N previous Givens rotations.
C-----------------------------------------------------------------------
DO 100 K = 1,NM1
I = 2*(K-1) + 1
T1 = A(K,N)
T2 = A(K+1,N)
C = Q(I)
S = Q(I+1)
A(K,N) = C*T1 - S*T2
A(K+1,N) = S*T1 + C*T2
100 CONTINUE
C-----------------------------------------------------------------------
C Complete update of decomposition by forming last Givens rotation,
C and multiplying it times the column vector (A(N,N),A(NP1,N)).
C-----------------------------------------------------------------------
INFO = 0
T1 = A(N,N)
T2 = A(N+1,N)
IF (T2 .NE. 0.0D0) GO TO 110
C = 1.0D0
S = 0.0D0
GO TO 130
110 CONTINUE
IF (ABS(T2) .LT. ABS(T1)) GO TO 120
T = T1/T2
S = -1.0D0/SQRT(1.0D0+T*T)
C = -S*T
GO TO 130
120 CONTINUE
T = T2/T1
C = 1.0D0/SQRT(1.0D0+T*T)
S = -C*T
130 CONTINUE
IQ = 2*N - 1
Q(IQ) = C
Q(IQ+1) = S
A(N,N) = C*T1 - S*T2
IF (A(N,N) .EQ. 0.0D0) INFO = N
RETURN
C
C------END OF SUBROUTINE DHEQR------------------------------------------
END
SUBROUTINE DHELS (A, LDA, N, Q, B)
C
C***BEGIN PROLOGUE DHELS
C***DATE WRITTEN 890101 (YYMMDD)
C***REVISION DATE 900926 (YYMMDD)
C
C
C-----------------------------------------------------------------------
C***DESCRIPTION
C
C This is similar to the LINPACK routine DGESL except that
C A is an upper Hessenberg matrix.
C
C DHELS solves the least squares problem
C
C MIN (B-A*X,B-A*X)
C
C using the factors computed by DHEQR.
C
C On entry
C
C A DOUBLE PRECISION (LDA, N)
C The output from DHEQR which contains the upper
C triangular factor R in the QR decomposition of A.
C
C LDA INTEGER
C The leading dimension of the array A .
C
C N INTEGER
C A is originally an (N+1) by N matrix.
C
C Q DOUBLE PRECISION(2*N)
C The coefficients of the N givens rotations
C used in the QR factorization of A.
C
C B DOUBLE PRECISION(N+1)
C The right hand side vector.
C
C
C On return
C
C B The solution vector X.
C
C
C Modification of LINPACK.
C Peter Brown, Lawrence Livermore Natl. Lab.
C
C-----------------------------------------------------------------------
C***ROUTINES CALLED
C DAXPY
C
C***END PROLOGUE DHELS
C
INTEGER LDA, N
DOUBLE PRECISION A(LDA,*), B(*), Q(*)
INTEGER IQ, K, KB, KP1
DOUBLE PRECISION C, S, T, T1, T2
C
C Minimize (B-A*X,B-A*X).
C First form Q*B.
C
DO 20 K = 1, N
KP1 = K + 1
IQ = 2*(K-1) + 1
C = Q(IQ)
S = Q(IQ+1)
T1 = B(K)
T2 = B(KP1)
B(K) = C*T1 - S*T2
B(KP1) = S*T1 + C*T2
20 CONTINUE
C
C Now solve R*X = Q*B.
C
DO 40 KB = 1, N
K = N + 1 - KB
B(K) = B(K)/A(K,K)
T = -B(K)
CALL DAXPY (K-1, T, A(1,K), 1, B(1), 1)
40 CONTINUE
RETURN
C
C------END OF SUBROUTINE DHELS------------------------------------------
END