Beispiel #1
0
// Create driver/stepper that treats real and imaginary parts separately before recombining
public static Tuple<List<complex>, List<complex>, int, List<double>> cdrive_split(Func<complex,complex, complex> f, complex a, complex b, complex ya, complex h= default(complex), double acc=1e-4, double eps=1e-4, int nmax=100000){
	// Return lists. I use lists because arrays and vectors don't play nice with complex
	List<complex> zs = new List<complex>(){a};
	List<complex> ys = new List<complex>(){ya};
	List<double> errs = new List<double>();
	int nsteps=0;
	complex ar = new complex(a.Re,0); complex ai = new complex(0,a.Im);
	complex br = new complex(b.Re,0); complex bi = new complex(0,b.Im);
	if(h.Equals(default(complex)))h=(b-a)/1000;
	double dist = abs(b-a);
	double newdist = abs(b-a)-acc;

	do{
		if(abs(b-a)<acc)break; // End statement
		if(nsteps>nmax){
			Write("Error: Did not converge within iteration limit\n");
			break;
		}
		if(abs(a+h)>abs(b-a))h=b-a;
		nsteps++;
		double err=0; // = new complex();
		complex y_re = crkstep45_single(f,ar,ya,h,err);
		double tol_re = abs(sqrt(h/(br-ar)))*(eps*abs(y_re)+acc);
		complex y_im = crkstep45_single(f,ai,ya,h,err);
		double tol_im = abs(sqrt(h/(bi-ai)))*(eps*abs(y_im)+acc);
		complex y_next = new complex(y_re.Re, y_im.Im);
		double tol = Sqrt(Pow(tol_re,2)+Pow(tol_im,2));
	
		if(err==0)err=tol/4; 
		// Relative error, and checking for bad steps
		double rel_arr = tol/err;
		bool crap = false;
		if(rel_arr<1.0)crap=true;

		if(!crap){
			dist = abs(b-a);
			a+=h;
			newdist = abs(b-a);
			ya = y_next;
			zs.Add(a);
			ys.Add(ya);
			errs.Add(rel_arr);
		}

		// Calculating the next step size, using eq. 40 
		h = h*(Pow(rel_arr,0.25)*0.95);
	}while(newdist<dist); //End of while-loop





	return Tuple.Create(zs, ys, nsteps, errs);
}