19#define SDIRK_VECTORS 16
20#define SDIRK_NEWTON_MAX 12
25 {0.25, 0.0, 0.0, 0.0, 0.0},
26 {0.5, 0.25, 0.0, 0.0, 0.0},
27 {0.34, -0.04, 0.25, 0.0, 0.0},
28 {371.0 / 1360.0, -137.0 / 2720.0, 15.0 / 544.0, 0.25, 0.0},
29 {25.0 / 24.0, -49.0 / 48.0, 125.0 / 16.0, -85.0 / 12.0, 0.25}
32 25.0 / 24.0, -49.0 / 48.0, 125.0 / 16.0, -85.0 / 12.0, 0.25
35 59.0 / 48.0, -17.0 / 96.0, 225.0 / 32.0, -85.0 / 12.0, 0.0
75 int callback_failed = 0;
88 for (i = 0; i < s->
dim; ++i) {
89 for (j = 0; j < s->
dim; ++j) {
97 for (i = 0; i < s->
dim; ++i) s->
k[stage][i] += s->
delta[i];
107 for (i = 0; i < s->
dim; ++i) s->
error[i] = s->
h * derivative[i];
111 for (i = 0; i < s->
dim; ++i) {
114 if (!isfinite(scale) || !isfinite(s->
error[i])) {
117 if (scale == 0.0) zero_scale = 1;
121 *out_norm = INFINITY;
131 int callback_failed = 0;
133 for (i = 0; i < s->
dim; ++i) {
145 for (i = 0; i < s->
dim; ++i) {
148 if (s->
residual[i] != 0.0) { *residual_zero = 0; }
155 size_t i, j, corrections = 0;
158 for (j = 0; j < stage; ++j) {
159 for (i = 0; i < s->
dim; ++i) {
160 s->
rhs_sum[i] += sdirk_a[stage][j] * s->
k[j][i];
163 if (stage == 0) { memset(s->
k[stage], 0, s->
work_bytes); }
164 else { memcpy(s->
k[stage], s->
k[stage - 1], s->
work_bytes); }
168 st = sdirk_stage_residual(s, stage, &residual_zero);
172 if (corrections != 0) {
174 st = sdirk_stage_norm(s, s->
residual, &residual_norm);
176 st = sdirk_stage_norm(s, s->
delta, &correction_norm);
178 if (residual_norm <= eta && correction_norm <= eta) {
return LMMC_STATUS_OK; }
184 st = sdirk_newton_correction(s, stage);
192 int callback_failed = 0;
194 for (i = 0; i < s->
dim; ++i) {
198 s->
y_new[i] += s->
h * sdirk_b[stage] * s->
k[stage][i];
199 s->
y_hat[i] += s->
h * sdirk_bhat[stage] * s->
k[stage][i];
225 for (i = 0; i < s->
dim; ++i) {
226 for (j = 0; j < s->
dim; ++j) {
242 while (s->
t < t_end && attempts < s->local_cfg.max_steps) {
245 if (s->
h > t_end - s->
t) s->
h = t_end - s->
t;
247 st = sdirk_solve_stage(s, stage);
250 st = sdirk_estimate_error(s, &error_norm);
252 if (error_norm <= 1.0) {
300 size_t vectors_bytes = 0, matrix_count = 0, matrix_bytes = 0, pivot_bytes = 0;
313 !lmmc_safe_mul_size(s->
dim, s->
dim, &matrix_count) ||
314 !lmmc_safe_mul_size(matrix_count,
sizeof(
lmmc_real_t), &matrix_bytes) ||
315 !lmmc_safe_mul_size(s->
dim,
sizeof(
size_t), &pivot_bytes)) {
325 return sdirk_cleanup(s, st);
342 if (s->
h > t_end - t_start) s->
h = t_end - t_start;
344 st = sdirk_integrate(s, t_end);
345 return sdirk_cleanup(s, st);
double lmmc_real_t
Public and internal LMMC real type.
稠密矩阵直接分解接口(LU、Cholesky、QR)。
lmmc_status_t lmmc_lu_solve(const lmmc_mat_t *lu, const size_t *pivots, const lmmc_vec_t *b, lmmc_vec_t *x)
利用 LU 分解结果求解线性系统 A*x = b。
lmmc_status_t lmmc_lu_decompose_inplace(lmmc_mat_t *a, size_t *pivots, size_t *out_swap_count)
就地 LU 分解(带部分主元选取):P*A = L*U。
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_INVALID_DIMENSION
@ LMMC_ODE_FAILURE_MAX_STEPS
lmmc_ode_failure_t failure_reason
lmmc_status_t lmmc_ode_sdirk4_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)
4 阶 SDIRK 求解器,采用嵌入误差估计和自适应步长。 非线性阶段按 abs_tol/rel_tol、当前及阶段状态计算 h*残差与 h*修正的加权 RMS。 迭代耗尽时保留最后接受的 y、fina...
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 lmmc_ode_jacobian_eval(const lmmc_ode_jacobian_request_t *request)
lmmc_real_t lmmc_ode_next_step(lmmc_real_t h, lmmc_real_t error_norm, const lmmc_ode_config_t *cfg)
lmmc_status_t lmmc_ode_values_are_finite(const lmmc_real_t *values, size_t count)
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)
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_ode_weighted_rms(const lmmc_real_t *error, const lmmc_real_t *y_old, const lmmc_real_t *y_new, size_t dim, lmmc_real_t abs_tol, lmmc_real_t rel_tol, lmmc_real_t *out_norm)
lmmc_real_t * matrix_data
lmmc_ode_config_t local_cfg
lmmc_real_t * k[SDIRK_STAGES]
lmmc_ode_result_t * out_result
lmmc_status_t
LMMC 库统一返回的状态码.
@ LMMC_STATUS_CONVERGENCE_FAILED
@ LMMC_STATUS_NUMERICAL_FAILURE
@ LMMC_STATUS_ALLOCATION_FAILED
@ LMMC_STATUS_INVALID_ARGUMENT