ezp
lightweight C++ wrapper for selected distributed solvers for linear systems
lis.hpp
Go to the documentation of this file.
1 /*******************************************************************************
2  * Copyright (C) 2025-2026 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  ******************************************************************************/
35 #ifndef LIS_HPP
36 #define LIS_HPP
37 
38 #include "abstract/sparse_solver.hpp"
39 
40 #include <mpl/mpl.hpp>
41 
42 using LIS_INT = int_t;
43 using LIS_SCALAR = double;
44 using LIS_REAL = double;
45 using LIS_Comm = MPI_Comm;
46 
48  LIS_INT label;
49  LIS_INT status;
50  LIS_INT precision;
51  LIS_INT gn;
52  LIS_INT n;
53  LIS_INT np;
54  LIS_INT pad;
55  LIS_INT origin;
56  LIS_INT is_copy;
57  LIS_INT is_destroy;
58  LIS_INT is_scaled;
59  LIS_INT my_rank;
60  LIS_INT nprocs;
61  LIS_Comm comm;
62  LIS_INT is;
63  LIS_INT ie;
64  LIS_INT* ranges;
65  LIS_SCALAR* value;
66  LIS_SCALAR* value_lo;
67  LIS_SCALAR* work;
68  LIS_INT intvalue;
69 };
70 
72 
74  LIS_INT nnz;
75  LIS_INT ndz;
76  LIS_INT bnr;
77  LIS_INT bnc;
78  LIS_INT nr;
79  LIS_INT nc;
80  LIS_INT bnnz;
81  LIS_INT nnd;
82  LIS_INT maxnzr;
83  LIS_INT* ptr;
84  LIS_INT* row;
85  LIS_INT* col;
86  LIS_INT* index;
87  LIS_INT* bptr;
88  LIS_INT* bindex;
89  LIS_SCALAR* value;
90  LIS_SCALAR* work;
91 };
92 
94 
96  LIS_INT label;
97  LIS_INT status;
98  LIS_INT precision;
99  LIS_INT gn;
100  LIS_INT n;
101  LIS_INT np;
102  LIS_INT pad;
103  LIS_INT origin;
104  LIS_INT is_copy;
105  LIS_INT is_destroy;
106  LIS_INT is_scaled;
107  LIS_INT my_rank;
108  LIS_INT nprocs;
109  LIS_Comm comm;
110  LIS_INT is;
111  LIS_INT ie;
112  LIS_INT* ranges;
113  LIS_SCALAR* value;
114  LIS_SCALAR* work;
115 
116  LIS_INT bn;
117  LIS_INT nr;
118  LIS_INT* bns;
119  LIS_INT* ptr;
120  LIS_SCALAR** v_value;
121 };
122 
124 
126  LIS_Comm comm;
127  LIS_INT pad;
128  LIS_INT neibpetot;
129  LIS_INT imnnz;
130  LIS_INT exnnz;
131  LIS_INT wssize;
132  LIS_INT wrsize;
133  LIS_INT* neibpe;
134  LIS_INT* import_ptr;
135  LIS_INT* import_index;
136  LIS_INT* export_ptr;
137  LIS_INT* export_index;
138  LIS_SCALAR* ws;
139  LIS_SCALAR* wr;
140  MPI_Request *req1, *req2;
141  MPI_Status *sta1, *sta2;
142 };
143 
145 
147  LIS_INT label;
148  LIS_INT status;
149  LIS_INT precision;
150  LIS_INT gn;
151  LIS_INT n;
152  LIS_INT np;
153  LIS_INT pad;
154  LIS_INT origin;
155  LIS_INT is_copy;
156  LIS_INT is_destroy;
157  LIS_INT is_scaled;
158  LIS_INT my_rank;
159  LIS_INT nprocs;
160  LIS_Comm comm;
161  LIS_INT is;
162  LIS_INT ie;
163  LIS_INT* ranges;
164 
165  LIS_INT matrix_type;
166  LIS_INT nnz; /* CSR,CSC,MSR,JAD,VBR,COO */
167  LIS_INT ndz; /* MSR */
168  LIS_INT bnr; /* BSR,BSC */
169  LIS_INT bnc; /* BSR,BSC */
170  LIS_INT nr; /* BSR,BSC,VBR */
171  LIS_INT nc; /* BSR,BSC,VBR */
172  LIS_INT bnnz; /* BSR,BSC,VBR */
173  LIS_INT nnd; /* DIA */
174  LIS_INT maxnzr; /* ELL,JAD */
175  LIS_INT* ptr; /* CSR,CSC,JAD */
176  LIS_INT* row; /* JAD,VBR,COO */
177  LIS_INT* col; /* JAD,VBR,COO */
178  LIS_INT* index; /* CSR,CSC,MSR,DIA,ELL,JAD */
179  LIS_INT* bptr; /* BSR,BSC,VBR */
180  LIS_INT* bindex; /* BSR,BSC,VBR */
181  LIS_SCALAR* value; /* CSR,CSC,MSR,DIA,ELL,JAD,BSR,BSC,VBR,DNS,COO */
182  LIS_SCALAR* work;
183 
184  LIS_MATRIX_CORE L;
185  LIS_MATRIX_CORE U;
186  LIS_MATRIX_DIAG D;
187  LIS_MATRIX_DIAG WD;
188 
189  LIS_INT is_block;
190  LIS_INT pad_comm;
191  LIS_INT is_pmat;
192  LIS_INT is_sorted;
193  LIS_INT is_splited;
194  LIS_INT is_save;
195  LIS_INT is_comm;
196  LIS_INT is_fallocated;
197  LIS_INT use_wd;
198  LIS_INT conv_bnr;
199  LIS_INT conv_bnc;
200  LIS_INT* conv_row;
201  LIS_INT* conv_col;
202  LIS_INT options[10];
203 
204  LIS_INT w_annz;
205  LIS_INT* w_nnz;
206  LIS_INT* w_row;
207  LIS_INT** w_index;
208  LIS_SCALAR** w_value;
209  LIS_SCALAR*** v_value;
210 
211  LIS_INT* l2g_map;
212  LIS_COMMTABLE commtable;
213 };
214 
216 
218  LIS_INT n;
219  LIS_INT bs;
220  LIS_INT* nnz_ma;
221  LIS_INT* nnz;
222  LIS_INT* bsz;
223  LIS_INT** index;
224  LIS_SCALAR** value;
225  LIS_SCALAR*** values;
226 };
227 
229 
231  LIS_INT precon_type;
232  LIS_MATRIX A; /* SSOR */
233  LIS_MATRIX Ah;
234  LIS_MATRIX_ILU L; /* ilu(k),ilut,iluc,sainv */
235  LIS_MATRIX_ILU U; /* ilu(k),ilut,iluc,sainv */
236  LIS_MATRIX_DIAG WD; /* bilu(k),bilut,biluc,bjacobi */
237  LIS_VECTOR D; /* ilu(k),ilut,iluc,jacobi,sainv */
238  LIS_VECTOR Pb; /* i+s */
239  LIS_VECTOR temp; /* saamg */
240  LIS_REAL theta; /* saamg */
241  LIS_VECTOR* work; /* adds */
242  struct LIS_SOLVER_STRUCT* solver; /* hybrid */
243  LIS_INT worklen; /* adds */
244  LIS_INT level_num; /* saamg */
245  LIS_INT wsize; /* saamg */
246  LIS_INT solver_comm; /* saamg */
247  LIS_INT my_rank; /* saamg */
248  LIS_INT nprocs; /* saamg */
249  LIS_INT is_copy;
250  LIS_COMMTABLE commtable; /* saamg */
251 };
252 
254 
256  LIS_MATRIX A, Ah;
257  LIS_VECTOR b, x, xx, d;
258  LIS_MATRIX_DIAG WD;
259  LIS_PRECON precon;
260  LIS_VECTOR* work;
261  LIS_REAL* rhistory;
262  LIS_INT worklen;
263  LIS_INT options[27];
264  LIS_SCALAR params[15];
265  LIS_INT retcode;
266  LIS_INT iter;
267  LIS_INT iter2;
268  LIS_REAL resid;
269  double time;
270  double itime;
271  double ptime;
272  double p_c_time;
273  double p_i_time;
274  LIS_INT precision;
275  LIS_REAL bnrm;
276  LIS_REAL tol;
277  LIS_REAL tol_switch;
278  LIS_INT setup;
279 };
280 
282 
283 extern "C" {
284 LIS_INT lis_finalize(void);
285 LIS_INT lis_initialize(int* argc, char** argv[]);
286 LIS_INT lis_matrix_assemble(LIS_MATRIX A);
287 LIS_INT lis_matrix_create(LIS_Comm comm, LIS_MATRIX* Amat);
288 LIS_INT lis_matrix_destroy(LIS_MATRIX Amat);
289 LIS_INT lis_matrix_set_csr(LIS_INT nnz, LIS_INT* row, LIS_INT* index, LIS_SCALAR* value, LIS_MATRIX A);
290 LIS_INT lis_matrix_set_size(LIS_MATRIX A, LIS_INT local_n, LIS_INT global_n);
291 LIS_INT lis_matrix_unset(LIS_MATRIX A);
292 LIS_INT lis_solve(LIS_MATRIX A, LIS_VECTOR b, LIS_VECTOR x, LIS_SOLVER solver);
293 LIS_INT lis_solver_create(LIS_SOLVER* solver);
294 LIS_INT lis_solver_destroy(LIS_SOLVER solver);
295 LIS_INT lis_solver_set_option(const char* text, LIS_SOLVER solver);
296 LIS_INT lis_vector_create(LIS_Comm comm, LIS_VECTOR* vec);
297 LIS_INT lis_vector_destroy(LIS_VECTOR vec);
298 LIS_INT lis_vector_set_size(LIS_VECTOR vec, LIS_INT local_n, LIS_INT global_n);
299 LIS_INT lis_vector_set(LIS_VECTOR vec, LIS_SCALAR* value);
300 LIS_INT lis_vector_unset(LIS_VECTOR vec);
301 void lis_do_not_handle_mpi();
302 }
303 
304 namespace ezp {
305  namespace detail {
306  struct lis_env {
307  const mpl::communicator& comm_world{mpl::environment::comm_world()};
308 
309  lis_env() {
310  lis_do_not_handle_mpi();
311  lis_initialize(nullptr, nullptr);
312  }
313  ~lis_env() { lis_finalize(); }
314 
315  [[nodiscard]] auto rank() const { return comm_world.rank(); }
316 
317  [[nodiscard]] auto native_handle() const { return comm_world.native_handle(); }
318  };
319 
320  inline auto& get_lis_env() {
321  static const lis_env env;
322  return env;
323  }
324 
325  class lis_matrix final {
326  LIS_MATRIX a_mat{};
327 
328  bool is_set = false;
329 
330  auto unset() {
331  if(is_set) lis_matrix_unset(a_mat);
332  lis_matrix_destroy(a_mat);
333  is_set = false;
334  }
335 
336  auto create() { return lis_matrix_create(get_lis_env().native_handle(), &a_mat); }
337 
338  public:
339  lis_matrix() { create(); }
340 
341  lis_matrix(const lis_matrix&)
342  : lis_matrix() {}
343  lis_matrix(lis_matrix&&) = delete;
344  lis_matrix& operator=(const lis_matrix&) = delete;
345  lis_matrix& operator=(lis_matrix&&) = delete;
346 
347  ~lis_matrix() { unset(); }
348 
349  explicit lis_matrix(const sparse_csr_mat<LIS_SCALAR, LIS_INT>& A) { set(A); }
350 
351  [[nodiscard]] auto get() const { return a_mat; }
352 
353  void set(const sparse_csr_mat<LIS_SCALAR, LIS_INT>& A) {
354  unset();
355  create();
356  const bool is_root = 0 == get_lis_env().rank();
357  lis_matrix_set_size(a_mat, is_root ? A.n : 0, 0);
358  lis_matrix_set_csr(is_root ? A.nnz : 0, A.row_ptr, A.col_idx, A.data, a_mat);
359  lis_matrix_assemble(a_mat);
360  is_set = true;
361  }
362  };
363 
364  class lis_vector final {
365  LIS_VECTOR v{};
366 
367  bool is_set = false;
368 
369  auto unset() {
370  if(is_set) lis_vector_unset(v);
371  is_set = false;
372  }
373 
374  public:
375  explicit lis_vector(const LIS_INT n = 0) {
376  lis_vector_create(get_lis_env().native_handle(), &v);
377  if(n > 0) lis_vector_set_size(v, 0 == get_lis_env().rank() ? n : 0, 0);
378  }
379 
380  lis_vector(const lis_vector&) = delete;
381  lis_vector(lis_vector&&) = delete;
382  lis_vector& operator=(const lis_vector&) = delete;
383  lis_vector& operator=(lis_vector&&) = delete;
384 
385  ~lis_vector() {
386  unset();
387  lis_vector_destroy(v);
388  }
389 
390  [[nodiscard]] auto get() const { return v; }
391 
392  auto& set(LIS_SCALAR* value) {
393  unset();
394  is_set = true;
395  lis_vector_set(v, 0 == get_lis_env().rank() ? value : nullptr);
396  return *this;
397  }
398  };
399 
400  class lis_solver final {
401  LIS_SOLVER solver{};
402 
403  public:
404  lis_solver() { lis_solver_create(&solver); }
405 
406  lis_solver(const lis_solver&)
407  : lis_solver() {};
408  lis_solver(lis_solver&&) = delete;
409  lis_solver& operator=(const lis_solver&) = delete;
410  lis_solver& operator=(lis_solver&&) = delete;
411 
412  ~lis_solver() { lis_solver_destroy(solver); }
413 
414  explicit lis_solver(const std::string_view setting)
415  : lis_solver() { set_option(setting); }
416 
417  void set_option(const std::string_view setting) const { lis_solver_set_option(setting.data(), solver); }
418 
419  auto solve(const lis_matrix& A, const lis_vector& B, const lis_vector& X) const { return lis_solve(A.get(), B.get(), X.get(), solver); }
420  };
421 
422  class lis_base {
423  protected:
424  const detail::lis_env& env = detail::get_lis_env();
425 
426  [[nodiscard]] auto sync_error(LIS_INT error) const {
427  env.comm_world.allreduce(mpl::min<LIS_INT>(), error);
428  return error;
429  }
430 
431  public:
432  lis_base() = default;
433  };
434  } // namespace detail
435 
436  class lis final : public detail::lis_base {
437  detail::lis_solver solver;
438  detail::lis_matrix a_loc;
439 
440  public:
441  lis() = default;
442 
443  explicit lis(const std::string_view setting)
444  : solver(setting) {}
445 
446  void set_option(const std::string_view setting) const { solver.set_option(setting); }
447 
449  a_loc.set(std::move(A));
450 
451  return solve(std::move(B));
452  }
453 
454  LIS_INT solve(full_mat<LIS_SCALAR, LIS_INT>&& B) const {
455  if(a_loc.get()->gn != B.n_rows) return -1;
456 
457  LIS_INT error = 0;
458 
459  std::vector<LIS_SCALAR> b_ref;
460  if(0 == env.rank()) {
461  b_ref.resize(B.n_rows * B.n_cols);
462  std::copy_n(B.data, b_ref.size(), b_ref.data());
463  }
464 
465  detail::lis_vector b_loc{B.n_rows}, x_loc{B.n_rows};
466 
467  for(decltype(B.n_rows) I = 0; I < B.n_rows * B.n_cols; I += B.n_rows) {
468  error = solver.solve(a_loc, b_loc.set(b_ref.data() + I), x_loc.set(B.data + I));
469 
470  if(0 != error) break;
471  }
472 
473  return error;
474  }
475  };
476 } // namespace ezp
477 
478 #endif
479 
Definition: lis.hpp:422
Definition: lis.hpp:325
Definition: lis.hpp:400
Definition: lis.hpp:364
Definition: lis.hpp:436
Definition: lis.hpp:125
Definition: lis.hpp:73
Definition: lis.hpp:95
Definition: lis.hpp:217
Definition: lis.hpp:146
Definition: lis.hpp:230
Definition: lis.hpp:255
Definition: lis.hpp:47
Definition: lis.hpp:306
Definition: traits.hpp:85
Definition: sparse_solver.hpp:69