LMMC
Lamina Mathematic core
载入中...
搜索中...
未找到
ode_support.c
浏览该文件的文档.
1#include "ode_internal.h"
2
3void 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) {
4 const lmmc_real_t values[] = {t, dim > 0 ? y[0] : 0.0};
5 const lmmc_diagnostic_t diagnostic = {
6 LMMC_DIAGNOSTIC_TRACE, "ode", "accepted step", step, values, 2
7 };
8 lmmc_diagnostic_emit(&cfg->diagnostics, &diagnostic);
9}
10
12 if (out_result == NULL) {
13 return;
14 }
15
16 out_result->converged = 0;
17 out_result->num_steps = 0;
18 out_result->num_rhs_evals = 0;
19 out_result->final_t = t_start;
21}
22
23static lmmc_status_t ode_invalid_config(
25) {
26 if (result != NULL) result->failure_reason = reason;
28}
29
30static int ode_tolerances_valid(const lmmc_ode_config_t* cfg) {
31 if (!lmmc_is_finite(&cfg->abs_tol) || !lmmc_is_finite(&cfg->rel_tol)) { return 0; }
32 if (cfg->abs_tol < 0.0 || cfg->rel_tol < 0.0) { return 0; }
33 return cfg->abs_tol != 0.0 || cfg->rel_tol != 0.0;
34}
35
36static int ode_steps_valid(const lmmc_ode_config_t* cfg) {
37 if (!lmmc_is_finite(&cfg->initial_step) || !lmmc_is_finite(&cfg->min_step)) {
38 return 0;
39 }
40 if (!lmmc_is_finite(&cfg->max_step)) {
41 return 0;
42 }
43 if (cfg->initial_step <= 0.0 || cfg->min_step <= 0.0 || cfg->max_step <= 0.0) {
44 return 0;
45 }
46 if (cfg->min_step > cfg->max_step || cfg->max_steps == 0) {
47 return 0;
48 }
49 return lmmc_is_finite(&cfg->adaptive_step_beta) &&
50 cfg->adaptive_step_beta > 0.0 && cfg->adaptive_step_beta <= 1.0;
51}
52
54 size_t dim,
55 lmmc_real_t t_start,
56 lmmc_real_t t_end,
57 const lmmc_ode_config_t* cfg,
58 lmmc_ode_config_t* out_cfg,
59 lmmc_ode_result_t* out_result
60) {
61 if (dim == 0) { return ode_invalid_config(out_result, LMMC_ODE_FAILURE_INVALID_DIMENSION); }
62 if (!lmmc_is_finite(&t_start) || !lmmc_is_finite(&t_end) || !(t_end > t_start)) { return ode_invalid_config(out_result, LMMC_ODE_FAILURE_INVALID_STEP); }
63 if (out_cfg == NULL) { return ode_invalid_config(out_result, LMMC_ODE_FAILURE_INVALID_STEP); }
64 if (cfg != NULL) {
65 *out_cfg = *cfg;
66 } else {
67 lmmc_status_t st = lmmc_ode_default_config(t_start, t_end, dim, out_cfg);
68 if (st != LMMC_STATUS_OK) {
69 ode_invalid_config(out_result, LMMC_ODE_FAILURE_INVALID_STEP);
70 return st;
71 }
72 }
73 if (!ode_tolerances_valid(out_cfg)) { return ode_invalid_config(out_result, LMMC_ODE_FAILURE_TOLERANCE_INCONSISTENT); }
74 if (!ode_steps_valid(out_cfg)) { return ode_invalid_config(out_result, LMMC_ODE_FAILURE_INVALID_STEP); }
75 return LMMC_STATUS_OK;
76}
77
81 const lmmc_real_t* y,
82 lmmc_real_t* y_prime,
83 size_t dim,
84 void* user_data,
85 size_t* io_eval_count,
86 int* out_callback_failed
87) {
89
90 if (rhs == NULL || y == NULL || y_prime == NULL || io_eval_count == NULL || out_callback_failed == NULL) {
92 }
93
94 *out_callback_failed = 0;
95 *io_eval_count += 1;
96 st = rhs(t, y, y_prime, dim, user_data);
97 if (st != LMMC_STATUS_OK) {
98 *out_callback_failed = 1;
99 return st;
100 }
101 return lmmc_ode_values_are_finite(y_prime, dim);
102}
103
104int lmmc_ode_state_is_finite(const lmmc_real_t* y, size_t dim) {
105 if (y == NULL || dim == 0) {
106 return 0;
107 }
108
110}
111
113 lmmc_ode_rhs_t rhs,
114 size_t dim,
115 lmmc_real_t t_start,
116 lmmc_real_t t_end,
117 const lmmc_real_t* y,
118 const lmmc_ode_config_t* cfg,
119 lmmc_ode_config_t* out_cfg,
120 lmmc_ode_result_t* out_result,
121 size_t* out_work_bytes
122) {
123 lmmc_ode_reset_result(out_result, t_start);
124
125 if (rhs == NULL || y == NULL || out_result == NULL || out_cfg == NULL || out_work_bytes == NULL) {
127 }
128 if (lmmc_ode_load_and_validate_config(dim, t_start, t_end, cfg, out_cfg, out_result) != LMMC_STATUS_OK) {
130 }
131
132 if (!lmmc_ode_state_is_finite(y, dim)) {
135 }
136
137 if (!lmmc_safe_mul_size(dim, sizeof(lmmc_real_t), out_work_bytes)) {
140 }
141
142 return LMMC_STATUS_OK;
143}
144
146 const lmmc_real_t* error,
147 const lmmc_real_t* y_old,
148 const lmmc_real_t* y_new,
149 size_t dim,
150 lmmc_real_t abs_tol,
151 lmmc_real_t rel_tol,
152 lmmc_real_t* out_norm
153) {
154 lmmc_real_t sum = 0.0;
155 size_t i;
156 if (error == NULL || y_old == NULL || y_new == NULL || out_norm == NULL || dim == 0) {
158 }
159 for (i = 0; i < dim; ++i) {
160 lmmc_real_t scale = abs_tol + rel_tol * fmax(fabs(y_old[i]), fabs(y_new[i]));
161 lmmc_real_t ratio;
162 if (!isfinite(scale) || scale <= 0.0 || !isfinite(error[i])) {
164 }
165 ratio = error[i] / scale;
166 sum += ratio * ratio;
167 if (!isfinite(sum)) {
169 }
170 }
171 *out_norm = sqrt(sum / (lmmc_real_t)dim);
172 return isfinite(*out_norm) ? LMMC_STATUS_OK : LMMC_STATUS_NUMERICAL_FAILURE;
173}
174
176 lmmc_real_t h,
177 lmmc_real_t error_norm,
178 const lmmc_ode_config_t* cfg
179) {
180 lmmc_real_t factor = 5.0;
181 if (error_norm > 0.0 && isfinite(error_norm)) {
182 factor = cfg->adaptive_step_beta * pow(error_norm, -0.25);
183 }
184 factor = lmmc_clamp(factor, 0.2, 5.0);
185 return lmmc_clamp(h * factor, cfg->min_step, cfg->max_step);
186}
187
189 const lmmc_real_t* values,
190 size_t count
191) {
192 if (values == NULL) { return LMMC_STATUS_INVALID_ARGUMENT; }
193 return lmmc_real_range_is_finite(values, count)
196}
double lmmc_real_t
Public and internal LMMC real type.
void lmmc_diagnostic_emit(const lmmc_diagnostic_sink_t *sink, const lmmc_diagnostic_t *diagnostic)
通过调用方持有的接收器发送一个诊断事件;空接收器直接完成.
@ LMMC_DIAGNOSTIC_TRACE
size_t num_rhs_evals
定义 ode.h:49
lmmc_status_t lmmc_ode_default_config(lmmc_real_t t_start, lmmc_real_t t_end, size_t problem_dim, lmmc_ode_config_t *out_cfg)
根据积分区间与维度生成合理的默认求解配置。
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 右端函数签名 。
定义 ode.h:26
lmmc_diagnostic_sink_t diagnostics
定义 ode.h:99
lmmc_real_t initial_step
定义 ode.h:92
lmmc_ode_failure_t
ODE 求解失败原因。
定义 ode.h:35
@ LMMC_ODE_FAILURE_NUMERICAL_ISSUE
定义 ode.h:40
@ LMMC_ODE_FAILURE_INVALID_STEP
定义 ode.h:38
@ LMMC_ODE_FAILURE_TOLERANCE_INCONSISTENT
定义 ode.h:42
@ LMMC_ODE_FAILURE_NONE
定义 ode.h:36
@ LMMC_ODE_FAILURE_INVALID_DIMENSION
定义 ode.h:37
lmmc_real_t final_t
定义 ode.h:50
lmmc_real_t abs_tol
定义 ode.h:95
lmmc_real_t rel_tol
定义 ode.h:96
lmmc_ode_failure_t failure_reason
定义 ode.h:51
lmmc_real_t max_step
定义 ode.h:94
lmmc_real_t adaptive_step_beta
定义 ode.h:98
lmmc_real_t min_step
定义 ode.h:93
ODE 求解配置。
定义 ode.h:91
ODE 求解结果统计。
定义 ode.h:46
ODE 求解器共享的内部辅助函数。
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_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_reset_result(lmmc_ode_result_t *out_result, lmmc_real_t t_start)
int lmmc_ode_state_is_finite(const lmmc_real_t *y, size_t dim)
lmmc_status_t lmmc_ode_load_and_validate_config(size_t dim, lmmc_real_t t_start, lmmc_real_t t_end, const lmmc_ode_config_t *cfg, lmmc_ode_config_t *out_cfg, lmmc_ode_result_t *out_result)
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_status_t
LMMC 库统一返回的状态码.
@ LMMC_STATUS_OK
@ LMMC_STATUS_NUMERICAL_FAILURE
@ LMMC_STATUS_INVALID_ARGUMENT