* D02NJF Example Program Text * Mark 14 Revised. NAG Copyright 1989. * .. Parameters .. INTEGER NOUT PARAMETER (NOUT=6) INTEGER NEQ, NEQMAX, NRW, NINF, NELTS, NJCPVT, NWKJAC, + NIA, NJA, MAXORD, SDYSAV, MAXSTP, MXHNIL, LDYSAV PARAMETER (NEQ=3,NEQMAX=NEQ,NRW=50+4*NEQMAX,NINF=23, + NELTS=8,NJCPVT=150,NWKJAC=100,NIA=NEQ+1, + NJA=NELTS,MAXORD=5,SDYSAV=MAXORD+1,MAXSTP=200, + MXHNIL=5,LDYSAV=NEQ) DOUBLE PRECISION H0, HMAX, HMIN, TCRIT PARAMETER (H0=0.0D0,HMAX=10.0D0,HMIN=1.0D-10,TCRIT=0.0D0) LOGICAL PETZLD PARAMETER (PETZLD=.TRUE.) DOUBLE PRECISION ETA, U, SENS PARAMETER (ETA=1.0D-4,U=0.1D0,SENS=1.0D-6) LOGICAL LBLOCK PARAMETER (LBLOCK=.TRUE.) * .. Local Scalars .. DOUBLE PRECISION H, HU, T, TCUR, TOLSF, TOUT INTEGER I, ICALL, IFAIL, IGROW, IMXER, ISPLIT, ITASK, + ITOL, ITRACE, LIWREQ, LIWUSD, LRWREQ, LRWUSD, + NBLOCK, NGP, NITER, NJE, NLU, NNZ, NQ, NQU, NRE, + NST, OUTCHN * .. Local Arrays .. DOUBLE PRECISION ATOL(NEQ), CONST(6), RTOL(NEQ), RWORK(NRW), + WKJAC(NWKJAC), Y(NEQ), YDOT(NEQ), + YSAV(LDYSAV,SDYSAV) INTEGER IA(NIA), INFORM(NINF), JA(NJA), JACPVT(NJCPVT) LOGICAL ALGEQU(NEQ), LDERIV(2) * .. External Subroutines .. EXTERNAL D02NJF, D02NUF, D02NVF, D02NXF, D02NYF, JAC, + MONITR, RESID, X04ABF * .. Data statements .. DATA IA/1, 3, 6, 9/, JA/1, 2, 1, 2, 3, 1, 2, 3/ * .. Executable Statements .. WRITE (NOUT,*) 'D02NJF Example Program Results' OUTCHN = NOUT CALL X04ABF(1,OUTCHN) * * First case. Integrate to TOUT by overshooting (ITASK=1) using * B.D.F formulae with a Newton method. Also set PETZLD to * .TRUE. so that the Petzold error test is used (since an algebraic * equation is defined in the system). Default values for the * array CONST are used. Employ vector relative tolerance and scalar * absolute tolerance. The Jacobian is supplied by JAC and its * structure is determined internally by calls to JAC. * The MONITR routine is used to force a return when the first * component of the system falls below the value 0.9. * T = 0.0D0 TOUT = 10.0D0 ITASK = 1 Y(1) = 1.0D0 Y(2) = 0.0D0 Y(3) = 0.0D0 LDERIV(1) = .FALSE. LDERIV(2) = .FALSE. ITOL = 3 RTOL(1) = 1.0D-4 RTOL(2) = 1.0D-3 RTOL(3) = 1.0D-4 ATOL(1) = 1.0D-7 DO 20 I = 1, 6 CONST(I) = 0.0D0 20 CONTINUE ISPLIT = 0 IFAIL = 1 * CALL D02NVF(NEQMAX,SDYSAV,MAXORD,'Newton',PETZLD,CONST,TCRIT,HMIN, + HMAX,H0,MAXSTP,MXHNIL,'Average-L2',RWORK,IFAIL) IF (IFAIL.NE.0) THEN WRITE (NOUT,99988) IFAIL GO TO 40 END IF IFAIL = 0 CALL D02NUF(NEQ,NEQMAX,'Analytical',NWKJAC,IA,NIA,JA,NJA,JACPVT, + NJCPVT,SENS,U,ETA,LBLOCK,ISPLIT,RWORK,IFAIL) * WRITE (NOUT,*) WRITE (NOUT,*) ' Analytic Jacobian, structure not supplied' WRITE (NOUT,*) WRITE (NOUT,*) ' X Y(1) Y(2) Y(3)' WRITE (NOUT,99999) T, (Y(I),I=1,NEQ) * * Soft fail and error messages only ITRACE = 0 IFAIL = 1 * CALL D02NJF(NEQ,LDYSAV,T,TOUT,Y,YDOT,RWORK,RTOL,ATOL,ITOL,INFORM, + RESID,YSAV,SDYSAV,JAC,WKJAC,NWKJAC,JACPVT,NJCPVT, + MONITR,LDERIV,ITASK,ITRACE,IFAIL) * IF (IFAIL.EQ.0 .OR. IFAIL.EQ.12) THEN WRITE (NOUT,99999) T, (Y(I),I=1,NEQ) IFAIL = 0 * CALL D02NYF(NEQ,NEQMAX,HU,H,TCUR,TOLSF,RWORK,NST,NRE,NJE,NQU, + NQ,NITER,IMXER,ALGEQU,INFORM,IFAIL) * WRITE (NOUT,*) WRITE (NOUT,99997) HU, H, TCUR WRITE (NOUT,99996) NST, NRE, NJE WRITE (NOUT,99995) NQU, NQ, NITER WRITE (NOUT,99994) ' Max err comp = ', IMXER ICALL = 0 * CALL D02NXF(ICALL,LIWREQ,LIWUSD,LRWREQ,LRWUSD,NLU,NNZ,NGP, + ISPLIT,IGROW,LBLOCK,NBLOCK,INFORM) * WRITE (NOUT,*) WRITE (NOUT,99993) LIWREQ, LIWUSD WRITE (NOUT,99992) LRWREQ, LRWUSD WRITE (NOUT,99991) NLU, NNZ WRITE (NOUT,99990) NGP, ISPLIT WRITE (NOUT,99989) IGROW, NBLOCK ELSE IF (IFAIL.EQ.10) THEN ICALL = 1 * CALL D02NXF(ICALL,LIWREQ,LIWUSD,LRWREQ,LRWUSD,NLU,NNZ,NGP, + ISPLIT,IGROW,LBLOCK,NBLOCK,INFORM) * WRITE (NOUT,*) WRITE (NOUT,99993) LIWREQ, LIWUSD WRITE (NOUT,99992) LRWREQ, LRWUSD ELSE WRITE (NOUT,*) WRITE (NOUT,99998) 'Exit D02NJF with IFAIL = ', IFAIL, + ' and T = ', T END IF * * Second case. Integrate to TOUT by overshooting (ITASK=1) using * B.D.F formulae with a Newton method. Also set PETZLD to * .TRUE. so that the Petzold error test is used (since an algebraic * equation is defined in the system). Default values for the * array CONST are used. Employ vector relative tolerance and scalar * absolute tolerance. The Jacobian is supplied by JAC and its * structure is also supplied. * The MONITR routine is used to force a return when the first * component of the system falls below the value 0.9. * T = 0.0D0 Y(1) = 1.0D0 Y(2) = 0.0D0 Y(3) = 0.0D0 * ISPLIT = 0 IFAIL = 1 * CALL D02NVF(NEQMAX,SDYSAV,MAXORD,'Newton',PETZLD,CONST,TCRIT,HMIN, + HMAX,H0,MAXSTP,MXHNIL,'Average-L2',RWORK,IFAIL) * IF (IFAIL.NE.0) THEN WRITE (NOUT,99993) IFAIL GO TO 40 END IF IFAIL = 0 CALL D02NUF(NEQ,NEQMAX,'Full information',NWKJAC,IA,NIA,JA,NJA, + JACPVT,NJCPVT,SENS,U,ETA,LBLOCK,ISPLIT,RWORK,IFAIL) * LDERIV(1) = .FALSE. LDERIV(2) = .FALSE. * WRITE (NOUT,*) WRITE (NOUT,*) ' Analytic Jacobian, structure supplied' WRITE (NOUT,*) WRITE (NOUT,*) ' X Y(1) Y(2) Y(3)' WRITE (NOUT,99999) T, (Y(I),I=1,NEQ) IFAIL = 1 * CALL D02NJF(NEQ,LDYSAV,T,TOUT,Y,YDOT,RWORK,RTOL,ATOL,ITOL,INFORM, + RESID,YSAV,SDYSAV,JAC,WKJAC,NWKJAC,JACPVT,NJCPVT, + MONITR,LDERIV,ITASK,ITRACE,IFAIL) * IF (IFAIL.EQ.0 .OR. IFAIL.EQ.12) THEN WRITE (NOUT,99999) T, (Y(I),I=1,NEQ) IFAIL = 0 * CALL D02NYF(NEQ,NEQMAX,HU,H,TCUR,TOLSF,RWORK,NST,NRE,NJE,NQU, + NQ,NITER,IMXER,ALGEQU,INFORM,IFAIL) * WRITE (NOUT,*) WRITE (NOUT,99997) HU, H, TCUR WRITE (NOUT,99996) NST, NRE, NJE WRITE (NOUT,99995) NQU, NQ, NITER WRITE (NOUT,99994) ' Max err comp = ', IMXER WRITE (NOUT,*) ICALL = 0 * CALL D02NXF(ICALL,LIWREQ,LIWUSD,LRWREQ,LRWUSD,NLU,NNZ,NGP, + ISPLIT,IGROW,LBLOCK,NBLOCK,INFORM) * WRITE (NOUT,*) WRITE (NOUT,99993) LIWREQ, LIWUSD WRITE (NOUT,99992) LRWREQ, LRWUSD WRITE (NOUT,99991) NLU, NNZ WRITE (NOUT,99990) NGP, ISPLIT WRITE (NOUT,99989) IGROW, NBLOCK ELSE IF (IFAIL.EQ.10) THEN ICALL = 1 * CALL D02NXF(ICALL,LIWREQ,LIWUSD,LRWREQ,LRWUSD,NLU,NNZ,NGP, + ISPLIT,IGROW,LBLOCK,NBLOCK,INFORM) * WRITE (NOUT,*) WRITE (NOUT,99993) LIWREQ, LIWUSD WRITE (NOUT,99992) LRWREQ, LRWUSD ELSE WRITE (NOUT,*) WRITE (NOUT,99998) 'Exit D02NJF with IFAIL = ', IFAIL, + ' and T = ', T END IF 40 CONTINUE * 99999 FORMAT (1X,F8.3,3(F13.5,2X)) 99998 FORMAT (1X,A,I2,A,E12.5) 99997 FORMAT (1X,' HUSED = ',E12.5,' HNEXT = ',E12.5,' TCUR = ',E12.5) 99996 FORMAT (1X,' NST = ',I6,' NRE = ',I6,' NJE = ',I6) 99995 FORMAT (1X,' NQU = ',I6,' NQ = ',I6,' NITER = ',I6) 99994 FORMAT (1X,A,I4) 99993 FORMAT (1X,' NJCPVT (required ',I4,' used ',I8,')') 99992 FORMAT (1X,' NWKJAC (required ',I4,' used ',I8,')') 99991 FORMAT (1X,' No. of LU-decomps ',I4,' No. of nonzeros ',I8) 99990 FORMAT (1X,' No. of FCN calls to form Jacobian ',I4,' Try ISPLI', + 'T ',I4) 99989 FORMAT (1X,' Growth est ',I8,' No. of blocks on diagonal ',I4) 99988 FORMAT (1X,/1X,' ** D02NVF returned with IFAIL = ',I5) END * SUBROUTINE RESID(NEQ,T,Y,YDOT,R,IRES) * .. Scalar Arguments .. DOUBLE PRECISION T INTEGER IRES, NEQ * .. Array Arguments .. DOUBLE PRECISION R(NEQ), Y(NEQ), YDOT(NEQ) * .. Executable Statements .. R(1) = 0.0D0 R(2) = -YDOT(2) R(3) = -YDOT(3) IF (IRES.EQ.1) THEN R(1) = Y(1) + Y(2) + Y(3) - 1.0D0 + R(1) R(2) = 0.04D0*Y(1) - 1.0D4*Y(2)*Y(3) - 3.0D7*Y(2)*Y(2) + R(2) R(3) = 3.0D7*Y(2)*Y(2) + R(3) END IF RETURN END * SUBROUTINE JAC(NEQ,T,Y,YDOT,H,D,J,PDJ) * .. Scalar Arguments .. DOUBLE PRECISION D, H, T INTEGER J, NEQ * .. Array Arguments .. DOUBLE PRECISION PDJ(NEQ), Y(NEQ), YDOT(NEQ) * .. Local Scalars .. DOUBLE PRECISION HXD * .. Executable Statements .. HXD = H*D IF (J.EQ.1) THEN PDJ(1) = 0.0D0 - HXD*(1.0D0) PDJ(2) = 0.0D0 - HXD*(0.04D0) * PDJ(3) = 0.0 - HXD*(0.) ELSE IF (J.EQ.2) THEN PDJ(1) = 0.0D0 - HXD*(1.0D0) PDJ(2) = 1.0D0 - HXD*(-1.0D4*Y(3)-6.0D7*Y(2)) PDJ(3) = 0.0D0 - HXD*(6.0D7*Y(2)) ELSE IF (J.EQ.3) THEN PDJ(1) = 0.0D0 - HXD*(1.0D0) PDJ(2) = 0.0D0 - HXD*(-1.0D4*Y(2)) PDJ(3) = 1.0D0 - HXD*(0.0D0) END IF RETURN END * SUBROUTINE MONITR(N,LDYSAV,T,HLAST,H,Y,YDOT,YSAV,R,ACOR,IMON,INLN, + HMIN,HMXI,NQU) * .. Scalar Arguments .. DOUBLE PRECISION H, HLAST, HMIN, HMXI, T INTEGER IMON, INLN, LDYSAV, N, NQU * .. Array Arguments .. DOUBLE PRECISION ACOR(N,2), R(N), Y(N), YDOT(N), YSAV(LDYSAV,*) * .. Executable Statements .. IF (Y(1).LE.0.9D0) IMON = -2 RETURN END