#include #include #include "xpplim.h" extern int NFlags; #define RKQS 8 #define STIFF 9 #define MAX(a,b) ((a)>(b)?(a):(b)) #define MIN(a,b) ((a)<(b)?(a):(b)) #define SIGN(a,b) ((b)>=0.0 ? fabs(a):-fabs(a)) /* #define MAXODE 100 */ #define SAFETY 0.9 #define GROW 1.5 #define PGROW -0.25 #define SHRNK 0.5 #define PSHRNK (-1.0/3.0) #define ERRCON 0.1296 #define MAXTRY 40 #define GAM (1.0/2.0) #define A21 2.0 #define A31 (48.0/25.0) #define A32 (6.0/25.0) #define C21 -8.0 #define C31 (372.0/25.0) #define C32 (12.0/5.0) #define C41 (-112.0/125.0) #define C42 (-54.0/125.0) #define C43 (-2.0/5.0) #define B1 (19.0/9.0) #define B2 (1.0/2.0) #define B3 (25.0/108.0) #define B4 (125.0/108.0) #define E1 (17.0/54.0) #define E2 (7.0/36.0) #define E3 0.0 #define E4 (125.0/108.0) #define C1X (1.0/2.0) #define C2X (-3.0/2.0) #define C3X (121.0/50.0) #define C4X (29.0/250.0) #define A2X 1.0 #define A3X (3.0/5.0) #define MAXSTP 100000 #define TINY 1.0e-30 #define PGROW2 -0.2 #define PSHRNK2 -0.25 #define ERRCON2 1.89e-4 double sdot(); extern (*rhs)(); jacobn(x,y,dfdx,dermat,eps,work,n) double x,*y,*dermat,*dfdx,eps,*work; int n; { int i,j,k; double r; double *yval,*ynew,ytemp; yval=work; ynew=work+n; rhs(x,y,yval,n); r=eps*MAX(eps,fabs(x)); rhs(x+r,y,ynew,n); for(i=0;i 0.0) h=x2-x; if(iflag==STIFF) stiff(y,dydx,nvar,&x,h,eps,yscal,&hdid,&hnext,work2,epjac,ier); else rkqs(y,dydx,nvar,&x,h,eps,yscal,&hdid,&hnext,work2,ier); if(*ier>0)return -1; if ((x-x2)*(x2-x1) >= 0.0) { for (i=0;i ERRCON ? SAFETY*h*pow(errmax,PGROW) : GROW*h); return 0; } else { *hnext=SAFETY*h*pow(errmax,PSHRNK); h=(h >= 0.0 ? MAX(*hnext,SHRNK*h) : MIN(*hnext,SHRNK*h)); } } *ier=4; return -1; } rkqs(y,dydx,n,x,htry,eps,yscal,hdid,hnext,work,ier) double *hdid,*hnext,*x,*dydx,eps,htry,*y,*yscal,*work; int n,*ier; { int i; double errmax,h,htemp,xnew,*yerr,*ytemp; double *work2; yerr=work; ytemp=work+n; work2=ytemp+n; h=htry; *ier=0; for (;;) { rkck(y,dydx,n,*x,h,ytemp,yerr,work2); errmax=0.0; for (i=0;i 1.0) { htemp=SAFETY*h*pow(errmax,PSHRNK2); h=(h >= 0.0 ? MAX(htemp,0.1*h) : MIN(htemp,0.1*h)); xnew=(*x)+h; if (xnew == *x) { *ier=1; return -1; } continue; } else { if (errmax > ERRCON2) *hnext=SAFETY*h*pow(errmax,PGROW2); else *hnext=5.0*h; *x += (*hdid=h); for (i=0;i