SUBROUTINE rkfn78( N, FCN, X, Y, YP, XEND, EPS, HMAX, H ) C ---------------------------------------------------------------------- C C RKFN78 ( N, FCN, X, Y, YP, XEND, EPS, HMAX, H ) C C Numerical solution of a system of second order C ordinary differential equations y"=f(x,y,dy) C This is an embedded nystroem method of order 7(8) C due to Fehlberg with stepsize control C C input parameters C ---------------- C N dimension of the system (N.LE.51) C FCN name (external) of subroutine computing the C second derivative F(X,Y,DY): C SUBROUTINE FCN(X,Y,DY,F) C REAL*8 X,Y(N),DY(N),F(N) C F(1)=... ETC. C X initial x-value C XEND final x-value (XEND.GT.X) C Y(N) initial values for y C YP(N) initial values for y' C EPS local tolerance C HMAX maximal stepsize C H initial stepsize guess C C output parameters C ----------------- C Y(N) solution at xend C YP(N) derivative of solution at xend C C COMMON STAT can be used for statistics C NFCN number of function evaluations C NSTEP number of computed steps C NACCPT number of accepted steps C NREJCT number of rejected steps C C Ref.: Erwin Fehlberg, Computing 14, p.371, 1975 C ---------------------------------------------------------------------- C23456789012345678901234567890123456789012345678901234567890123456789012 implicit none ! I/O list INTEGER*4 N REAL*8 X, Y(N), YP(N), XEND, EPS, HMAX, H ! method related constants INTEGER*4 N_STAGE, P PARAMETER ( N_STAGE=13, P=7 ) ! implementation dependant constants INTEGER*4 N_MAX, MAX_STEPS REAL*8 UROUND PARAMETER ( N_MAX=180, MAX_STEPS=2147483647, UROUND=1.1D-16 ) ! auxiliary variables REAL*8 K ( 1:N_MAX, 0:N_STAGE ) REAL*8 Y1 ( 1:N_MAX ), YP1 ( 1:N_MAX ), TE ( 1:N_MAX ) REAL*8 POSNEG, HNEW, DENOM, ERR, FAC, H2, SUM, SUMP INTEGER I_STAGE, I, J, L LOGICAL REJECT ! coefficients REAL*8 ALPHA_(1:13), BETA_(1:13,0:12), GAMMA_(1:13,0:12) COMMON /CRKFN78/ ALPHA_, BETA_, GAMMA_ ! statistics INTEGER*4 NFCN,NSTEP,NACCPT,NREJCT COMMON /STAT/ NFCN,NSTEP,NACCPT,NREJCT Cf2py intent(in) N, FCN, X, XEND Cf2py intent(inout) Y, YP, HMAX, H, EPS Cf2py depend(in) Y, YP ! initial preparations IF (ALPHA_(13).NE.1.0D0) THEN CALL FN78INI END IF POSNEG = SIGN ( 1.0D0, XEND-X) HMAX = ABS(HMAX) H = MIN ( MAX(1.0D-8,ABS(H)) , HMAX ) H = SIGN ( H, POSNEG ) EPS = MAX ( EPS, 9.0*UROUND ) REJECT = .FALSE. NFCN = NFCN + 1 CALL FCN ( X, Y, YP, K(1,0) ) ! basic integration step DO WHILE ( POSNEG*(X-XEND)+UROUND .LE. 0.0 ) ! failure exit IF ( NSTEP.GT.MAX_STEPS .OR. X+0.05*H.EQ.X ) THEN WRITE (*,*) 'Exit of RKNF78 at x = ', X WRITE (*,*) 'NSTEP = ', NSTEP WRITE (*,*) 'MAX_STEPS = ', MAX_STEPS WRITE (*,*) 'H = ', H WRITE (*,*) 'X+0.05*H = ', X+0.05*H STOP END IF ! limit step size IF ( (X+H-XEND)*POSNEG .GT. 0.0 ) THEN H = XEND-X END IF H2 = H**2 NSTEP = NSTEP+1 ! calculate K(*,1) .. K(*,N_STAGE) DO I_STAGE = 1,N_STAGE DO L=1,N SUM = 0.0 SUMP = 0.0 DO J=0,(I_STAGE-1) SUM = SUM + GAMMA_(I_STAGE,J)*K(L,J) SUMP = SUMP + BETA_ (I_STAGE,J)*K(L,J) END DO Y1(L) = Y(L) + ALPHA_(I_STAGE)*H*YP(L) + H2*SUM YP1(L) = YP(L) + H*SUMP END DO CALL FCN( X + ALPHA_(I_STAGE)*H, Y1, YP1, K(1,I_STAGE) ) END DO ! end of loop over stages NFCN = NFCN+N_STAGE ! error term and relative error estimation DO L=1,N TE(L) = GAMMA_(N_STAGE,N_STAGE-1) * H2 . * ( K(L,N_STAGE-1) - K(L,N_STAGE) ) END DO ERR = 0.0 DO L=1,N DENOM = MAX ( 1.0D-6, ABS(Y(L)), ABS(Y1(L)), 2.0*UROUND/EPS ) ERR = ERR + ( TE(L) / DENOM )**2 END DO ERR = SQRT ( ERR / N ) ! new step size 0.1