34 for (
size_t stage = 0; stage < stages; ++stage) {
36 if (s->
k[stage] == NULL) { allocated = 0; }
39 if (s->
y_tmp == NULL) { allocated = 0; }
41 explicit_free(s, stages);
51 int callback_failed = 0;
67 if (!lmmc_is_finite(&s->
t)) {
95 if (rem <= 0.0 || !lmmc_is_finite(&rem)) {
103 st = explicit_rhs(s, s->
t, s->
y, s->
k[0]);
105 for (i = 0; i < s->
dim; ++i) {
110 st = explicit_advance(s);
113 return explicit_finish(s, t_end);
138 if (s->
k[0] == NULL) {
152 st = euler_integrate(s, t_end);
193static const lmmc_real_t ck_a64 = 44275.0 / 110592.0;
208 37.0 / 378.0 - 2825.0 / 27648.0,
210 250.0 / 621.0 - 18575.0 / 48384.0,
211 125.0 / 594.0 - 13525.0 / 55296.0,
212 0.0 - 277.0 / 14336.0,
213 512.0 / 1771.0 - 1.0 / 4.0
219 st = explicit_rhs(s, s->
t, s->
y, s->
k[0]);
222 for (i = 0; i < s->
dim; ++i) {
223 s->
y_tmp[i] = s->
y[i] + s->
h * ck_a21 * s->
k[0][i];
225 st = explicit_rhs(s, s->
t + ck_c[1] * s->
h, s->
y_tmp, s->
k[1]);
228 for (i = 0; i < s->
dim; ++i) {
229 s->
y_tmp[i] = s->
y[i] + s->
h * (ck_a31 * s->
k[0][i] + ck_a32 * s->
k[1][i]);
231 st = explicit_rhs(s, s->
t + ck_c[2] * s->
h, s->
y_tmp, s->
k[2]);
234 for (i = 0; i < s->
dim; ++i) {
235 s->
y_tmp[i] = s->
y[i] + s->
h * (ck_a41 * s->
k[0][i] + ck_a42 * s->
k[1][i] + ck_a43 * s->
k[2][i]);
237 st = explicit_rhs(s, s->
t + ck_c[3] * s->
h, s->
y_tmp, s->
k[3]);
240 for (i = 0; i < s->
dim; ++i) {
241 s->
y_tmp[i] = s->
y[i] + s->
h * (ck_a51 * s->
k[0][i] + ck_a52 * s->
k[1][i] +
242 ck_a53 * s->
k[2][i] + ck_a54 * s->
k[3][i]);
244 st = explicit_rhs(s, s->
t + ck_c[4] * s->
h, s->
y_tmp, s->
k[4]);
247 for (i = 0; i < s->
dim; ++i) {
248 s->
y_tmp[i] = s->
y[i] + s->
h * (ck_a61 * s->
k[0][i] + ck_a62 * s->
k[1][i] +
249 ck_a63 * s->
k[2][i] + ck_a64 * s->
k[3][i] +
250 ck_a65 * s->
k[4][i]);
252 st = explicit_rhs(s, s->
t + ck_c[5] * s->
h, s->
y_tmp, s->
k[5]);
262 for (i = 0; i < s->
dim; ++i) {
263 lmmc_real_t err_i = s->
h * (ck_e[0] * s->
k[0][i] + ck_e[2] * s->
k[2][i] +
264 ck_e[3] * s->
k[3][i] + ck_e[4] * s->
k[4][i] +
265 ck_e[5] * s->
k[5][i]);
268 s->
y_tmp[i] = s->
y[i] + s->
h * (ck_b5[0] * s->
k[0][i] + ck_b5[2] * s->
k[2][i] +
269 ck_b5[3] * s->
k[3][i] + ck_b5[5] * s->
k[5][i]);
272 ratio = err_i / scale;
273 err_norm += ratio * ratio;
281 if (err_norm > 0.0 && isfinite(err_norm)) {
283 factor = lmmc_clamp(factor, 0.2, 5.0);
289 if (!step_accepted) {
291 if (h_new <= s->local_cfg.min_step && err_norm > 1.0) {
305 while (s->
t < t_end && attempts < s->local_cfg.max_steps) {
309 int step_accepted = 0;
313 if (rem <= 0.0 || !lmmc_is_finite(&rem)) {
320 st = cash_karp_stages(s);
322 err_norm = cash_karp_error(s);
323 if (err_norm <= 1.0) {
326 st = explicit_advance(s);
329 st = cash_karp_control(s, err_norm, step_accepted);
332 return explicit_finish(s, t_end);
356 st = explicit_allocate(s, 6);
368 st = cash_karp_integrate(s, t_end);
383 st = explicit_rhs(s, s->
t, s->
y, s->
k[0]);
387 for (i = 0; i < s->
dim; ++i) {
394 st = explicit_rhs(s, t_mid, s->
y_tmp, s->
k[1]);
397 for (i = 0; i < s->
dim; ++i) {
403 st = explicit_rhs(s, t_mid, s->
y_tmp, s->
k[2]);
406 for (i = 0; i < s->
dim; ++i) {
413 st = explicit_rhs(s, t_next, s->
y_tmp, s->
k[3]);
417 for (i = 0; i < s->
dim; ++i) {
418 lmmc_real_t t2k2, t2k3, sum1, sum2, sum3, weighted;
427 return explicit_advance(s);
435 if (rem <= 0.0 || !lmmc_is_finite(&rem)) {
445 return explicit_finish(s, t_end);
469 st = explicit_allocate(s, 4);
481 st = rk4_integrate(s, t_end);
#define LMMC_REAL_ADD(res, a, b)
计算 *res = *a + *b 。
#define LMMC_REAL_DIV(res, a, b)
计算 *res = *a / *b 。
#define LMMC_REAL_SUB(res, a, b)
计算 *res = *a - *b 。
double lmmc_real_t
Public and internal LMMC real type.
#define LMMC_REAL_MUL(res, a, b)
计算 *res = *a * *b 。
void * lmmc_memory_alloc(size_t size)
void lmmc_memory_free(void *pointer)
Private recoverable allocator for persistent LMMC ownership.
常微分方程初值问题求解器:Euler、RK4、RK45(自适应)。
lmmc_status_t(*) lmmc_ode_rhs_t(lmmc_real_t t, const lmmc_real_t *y, lmmc_real_t *y_prime, size_t dim, void *user_data)
ODE 右端函数签名 。
@ LMMC_ODE_FAILURE_NUMERICAL_ISSUE
@ LMMC_ODE_FAILURE_INVALID_STEP
@ LMMC_ODE_FAILURE_RHS_EVAL_FAILED
@ LMMC_ODE_FAILURE_MAX_STEPS
lmmc_status_t lmmc_ode_rk4_solve(lmmc_ode_rhs_t rhs, void *user_data, size_t dim, lmmc_real_t t_start, lmmc_real_t t_end, lmmc_real_t *y, const lmmc_ode_config_t *cfg, lmmc_ode_result_t *out_result)
经典四阶 Runge-Kutta 法求解 (固定步长)。
lmmc_ode_failure_t failure_reason
lmmc_status_t lmmc_ode_rk45_solve(lmmc_ode_rhs_t rhs, void *user_data, size_t dim, lmmc_real_t t_start, lmmc_real_t t_end, lmmc_real_t *y, const lmmc_ode_config_t *cfg, lmmc_ode_result_t *out_result)
自适应 Runge-Kutta-Fehlberg (RK45) 求解器。
lmmc_status_t lmmc_ode_euler_solve(lmmc_ode_rhs_t rhs, void *user_data, size_t dim, lmmc_real_t t_start, lmmc_real_t t_end, lmmc_real_t *y, const lmmc_ode_config_t *cfg, lmmc_ode_result_t *out_result)
显式 Euler 法求解常微分方程初值问题 。
lmmc_real_t adaptive_step_beta
lmmc_ode_config_t local_cfg
lmmc_ode_result_t * out_result
lmmc_status_t lmmc_ode_rhs_eval(lmmc_ode_rhs_t rhs, lmmc_real_t t, const lmmc_real_t *y, lmmc_real_t *y_prime, size_t dim, void *user_data, size_t *io_eval_count, int *out_callback_failed)
lmmc_status_t validate_and_init_ode_config(lmmc_ode_rhs_t rhs, size_t dim, lmmc_real_t t_start, lmmc_real_t t_end, const lmmc_real_t *y, const lmmc_ode_config_t *cfg, lmmc_ode_config_t *out_cfg, lmmc_ode_result_t *out_result, size_t *out_work_bytes)
int lmmc_ode_state_is_finite(const lmmc_real_t *y, size_t dim)
void lmmc_ode_do_log(const lmmc_ode_config_t *cfg, size_t step, lmmc_real_t t, const lmmc_real_t *y, size_t dim)
lmmc_status_t
LMMC 库统一返回的状态码.
@ LMMC_STATUS_CONVERGENCE_FAILED
@ LMMC_STATUS_NUMERICAL_FAILURE
@ LMMC_STATUS_ALLOCATION_FAILED