#include #define ONE Complex(1.0,0.0) #define MAXSTP 10000 #define TINY 1.0e-30 #define KMAXX 8 #define IMAXX (KMAXX+1) #define SAFE1 0.25 #define SAFE2 0.7 #define REDMAX 1.0e-5 #define REDMIN 0.7 #define SCALMX 0.1 extern int kmax,kount; extern double *xp,**yp,dxsav; extern dcomplex aa,bb,cc,z0,dz; double **d,*x; void odeint(double ystart[],int nvar,double x1,double x2,double eps,double h1, double hmin, int *nok, int *nbad, void (*derivs)(double, double [], double []), void (*rkqs)(double [],double [],int,double *,double,double,double [], double *, double *, void (*)(double, double [], double []))) { int nstp,i; double xsav,x,hnext,hdid,h; double *yscal,*y,*dydx; yscal=dvector(1,nvar); y=dvector(1,nvar); dydx=dvector(1,nvar); x=x1; h=sign(h1,x2-x1); *nok = (*nbad) = kount = 0; for (i=1;i<=nvar;i++) y[i]=ystart[i]; if (kmax > 0) xsav=x-dxsav*2.0; for (nstp=1;nstp<=MAXSTP;nstp++) { (*derivs)(x,y,dydx); for (i=1;i<=nvar;i++) yscal[i]=fabs(y[i])+fabs(dydx[i]*h)+TINY; if (kmax > 0 && kount < kmax-1 && fabs(x-xsav) > fabs(dxsav)) { xp[++kount]=x; for (i=1;i<=nvar;i++) yp[i][kount]=y[i]; xsav=x; } if ((x+h-x2)*(x+h-x1) > 0.0) h=x2-x; (*rkqs)(y,dydx,nvar,&x,h,eps,yscal,&hdid,&hnext,derivs); if (hdid == h) ++(*nok); else ++(*nbad); if ((x-x2)*(x2-x1) >= 0.0) { for (i=1;i<=nvar;i++) ystart[i]=y[i]; if (kmax) { xp[++kount]=x; for (i=1;i<=nvar;i++) yp[i][kount]=y[i]; } free_dvector(dydx,1,nvar); free_dvector(y,1,nvar); free_dvector(yscal,1,nvar); return; } if (fabs(hnext) <= hmin) nrerror("Step size too small in odeint"); h=hnext; } nrerror("Too many steps in routine odeint"); } void hypdrv(double s, double yy[], double dyyds[]) { dcomplex z,y[3],dyds[3]; y[1]=Complex(yy[1],yy[2]); y[2]=Complex(yy[3],yy[4]); z=Cadd(z0,CRmul(s,dz)); dyds[1]=Cmul(y[2],dz); dyds[2]=Cmul(Csub(Cmul(Cmul(aa,bb),y[1]),Cmul(Csub(cc, Cmul(Cadd(Cadd(aa,bb),ONE),z)),y[2])), Cmul(dz,Cinv(Cmul(z,Csub(ONE,z))))); dyyds[1]=dyds[1].re; dyyds[2]=dyds[1].im; dyyds[3]=dyds[2].re; dyyds[4]=dyds[2].im; } void bsstep(double y[],double dydx[],int nv,double *xx,double htry,double eps, double yscal[], double *hdid, double *hnext, void (*derivs)(double, double [], double [])) { void mmid(double y[], double dydx[], int nvar, double xs, double htot, int nstep,double yout[],void (*derivs)(double,double[],double[])); void pzextr(int iest,double xest,double yest[],double yz[],double dy[], int nv); int i,iq,k,kk,km; static int first=1,kmax,kopt; static double epsold = -1.0,xnew; double eps1,errmax,fact,h,red,scale,work,wrkmin,xest; double *err,*yerr,*ysav,*yseq; static double a[IMAXX+1]; static double alf[KMAXX+1][KMAXX+1]; static int nseq[IMAXX+1]={0,2,4,6,8,10,12,14,16,18}; int reduct,exitflag=0; d=dmatrix(1,KMAXX,1,KMAXX); err=dvector(1,KMAXX); x=dvector(1,KMAXX); yerr=dvector(1,nv); ysav=dvector(1,nv); yseq=dvector(1,nv); if (eps != epsold) { *hnext = xnew = -1.0e29; eps1=SAFE1*eps; a[1]=nseq[1]+1; for (k=1;k<=KMAXX;k++) a[k+1]=a[k]+nseq[k+1]; for (iq=2;iq<=KMAXX;iq++) { for (k=1;k a[kopt]*alf[kopt-1][kopt]) break; kmax=kopt; } h=htry; for (i=1;i<=nv;i++) ysav[i]=y[i]; if (*xx != xnew || h != (*hnext)) { first=1; kopt=kmax; } reduct=0; for (;;) { for (k=1;k<=kmax;k++) { xnew=(*xx)+h; if (xnew == (*xx)) nrerror("step size underflow in bsstep"); mmid(ysav,dydx,nv,*xx,h,nseq[k],yseq,derivs); xest=pow(h/nseq[k],2.); pzextr(k,xest,yseq,y,yerr,nv); if (k != 1) { errmax=TINY; for (i=1;i<=nv;i++) errmax=fmax(errmax,fabs(yerr[i]/yscal[i])); errmax /= eps; km=k-1; err[km]=pow(errmax/SAFE1,1.0/(2*km+1)); } if (k != 1 && (k >= kopt-1 || first)) { if (errmax < 1.0) { exitflag=1; break; } if (k == kmax || k == kopt+1) { red=SAFE2/err[km]; break; } else if (k == kopt && alf[kopt-1][kopt] < err[km]) { red=1.0/err[km]; break; } else if (kopt == kmax && alf[km][kmax-1] < err[km]) { red=alf[km][kmax-1]*SAFE2/err[km]; break; } else if (alf[km][kopt] < err[km]) { red=alf[km][kopt-1]/err[km]; break; } } } if (exitflag) break; red=fmin(red,REDMIN); red=fmax(red,REDMAX); h *= red; reduct=1; } *xx=xnew; *hdid=h; first=0; wrkmin=1.0e35; for (kk=1;kk<=km;kk++) { fact=fmax(err[kk],SCALMX); work=fact*a[kk+1]; if (work < wrkmin) { scale=fact; wrkmin=work; kopt=kk+1; } } *hnext=h/scale; if (kopt >= k && kopt != kmax && !reduct) { fact=fmax(scale/alf[kopt-1][kopt],SCALMX); if (a[kopt+1]*fact <= wrkmin) { *hnext=h/fact; kopt++; } } free_dvector(yseq,1,nv); free_dvector(ysav,1,nv); free_dvector(yerr,1,nv); free_dvector(x,1,KMAXX); free_dvector(err,1,KMAXX); free_dmatrix(d,1,KMAXX,1,KMAXX); } void mmid(double y[],double dydx[],int nvar,double xs,double htot,int nstep, double yout[], void (*derivs)(double, double[], double[])) { int n,i; double x,swap,h2,h,*ym,*yn; ym=dvector(1,nvar); yn=dvector(1,nvar); h=htot/nstep; for (i=1;i<=nvar;i++) { ym[i]=y[i]; yn[i]=y[i]+h*dydx[i]; } x=xs+h; (*derivs)(x,yn,yout); h2=2.0*h; for (n=2;n<=nstep;n++) { for (i=1;i<=nvar;i++) { swap=ym[i]+h2*yout[i]; ym[i]=yn[i]; yn[i]=swap; } x += h; (*derivs)(x,yn,yout); } for (i=1;i<=nvar;i++) yout[i]=0.5*(ym[i]+yn[i]+h*yout[i]); free_dvector(yn,1,nvar); free_dvector(ym,1,nvar); } void pzextr(int iest, double xest, double yest[], double yz[], double dy[], int nv) { int k1,j; double q,f2,f1,delta,*c; c=dvector(1,nv); x[iest]=xest; for (j=1;j<=nv;j++) dy[j]=yz[j]=yest[j]; if (iest == 1) { for (j=1;j<=nv;j++) d[j][1]=yest[j]; } else { for (j=1;j<=nv;j++) c[j]=yest[j]; for (k1=1;k1