19#include "mdb_thread.h"
21void new_scale_factors_dp(
double *yscale,
double *y0,
double *dydx0,
22 double h_start,
double *tiny,
long *accmode,
double *accuracy,
24void initial_scale_factors_dp(
double *yscale,
double *y0,
double *dydx0,
25 double h_start,
double *tiny,
long *accmode,
double *accuracy,
26 double *accur,
double x0,
double xf,
long n_eq);
28static double stepIncreaseFactor = 0.50;
29static double stepDecreaseFactor = 0.95;
30static MDB_THREAD_LOCK bs_qctune_lock = MDB_THREAD_LOCK_INITIALIZER;
32void bs_qctune(
double newStepIncreaseFactor,
double newStepDecreaseFactor) {
33 mdb_thread_lock(&bs_qctune_lock);
34 if (newStepIncreaseFactor > 0)
35 stepIncreaseFactor = newStepIncreaseFactor;
36 if (newStepDecreaseFactor > 0)
37 stepDecreaseFactor = newStepDecreaseFactor;
38 mdb_thread_unlock(&bs_qctune_lock);
58 double *stepRecommended,
61 void (*derivs)(
double *dydx,
double *y,
double x),
65 static MDB_THREAD_LOCAL
double **solution = NULL, *hSqr = NULL, *yLast = NULL, *yError = NULL;
66 long i, j, iWorst = 0, code, nuse;
67 double maxError, error, yInterp;
68 double localStepIncreaseFactor, localStepDecreaseFactor;
69 static const long mmidSteps[IMAX] = {2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96};
70 static MDB_THREAD_LOCAL
long lastEquations = 0;
72 mdb_thread_lock(&bs_qctune_lock);
73 localStepIncreaseFactor = stepIncreaseFactor;
74 localStepDecreaseFactor = stepDecreaseFactor;
75 mdb_thread_unlock(&bs_qctune_lock);
77 if (equations > lastEquations) {
78 if (lastEquations != 0) {
82 free_array_2d((
void **)solution,
sizeof(*solution), 0, lastEquations - 1, 0, NUSE - 1);
84 yLast =
tmalloc(
sizeof(
double) * equations);
85 yError =
tmalloc(
sizeof(
double) * equations);
86 hSqr =
tmalloc(
sizeof(
double) * IMAX);
87 solution = (
double **)
array_2d(
sizeof(
double), 0, equations - 1, 0, NUSE - 1);
88 lastEquations = equations;
93 printf(
"step = %e\n", step);
95 for (i = 0; i < IMAX; i++) {
96 mmid(yInitial, dydxInitial, equations, *x, step, mmidSteps[i], yFinal, derivs);
97 hSqr[i % NUSE] = sqr(step / mmidSteps[i]);
98 nuse = i > NUSE ? NUSE : i;
99 for (j = 0; j < equations; j++) {
101 solution[j][i % NUSE] = yFinal[j];
110 yError[j] = yInterp - yLast[j];
114 printf(
"i = %ld, j = %ld: yFinal = %.10e, yError = %.10e, yScale = %.10e\n",
115 i, j, yFinal[j], yInterp, yError[j], yScale[j]);
120 for (j = 0; j < equations; j++)
121 if (maxError < (error = FABS(yError[j] / yScale[j]))) {
126 printf(
"maxError = %e, iWorst = %ld\n", maxError, iWorst);
128 if (maxError < 1.0) {
130 *stepRecommended = *stepUsed = step;
133 *stepRecommended *= localStepDecreaseFactor;
136 *stepRecommended *= localStepIncreaseFactor / sqrt(maxError);
139 printf(
"returning with i=%ld, stepUsed=%e, stepRec=%e\n", i, *stepUsed, *stepRecommended);
141 for (j = 0; j < equations; j++)
142 yFinal[j] = yLast[j];
151 for (i = 0; i < (IMAX - NUSE) / 2; i++)
153 }
while ((*x + step) != *x);
154 fprintf(stderr,
"error: step size underflow in bs_step()--step reduced to %e\n", step);
191 void (*derivs)(
double *dydx,
double *y,
double x),
207 double (*exit_func)(
double *dydx,
double *y,
double x),
209 double exit_accuracy,
212 void (*store_data)(
double *dydx,
double *y,
double x,
double exf)
214 double *y_return, *accur;
215 double *dydx0, *y1, *dydx1, *dydx2, *y2;
216 double ex0, ex1, ex2, x1, x2, *yscale;
217 double h_used, h_next, xdiff;
218 long i, n_step_ups = 0, is_zero;
219#define MAX_N_STEP_UPS 10
222 return (DIFFEQ_XI_GT_XF);
223 if (FABS(*x0 - xf) < x_accuracy)
224 return (DIFFEQ_SOLVED_ALREADY);
237 for (i = 0; i < n_eq; i++) {
238 if (accmode[i] < 0 || accmode[i] > 3)
239 bomb(
"accmode must be on [0, 3] (bs_odeint)", NULL);
240 if (accmode[i] < 2 && tiny[i] < TINY)
246 dydx0 =
tmalloc(
sizeof(
double) * n_eq);
247 y1 =
tmalloc(
sizeof(
double) * n_eq);
248 dydx1 =
tmalloc(
sizeof(
double) * n_eq);
249 y2 =
tmalloc(
sizeof(
double) * n_eq);
250 dydx2 =
tmalloc(
sizeof(
double) * n_eq);
251 yscale =
tmalloc(
sizeof(
double) * n_eq);
254 (*derivs)(dydx0, y0, *x0);
259 accur =
tmalloc(
sizeof(
double) * n_eq);
260 initial_scale_factors_dp(yscale, y0, dydx0, h_start, tiny, accmode,
261 accuracy, accur, *x0, xf, n_eq);
263 ex0 = exit_func ? (*exit_func)(dydx0, y0, *x0) : 0;
265 (*store_data)(dydx0, y0, *x0, ex0);
270 if (exit_func && FABS(ex0) < exit_accuracy) {
272 if (n_to_skip == 0) {
274 (*store_data)(dydx0, y0, *x0, ex0);
275 for (i = 0; i < n_eq; i++)
289 return (DIFFEQ_ZERO_FOUND);
298 if ((xdiff = xf - *x0) < h_start)
302 if (!bs_step(y1, &x1, y0, dydx0, h_start, &h_used, &h_next,
303 yscale, n_eq, derivs, misses)) {
304 if (n_step_ups++ > MAX_N_STEP_UPS)
305 bomb(
"error: cannot take initial step (bs_odeint--1)", NULL);
306 h_start = (n_step_ups - 1 ? h_start * 10 : h_used * 10);
310 (*derivs)(dydx1, y1, x1);
311 ex1 = exit_func ? (*exit_func)(dydx1, y1, x1) : 0;
313 (*store_data)(dydx1, y1, x1, ex1);
315 if (exit_func && SIGN(ex0) != SIGN(ex1) && !is_zero) {
324 if (FABS(xdiff = xf - x1) < x_accuracy) {
327 (*derivs)(dydx1, y1, x1);
328 ex1 = exit_func ? (*exit_func)(dydx1, y1, x1) : 0;
329 (*store_data)(dydx1, y1, x1, ex1);
331 for (i = 0; i < n_eq; i++)
346 return (DIFFEQ_END_OF_INTERVAL);
349 SWAP_PTR(dydx0, dydx1);
354 h_start = (h_next > h_max ? (h_max ? h_max : h_next) : h_next);
356 new_scale_factors_dp(yscale, y0, dydx0, h_start, tiny, accmode,
362 printf(
"failure in bs_odeint(): solution stepped outside interval\n");
374 return (DIFFEQ_OUTSIDE_INTERVAL);
377 if (FABS(ex1) < exit_accuracy) {
378 for (i = 0; i < n_eq; i++)
392 return (DIFFEQ_ZERO_FOUND);
398 h_start = -ex0 * (x1 - *x0) / (ex1 - ex0 + TINY);
401 new_scale_factors_dp(yscale, y0, dydx0, h_start, tiny, accmode,
403 if (!bs_step(y2, &x2, y0, dydx0, h_start, &h_used, &h_next,
404 yscale, n_eq, derivs, misses))
405 bomb(
"step size too small (bs_odeint--2)", NULL);
407 (*derivs)(dydx2, y2, x2);
408 ex2 = (*exit_func)(dydx2, y2, x2);
409 if (FABS(ex2) < exit_accuracy) {
410 for (i = 0; i < n_eq; i++)
424 return (DIFFEQ_ZERO_FOUND);
427 if (SIGN(ex1) == SIGN(ex2)) {
429 SWAP_PTR(dydx1, dydx2);
434 SWAP_PTR(dydx0, dydx2);
468 void (*derivs)(
double *yp,
double *y,
double x),
485 double *dydx0, *y1, *dydx1, *dydx2, *y2;
486 double x1, *yscale, *accur;
487 double h_used, h_next, xdiff;
488 long i, n_step_ups = 0;
489#define MAX_N_STEP_UPS 10
492 return (DIFFEQ_XI_GT_XF);
493 if (fabs(*x0 - xf) < x_accuracy)
494 return (DIFFEQ_SOLVED_ALREADY);
507 for (i = 0; i < n_eq; i++) {
508 if (accmode[i] < 0 || accmode[i] > 3)
509 bomb(
"accmode must be on [0, 3] (bs_odeint)", NULL);
510 if (accmode[i] < 2 && tiny[i] < TINY)
516 dydx0 =
tmalloc(
sizeof(
double) * n_eq);
517 y1 =
tmalloc(
sizeof(
double) * n_eq);
518 dydx1 =
tmalloc(
sizeof(
double) * n_eq);
519 y2 =
tmalloc(
sizeof(
double) * n_eq);
520 dydx2 =
tmalloc(
sizeof(
double) * n_eq);
521 yscale =
tmalloc(
sizeof(
double) * n_eq);
524 (*derivs)(dydx0, y0, *x0);
529 accur =
tmalloc(
sizeof(
double) * n_eq);
530 initial_scale_factors_dp(yscale, y0, dydx0, h_start, tiny, accmode,
531 accuracy, accur, *x0, xf, n_eq);
535 if ((xdiff = xf - *x0) < h_start)
539 if (!bs_step(y1, &x1, y0, dydx0, h_start, &h_used, &h_next,
540 yscale, n_eq, derivs, misses)) {
541 if (n_step_ups++ > MAX_N_STEP_UPS)
542 bomb(
"error: cannot take initial step (bs_odeint1--1)", NULL);
543 h_start = (n_step_ups - 1 ? h_start * 10 : h_used * 10);
547 if (fabs(xdiff = xf - x1) < x_accuracy) {
549 for (i = 0; i < n_eq; i++)
564 return (DIFFEQ_END_OF_INTERVAL);
567 (*derivs)(dydx1, y1, x1);
569 SWAP_PTR(dydx0, dydx1);
573 h_start = (h_next > h_max ? (h_max ? h_max : h_next) : h_next);
575 new_scale_factors_dp(yscale, y0, dydx0, h_start, tiny, accmode,
612 void (*derivs)(
double *dydx,
double *y,
double x),
630 double exit_accuracy,
633 double *y_return, *accur;
634 double *dydx0, *y1, *dydx1, *dydx2, *y2;
635 double ex0, ex1, ex2, x1, x2, *yscale;
636 double h_used, h_next, xdiff;
637 long i, n_step_ups = 0, is_zero;
638#define MAX_N_STEP_UPS 10
641 return (DIFFEQ_XI_GT_XF);
642 if (fabs(*x0 - xf) < x_accuracy)
643 return (DIFFEQ_SOLVED_ALREADY);
644 if (i_exit_value < 0 || i_exit_value >= n_eq)
645 bomb(
"index of variable for exit testing is out of range (bs_odeint2)", NULL);
658 for (i = 0; i < n_eq; i++) {
659 if (accmode[i] < 0 || accmode[i] > 3)
660 bomb(
"accmode must be on [0, 3] (bs_odeint2)", NULL);
661 if (accmode[i] < 2 && tiny[i] < TINY)
667 dydx0 =
tmalloc(
sizeof(
double) * n_eq);
668 y1 =
tmalloc(
sizeof(
double) * n_eq);
669 dydx1 =
tmalloc(
sizeof(
double) * n_eq);
670 y2 =
tmalloc(
sizeof(
double) * n_eq);
671 dydx2 =
tmalloc(
sizeof(
double) * n_eq);
672 yscale =
tmalloc(
sizeof(
double) * n_eq);
675 (*derivs)(dydx0, y0, *x0);
680 accur =
tmalloc(
sizeof(
double) * n_eq);
681 initial_scale_factors_dp(yscale, y0, dydx0, h_start, tiny, accmode,
682 accuracy, accur, *x0, xf, n_eq);
684 ex0 = exit_value - y0[i_exit_value];
688 if (fabs(ex0) < exit_accuracy) {
690 if (n_to_skip == 0) {
691 for (i = 0; i < n_eq; i++)
705 return (DIFFEQ_ZERO_FOUND);
714 if ((xdiff = xf - *x0) < h_start)
718 if (!bs_step(y1, &x1, y0, dydx0, h_start, &h_used, &h_next,
719 yscale, n_eq, derivs, misses)) {
720 if (n_step_ups++ > MAX_N_STEP_UPS) {
721 bomb(
"error: cannot take initial step (bs_odeint2--1)", NULL);
723 h_start = (n_step_ups - 1 ? h_start * 10 : h_used * 10);
727 (*derivs)(dydx1, y1, x1);
728 ex1 = exit_value - y1[i_exit_value];
730 if (SIGN(ex0) != SIGN(ex1) && !is_zero) {
739 if (fabs(xdiff = xf - x1) < x_accuracy) {
741 for (i = 0; i < n_eq; i++)
756 return (DIFFEQ_END_OF_INTERVAL);
759 SWAP_PTR(dydx0, dydx1);
764 h_start = (h_next > h_max ? (h_max ? h_max : h_next) : h_next);
766 new_scale_factors_dp(yscale, y0, dydx0, h_start, tiny, accmode,
774 h_start = -ex0 * (x1 - *x0) / (ex1 - ex0 + TINY);
777 new_scale_factors_dp(yscale, y0, dydx0, h_start, tiny, accmode,
779 if (!bs_step(y2, &x2, y0, dydx0, h_start, &h_used, &h_next,
780 yscale, n_eq, derivs, misses))
781 bomb(
"step size too small (bs_odeint2--2)", NULL);
783 (*derivs)(dydx2, y2, x2);
784 ex2 = exit_value - y2[i_exit_value];
785 if (fabs(ex2) < exit_accuracy) {
786 for (i = 0; i < n_eq; i++)
800 return (DIFFEQ_ZERO_FOUND);
803 if (SIGN(ex1) == SIGN(ex2)) {
805 SWAP_PTR(dydx1, dydx2);
810 SWAP_PTR(dydx0, dydx2);
848 void (*derivs)(
double *dydx,
double *y,
double x),
864 double (*exit_func)(
double *dydx,
double *y,
double x),
868 static MDB_THREAD_LOCAL
double *yscale = NULL;
869 static MDB_THREAD_LOCAL
double *dydx0 = NULL, *y1 = NULL, *dydx1 = NULL, *dydx2 = NULL, *y2 = NULL, *accur = NULL, *y0 = NULL;
870 static MDB_THREAD_LOCAL
long last_neq = 0;
871 double ex0, ex1, ex2, x1, x2;
872 double h_used, h_next, xdiff;
873 long i, n_step_ups = 0;
874#define MAX_N_STEP_UPS 10
877 return (DIFFEQ_XI_GT_XF);
878 if (FABS(*x0 - xf) < x_accuracy)
879 return (DIFFEQ_SOLVED_ALREADY);
892 for (i = 0; i < n_eq; i++) {
893 if (accmode[i] < 0 || accmode[i] > 3)
894 bomb(
"accmode must be on [0, 3] (bs_odeint)", NULL);
895 if (accmode[i] < 2 && tiny[i] < TINY)
900 if (last_neq < n_eq) {
911 y0 =
tmalloc(
sizeof(
double) * n_eq);
912 dydx0 =
tmalloc(
sizeof(
double) * n_eq);
913 y1 =
tmalloc(
sizeof(
double) * n_eq);
914 dydx1 =
tmalloc(
sizeof(
double) * n_eq);
915 y2 =
tmalloc(
sizeof(
double) * n_eq);
916 dydx2 =
tmalloc(
sizeof(
double) * n_eq);
917 yscale =
tmalloc(
sizeof(
double) * n_eq);
918 accur =
tmalloc(
sizeof(
double) * n_eq);
922 for (i = 0; i < n_eq; i++)
926 (*derivs)(dydx0, y0, *x0);
931 initial_scale_factors_dp(yscale, y0, dydx0, h_start, tiny, accmode,
932 accuracy, accur, *x0, xf, n_eq);
934 ex0 = (*exit_func)(dydx0, y0, *x0);
938 if (FABS(ex0) < exit_accuracy) {
939 for (i = 0; i < n_eq; i++)
942 return (DIFFEQ_ZERO_FOUND);
946 if ((xdiff = xf - *x0) < h_start)
950 if (!bs_step(y1, &x1, y0, dydx0, h_start, &h_used, &h_next,
951 yscale, n_eq, derivs, misses)) {
952 if (n_step_ups++ > MAX_N_STEP_UPS)
953 bomb(
"error: cannot take initial step (bs_odeint3--1)", NULL);
954 h_start = (n_step_ups - 1 ? h_start * 10 : h_used * 10);
958 (*derivs)(dydx1, y1, x1);
959 ex1 = (*exit_func)(dydx1, y1, x1);
960 if (SIGN(ex0) != SIGN(ex1))
963 if (FABS(xdiff = xf - x1) < x_accuracy) {
965 for (i = 0; i < n_eq; i++)
969 return (DIFFEQ_END_OF_INTERVAL);
972 SWAP_PTR(dydx0, dydx1);
977 h_start = (h_next > h_max ? (h_max ? h_max : h_next) : h_next);
979 new_scale_factors_dp(yscale, y0, dydx0, h_start, tiny, accmode,
985 printf(
"failure in bs_odeint3(): solution stepped outside interval\n");
986 return (DIFFEQ_OUTSIDE_INTERVAL);
989 if (FABS(ex1) < exit_accuracy) {
990 for (i = 0; i < n_eq; i++)
993 return (DIFFEQ_ZERO_FOUND);
999 h_start = -ex0 * (x1 - *x0) / (ex1 - ex0 + TINY);
1002 new_scale_factors_dp(yscale, y0, dydx0, h_start, tiny, accmode,
1004 if (!bs_step(y2, &x2, y0, dydx0, h_start, &h_used, &h_next,
1005 yscale, n_eq, derivs, misses))
1006 bomb(
"step size too small (bs_odeint3--2)", NULL);
1008 (*derivs)(dydx2, y2, x2);
1009 ex2 = (*exit_func)(dydx2, y2, x2);
1010 if (FABS(ex2) < exit_accuracy) {
1011 for (i = 0; i < n_eq; i++)
1014 return (DIFFEQ_ZERO_FOUND);
1017 if (SIGN(ex1) == SIGN(ex2)) {
1019 SWAP_PTR(dydx1, dydx2);
1024 SWAP_PTR(dydx0, dydx2);
1064 void (*derivs)(
double *dydx,
double *y,
double x),
1082 double exit_accuracy,
1084 void (*store_data)(
double *dydx,
double *y,
double x,
double exf)
1086 double *y_return, *accur;
1087 double *dydx0, *y1, *dydx1, *dydx2, *y2;
1088 double ex0, ex1, ex2, x1, x2, *yscale;
1089 double h_used, h_next, xdiff;
1090 long i, n_step_ups = 0, is_zero;
1091#define MAX_N_STEP_UPS 10
1094 return (DIFFEQ_XI_GT_XF);
1095 if (fabs(*x0 - xf) < x_accuracy)
1096 return (DIFFEQ_SOLVED_ALREADY);
1097 if (i_exit_value < 0 || i_exit_value >= n_eq)
1098 bomb(
"index of variable for exit testing is out of range (bs_odeint4)", NULL);
1111 for (i = 0; i < n_eq; i++) {
1112 if (accmode[i] < 0 || accmode[i] > 3)
1113 bomb(
"accmode must be on [0, 3] (bs_odeint4)", NULL);
1114 if (accmode[i] < 2 && tiny[i] < TINY)
1120 dydx0 =
tmalloc(
sizeof(
double) * n_eq);
1121 y1 =
tmalloc(
sizeof(
double) * n_eq);
1122 dydx1 =
tmalloc(
sizeof(
double) * n_eq);
1123 y2 =
tmalloc(
sizeof(
double) * n_eq);
1124 dydx2 =
tmalloc(
sizeof(
double) * n_eq);
1125 yscale =
tmalloc(
sizeof(
double) * n_eq);
1128 (*derivs)(dydx0, y0, *x0);
1133 accur =
tmalloc(
sizeof(
double) * n_eq);
1134 initial_scale_factors_dp(yscale, y0, dydx0, h_start, tiny, accmode,
1135 accuracy, accur, *x0, xf, n_eq);
1137 ex0 = exit_value - y0[i_exit_value];
1139 (*store_data)(dydx0, y0, *x0, ex0);
1143 if (fabs(ex0) < exit_accuracy) {
1145 if (n_to_skip == 0) {
1147 (*store_data)(dydx0, y0, *x0, ex0);
1148 for (i = 0; i < n_eq; i++)
1149 y_return[i] = y0[i];
1162 return (DIFFEQ_ZERO_FOUND);
1171 if ((xdiff = xf - *x0) < h_start)
1175 if (!bs_step(y1, &x1, y0, dydx0, h_start, &h_used, &h_next,
1176 yscale, n_eq, derivs, misses)) {
1177 if (n_step_ups++ > MAX_N_STEP_UPS) {
1178 bomb(
"error: cannot take initial step (bs_odeint4--1)", NULL);
1180 h_start = (n_step_ups - 1 ? h_start * 10 : h_used * 10);
1184 (*derivs)(dydx1, y1, x1);
1185 ex1 = exit_value - y1[i_exit_value];
1187 (*store_data)(dydx1, y1, x1, ex1);
1189 if (SIGN(ex0) != SIGN(ex1) && !is_zero) {
1198 if (fabs(xdiff = xf - x1) < x_accuracy) {
1201 (*derivs)(dydx1, y1, x1);
1202 ex1 = exit_value - y0[i_exit_value];
1203 (*store_data)(dydx1, y1, x1, ex1);
1205 for (i = 0; i < n_eq; i++)
1206 y_return[i] = y1[i];
1220 return (DIFFEQ_END_OF_INTERVAL);
1223 SWAP_PTR(dydx0, dydx1);
1228 h_start = (h_next > h_max ? (h_max ? h_max : h_next) : h_next);
1230 new_scale_factors_dp(yscale, y0, dydx0, h_start, tiny, accmode,
1238 h_start = -ex0 * (x1 - *x0) / (ex1 - ex0 + TINY);
1241 new_scale_factors_dp(yscale, y0, dydx0, h_start, tiny, accmode,
1243 if (!bs_step(y2, &x2, y0, dydx0, h_start, &h_used, &h_next,
1244 yscale, n_eq, derivs, misses))
1245 bomb(
"step size too small (bs_odeint4--2)", NULL);
1247 (*derivs)(dydx2, y2, x2);
1248 ex2 = exit_value - y2[i_exit_value];
1249 if (fabs(ex2) < exit_accuracy) {
1250 for (i = 0; i < n_eq; i++)
1251 y_return[i] = y2[i];
1264 return (DIFFEQ_ZERO_FOUND);
1267 if (SIGN(ex1) == SIGN(ex2)) {
1269 SWAP_PTR(dydx1, dydx2);
1274 SWAP_PTR(dydx0, dydx2);
void ** array_2d(uint64_t size, uint64_t lower1, uint64_t upper1, uint64_t lower2, uint64_t upper2)
Allocates a 2D array with specified lower and upper indices for both dimensions.
int tfree(void *ptr)
Frees a memory block and records the deallocation if tracking is enabled.
int free_array_2d(void **array, uint64_t size, uint64_t lower1, uint64_t upper1, uint64_t lower2, uint64_t upper2)
Frees a 2D array and its associated memory.
void * tmalloc(uint64_t size_of_block)
Allocates a memory block of the specified size with zero initialization.
void bomb(char *error, char *usage)
Reports error messages to the terminal and aborts the program.
long bs_odeint1(double *y0, void(*derivs)(double *yp, double *y, double x), long n_eq, double *accuracy, long *accmode, double *tiny, long *misses, double *x0, double xf, double x_accuracy, double h_start, double h_max, double *h_rec)
Integrates a system of ordinary differential equations to a specified upper limit without exit condit...
long bs_odeint3(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_start, double h_max, double *h_rec, double(*exit_func)(double *dydx, double *y, double x), double exit_accuracy)
Integrates a system of ordinary differential equations using the Bulirsch-Stoer method with optimized...
long bs_odeint4(double *y0, 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_start, double h_max, double *h_rec, double exit_value, long i_exit_value, double exit_accuracy, long n_to_skip, void(*store_data)(double *dydx, double *y, double x, double exf))
Integrates a system of ordinary differential equations until a specified component reaches a target v...
long bs_odeint2(double *y0, 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_start, double h_max, double *h_rec, double exit_value, long i_exit_value, double exit_accuracy, long n_to_skip)
Integrates a system of ordinary differential equations until a specified component reaches a target v...
long bs_odeint(double *y0, 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_start, double h_max, double *h_rec, double(*exit_func)(double *dydx, double *y, double x), double exit_accuracy, long n_to_skip, void(*store_data)(double *dydx, double *y, double x, double exf))
Integrates a system of ordinary differential equations using the Bulirsch-Stoer method.
double LagrangeInterp(double *x, double *f, long order1, double x0, long *returnCode)
Performs Lagrange interpolation of data.
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.