suanPan
ILU.hpp
Go to the documentation of this file.
1/*******************************************************************************
2 * Copyright (C) 2017-2024 Theodore Chang
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 ******************************************************************************/
29// ReSharper disable CppCStyleCast
30#ifndef ILU_HPP
31#define ILU_HPP
32
33#ifndef SUANPAN_SUPERLUMT
34
35#include <superlu-mt/superlu-mt.h>
36#include "Preconditioner.hpp"
37#include "csc_form.hpp"
38#include "triplet_form.hpp"
39
40template<sp_d data_t> class ILU final : public Preconditioner<data_t> {
41 inline static char equed = 'N';
42
43 SuperMatrix A{}, L{}, U{};
44
45 SuperLUStat_t stat{};
46 GlobalLU_t global_setting{};
47 superlu_options_t options{};
48 mem_usage_t usage{};
49
50 void* t_val = nullptr;
51 int* t_row = nullptr;
52 int* t_col = nullptr;
53
54 int* perm_r = nullptr;
55 int* perm_c = nullptr;
56
57 void* scale_r = nullptr;
58 void* scale_c = nullptr;
59
60 int* etree = nullptr;
61
62 static void wrap_b(SuperMatrix*, const Col<data_t>&);
63
64 int apply_solver(SuperMatrix*, SuperMatrix*);
65
66 void apply_row_scale(Col<data_t>&);
67 void apply_column_scale(Col<data_t>&);
68
69 template<sp_i index_t> void allocate(triplet_form<data_t, index_t>&);
70
71public:
72 template<sp_i index_t> explicit ILU(triplet_form<data_t, index_t>&&);
73 template<sp_i index_t> explicit ILU(triplet_form<data_t, index_t>&);
74
75 ~ILU() override;
76
77 int init() override;
78
79 [[nodiscard]] Col<data_t> apply(const Col<data_t>&) override;
80};
81
82template<sp_d data_t> void ILU<data_t>::wrap_b(SuperMatrix* out, const Col<data_t>& in) {
83 if(std::is_same_v<data_t, float>) {
84 using E = float;
85 sCreate_Dense_Matrix(out, (int)in.n_rows, (int)in.n_cols, (E*)in.memptr(), (int)in.n_rows, Stype_t::SLU_DN, Dtype_t::SLU_S, Mtype_t::SLU_GE); // NOLINT(clang-diagnostic-cast-qual)
86 }
87 else {
88 using E = double;
89 dCreate_Dense_Matrix(out, (int)in.n_rows, (int)in.n_cols, (E*)in.memptr(), (int)in.n_rows, Stype_t::SLU_DN, Dtype_t::SLU_D, Mtype_t::SLU_GE); // NOLINT(clang-diagnostic-cast-qual)
90 }
91}
92
93template<sp_d data_t> int ILU<data_t>::apply_solver(SuperMatrix* X, SuperMatrix* B) {
94 int info;
95
96 if(std::is_same_v<data_t, float>) {
97 using E = float;
98 sgsisx(&options, &A, perm_c, perm_r, etree, &equed, (E*)scale_r, (E*)scale_c, &L, &U, nullptr, 0, B, X, nullptr, nullptr, &global_setting, &usage, &stat, &info);
99 }
100 else {
101 using E = double;
102 dgsisx(&options, &A, perm_c, perm_r, etree, &equed, (E*)scale_r, (E*)scale_c, &L, &U, nullptr, 0, B, X, nullptr, nullptr, &global_setting, &usage, &stat, &info);
103 }
104
105 return info;
106}
107
108template<sp_d data_t> void ILU<data_t>::apply_row_scale(Col<data_t>& in_mat) { in_mat %= Col<data_t>((data_t*)scale_r, in_mat.n_elem); }
109
110template<sp_d data_t> void ILU<data_t>::apply_column_scale(Col<data_t>& in_mat) { in_mat %= Col<data_t>((data_t*)scale_c, in_mat.n_elem); }
111
112template<sp_d data_t> template<sp_i index_t> void ILU<data_t>::allocate(triplet_form<data_t, index_t>& triplet_mat) {
113 csc_form<data_t, int> csc_mat(triplet_mat);
114
115 auto t_size = sizeof(data_t) * csc_mat.n_elem;
116 t_val = superlu_malloc(t_size);
117 std::memcpy(t_val, (void*)csc_mat.val_mem(), t_size);
118
119 t_size = sizeof(int) * csc_mat.n_elem;
120 t_row = (int*)superlu_malloc(t_size);
121 std::memcpy(t_row, (void*)csc_mat.row_mem(), t_size);
122
123 t_size = sizeof(int) * (csc_mat.n_cols + 1llu);
124 t_col = (int*)superlu_malloc(t_size);
125 std::memcpy(t_col, (void*)csc_mat.col_mem(), t_size);
126
127 if(std::is_same_v<data_t, float>) {
128 using E = float;
129 sCreate_CompCol_Matrix(&A, csc_mat.n_rows, csc_mat.n_cols, csc_mat.n_elem, (E*)t_val, t_row, t_col, Stype_t::SLU_NC, Dtype_t::SLU_S, Mtype_t::SLU_GE);
130 }
131 else {
132 using E = double;
133 dCreate_CompCol_Matrix(&A, csc_mat.n_rows, csc_mat.n_cols, csc_mat.n_elem, (E*)t_val, t_row, t_col, Stype_t::SLU_NC, Dtype_t::SLU_D, Mtype_t::SLU_GE);
134 }
135
136 perm_r = (int*)superlu_malloc(sizeof(int) * (csc_mat.n_rows + 1llu));
137 perm_c = (int*)superlu_malloc(sizeof(int) * (csc_mat.n_cols + 1llu));
138 scale_r = superlu_malloc(sizeof(data_t) * (csc_mat.n_rows + 1llu));
139 scale_c = superlu_malloc(sizeof(data_t) * (csc_mat.n_cols + 1llu));
140
141 etree = (int*)superlu_malloc(sizeof(int) * (csc_mat.n_cols + 1llu));
142
143 ilu_set_default_options(&options);
144
145 StatInit(&stat);
146}
147
148template<sp_d data_t> template<sp_i index_t> ILU<data_t>::ILU(triplet_form<data_t, index_t>&& triplet_mat)
149 : Preconditioner<data_t>() { this->allocate(triplet_mat); }
150
151template<sp_d data_t> template<sp_i index_t> ILU<data_t>::ILU(triplet_form<data_t, index_t>& triplet_mat)
152 : Preconditioner<data_t>() { this->allocate(triplet_mat); }
153
154template<sp_d data_t> ILU<data_t>::~ILU() {
155 Destroy_SuperMatrix_Store(&A);
156 Destroy_SuperNode_Matrix(&L);
157 Destroy_CompCol_Matrix(&U);
158
159 if(t_val) superlu_free(t_val);
160 if(t_row) superlu_free(t_row);
161 if(t_col) superlu_free(t_col);
162 if(etree) superlu_free(etree);
163 if(perm_r) superlu_free(perm_r);
164 if(perm_c) superlu_free(perm_c);
165 if(scale_r) superlu_free(scale_r);
166 if(scale_c) superlu_free(scale_c);
167}
168
169template<sp_d data_t> int ILU<data_t>::init() {
170 Col<data_t> in(A.ncol, 1, fill::none);
171 Col<data_t> out(A.nrow, 1, fill::none);
172
173 SuperMatrix B, X;
174 this->wrap_b(&X, out);
175 this->wrap_b(&B, in);
176
177 B.ncol = 0;
178
179 if(const auto code = this->apply_solver(&X, &B); 0 != code) {
180 suanpan_error("Error code {} received.\n", code);
181 return SUANPAN_FAIL;
182 }
183
184 Destroy_SuperMatrix_Store(&X);
185 Destroy_SuperMatrix_Store(&B);
186
187 options.Fact = superlu::FACTORED;
188
189 return SUANPAN_SUCCESS;
190}
191
192template<sp_d data_t> Col<data_t> ILU<data_t>::apply(const Col<data_t>& in) {
193 Col<data_t> out(arma::size(in), fill::none);
194
195 SuperMatrix X, B;
196 this->wrap_b(&X, out);
197 this->wrap_b(&B, in);
198
199 this->apply_solver(&X, &B);
200
201 // this->apply_column_scale(out);
202
203 Destroy_SuperMatrix_Store(&X);
204 Destroy_SuperMatrix_Store(&B);
205
206 return out;
207}
208
209#endif
210
211#endif
212
A ILU class.
Definition: ILU.hpp:40
A Preconditioner class.
Definition: Preconditioner.hpp:34
Definition: csc_form.hpp:25
Definition: triplet_form.hpp:62
Col< data_t > apply(const Col< data_t > &) override
Definition: ILU.hpp:192
ILU(triplet_form< data_t, index_t > &&)
Definition: ILU.hpp:148
int init() override
Definition: ILU.hpp:169
~ILU() override
Definition: ILU.hpp:154
void info(const std::string_view format_str, const T &... args)
Definition: suanPan.h:249
constexpr auto SUANPAN_SUCCESS
Definition: suanPan.h:172
constexpr auto SUANPAN_FAIL
Definition: suanPan.h:173
#define suanpan_error(...)
Definition: suanPan.h:309