suanPan
ILU.hpp
Go to the documentation of this file.
1 /*******************************************************************************
2  * Copyright (C) 2017-2023 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 
40 template<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 
71 public:
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 
82 template<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 
93 template<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 
108 template<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 
110 template<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 
112 template<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 
148 template<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 
151 template<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 
154 template<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 
169 template<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 
192 template<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:237
constexpr auto SUANPAN_SUCCESS
Definition: suanPan.h:162
constexpr auto SUANPAN_FAIL
Definition: suanPan.h:163
#define suanpan_error(...)
Definition: suanPan.h:297