LMMC
Lamina Mathematic core
载入中...
搜索中...
未找到
itersolve_gmres_support.c
浏览该文件的文档.
2
3static lmmc_vec_t lmmc_gmres_view(size_t n, lmmc_real_t** next) {
4 lmmc_vec_t view = {n, *next, 0};
5 *next += n;
6 return view;
7}
8
9static lmmc_status_t lmmc_gmres_scalar_count(size_t n, size_t restart,
10 size_t* h_count, size_t* scalar_count) {
11 size_t basis_count, vector_count, rotations;
12 if (!lmmc_safe_add_size(restart, 1, &basis_count) ||
13 !lmmc_safe_mul_size(basis_count, restart, h_count)) {
15 }
16 if (!lmmc_safe_add_size(basis_count, 6, &vector_count) ||
17 !lmmc_safe_mul_size(vector_count, n, scalar_count)) {
19 }
20 if (!lmmc_safe_mul_size(restart, 4, &rotations) ||
21 !lmmc_safe_add_size(rotations, 1, &rotations)) {
23 }
24 if (!lmmc_safe_add_size(*scalar_count, *h_count, scalar_count) ||
25 !lmmc_safe_add_size(*scalar_count, rotations, scalar_count)) {
27 }
28 return LMMC_STATUS_OK;
29}
30
31static lmmc_status_t lmmc_gmres_allocation_bytes(size_t basis_count,
32 size_t scalar_count, size_t* metadata, size_t* bytes) {
33 if (!lmmc_safe_mul_size(basis_count, sizeof(lmmc_vec_t), metadata)) {
35 }
36 const size_t alignment = _Alignof(lmmc_real_t);
37 size_t padding = (alignment - *metadata % alignment) % alignment;
38 if (!lmmc_safe_add_size(*metadata, padding, metadata) ||
39 !lmmc_safe_mul_size(scalar_count, sizeof(lmmc_real_t), bytes) ||
40 !lmmc_safe_add_size(*metadata, *bytes, bytes)) {
42 }
43 return LMMC_STATUS_OK;
44}
45
46lmmc_status_t lmmc_gmres_workspace(size_t n, size_t restart,
48 size_t scalar_count, bytes, metadata;
49 s->restart = restart == 0 ? (n < 30 ? n : 30) : restart;
50 if (s->restart > n) {
51 s->restart = n;
52 }
53 if (s->restart == 0) {
55 }
56 lmmc_status_t st = lmmc_gmres_scalar_count(n, s->restart, &s->h_count, &scalar_count);
57 if (st != LMMC_STATUS_OK) {
58 return st;
59 }
60 size_t basis_count = s->restart + 1;
61 st = lmmc_gmres_allocation_bytes(basis_count, scalar_count, &metadata, &bytes);
62 if (st != LMMC_STATUS_OK) {
63 return st;
64 }
65 s->basis = lmmc_memory_alloc(bytes);
66 if (s->basis == NULL) {
68 }
69 memset(s->basis, 0, bytes);
70 lmmc_real_t* next = (lmmc_real_t*)((unsigned char*)s->basis + metadata);
71 s->r = lmmc_gmres_view(n, &next);
72 s->z = lmmc_gmres_view(n, &next);
73 s->w = lmmc_gmres_view(n, &next);
74 s->ax = lmmc_gmres_view(n, &next);
75 s->x_base = lmmc_gmres_view(n, &next);
76 s->x_trial = lmmc_gmres_view(n, &next);
77 for (size_t i = 0; i < basis_count; ++i) {
78 s->basis[i] = lmmc_gmres_view(n, &next);
79 }
80 s->h = next;
81 next += s->h_count;
82 s->cs = next;
83 next += s->restart;
84 s->sn = next;
85 next += s->restart;
86 s->g = next;
87 next += basis_count;
88 s->y = next;
89 return LMMC_STATUS_OK;
90}
91
93 const lmmc_precond_t* precond, lmmc_gmres_state_t* s,
94 size_t j, lmmc_real_t* h_next) {
95 lmmc_status_t st = lmmc_sparse_mat_vec_mul(a, &s->basis[j], &s->ax);
96 if (st != LMMC_STATUS_OK) {
97 return st;
98 }
99 st = lmmc_apply_precond_or_identity(precond, &s->ax, &s->w);
100 if (st != LMMC_STATUS_OK) {
101 return st;
102 }
103 for (size_t i = 0; i <= j; ++i) {
104 lmmc_real_t hij;
105 st = lmmc_vec_dot_checked(&s->basis[i], &s->w, &hij);
106 if (st != LMMC_STATUS_OK) {
107 return st;
108 }
109 s->h[i * s->restart + j] = hij;
110 st = lmmc_vec_axpy(-hij, &s->basis[i], &s->w);
111 if (st != LMMC_STATUS_OK) {
112 return st;
113 }
114 }
115 st = lmmc_vec_norm2_checked(&s->w, h_next);
116 if (st == LMMC_STATUS_OK) {
117 s->h[(j + 1) * s->restart + j] = *h_next;
118 }
119 return st;
120}
121
122static void lmmc_gmres_previous_rotations(lmmc_gmres_state_t* s, size_t j) {
123 for (size_t i = 0; i < j; ++i) {
124 lmmc_real_t h0 = s->h[i * s->restart + j];
125 lmmc_real_t h1 = s->h[(i + 1) * s->restart + j];
126 lmmc_real_t first = s->cs[i] * h0;
127 lmmc_real_t second = s->sn[i] * h1;
128 s->h[i * s->restart + j] = first + second;
129 first = -s->sn[i] * h0;
130 second = s->cs[i] * h1;
131 s->h[(i + 1) * s->restart + j] = first + second;
132 }
133}
134
136 *breakdown = 0;
137 lmmc_gmres_previous_rotations(s, j);
138 lmmc_real_t hj = s->h[j * s->restart + j];
139 lmmc_real_t hsub = s->h[(j + 1) * s->restart + j];
140 lmmc_real_t first = hj * hj;
141 lmmc_real_t second = hsub * hsub;
142 lmmc_real_t denom = sqrt(first + second);
143 if (!isfinite(denom)) {
145 }
146 if (denom <= 1e-30) {
147 *breakdown = 1;
148 return LMMC_STATUS_OK;
149 }
150 s->cs[j] = hj / denom;
151 s->sn[j] = hsub / denom;
152 if (!isfinite(s->cs[j]) || !isfinite(s->sn[j])) {
154 }
155 first = s->cs[j] * hj;
156 second = s->sn[j] * hsub;
157 s->h[j * s->restart + j] = first + second;
158 s->h[(j + 1) * s->restart + j] = 0.0;
159 lmmc_real_t gtmp = s->cs[j] * s->g[j];
160 s->g[j + 1] = -s->sn[j] * s->g[j];
161 s->g[j] = gtmp;
162 return LMMC_STATUS_OK;
163}
164
166 for (size_t ii = dim; ii > 0; --ii) {
167 size_t i = ii - 1;
168 lmmc_real_t sum = s->g[i];
169 for (size_t j = i + 1; j < dim; ++j) {
170 lmmc_real_t product = s->h[i * s->restart + j] * s->y[j];
171 sum = sum - product;
172 }
173 lmmc_real_t diag = s->h[i * s->restart + i];
174 if (!isfinite(sum) || !isfinite(diag) || fabs(diag) <= 1e-30) {
176 }
177 s->y[i] = sum / diag;
178 if (!isfinite(s->y[i])) {
180 }
181 }
182 return LMMC_STATUS_OK;
183}
184
186 for (size_t i = 0; i < s->x_base.size; ++i) {
187 lmmc_real_t val = s->x_base.data[i];
188 for (size_t k = 0; k <= j; ++k) {
189 lmmc_real_t product = s->y[k] * s->basis[k].data[i];
190 val = val + product;
191 }
192 if (!isfinite(val)) {
194 }
195 s->x_trial.data[i] = val;
196 }
197 return LMMC_STATUS_OK;
198}
199
201 const lmmc_vec_t* in, lmmc_real_t norm) {
202 for (size_t i = 0; i < out->size; ++i) {
203 out->data[i] = in->data[i] / norm;
204 if (!isfinite(out->data[i])) {
206 }
207 }
208 return LMMC_STATUS_OK;
209}
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_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_apply_precond_or_identity(const lmmc_precond_t *precond, const lmmc_vec_t *rhs, lmmc_vec_t *out)
lmmc_status_t lmmc_gmres_trial(lmmc_gmres_state_t *s, size_t j)
lmmc_status_t lmmc_gmres_normalize(lmmc_vec_t *out, const lmmc_vec_t *in, lmmc_real_t norm)
lmmc_status_t lmmc_gmres_workspace(size_t n, size_t restart, lmmc_gmres_state_t *s)
lmmc_status_t lmmc_gmres_arnoldi(const lmmc_sparse_mat_t *a, const lmmc_precond_t *precond, lmmc_gmres_state_t *s, size_t j, lmmc_real_t *h_next)
lmmc_status_t lmmc_gmres_back_substitute(lmmc_gmres_state_t *s, size_t dim)
lmmc_status_t lmmc_gmres_rotate(lmmc_gmres_state_t *s, size_t j, int *breakdown)
void * lmmc_memory_alloc(size_t size)
通用预处理子句柄。
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
@ LMMC_STATUS_ALLOCATION_FAILED
@ LMMC_STATUS_INVALID_ARGUMENT