// 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); }