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

📄 rkstept.c

📁 seismic software,very useful
💻 C
字号:
/* Copyright (c) Colorado School of Mines, 1990./* All rights reserved.                       */#include <math.h>#include <stdio.h>typedef struct _RKState {	/* Runga-Kutta state */	int n;	void *aux;	void (*fdydx)(float x, void *aux, float y[], float dydx[]);	float *w1,*w2,*w3,*w4,*w5,*w6;} RKState;RKState *rkcreate (int n, void *aux,	void (*fdydx)(float x, void *aux, float y[], float dydx[]))/*****************************************************************************Creates and returns a pointer to the state of a Runga-Kutta stepper.******************************************************************************Input:n		number of equations  aux		pointer to auxiliary parameters to be passed to fdydxfdydx		pointer to a function that calculates derivatives******************************************************************************Input to the user-supplied function fdydx:x		the independent variableaux		pointer to auxiliary variables required by fdydx.y[]		array of dependent variables y(x)******************************************************************************Output from the user-supplied function fdydx:dydx[]		array of derivatives y'(x)******************************************************************************Author:  Dave Hale, Colorado School of Mines, 10/10/89******************************************************************************/{	RKState *rk;		rk = (RKState*)malloc(sizeof(RKState));	rk->n = n;	rk->aux = aux;	rk->fdydx = fdydx;	rk->w1 = (float*)malloc(n*sizeof(float));	rk->w2 = (float*)malloc(n*sizeof(float));	rk->w3 = (float*)malloc(n*sizeof(float));	rk->w4 = (float*)malloc(n*sizeof(float));	rk->w5 = (float*)malloc(n*sizeof(float));	rk->w6 = (float*)malloc(n*sizeof(float));		return rk;}void rkdestroy (RKState *rk)/*****************************************************************************Destroys state of a Runga-Kutta stepper.******************************************************************************Input:rk		pointer to Runga-Kutta state  ******************************************************************************Author:  Dave Hale, Colorado School of Mines, 10/10/89******************************************************************************/{	free(rk->w1);	free(rk->w2);	free(rk->w3);	free(rk->w4);	free(rk->w5);	free(rk->w6);	free(rk);}void rkstep (RKState *rk,	float h, float x, float y[], float dydx[], float ynew[])/*****************************************************************************Performs one Runga-Kutta (4th order) step******************************************************************************Input:rk		pointer to Runga-Kutta stateh		step sizex		independent variable xy[]		array of dependent variables y(x)dydx[]		array of derivatives y'(x)******************************************************************************Output:ynew[]		array of y(x+h) (may be equivalenced to y[])******************************************************************************Notes:Adapted from function rk4 in Numerical Recipes in C, by Press, Flannery, Teukolsky, and Vetterling, 1988.******************************************************************************Author:  Dave Hale, Colorado School of Mines, 10/10/89******************************************************************************/{	int i;	float hhalf,hsixth,xhalf;	int n=rk->n;	float *dym=rk->w1,*dyt=rk->w2,*yt=rk->w3;	void *aux=rk->aux;		/* constants */	hhalf = h/2.0;	hsixth = h/6.0;	xhalf = x+hhalf;	/* 1st step */	for (i=0; i<n; i++)		yt[i] = y[i]+hhalf*dydx[i];			/* 2nd step */	rk->fdydx(xhalf,aux,yt,dyt);	for (i=0; i<n; i++)		yt[i] = y[i]+hhalf*dyt[i];		/* 3rd step */	rk->fdydx(xhalf,aux,yt,dym);	for (i=0; i<n; i++) {		yt[i] = y[i]+h*dym[i];		dym[i] += dyt[i];	}		/* 4th step; accumulate weighted results from prior steps */	rk->fdydx(x+h,aux,yt,dyt);	for (i=0; i<n; i++)		ynew[i] = y[i]+hsixth*(dydx[i]+dyt[i]+2.0*dym[i]);}#define PGROW -0.20		/* power for increasing step size */#define PSHRINK -0.25		/* power for decreasing step size */#define FCORR 0.066666666	/* fifth order correction factor = 1/15 */#define SAFETY 0.9		/* factor for step size adjustment */#define ERRCON 6.0e-4		/* error constant = (4/SAFETY)^(1/PGROW) */void rkastep (RKState *rk, 	float htry, float *hdid, float *hnext, float eps, float yscl[],	float x, float y[], float dydx[], float ynew[])/*****************************************************************************Performs one Runga-Kutta (5th order) step, with a step size that isadjusted to satisfy a user-specified error tolerance.The step size is adjusted until either (1) the error in all y[i](i = 0 to n-1) is less than eps*yscl[i], where eps is an overallerror tolerance and yscl[i] is a user-supplied scale factor, or(2) the step size becomes insignificant.******************************************************************************Input:rk		pointer to Runga-Kutta statehtry		step size to tryeps		overall error toleranceyscl		array of scale factors used to normalize errorsx		independent variable xy[]		array of dependent variables y(x)dydx[]		array of derivatives y'(x)******************************************************************************Output:hdid		step size actually taken (0 if step unsuccessful)hnext		step size recommended for next step (0 if step unsuccessful)ynew[]		array of y(x+hdid) (may be equivalenced to y[])******************************************************************************Notes:Adapted from function rkqc in Numerical Recipes in C, by Press, Flannery, Teukolsky, and Vetterling, 1988.******************************************************************************Author:  Dave Hale, Colorado School of Mines, 10/10/89******************************************************************************/{	int i;	float h,hhalf,temp,errmax;	int n=rk->n;	float *yt=rk->w4,*dydxt=rk->w5,*ys=rk->w6;	void *aux=rk->aux;		/* save current y */	for (i=0; i<n; i++)		ys[i] = y[i];		/* loop over trial step sizes (while trial step is significant) */	for (h=htry,*hdid=0.0,*hnext=0.0; x+h!=x;) {				/* take two half steps */		hhalf = h/2.0;		rkstep(rk,hhalf,x,ys,dydx,yt);		rk->fdydx(x+hhalf,aux,yt,dydxt);		rkstep(rk,hhalf,x+hhalf,yt,dydxt,ynew);				/* take one large step */		rkstep(rk,h,x,ys,dydx,yt);				/* determine maximum error scaled by required accuracy */		for (i=0,errmax=0.0; i<n; i++) {			yt[i] = ynew[i]-yt[i];			temp = fabs(yt[i]/yscl[i]);			if (errmax<temp) errmax = temp;		}		errmax /= eps;				/* if normalized maximum error is small enough */		if (errmax<1.0) {					/* compute size of next step */			*hdid = h;			*hnext = (errmax>ERRCON ?				SAFETY*h*pow(errmax,PGROW) :				4.0*h);			/* compensate for 5th order truncation error */			for (i=0; i<n; i++)				ynew[i] += yt[i]*FCORR;						/* we're done! */			return;				/* else if normalized maximum error is too big */		} else {					/* adjust step size for another try */			h = SAFETY*h*pow(errmax,PSHRINK);		}	}		/* step was unsuccessful, so set new y equal to input y */	for (i=0; i<n; i++)		ynew[i] = ys[i];}/* simple test */typedef struct _Parms {	float freq,phase;} Parms;void func (float x, Parms *parms, float y[]){	float freq=parms->freq,phase=parms->phase;	y[0] = sin(freq*x+phase);	y[1] = cos(freq*x+phase);}void dfunc (float x, Parms *parms, float y[], float dydx[]){	float freq=parms->freq,phase=parms->phase;	dydx[0] = freq*cos(freq*x+phase);	dydx[1] = -freq*sin(freq*x+phase);}#define N 2#define NX 20main(){		int n=N,nx=NX,ix;	float x,h=0.5,htry,hdid,hnext,eps=0.1;	float y[N],ye[N],dydx[N],yscl[N];	Parms p;	RKState *rk;		p.freq = 1.0;	p.phase = 3.0;		yscl[0] = 1.0;	yscl[1] = 1.0;		rk = rkcreate(n,&p,(void(*)(float,void*,float[],float[]))dfunc);			printf("\nEuler's method\n");	func(0.0,&p,y);	for (ix=0,x=0.0; ix<nx-1; ix++,x+=h) {		func(x,&p,ye);		printf("x = %8.3f  err[0] = %10.5f  err[1] = %10.5f\n",			x,y[0]-ye[0],y[1]-ye[1]);		dfunc(x,&p,y,dydx);		y[0] += h*dydx[0];		y[1] += h*dydx[1];	}		printf("\nRunga-Kutta with constant step size\n");	func(0.0,&p,y);	for (ix=0,x=0.0; ix<nx-1; ix++,x+=h) {		func(x,&p,ye);		printf("x = %8.3f  err[0] = %10.5f  err[1] = %10.5f\n",			x,y[0]-ye[0],y[1]-ye[1]);		dfunc(x,&p,y,dydx);		rkstep(rk,h,x,y,dydx,y);	}		printf("\nRunga-Kutta with adaptive step size\n");	func(0.0,&p,y);	for (ix=0,x=0.0,htry=h; ix<nx-1; ix++,x+=hdid,htry=hnext) {		func(x,&p,ye);		printf("x = %8.3f  err[0] = %10.5f  err[1] = %10.5f\n",			x,y[0]-ye[0],y[1]-ye[1]);		dfunc(x,&p,y,dydx);		rkastep(rk,htry,&hdid,&hnext,eps,yscl,x,y,dydx,y);		if (hdid==0.0) break;	}}

⌨️ 快捷键说明

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