51 void (*derivs)(
double *_dydx,
double *_y,
double _x)) {
53 double x = 0, ynSave, h, hTimes2;
54 static MDB_THREAD_LOCAL
double *ym = NULL, *yn = NULL;
55 static MDB_THREAD_LOCAL
long last_equations = 0;
58 if (equations > last_equations) {
64 ym =
tmalloc(
sizeof(*ym) * equations);
65 yn =
tmalloc(
sizeof(*yn) * equations);
66 last_equations = equations;
69 hTimes2 = (h = interval / steps) * 2;
72 for (i = 0; i < equations; i++) {
74 yn[i] = yInitial[i] + h * dydxInitial[i];
78 for (j = 1; j < steps; j++) {
80 (*derivs)(dydxTemp, yn, x);
81 for (i = 0; i < equations; i++) {
83 yn[i] = ym[i] + hTimes2 * dydxTemp[i];
89 (*derivs)(dydxTemp, yn, x + interval);
90 for (i = 0; i < equations; i++)
91 yFinal[i] = (ym[i] + yn[i] + h * dydxTemp[i]) / 2;
120 void (*derivs)(
double *_dydx,
double *_y,
double _x)) {
121 static MDB_THREAD_LOCAL
double *yFinal2 = NULL;
122 static MDB_THREAD_LOCAL
long last_equations = 0;
130 if (equations > last_equations) {
131 if (last_equations) {
135 yFinal2 =
tmalloc(
sizeof(*yFinal2) * equations);
136 last_equations = equations;
139 mmid(y, dydx, equations, x0, interval, steps, yFinal, derivs);
140 mmid(y, dydx, equations, x0, interval, steps / 2, yFinal2, derivs);
141 for (i = 0; i < equations; i++)
142 yFinal[i] = (4 * yFinal[i] - yFinal2[i]) / 3;
176 void (*derivs)(
double *dydx,
double *y,
double x),
191 double (*exit_func)(
double *dydx,
double *y,
double x),
195 static MDB_THREAD_LOCAL
double *y0 = NULL, *yscale = NULL;
196 static MDB_THREAD_LOCAL
double *dydx0 = NULL, *y1 = NULL, *dydx1 = NULL, *dydx2 = NULL, *y2 = NULL, *accur = NULL;
197 static MDB_THREAD_LOCAL
long last_neq = 0;
198 double ex0, ex1, ex2, x1, x2;
200 long i, n_exit_iterations;
201#define MAX_N_STEP_UPS 10
204 return (DIFFEQ_XI_GT_XF);
205 if (FABS(*x0 - xf) < x_accuracy)
206 return (DIFFEQ_SOLVED_ALREADY);
208 if (last_neq < n_eq) {
219 y0 =
tmalloc(
sizeof(
double) * n_eq);
220 dydx0 =
tmalloc(
sizeof(
double) * n_eq);
221 y1 =
tmalloc(
sizeof(
double) * n_eq);
222 dydx1 =
tmalloc(
sizeof(
double) * n_eq);
223 y2 =
tmalloc(
sizeof(
double) * n_eq);
224 dydx2 =
tmalloc(
sizeof(
double) * n_eq);
228 for (i = 0; i < n_eq; i++)
232 (*derivs)(dydx0, y0, *x0);
233 ex0 = (*exit_func)(dydx0, y0, *x0);
237 if (FABS(ex0) < exit_accuracy) {
238 for (i = 0; i < n_eq; i++)
240 return (DIFFEQ_ZERO_FOUND);
244 if ((xdiff = xf - *x0) < h_step)
248 mmid2(y0, dydx0, n_eq, x1, h_step, 8, y1, derivs);
251 (*derivs)(dydx1, y1, x1);
252 ex1 = (*exit_func)(dydx1, y1, x1);
253 if (SIGN(ex0) != SIGN(ex1))
256 if (FABS(xdiff = xf - x1) < x_accuracy) {
258 for (i = 0; i < n_eq; i++)
261 return (DIFFEQ_END_OF_INTERVAL);
264 SWAP_PTR(dydx0, dydx1);
271 printf(
"failure in mmid_odeint3_na(): solution stepped outside interval\n");
272 return (DIFFEQ_OUTSIDE_INTERVAL);
275 if (FABS(ex1) < exit_accuracy) {
276 for (i = 0; i < n_eq; i++)
279 return (DIFFEQ_ZERO_FOUND);
283 n_exit_iterations = MAX_EXIT_ITERATIONS;
286 h_step = -ex0 * (x1 - *x0) / (ex1 - ex0) * ITER_FACTOR;
288 mmid2(y0, dydx0, n_eq, x2, h_step, 8, y2, derivs);
291 (*derivs)(dydx2, y2, x2);
292 ex2 = (*exit_func)(dydx2, y2, x2);
293 if (FABS(ex2) < exit_accuracy) {
294 for (i = 0; i < n_eq; i++)
297 return (DIFFEQ_ZERO_FOUND);
300 if (SIGN(ex1) == SIGN(ex2)) {
302 SWAP_PTR(dydx1, dydx2);
307 SWAP_PTR(dydx0, dydx2);
311 }
while (n_exit_iterations--);
312 return (DIFFEQ_EXIT_COND_FAILED);
long mmid_odeint3_na(double *yif, void(*derivs)(double *dydx, double *y, double x), long n_eq, double *accuracy, long *accmode, double *tiny, long *misses, double *x0, double xf, double x_accuracy, double h_step, double h_max, double *h_rec, double(*exit_func)(double *dydx, double *y, double x), double exit_accuracy)
Integrates ODEs until a condition is met or the interval is reached.
void mmid(double *yInitial, double *dydxInitial, long equations, double xInitial, double interval, long steps, double *yFinal, void(*derivs)(double *_dydx, double *_y, double _x))
Integrates a system of ODEs using the modified midpoint method.
void mmid2(double *y, double *dydx, long equations, double x0, double interval, long steps, double *yFinal, void(*derivs)(double *_dydx, double *_y, double _x))
Enhances the modified midpoint method with error correction.