LMMC
Lamina Mathematic core
载入中...
搜索中...
未找到
itersolve_bicgstab.c
浏览该文件的文档.
2
7
8static lmmc_status_t lmmc_bicgstab_start(const lmmc_sparse_mat_t* a,
9 const lmmc_vec_t* b, const lmmc_itersolve_config_t* cfg,
11 lmmc_status_t st = lmmc_itersolve_residual(a, b, x, &s->ax, &s->r);
12 if (st != LMMC_STATUS_OK) {
13 return st;
14 }
15 st = lmmc_vec_copy(&s->r, &s->r_hat);
16 if (st != LMMC_STATUS_OK) {
17 return st;
18 }
19 return lmmc_itersolve_threshold(cfg, b, &s->r, &s->norm, &s->threshold);
20}
21
22static lmmc_status_t lmmc_bicgstab_direction(lmmc_bicgstab_state_t* s, size_t iter) {
24 if (st != LMMC_STATUS_OK) {
25 return st;
26 }
27 if (fabs(s->rho_hat) <= 1e-30) {
29 }
30 if (iter == 0) {
31 return lmmc_vec_copy(&s->r, &s->p);
32 }
33 if (fabs(s->omega) <= 1e-30) {
35 }
36 lmmc_real_t beta = (s->rho_hat / s->rho) * (s->alpha / s->omega);
37 if (!isfinite(beta)) {
39 }
40 for (size_t i = 0; i < s->p.size; ++i) {
41 lmmc_real_t product = s->omega * s->v.data[i];
42 lmmc_real_t difference = s->p.data[i] - product;
43 product = beta * difference;
44 s->p.data[i] = s->r.data[i] + product;
45 if (!isfinite(s->p.data[i])) {
47 }
48 }
49 return LMMC_STATUS_OK;
50}
51
52static lmmc_status_t lmmc_bicgstab_alpha(const lmmc_sparse_mat_t* a,
53 const lmmc_precond_t* precond, lmmc_bicgstab_state_t* s) {
54 lmmc_real_t denom;
55 lmmc_status_t st = lmmc_apply_precond_or_identity(precond, &s->p, &s->y);
56 if (st != LMMC_STATUS_OK) {
57 return st;
58 }
59 st = lmmc_sparse_mat_vec_mul(a, &s->y, &s->v);
60 if (st != LMMC_STATUS_OK) {
61 return st;
62 }
63 st = lmmc_vec_dot_checked(&s->r_hat, &s->v, &denom);
64 if (st != LMMC_STATUS_OK) {
65 return st;
66 }
67 if (fabs(denom) <= 1e-30) {
69 }
70 s->alpha = s->rho_hat / denom;
71 if (!isfinite(s->alpha)) {
73 }
74 st = lmmc_vec_copy(&s->r, &s->s);
75 if (st != LMMC_STATUS_OK) {
76 return st;
77 }
78 st = lmmc_vec_axpy(-s->alpha, &s->v, &s->s);
79 if (st != LMMC_STATUS_OK) {
80 return st;
81 }
82 return lmmc_vec_norm2_checked(&s->s, &s->norm_s);
83}
84
85static lmmc_status_t lmmc_bicgstab_omega(const lmmc_sparse_mat_t* a,
86 const lmmc_precond_t* precond, lmmc_bicgstab_state_t* s) {
87 lmmc_real_t ts, tt;
88 lmmc_status_t st = lmmc_apply_precond_or_identity(precond, &s->s, &s->z);
89 if (st != LMMC_STATUS_OK) {
90 return st;
91 }
92 st = lmmc_sparse_mat_vec_mul(a, &s->z, &s->t);
93 if (st != LMMC_STATUS_OK) {
94 return st;
95 }
96 st = lmmc_vec_dot_checked(&s->t, &s->s, &ts);
97 if (st != LMMC_STATUS_OK) {
98 return st;
99 }
100 st = lmmc_vec_dot_checked(&s->t, &s->t, &tt);
101 if (st != LMMC_STATUS_OK) {
102 return st;
103 }
104 if (fabs(tt) <= 1e-30) {
106 }
107 s->omega = ts / tt;
108 return isfinite(s->omega) ? LMMC_STATUS_OK : LMMC_STATUS_NUMERICAL_FAILURE;
109}
110
111static lmmc_status_t lmmc_bicgstab_update(lmmc_vec_t* x,
112 lmmc_bicgstab_state_t* s, int early) {
113 for (size_t i = 0; i < x->size; ++i) {
114 lmmc_real_t delta = s->alpha * s->y.data[i];
115 if (!early) {
116 lmmc_real_t second = s->omega * s->z.data[i];
117 delta = delta + second;
118 }
119 x->data[i] = x->data[i] + delta;
120 if (!isfinite(x->data[i])) {
122 }
123 }
124 if (early) {
125 s->norm = s->norm_s;
126 return LMMC_STATUS_OK;
127 }
128 lmmc_status_t st = lmmc_vec_copy(&s->s, &s->r);
129 if (st != LMMC_STATUS_OK) {
130 return st;
131 }
132 st = lmmc_vec_axpy(-s->omega, &s->t, &s->r);
133 if (st != LMMC_STATUS_OK) {
134 return st;
135 }
136 return lmmc_vec_norm2_checked(&s->r, &s->norm);
137}
138
139static lmmc_status_t lmmc_bicgstab_step(const lmmc_sparse_mat_t* a,
140 const lmmc_precond_t* precond, lmmc_vec_t* x,
141 lmmc_bicgstab_state_t* s, size_t iter) {
142 lmmc_status_t st = lmmc_bicgstab_direction(s, iter);
143 if (st != LMMC_STATUS_OK) {
144 return st;
145 }
146 st = lmmc_bicgstab_alpha(a, precond, s);
147 if (st != LMMC_STATUS_OK) {
148 return st;
149 }
150 if (s->norm_s <= s->threshold) {
151 return lmmc_bicgstab_update(x, s, 1);
152 }
153 st = lmmc_bicgstab_omega(a, precond, s);
154 if (st != LMMC_STATUS_OK) {
155 return st;
156 }
157 return lmmc_bicgstab_update(x, s, 0);
158}
159
160static lmmc_status_t lmmc_bicgstab_iterate(const lmmc_sparse_mat_t* a,
161 const lmmc_precond_t* precond, const lmmc_itersolve_config_t* cfg,
163 size_t* iterations, int* converged) {
164 for (size_t iter = 0; iter < cfg->max_iter; ++iter) {
165 lmmc_status_t st = lmmc_bicgstab_step(a, precond, x, s, iter);
166 if (st != LMMC_STATUS_OK) {
167 return st;
168 }
169 *iterations = iter + 1;
170 if (result != NULL) {
171 result->final_residual_norm = s->norm;
172 }
173 lmmc_itersolve_do_log(cfg, *iterations, s->norm);
174 if (s->norm <= s->threshold) {
175 *converged = 1;
176 break;
177 }
178 if (fabs(s->omega) <= 1e-30) {
180 }
181 s->rho = s->rho_hat;
182 }
183 return LMMC_STATUS_OK;
184}
185
187 const lmmc_vec_t* b, const lmmc_precond_t* precond,
188 const lmmc_itersolve_config_t* cfg, lmmc_vec_t* x,
189 lmmc_itersolve_result_t* out_result) {
190 lmmc_itersolve_config_t local = {0};
191 lmmc_bicgstab_state_t s = {0};
192 lmmc_real_t* storage = NULL;
193 size_t iterations = 0;
194 int converged = 0;
195 s.rho = s.alpha = s.omega = 1.0;
196 lmmc_status_t st = lmmc_itersolve_validate(a, b, precond, cfg, x, &local, out_result);
197 if (st != LMMC_STATUS_OK) {
198 goto cleanup;
199 }
200 lmmc_vec_t* vectors[] = {&s.r, &s.r_hat, &s.p, &s.v, &s.s, &s.t, &s.y, &s.z, &s.ax};
201 const size_t n = b->size;
202 const size_t sizes[] = {n, n, n, n, n, n, n, n, n};
203 st = lmmc_itersolve_workspace(vectors, sizes, 9, &storage);
204 if (st != LMMC_STATUS_OK) {
205 goto cleanup;
206 }
207 st = lmmc_bicgstab_start(a, b, &local, x, &s);
208 if (st != LMMC_STATUS_OK) {
209 goto cleanup;
210 }
211 lmmc_itersolve_initial(out_result, s.norm);
212 lmmc_itersolve_do_log(&local, 0, s.norm);
213 if (s.norm <= s.threshold) {
214 converged = 1;
215 }
216 else {
217 st = lmmc_bicgstab_iterate(a, precond, &local, x, &s, out_result, &iterations, &converged);
218 }
219cleanup:
220 lmmc_itersolve_finish(out_result, converged, iterations, s.norm);
221 lmmc_memory_free(storage);
222 return st;
223}
double lmmc_real_t
Public and internal LMMC real type.
lmmc_status_t lmmc_vec_axpy(lmmc_real_t alpha, const lmmc_vec_t *x, lmmc_vec_t *y)
向量 AXPY 运算: 。
lmmc_status_t lmmc_vec_copy(const lmmc_vec_t *src, lmmc_vec_t *dst)
逐元素复制向量内容:dst = src。
lmmc_real_t * data
一维稠密向量。
lmmc_status_t lmmc_vec_dot_checked(const lmmc_vec_t *a, const lmmc_vec_t *b, lmmc_real_t *out_dot)
lmmc_status_t lmmc_vec_norm2_checked(const lmmc_vec_t *v, lmmc_real_t *out_norm)
lmmc_status_t lmmc_itersolve_threshold(const lmmc_itersolve_config_t *cfg, const lmmc_vec_t *b, const lmmc_vec_t *r, lmmc_real_t *norm, lmmc_real_t *threshold)
lmmc_status_t lmmc_apply_precond_or_identity(const lmmc_precond_t *precond, const lmmc_vec_t *rhs, lmmc_vec_t *out)
lmmc_status_t lmmc_itersolve_validate(const lmmc_sparse_mat_t *a, const lmmc_vec_t *b, const lmmc_precond_t *precond, const lmmc_itersolve_config_t *cfg, lmmc_vec_t *x, lmmc_itersolve_config_t *out_cfg, lmmc_itersolve_result_t *out_result)
lmmc_status_t lmmc_itersolve_workspace(lmmc_vec_t *const *vectors, const size_t *sizes, size_t count, lmmc_real_t **storage)
所有视图借用求解过程统一分配的存储区,最后一次日志回调后释放。
void lmmc_itersolve_finish(lmmc_itersolve_result_t *result, int converged, size_t iterations, lmmc_real_t norm)
lmmc_status_t lmmc_itersolve_residual(const lmmc_sparse_mat_t *a, const lmmc_vec_t *b, const lmmc_vec_t *x, lmmc_vec_t *ax, lmmc_vec_t *r)
void lmmc_itersolve_initial(lmmc_itersolve_result_t *result, lmmc_real_t norm)
void lmmc_itersolve_do_log(const lmmc_itersolve_config_t *cfg, size_t iter, lmmc_real_t residual_norm)
lmmc_status_t lmmc_bicgstab_solve(const lmmc_sparse_mat_t *a, const lmmc_vec_t *b, const lmmc_precond_t *precond, const lmmc_itersolve_config_t *cfg, lmmc_vec_t *x, lmmc_itersolve_result_t *out_result)
稳定双共轭梯度法(BiCGSTAB)求解一般非对称稀疏系统 A*x = b。
迭代求解器配置。
迭代求解的结果统计。
void lmmc_memory_free(void *pointer)
通用预处理子句柄。
lmmc_status_t lmmc_sparse_mat_vec_mul(const lmmc_sparse_mat_t *sparse, const lmmc_vec_t *x, lmmc_vec_t *y)
稀疏矩阵-稠密向量乘法:y = A * x。
通用稀疏矩阵(CSR / CSC 共用同一结构)。
lmmc_status_t
LMMC 库统一返回的状态码.
@ LMMC_STATUS_OK
@ LMMC_STATUS_NUMERICAL_FAILURE