123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458 |
- *DECK SDSTP
- SUBROUTINE SDSTP (EPS, F, FA, HMAX, IMPL, IERROR, JACOBN, MATDIM,
- 8 MAXORD, MINT, MITER, ML, MU, N, NDE, YWT, UROUND, USERS, AVGH,
- 8 AVGORD, H, HUSED, JTASK, MNTOLD, MTROLD, NFE, NJE, NQUSED,
- 8 NSTEP, T, Y, YH, A, CONVRG, DFDY, EL, FAC, HOLD, IPVT, JSTATE,
- 8 JSTEPL, NQ, NWAIT, RC, RMAX, SAVE1, SAVE2, TQ, TREND, ISWFLG,
- 8 MTRSV, MXRDSV)
- C***BEGIN PROLOGUE SDSTP
- C***SUBSIDIARY
- C***PURPOSE SDSTP performs one step of the integration of an initial
- C value problem for a system of ordinary differential
- C equations.
- C***LIBRARY SLATEC (SDRIVE)
- C***TYPE SINGLE PRECISION (SDSTP-S, DDSTP-D, CDSTP-C)
- C***AUTHOR Kahaner, D. K., (NIST)
- C National Institute of Standards and Technology
- C Gaithersburg, MD 20899
- C Sutherland, C. D., (LANL)
- C Mail Stop D466
- C Los Alamos National Laboratory
- C Los Alamos, NM 87545
- C***DESCRIPTION
- C
- C Communication with SDSTP is done with the following variables:
- C
- C YH An N by MAXORD+1 array containing the dependent variables
- C and their scaled derivatives. MAXORD, the maximum order
- C used, is currently 12 for the Adams methods and 5 for the
- C Gear methods. YH(I,J+1) contains the J-th derivative of
- C Y(I), scaled by H**J/factorial(J). Only Y(I),
- C 1 .LE. I .LE. N, need be set by the calling program on
- C the first entry. The YH array should not be altered by
- C the calling program. When referencing YH as a
- C 2-dimensional array, use a column length of N, as this is
- C the value used in SDSTP.
- C DFDY A block of locations used for partial derivatives if MITER
- C is not 0. If MITER is 1 or 2 its length must be at least
- C N*N. If MITER is 4 or 5 its length must be at least
- C (2*ML+MU+1)*N.
- C YWT An array of N locations used in convergence and error tests
- C SAVE1
- C SAVE2 Arrays of length N used for temporary storage.
- C IPVT An integer array of length N used by the linear system
- C solvers for the storage of row interchange information.
- C A A block of locations used to store the matrix A, when using
- C the implicit method. If IMPL is 1, A is a MATDIM by N
- C array. If MITER is 1 or 2 MATDIM is N, and if MITER is 4
- C or 5 MATDIM is 2*ML+MU+1. If IMPL is 2 its length is N.
- C If IMPL is 3, A is a MATDIM by NDE array.
- C JTASK An integer used on input.
- C It has the following values and meanings:
- C .EQ. 0 Perform the first step. This value enables
- C the subroutine to initialize itself.
- C .GT. 0 Take a new step continuing from the last.
- C Assumes the last step was successful and
- C user has not changed any parameters.
- C .LT. 0 Take a new step with a new value of H and/or
- C MINT and/or MITER.
- C JSTATE A completion code with the following meanings:
- C 1 The step was successful.
- C 2 A solution could not be obtained with H .NE. 0.
- C 3 A solution was not obtained in MXTRY attempts.
- C 4 For IMPL .NE. 0, the matrix A is singular.
- C On a return with JSTATE .GT. 1, the values of T and
- C the YH array are as of the beginning of the last
- C step, and H is the last step size attempted.
- C***ROUTINES CALLED SDCOR, SDCST, SDNTL, SDPSC, SDPST, SDSCL, SNRM2
- C***REVISION HISTORY (YYMMDD)
- C 790601 DATE WRITTEN
- C 900329 Initial submission to SLATEC.
- C***END PROLOGUE SDSTP
- EXTERNAL F, JACOBN, FA, USERS
- INTEGER I, IERROR, IMPL, IPVT(*), ISWFLG, ITER, J, JSTATE, JSTEPL,
- 8 JTASK, MATDIM, MAXORD, MINT, MITER, ML, MNTOLD, MTROLD,
- 8 MTRSV, MU, MXFAIL, MXITER, MXRDSV, MXTRY, N, NDE, NDJSTP,
- 8 NFAIL, NFE, NJE, NQ, NQUSED, NSTEP, NSV, NTRY, NWAIT
- REAL A(MATDIM,*), AVGH, AVGORD, BIAS1, BIAS2, BIAS3,
- 8 BND, CTEST, D, DENOM, DFDY(MATDIM,*), D1, EL(13,12), EPS,
- 8 ERDN, ERUP, ETEST, FAC(*), H, HMAX, HN, HOLD, HS, HUSED,
- 8 NUMER, RC, RCTEST, RH, RH1, RH2, RH3, RMAX, RMFAIL, RMNORM,
- 8 SAVE1(*), SAVE2(*), SNRM2, T, TOLD, TQ(3,12), TREND, TRSHLD,
- 8 UROUND, Y(*), YH(N,*), YWT(*), Y0NRM
- LOGICAL CONVRG, EVALFA, EVALJC, IER, SWITCH
- PARAMETER(BIAS1 = 1.3E0, BIAS2 = 1.2E0, BIAS3 = 1.4E0, MXFAIL = 3,
- 8 MXITER = 3, MXTRY = 50, RCTEST = .3E0, RMFAIL = 2.E0,
- 8 RMNORM = 10.E0, TRSHLD = 1.E0)
- PARAMETER (NDJSTP = 10)
- DATA IER /.FALSE./
- C***FIRST EXECUTABLE STATEMENT SDSTP
- NSV = N
- BND = 0.E0
- SWITCH = .FALSE.
- NTRY = 0
- TOLD = T
- NFAIL = 0
- IF (JTASK .LE. 0) THEN
- CALL SDNTL (EPS, F, FA, HMAX, HOLD, IMPL, JTASK, MATDIM,
- 8 MAXORD, MINT, MITER, ML, MU, N, NDE, SAVE1, T,
- 8 UROUND, USERS, Y, YWT, H, MNTOLD, MTROLD, NFE, RC,
- 8 YH, A, CONVRG, EL, FAC, IER, IPVT, NQ, NWAIT, RH,
- 8 RMAX, SAVE2, TQ, TREND, ISWFLG, JSTATE)
- IF (N .EQ. 0) GO TO 440
- IF (H .EQ. 0.E0) GO TO 400
- IF (IER) GO TO 420
- END IF
- 100 NTRY = NTRY + 1
- IF (NTRY .GT. MXTRY) GO TO 410
- T = T + H
- CALL SDPSC (1, N, NQ, YH)
- EVALJC = (((ABS(RC - 1.E0) .GT. RCTEST) .OR.
- 8 (NSTEP .GE. JSTEPL + NDJSTP)) .AND. (MITER .NE. 0))
- EVALFA = .NOT. EVALJC
- C
- 110 ITER = 0
- DO 115 I = 1,N
- 115 Y(I) = YH(I,1)
- CALL F (N, T, Y, SAVE2)
- IF (N .EQ. 0) THEN
- JSTATE = 6
- GO TO 430
- END IF
- NFE = NFE + 1
- IF (EVALJC .OR. IER) THEN
- CALL SDPST (EL, F, FA, H, IMPL, JACOBN, MATDIM, MITER, ML,
- 8 MU, N, NDE, NQ, SAVE2, T, USERS, Y, YH, YWT, UROUND,
- 8 NFE, NJE, A, DFDY, FAC, IER, IPVT, SAVE1, ISWFLG,
- 8 BND, JSTATE)
- IF (N .EQ. 0) GO TO 430
- IF (IER) GO TO 160
- CONVRG = .FALSE.
- RC = 1.E0
- JSTEPL = NSTEP
- END IF
- DO 125 I = 1,N
- 125 SAVE1(I) = 0.E0
- C Up to MXITER corrector iterations are taken.
- C Convergence is tested by requiring the r.m.s.
- C norm of changes to be less than EPS. The sum of
- C the corrections is accumulated in the vector
- C SAVE1(I). It is approximately equal to the L-th
- C derivative of Y multiplied by
- C H**L/(factorial(L-1)*EL(L,NQ)), and is thus
- C proportional to the actual errors to the lowest
- C power of H present (H**L). The YH array is not
- C altered in the correction loop. The norm of the
- C iterate difference is stored in D. If
- C ITER .GT. 0, an estimate of the convergence rate
- C constant is stored in TREND, and this is used in
- C the convergence test.
- C
- 130 CALL SDCOR (DFDY, EL, FA, H, IERROR, IMPL, IPVT, MATDIM, MITER,
- 8 ML, MU, N, NDE, NQ, T, USERS, Y, YH, YWT, EVALFA,
- 8 SAVE1, SAVE2, A, D, JSTATE)
- IF (N .EQ. 0) GO TO 430
- IF (ISWFLG .EQ. 3 .AND. MINT .EQ. 1) THEN
- IF (ITER .EQ. 0) THEN
- NUMER = SNRM2(N, SAVE1, 1)
- DO 132 I = 1,N
- 132 DFDY(1,I) = SAVE1(I)
- Y0NRM = SNRM2(N, YH, 1)
- ELSE
- DENOM = NUMER
- DO 134 I = 1,N
- 134 DFDY(1,I) = SAVE1(I) - DFDY(1,I)
- NUMER = SNRM2(N, DFDY, MATDIM)
- IF (EL(1,NQ)*NUMER .LE. 100.E0*UROUND*Y0NRM) THEN
- IF (RMAX .EQ. RMFAIL) THEN
- SWITCH = .TRUE.
- GO TO 170
- END IF
- END IF
- DO 136 I = 1,N
- 136 DFDY(1,I) = SAVE1(I)
- IF (DENOM .NE. 0.E0)
- 8 BND = MAX(BND, NUMER/(DENOM*ABS(H)*EL(1,NQ)))
- END IF
- END IF
- IF (ITER .GT. 0) TREND = MAX(.9E0*TREND, D/D1)
- D1 = D
- CTEST = MIN(2.E0*TREND, 1.E0)*D
- IF (CTEST .LE. EPS) GO TO 170
- ITER = ITER + 1
- IF (ITER .LT. MXITER) THEN
- DO 140 I = 1,N
- 140 Y(I) = YH(I,1) + EL(1,NQ)*SAVE1(I)
- CALL F (N, T, Y, SAVE2)
- IF (N .EQ. 0) THEN
- JSTATE = 6
- GO TO 430
- END IF
- NFE = NFE + 1
- GO TO 130
- END IF
- C The corrector iteration failed to converge in
- C MXITER tries. If partials are involved but are
- C not up to date, they are reevaluated for the next
- C try. Otherwise the YH array is retracted to its
- C values before prediction, and H is reduced, if
- C possible. If not, a no-convergence exit is taken.
- IF (CONVRG) THEN
- EVALJC = .TRUE.
- EVALFA = .FALSE.
- GO TO 110
- END IF
- 160 T = TOLD
- CALL SDPSC (-1, N, NQ, YH)
- NWAIT = NQ + 2
- IF (JTASK .NE. 0 .AND. JTASK .NE. 2) RMAX = RMFAIL
- IF (ITER .EQ. 0) THEN
- RH = .3E0
- ELSE
- RH = .9E0*(EPS/CTEST)**(.2E0)
- END IF
- IF (RH*H .EQ. 0.E0) GO TO 400
- CALL SDSCL (HMAX, N, NQ, RMAX, H, RC, RH, YH)
- GO TO 100
- C The corrector has converged. CONVRG is set
- C to .TRUE. if partial derivatives were used,
- C to indicate that they may need updating on
- C subsequent steps. The error test is made.
- 170 CONVRG = (MITER .NE. 0)
- IF (IERROR .EQ. 1 .OR. IERROR .EQ. 5) THEN
- DO 180 I = 1,NDE
- 180 SAVE2(I) = SAVE1(I)/YWT(I)
- ELSE
- DO 185 I = 1,NDE
- 185 SAVE2(I) = SAVE1(I)/MAX(ABS(Y(I)), YWT(I))
- END IF
- ETEST = SNRM2(NDE, SAVE2, 1)/(TQ(2,NQ)*SQRT(REAL(NDE)))
- C
- C The error test failed. NFAIL keeps track of
- C multiple failures. Restore T and the YH
- C array to their previous values, and prepare
- C to try the step again. Compute the optimum
- C step size for this or one lower order.
- IF (ETEST .GT. EPS) THEN
- T = TOLD
- CALL SDPSC (-1, N, NQ, YH)
- NFAIL = NFAIL + 1
- IF (NFAIL .LT. MXFAIL .OR. NQ .EQ. 1) THEN
- IF (JTASK .NE. 0 .AND. JTASK .NE. 2) RMAX = RMFAIL
- RH2 = 1.E0/(BIAS2*(ETEST/EPS)**(1.E0/(NQ+1)))
- IF (NQ .GT. 1) THEN
- IF (IERROR .EQ. 1 .OR. IERROR .EQ. 5) THEN
- DO 190 I = 1,NDE
- 190 SAVE2(I) = YH(I,NQ+1)/YWT(I)
- ELSE
- DO 195 I = 1,NDE
- 195 SAVE2(I) = YH(I,NQ+1)/MAX(ABS(Y(I)), YWT(I))
- END IF
- ERDN = SNRM2(NDE, SAVE2, 1)/(TQ(1,NQ)*SQRT(REAL(NDE)))
- RH1 = 1.E0/MAX(1.E0, BIAS1*(ERDN/EPS)**(1.E0/NQ))
- IF (RH2 .LT. RH1) THEN
- NQ = NQ - 1
- RC = RC*EL(1,NQ)/EL(1,NQ+1)
- RH = RH1
- ELSE
- RH = RH2
- END IF
- ELSE
- RH = RH2
- END IF
- NWAIT = NQ + 2
- IF (RH*H .EQ. 0.E0) GO TO 400
- CALL SDSCL (HMAX, N, NQ, RMAX, H, RC, RH, YH)
- GO TO 100
- END IF
- C Control reaches this section if the error test has
- C failed MXFAIL or more times. It is assumed that the
- C derivatives that have accumulated in the YH array have
- C errors of the wrong order. Hence the first derivative
- C is recomputed, the order is set to 1, and the step is
- C retried.
- NFAIL = 0
- JTASK = 2
- DO 215 I = 1,N
- 215 Y(I) = YH(I,1)
- CALL SDNTL (EPS, F, FA, HMAX, HOLD, IMPL, JTASK, MATDIM,
- 8 MAXORD, MINT, MITER, ML, MU, N, NDE, SAVE1, T,
- 8 UROUND, USERS, Y, YWT, H, MNTOLD, MTROLD, NFE, RC,
- 8 YH, A, CONVRG, EL, FAC, IER, IPVT, NQ, NWAIT, RH,
- 8 RMAX, SAVE2, TQ, TREND, ISWFLG, JSTATE)
- RMAX = RMNORM
- IF (N .EQ. 0) GO TO 440
- IF (H .EQ. 0.E0) GO TO 400
- IF (IER) GO TO 420
- GO TO 100
- END IF
- C After a successful step, update the YH array.
- NSTEP = NSTEP + 1
- HUSED = H
- NQUSED = NQ
- AVGH = ((NSTEP-1)*AVGH + H)/NSTEP
- AVGORD = ((NSTEP-1)*AVGORD + NQ)/NSTEP
- DO 230 J = 1,NQ+1
- DO 230 I = 1,N
- 230 YH(I,J) = YH(I,J) + EL(J,NQ)*SAVE1(I)
- DO 235 I = 1,N
- 235 Y(I) = YH(I,1)
- C If ISWFLG is 3, consider
- C changing integration methods.
- IF (ISWFLG .EQ. 3) THEN
- IF (BND .NE. 0.E0) THEN
- IF (MINT .EQ. 1 .AND. NQ .LE. 5) THEN
- HN = ABS(H)/MAX(UROUND, (ETEST/EPS)**(1.E0/(NQ+1)))
- HN = MIN(HN, 1.E0/(2.E0*EL(1,NQ)*BND))
- HS = ABS(H)/MAX(UROUND,
- 8 (ETEST/(EPS*EL(NQ+1,1)))**(1.E0/(NQ+1)))
- IF (HS .GT. 1.2E0*HN) THEN
- MINT = 2
- MNTOLD = MINT
- MITER = MTRSV
- MTROLD = MITER
- MAXORD = MIN(MXRDSV, 5)
- RC = 0.E0
- RMAX = RMNORM
- TREND = 1.E0
- CALL SDCST (MAXORD, MINT, ISWFLG, EL, TQ)
- NWAIT = NQ + 2
- END IF
- ELSE IF (MINT .EQ. 2) THEN
- HS = ABS(H)/MAX(UROUND, (ETEST/EPS)**(1.E0/(NQ+1)))
- HN = ABS(H)/MAX(UROUND,
- 8 (ETEST*EL(NQ+1,1)/EPS)**(1.E0/(NQ+1)))
- HN = MIN(HN, 1.E0/(2.E0*EL(1,NQ)*BND))
- IF (HN .GE. HS) THEN
- MINT = 1
- MNTOLD = MINT
- MITER = 0
- MTROLD = MITER
- MAXORD = MIN(MXRDSV, 12)
- RMAX = RMNORM
- TREND = 1.E0
- CONVRG = .FALSE.
- CALL SDCST (MAXORD, MINT, ISWFLG, EL, TQ)
- NWAIT = NQ + 2
- END IF
- END IF
- END IF
- END IF
- IF (SWITCH) THEN
- MINT = 2
- MNTOLD = MINT
- MITER = MTRSV
- MTROLD = MITER
- MAXORD = MIN(MXRDSV, 5)
- NQ = MIN(NQ, MAXORD)
- RC = 0.E0
- RMAX = RMNORM
- TREND = 1.E0
- CALL SDCST (MAXORD, MINT, ISWFLG, EL, TQ)
- NWAIT = NQ + 2
- END IF
- C Consider changing H if NWAIT = 1. Otherwise
- C decrease NWAIT by 1. If NWAIT is then 1 and
- C NQ.LT.MAXORD, then SAVE1 is saved for use in
- C a possible order increase on the next step.
- C
- IF (JTASK .EQ. 0 .OR. JTASK .EQ. 2) THEN
- RH = 1.E0/MAX(UROUND, BIAS2*(ETEST/EPS)**(1.E0/(NQ+1)))
- IF (RH.GT.TRSHLD) CALL SDSCL (HMAX, N, NQ, RMAX, H, RC, RH, YH)
- ELSE IF (NWAIT .GT. 1) THEN
- NWAIT = NWAIT - 1
- IF (NWAIT .EQ. 1 .AND. NQ .LT. MAXORD) THEN
- DO 250 I = 1,NDE
- 250 YH(I,MAXORD+1) = SAVE1(I)
- END IF
- C If a change in H is considered, an increase or decrease in
- C order by one is considered also. A change in H is made
- C only if it is by a factor of at least TRSHLD. Factors
- C RH1, RH2, and RH3 are computed, by which H could be
- C multiplied at order NQ - 1, order NQ, or order NQ + 1,
- C respectively. The largest of these is determined and the
- C new order chosen accordingly. If the order is to be
- C increased, we compute one additional scaled derivative.
- C If there is a change of order, reset NQ and the
- C coefficients. In any case H is reset according to RH and
- C the YH array is rescaled.
- ELSE
- IF (NQ .EQ. 1) THEN
- RH1 = 0.E0
- ELSE
- IF (IERROR .EQ. 1 .OR. IERROR .EQ. 5) THEN
- DO 270 I = 1,NDE
- 270 SAVE2(I) = YH(I,NQ+1)/YWT(I)
- ELSE
- DO 275 I = 1,NDE
- 275 SAVE2(I) = YH(I,NQ+1)/MAX(ABS(Y(I)), YWT(I))
- END IF
- ERDN = SNRM2(NDE, SAVE2, 1)/(TQ(1,NQ)*SQRT(REAL(NDE)))
- RH1 = 1.E0/MAX(UROUND, BIAS1*(ERDN/EPS)**(1.E0/NQ))
- END IF
- RH2 = 1.E0/MAX(UROUND, BIAS2*(ETEST/EPS)**(1.E0/(NQ+1)))
- IF (NQ .EQ. MAXORD) THEN
- RH3 = 0.E0
- ELSE
- IF (IERROR .EQ. 1 .OR. IERROR .EQ. 5) THEN
- DO 290 I = 1,NDE
- 290 SAVE2(I) = (SAVE1(I) - YH(I,MAXORD+1))/YWT(I)
- ELSE
- DO 295 I = 1,NDE
- SAVE2(I) = (SAVE1(I) - YH(I,MAXORD+1))/
- 8 MAX(ABS(Y(I)), YWT(I))
- 295 CONTINUE
- END IF
- ERUP = SNRM2(NDE, SAVE2, 1)/(TQ(3,NQ)*SQRT(REAL(NDE)))
- RH3 = 1.E0/MAX(UROUND, BIAS3*(ERUP/EPS)**(1.E0/(NQ+2)))
- END IF
- IF (RH1 .GT. RH2 .AND. RH1 .GE. RH3) THEN
- RH = RH1
- IF (RH .LE. TRSHLD) GO TO 380
- NQ = NQ - 1
- RC = RC*EL(1,NQ)/EL(1,NQ+1)
- ELSE IF (RH2 .GE. RH1 .AND. RH2 .GE. RH3) THEN
- RH = RH2
- IF (RH .LE. TRSHLD) GO TO 380
- ELSE
- RH = RH3
- IF (RH .LE. TRSHLD) GO TO 380
- DO 360 I = 1,N
- 360 YH(I,NQ+2) = SAVE1(I)*EL(NQ+1,NQ)/(NQ+1)
- NQ = NQ + 1
- RC = RC*EL(1,NQ)/EL(1,NQ-1)
- END IF
- IF (ISWFLG .EQ. 3 .AND. MINT .EQ. 1) THEN
- IF (BND.NE.0.E0) RH = MIN(RH, 1.E0/(2.E0*EL(1,NQ)*BND*ABS(H)))
- END IF
- CALL SDSCL (HMAX, N, NQ, RMAX, H, RC, RH, YH)
- RMAX = RMNORM
- 380 NWAIT = NQ + 2
- END IF
- C All returns are made through this section. H is saved
- C in HOLD to allow the caller to change H on the next step
- JSTATE = 1
- HOLD = H
- RETURN
- C
- 400 JSTATE = 2
- HOLD = H
- DO 405 I = 1,N
- 405 Y(I) = YH(I,1)
- RETURN
- C
- 410 JSTATE = 3
- HOLD = H
- RETURN
- C
- 420 JSTATE = 4
- HOLD = H
- RETURN
- C
- 430 T = TOLD
- CALL SDPSC (-1, NSV, NQ, YH)
- DO 435 I = 1,NSV
- 435 Y(I) = YH(I,1)
- 440 HOLD = H
- RETURN
- END
|