⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stepperstoerm.h

📁 经典numerical receip 配套代码
💻 H
字号:
template <class D>
struct StepperStoerm : StepperBS<D> {
	using StepperBS<D>::x; using StepperBS<D>::xold; using StepperBS<D>::y;
	using StepperBS<D>::dydx; using StepperBS<D>::dense; using StepperBS<D>::n;
	using StepperBS<D>::KMAXX; using StepperBS<D>::IMAXX; using StepperBS<D>::nseq;
	using StepperBS<D>::cost; using StepperBS<D>::mu; using StepperBS<D>::errfac;
	using StepperBS<D>::ysave; using StepperBS<D>::fsave;
	using StepperBS<D>::dens; using StepperBS<D>::neqn;
	MatDoub ysavep;
	StepperStoerm(VecDoub_IO &yy, VecDoub_IO &dydxx, Doub &xx,
		const Doub atol, const Doub rtol, bool dens);
	void dy(VecDoub_I &y, const Doub htot, const Int k, VecDoub_O &yend,
		Int &ipt,D &derivs);
	void prepare_dense(const Doub h,VecDoub_I &dydxnew, VecDoub_I &ysav,
		VecDoub_I &scale, const Int k, Doub &error);
	Doub dense_out(const Int i,const Doub x,const Doub h);
	void dense_interp(const Int n, VecDoub_IO &y, const Int imit);
};
template <class D>
StepperStoerm<D>::StepperStoerm(VecDoub_IO &yy, VecDoub_IO &dydxx, Doub &xx,
	const Doub atoll,const Doub rtoll, bool dens)
	: StepperBS<D>(yy,dydxx,xx,atoll,rtoll,dens),ysavep(IMAXX,n/2) {
	neqn=n/2;
	cost[0]=nseq[0]/2+1;
	for (Int k=0;k<KMAXX;k++)
		cost[k+1]=cost[k]+nseq[k+1]/2;
	for (Int i=0; i<2*IMAXX+1; i++) {
		Int ip7=i+7;
		Doub fac=1.5/ip7;
		errfac[i]=fac*fac*fac;
		Doub e = 0.5*sqrt(Doub(i+1)/ip7);
		for (Int j=0; j<=i; j++) {
			errfac[i] *= e/(j+1);
		}
	}
}
template <class D>
void StepperStoerm<D>::prepare_dense(const Doub h,VecDoub_I &dydxnew,
	VecDoub_I &ysav,VecDoub_I &scale,const Int k, Doub &error) {
	Doub h2=h*h;
	mu=MAX(1,2*k-3);
	for (Int i=0; i<neqn; i++) {
		dens[i]=ysav[i];
		dens[neqn+i]=h*ysav[neqn+i];
		dens[2*neqn+i]=h2*dydx[i];
		dens[3*neqn+i]=y[i];
		dens[4*neqn+i]=h*y[neqn+i];
		dens[5*neqn+i]=h2*dydxnew[i];
	}
	for (Int j=1; j<=k; j++) {
		Doub dblenj=nseq[j];
		for (Int l=j; l>=1; l--) {
			Doub factor=SQR(dblenj/nseq[l-1])-1.0;
			for (Int i=0; i<neqn; i++) {
				ysave[l-1][i]=ysave[l][i]+(ysave[l][i]-ysave[l-1][i])/factor;
				ysavep[l-1][i]=ysavep[l][i]+(ysavep[l][i]-ysavep[l-1][i])/factor;
			}
		}
	}
	for (Int i=0; i<neqn; i++) {
		dens[6*neqn+i]=ysave[0][i];
		dens[7*neqn+i]=h*ysavep[0][i];
	}
	for (Int kmi=2; kmi<=mu; kmi++) {
		Int kbeg=(kmi-2)/2;
		if (kmi == 2*kbeg+2) {
			if (kmi == 2) {
				for (Int i=0; i<neqn; i++)
					ysave[0][i]=0.5*(dydxnew[i]+fsave[0][i]);
				kbeg=1;
			}
			for (Int kk=kbeg; kk<=k; kk++) {
				Doub facnj=0.5*pow(nseq[kk]/2.0,kmi-2);
				Int ipt=kk*kk+kk+kmi/2-2;
				for (Int i=0; i<neqn; i++)
					ysave[kk][i]=(fsave[ipt][i]+fsave[ipt+1][i])*facnj;
			}
		} else {
			for (Int kk=kbeg; kk<=k; kk++) {
				Doub facnj=pow(nseq[kk]/2.0,kmi-2);
				Int ipt=kk*kk+kk+kbeg;
				for (Int i=0; i<neqn; i++)
					ysave[kk][i]=fsave[ipt][i]*facnj;
			}
		}
		for (Int j=kbeg+1; j<=k; j++) {
			Doub dblenj=nseq[j];
			for (Int l=j; l>=kbeg+1; l--) {
				Doub factor=SQR(dblenj/nseq[l-1])-1.0;
				for (Int i=0; i<neqn; i++)
					ysave[l-1][i]=ysave[l][i]+
						(ysave[l][i]-ysave[l-1][i])/factor;
			}
		}
		for (Int i=0; i<neqn; i++)
			dens[(kmi+6)*neqn+i]=ysave[kbeg][i]*h2;
		if (kmi == mu) continue;
		for (Int kk=(kmi-1)/2; kk<=k; kk++) {
			Int lbeg=kk*kk+kmi-2;
			Int lend=SQR(kk+1)-1;
			if (kmi == 2) lbeg++;
			for (Int l=lend; l>=lbeg; l--)
				for (Int i=0; i<neqn; i++)
					fsave[l][i]=fsave[l][i]-fsave[l-1][i];
			if (kmi == 2) {
				Int l=lbeg-1;
				for (Int i=0; i<neqn; i++)
					fsave[l][i]=fsave[l][i]-dydx[i];
			}
		}
	}
	dense_interp(neqn,dens,mu);
	error=0.0;
	if (mu >= 1) {
		for (Int i=0; i<neqn; i++)
			error += SQR(dens[(mu+6)*neqn+i]/scale[i]);
		error=sqrt(error/neqn)*errfac[mu-1];
	}
}
template <class D>
Doub StepperStoerm<D>::dense_out(const Int i,const Doub x,const Doub h) {
	Doub theta=(x-xold)/h;
	Doub theta1=1.0-theta;
	Int neqn=n/2;
	if (i>=neqn) throw("no dense output for y' in StepperStoerm");
	Doub yinterp=dens[i]+theta*(dens[neqn+i]+theta1*(dens[2*neqn+i]+
		theta*(dens[3*neqn+i]+theta1*(dens[4*neqn+i]*theta+
		dens[5*neqn+i]*theta1))));
	if (mu<0)
		return yinterp;
	Doub theta05=theta-0.5;
	Doub t4=theta*theta1;
	Doub c=dens[neqn*(mu+6)+i];
	for (Int j=mu;j>0; j--)
		c=dens[neqn*(j+5)+i]+c*theta05/j;
	yinterp += t4*t4*t4*c;
	return yinterp;
}
template <class D>
void StepperStoerm<D>::dense_interp(const Int n, VecDoub_IO &y, const Int imit) {
	Doub y0,y1,yp0,yp1,ypp0,ypp1,ydiff,ah,bh,ch,dh,eh,fh,gh,abh,gfh,gmf,
		ph0,ph1,ph2,ph3,ph4,ph5,fc1,fc2,fc3;
	VecDoub a(41);
	for (Int i=0; i<n; i++) {
		y0=y[i];
		y1=y[3*n+i];
		yp0=y[n+i];
		yp1=y[4*n+i];
		ypp0=y[2*n+i]/2.0;
		ypp1=y[5*n+i]/2.0;
		ydiff=y1-y0;
		ah=ydiff-yp0;
		bh=yp1-ydiff;
		ch=ah-ypp0;
		dh=bh-ah;
		eh=ypp1-bh;
		fh=dh-ch;
		gh=eh-dh;
		y[n+i]=ydiff;
		y[2*n+i]=-ah;
		y[3*n+i]=-dh;
		y[4*n+i]=gh;
		y[5*n+i]=fh;
		if (imit < 0) continue;
		abh=ah+bh;
		gfh=gh+fh;
		gmf=gh-fh;
		ph0=0.5*(y0+y1+0.25*(-abh+0.25*gfh));
		ph1=ydiff+0.25*(ah-bh+0.25*gmf);
		ph2=abh-0.5*gfh;
		ph3=6.0*(bh-ah)-3.0*gmf;
		ph4=12.0*gfh;
		ph5=120.0*gmf;
		if (imit >= 1) {
			a[1]=64.0*(y[7*n+i]-ph1);
			if (imit >= 3) {
				a[3]=64.0*(y[9*n+i]-ph3+a[1]*9.0/8.0);
				if (imit >= 5) {
					a[5]=64.0*(y[11*n+i]-ph5+a[3]*15.0/4.0-a[1]*90.0);
					for (Int im=7; im <=imit; im+=2) {
						fc1=im*(im-1)*3.0/16.0;
						fc2=fc1*(im-2)*(im-3)*4.0;
						fc3=im*(im-1)*(im-2)*(im-3)*(im-4)*(im-5);
						a[im]=64.0*(y[(im+6)*n+i]+fc1*a[im-2]-fc2*a[im-4]+fc3*a[im-6]);
					}
				}
			}
		}
		a[0]=64.0*(y[6*n+i]-ph0);
		if (imit >= 2) {
			a[2]=64.0*(y[n*8+i]-ph2+a[0]*3.0/8.0);
			if (imit >= 4) {
				a[4]=64.0*(y[n*10+i]-ph4+a[2]*9.0/4.0-a[0]*18.0);
				for (Int im=6; im<=imit; im+=2) {
					fc1=im*(im-1)*3.0/16.0;
					fc2=fc1*(im-2)*(im-3)*4.0;
					fc3=im*(im-1)*(im-2)*(im-3)*(im-4)*(im-5);
					a[im]=64.0*(y[n*(im+6)+i]+a[im-2]*fc1-a[im-4]*fc2+a[im-6]*fc3);
				}
			}
		}
		for (Int im=0; im<=imit; im++)
			y[n*(im+6)+i]=a[im];
	}
}
template <class D>
void StepperStoerm<D>::dy(VecDoub_I &y, const Doub htot, const Int k,
	VecDoub_O &yend, Int &ipt, D &derivs) {
	VecDoub ytemp(n);
	Int nstep=nseq[k];
	Doub h=htot/nstep;
	Doub h2=2.0*h;
	for (Int i=0;i<neqn;i++) {
		ytemp[i]=y[i];
		Int ni=neqn+i;
		ytemp[ni]=y[ni]+h*dydx[i];
	}
	Doub xnew=x;
	Int nstp2=nstep/2;
	for (Int nn=1;nn<=nstp2;nn++) {
		if (dense && nn == (nstp2+1)/2) {
			for (Int i=0;i<neqn;i++) {
				ysavep[k][i]=ytemp[neqn+i];
				ysave[k][i]=ytemp[i]+h*ytemp[neqn+i];
			}
		}
		for (Int i=0;i<neqn;i++)
			ytemp[i] += h2*ytemp[neqn+i];
		xnew += h2;
		derivs(xnew,ytemp,yend);
		if (dense && abs(nn-(nstp2+1)/2) < k+1) {
			ipt++;
			for (Int i=0;i<neqn;i++)
				fsave[ipt][i]=yend[i];
		}
		if (nn != nstp2) {
			for (Int i=0;i<neqn;i++)
				ytemp[neqn+i] += h2*yend[i];
		}
	}
	for (Int i=0;i<neqn;i++) {
		Int ni=neqn+i;
		yend[ni]=ytemp[ni]+h*yend[i];
		yend[i]=ytemp[i];
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -