LMMC
Lamina Mathematic core
载入中...
搜索中...
未找到
precond_ilu0.c
浏览该文件的文档.
1#include "precond_internal.h"
2
3static lmmc_status_t lmmc_ilu0_clone(const lmmc_sparse_mat_t* a,
5 size_t idx_bytes, val_bytes;
6 if (!lmmc_safe_mul_size(a->nnz, sizeof(size_t), &idx_bytes) ||
7 !lmmc_safe_mul_size(a->nnz, sizeof(lmmc_real_t), &val_bytes)) {
9 }
10 lmmc_precond_ilu_impl_t* impl = NULL;
12 if (st != LMMC_STATUS_OK) {
13 return st;
14 }
15 impl->nnz = impl->capacity = a->nnz;
16 if (a->nnz > 0) {
17 impl->col_idx = lmmc_memory_alloc(idx_bytes);
18 impl->lu_values = lmmc_memory_alloc(val_bytes);
19 if (impl->col_idx == NULL || impl->lu_values == NULL) {
22 }
23 memcpy(impl->col_idx, a->col_idx, idx_bytes);
24 memcpy(impl->lu_values, a->values, val_bytes);
25 }
26 memcpy(impl->row_ptr, a->row_ptr, (a->rows + 1) * sizeof(size_t));
27 *out = impl;
28 return LMMC_STATUS_OK;
29}
30
31static lmmc_status_t lmmc_ilu0_diagonals(lmmc_precond_ilu_impl_t* impl) {
32 for (size_t i = 0; i < impl->size; ++i) {
33 impl->diag_pos[i] = (size_t)-1;
34 if (!lmmc_find_col_pos(impl->col_idx, impl->row_ptr[i],
35 impl->row_ptr[i + 1], i, &impl->diag_pos[i])) {
37 }
38 }
39 return LMMC_STATUS_OK;
40}
41
43static lmmc_real_t lmmc_ilu0_entry_sum(const lmmc_precond_ilu_impl_t* impl,
44 size_t i, size_t p, size_t limit) {
45 const size_t j = impl->col_idx[p];
46 lmmc_real_t sum = impl->lu_values[p];
47 for (size_t q = impl->row_ptr[i]; q < impl->row_ptr[i + 1]; ++q) {
48 size_t k = impl->col_idx[q];
49 size_t pos;
50 if (k >= limit) {
51 continue;
52 }
53 if (lmmc_find_col_pos(impl->col_idx, impl->row_ptr[k],
54 impl->row_ptr[k + 1], j, &pos)) {
55 lmmc_real_t product = impl->lu_values[q] * impl->lu_values[pos];
56 sum = sum - product;
57 }
58 }
59 return sum;
60}
61
62static lmmc_status_t lmmc_ilu0_lower(lmmc_precond_ilu_impl_t* impl, size_t i) {
63 for (size_t p = impl->row_ptr[i]; p < impl->row_ptr[i + 1]; ++p) {
64 size_t j = impl->col_idx[p];
65 if (j >= i) {
66 continue;
67 }
68 lmmc_real_t sum = lmmc_ilu0_entry_sum(impl, i, p, j);
69 lmmc_real_t diag = impl->lu_values[impl->diag_pos[j]];
70 if (!isfinite(sum) || !isfinite(diag) || fabs(diag) <= 1e-15) {
72 }
73 impl->lu_values[p] = sum / diag;
74 if (!isfinite(impl->lu_values[p])) {
76 }
77 }
78 return LMMC_STATUS_OK;
79}
80
81static lmmc_status_t lmmc_ilu0_upper(lmmc_precond_ilu_impl_t* impl, size_t i) {
82 for (size_t p = impl->row_ptr[i]; p < impl->row_ptr[i + 1]; ++p) {
83 if (impl->col_idx[p] < i) {
84 continue;
85 }
86 lmmc_real_t sum = lmmc_ilu0_entry_sum(impl, i, p, i);
87 if (!isfinite(sum)) {
89 }
90 impl->lu_values[p] = sum;
91 }
92 lmmc_real_t diag = impl->lu_values[impl->diag_pos[i]];
93 if (!isfinite(diag) || fabs(diag) <= 1e-15) {
95 }
96 return LMMC_STATUS_OK;
97}
98
100 lmmc_precond_t* out_precond) {
101 lmmc_status_t st = lmmc_sparse_validate(a);
102 if (out_precond == NULL || st != LMMC_STATUS_OK || a->format != LMMC_SPARSE_CSR) {
104 }
105 if (a->rows != a->cols) {
107 }
108 lmmc_precond_ilu_impl_t* impl = NULL;
109 st = lmmc_ilu0_clone(a, &impl);
110 if (st != LMMC_STATUS_OK) {
111 return st;
112 }
113 st = lmmc_ilu0_diagonals(impl);
114 if (st != LMMC_STATUS_OK) {
115 goto fail;
116 }
117 for (size_t i = 0; i < a->rows; ++i) {
118 st = lmmc_ilu0_lower(impl, i);
119 if (st != LMMC_STATUS_OK) {
120 goto fail;
121 }
122 st = lmmc_ilu0_upper(impl, i);
123 if (st != LMMC_STATUS_OK) {
124 goto fail;
125 }
126 }
127 out_precond->type = LMMC_PRECOND_ILU0;
128 out_precond->size = a->rows;
129 out_precond->impl = impl;
130 out_precond->owns_data = 1;
131 return LMMC_STATUS_OK;
132fail:
134 return st;
135}
double lmmc_real_t
Public and internal LMMC real type.
void * lmmc_memory_alloc(size_t size)
lmmc_precond_type_t type
lmmc_status_t lmmc_precond_create_ilu0(const lmmc_sparse_mat_t *a, lmmc_precond_t *out_precond)
创建 ILU(0) 预处理子(零填充不完全 LU 分解)。
@ LMMC_PRECOND_ILU0
通用预处理子句柄。
lmmc_status_t lmmc_ilu_impl_create(size_t size, lmmc_precond_ilu_impl_t **out)
void lmmc_ilu_impl_destroy(lmmc_precond_ilu_impl_t *impl)
int lmmc_find_col_pos(const size_t *cols, size_t start, size_t end, size_t col, size_t *pos)
@ LMMC_SPARSE_CSR
lmmc_sparse_format_t format
通用稀疏矩阵(CSR / CSC 共用同一结构)。
lmmc_status_t
LMMC 库统一返回的状态码.
@ LMMC_STATUS_OK
@ LMMC_STATUS_NUMERICAL_FAILURE
@ LMMC_STATUS_DIMENSION_MISMATCH
@ LMMC_STATUS_ALLOCATION_FAILED
@ LMMC_STATUS_SINGULAR_MATRIX
@ LMMC_STATUS_INVALID_ARGUMENT