home *** CD-ROM | disk | FTP | other *** search
- PROCEDURE rkqc(VAR y,dydx: glarray; n: integer; VAR x: real;
- htry,eps: real; yscal: glarray; VAR hdid,hnext: real);
- (* Programs using routine RKQC must provide a
- PROCEDURE derivs(x:real; y:glnarray; VAR dydx:glnarray);
- which returns the derivatives dydx at location x, given both x and the
- function values y. They must also define the type
- TYPE
- glarray = ARRAY [1..n] OF real;
- in the main routine. *)
- LABEL 1;
- CONST
- pgrow=-0.20;
- pshrnk=-0.25;
- fcor=0.06666666; (* 1.0/15.0 *)
- one=1.0;
- safety=0.9;
- errcon=6.0e-4;
- VAR
- i: integer;
- xsav,hh,h,temp,errmax: real;
- dysav,ysav,ytemp: glarray;
- BEGIN
- xsav := x;
- FOR i := 1 TO n DO BEGIN
- ysav[i] := y[i];
- dysav[i] := dydx[i]
- END;
- h := htry;
- 1: hh := 0.5*h;
- rk4(ysav,dysav,n,xsav,hh,ytemp);
- x := xsav+hh;
- derivs(x,ytemp,dydx);
- rk4(ytemp,dydx,n,x,hh,y);
- x := xsav+h;
- IF (x = xsav) THEN BEGIN
- writeln('pause in routine RKQC');
- writeln('stepsize too small'); readln
- END;
- rk4(ysav,dysav,n,xsav,h,ytemp);
- errmax := 0.0;
- FOR i := 1 TO n DO BEGIN
- ytemp[i] := y[i]-ytemp[i];
- temp := abs(ytemp[i]/yscal[i]);
- IF (errmax < temp) THEN errmax := temp
- END;
- errmax := errmax/eps;
- IF (errmax > one) THEN BEGIN
- h := safety*h*exp(pshrnk*ln(errmax));
- GOTO 1 END
- ELSE BEGIN
- hdid := h;
- IF (errmax > errcon) THEN BEGIN
- hnext := safety*h*exp(pgrow*ln(errmax))
- END ELSE BEGIN
- hnext := 4.0*h
- END
- END;
- FOR i := 1 TO n DO BEGIN
- y[i] := y[i]+ytemp[i]*fcor
- END
- END;
-