11 namespace MDSimulation
18 inline double MAX(
const double a,
const double b)
23 inline double MIN(
const double a,
const double b)
33 template <
class Function>
39 Solver(Function& f,
int order,
double* x,
double* y);
55 int RK4(
double xMax,
double accuracy,
56 double step,
int steps,
double minStep = 0,
57 double maxStep = DBL_MAX,
double xMin = 0);
60 inline int GetSteps()
const
66 inline double GetNextStep()
const
72 inline double GetLastStep()
const
97 Function& Derivatives;
106 double yscal[MAX_ORDER];
116 double dydx[MAX_ORDER];
122 double yError[MAX_ORDER];
123 double ak2[MAX_ORDER];
124 double ak3[MAX_ORDER];
125 double ak4[MAX_ORDER];
126 double ak5[MAX_ORDER];
127 double ak6[MAX_ORDER];
128 double ytemp[MAX_ORDER];
135 template <
class Function>
139 assert(order <= MAX_ORDER);
149 template <
class Function>
150 void Solver<Function>::SingleStep()
155 printf(
"derp = 3000\n");
159 const double a2 = 0.2,
175 b61 = 1631.0/55296.0,
178 b64 = 44275.0/110592.0,
186 dc1 = c1 - 2825.0/27648.0,
187 dc3 = c3 - 18575.0/48384.0,
188 dc4 = c4 -13525.0/55296.0,
189 dc5 = -277.00/14336.0,
192 double ytemp[MAX_ORDER];
194 for (
int i = 0; i < Order; i++ )
195 { ytemp[i] = y[i] + b21*LastStep*dydx[i]; }
197 Derivatives(x + a2*LastStep, ytemp, ak2);
199 for (
int i = 0; i < Order; i++ )
200 { ytemp[i] = y[i] + LastStep*(b31*dydx[i] + b32*ak2[i]); }
202 Derivatives(x + a3*LastStep, ytemp, ak3);
204 for (
int i = 0; i < Order; i++ )
205 { ytemp[i] = y[i] + LastStep*(b41*dydx[i] + b42*ak2[i] + b43*ak3[i]); }
207 Derivatives(x + a4*LastStep, ytemp, ak4);
209 for (
int i = 0; i < Order; i++ )
210 { ytemp[i] = y[i] + LastStep*(b51*dydx[i] + b52*ak2[i] + b53*ak3[i] + b54*ak4[i]); }
212 Derivatives(x + a5*LastStep, ytemp, ak5);
214 for (
int i = 0; i < Order; i++ )
215 { ytemp[i] = y[i] + LastStep*(b61*dydx[i] + b62*ak2[i] + b63*ak3[i] + b64*ak4[i] + b65*ak5[i]); }
217 Derivatives(x + a6*LastStep, ytemp, ak6);
220 for (
int i = 0; i < Order; i++ )
221 { yOut[i] = y[i] + LastStep*(c1*dydx[i] + c3*ak3[i] + c4*ak4[i] + c6*ak6[i]); }
224 for (
int i = 0; i < Order; i++ )
225 { yError[i] = LastStep*(dc1*dydx[i] + dc3*ak3[i] + dc4*ak4[i] + dc5*ak5[i] + dc6*ak6[i]); }
228 template <
class Function>
229 void Solver<Function>::rkqs()
232 const double SAFETY = 0.9, PGROW = -0.2, PSHRNK = -0.25, ERRCON = 1.89E-4;
233 double maxError, tempStep, xnew;
241 for (
int i = 0; i < Order; i++ )
243 maxError = max(maxError, fabs(yError[i] / yscal[i]));
246 maxError /= Accuracy;
248 if ( maxError <= 1.0 ) {
break; }
250 tempStep = SAFETY*LastStep*pow(maxError,PSHRNK);
251 LastStep = (LastStep >= 0.0 ? max(tempStep, 0.1*LastStep)
252 : min(tempStep, 0.1*LastStep));
258 throw Error(STEPSIZE_UNDER_HMIN);
262 if ( maxError > ERRCON )
263 { NextStep = SAFETY*LastStep*pow(maxError, PGROW); }
265 { NextStep = 5.0*LastStep; }
270 template <
class Function>
271 int Solver<Function>::RK4(
double xMax,
double accuracy,
double step,
int steps,
272 double minStep,
double maxStep,
double xMin)
274 const double TINY = 1E-30;
278 double xsav = x =
X[0];
284 Step = (xMax - x) > 0 ? step : -step;
287 GoodSteps = BadSteps = 0;
308 bool isFinished = xMax > xStart ? (x >= xMax) : (x <= xMax);
313 printf(
"derp = 2228\n");
316 if ( fabs(x - xsav) > xMin || isFinished )
319 X[++CurrentStep] = xsav = x;
320 if ( CurrentStep == steps || isFinished )
321 {
return CurrentStep; }
324 Derivatives(x, y, dydx);
326 for (
int i = 0; i < Order; i++ )
328 yscal[i] = fabs(y[i]) + fabs(Step*dydx[i]) + TINY;
331 double hleft = xMax - x;
332 if ( fabs(Step) > fabs(hleft) ) { Step = hleft; }
338 if ( LastStep == Step )
344 if ( fabs(NextStep) <= minStep )
345 {
throw Error(STEPSIZE_UNDER_HMIN); }
349 { Step = MIN(NextStep, maxStep); }
351 { Step = MAX(NextStep, -maxStep); }
The Solver class is templatized by the function it will take.
Definition: Solver.h:34
const IntVector X(1, 0, 0)
Unit Vectors for each direction.