37 #if defined(GMM_USES_MUMPS)
39 #ifndef GMM_MUMPS_INTERFACE_H
40 #define GMM_MUMPS_INTERFACE_H
69 struct ij_sparse_matrix {
70 typedef typename number_traits<T>::magnitude_type R;
75 static const std::vector<size_type> no_sel;
78 void build_indices_vector(
const std::vector<size_type> &inp,
79 std::vector<int> &out) {
81 for (
size_type i = 0; i < out.size(); ++i) out[i] =
int(i+1);
83 for (
size_type i = 0; i < inp.size(); ++i) out[inp[i]] =
int(i+1);
90 void build_from(
const L& A, row_major,
91 bool lower_triangular=
false,
92 const std::vector<size_type> &rows=no_sel,
93 const std::vector<size_type> &cols=no_sel) {
94 std::vector<int> row_ind(mat_nrows(A),0), col_ind(mat_nrows(A),0);
95 build_indices_vector(rows, row_ind);
96 build_indices_vector(cols, col_ind);
97 for (
size_type i = 0; i < mat_nrows(A); ++i) {
98 const int ir = row_ind[i];
100 auto row = mat_const_row(A, i);
101 auto it = vect_const_begin(row), ite = vect_const_end(row);
102 for (; it != ite; ++it) {
103 const int jc = col_ind[it.index()];
104 if (jc > 0 && (*it != T(0))
105 && (!lower_triangular || ir >= jc)) {
115 template <
typename L>
116 void build_from(
const L& A, col_major,
117 bool lower_triangular=
false,
118 const std::vector<size_type> &rows=no_sel,
119 const std::vector<size_type> &cols=no_sel) {
120 std::vector<int> row_ind(mat_nrows(A),0), col_ind(mat_nrows(A),0);
121 build_indices_vector(rows, row_ind);
122 build_indices_vector(cols, col_ind);
123 for (
size_type j = 0; j < mat_ncols(A); ++j) {
124 const int jc = col_ind[j];
126 auto col = mat_const_col(A, j);
127 auto it = vect_const_begin(col), ite = vect_const_end(col);
128 for (; it != ite; ++it) {
129 const int ir = row_ind[it.index()];
130 if (ir > 0 && (*it != T(0))
131 && (!lower_triangular || ir >= jc)) {
141 template <
typename L>
142 ij_sparse_matrix(
const L& A,
bool lower_triangular=
false,
143 const std::vector<size_type> &rows=no_sel,
144 const std::vector<size_type> &cols=no_sel)
148 build_from(A,
typename principal_orientation_type
149 <
typename linalg_traits<L>::sub_orientation>
151 lower_triangular, rows, cols);
155 template<
typename T>
const std::vector<size_type>
156 ij_sparse_matrix<T>::no_sel= std::vector<size_type>();
163 template <
typename T>
struct mumps_interf {};
165 template <>
struct mumps_interf<float> {
166 typedef SMUMPS_STRUC_C MUMPS_STRUC_C;
167 typedef float value_type;
169 static void mumps_c(MUMPS_STRUC_C &
id) { smumps_c(&
id); }
172 template <>
struct mumps_interf<double> {
173 typedef DMUMPS_STRUC_C MUMPS_STRUC_C;
174 typedef double value_type;
175 static void mumps_c(MUMPS_STRUC_C &
id) { dmumps_c(&
id); }
178 template <>
struct mumps_interf<std::complex<float> > {
179 typedef CMUMPS_STRUC_C MUMPS_STRUC_C;
180 typedef mumps_complex value_type;
181 static void mumps_c(MUMPS_STRUC_C &
id) { cmumps_c(&
id); }
184 template <>
struct mumps_interf<std::complex<double> > {
185 typedef ZMUMPS_STRUC_C MUMPS_STRUC_C;
186 typedef mumps_double_complex value_type;
187 static void mumps_c(MUMPS_STRUC_C &
id) { zmumps_c(&
id); }
192 mumps_error_check(
int INFO1,
int INFO2) {
196 GMM_ASSERT1(
false,
"Solve with MUMPS failed: NZ = " << INFO2
197 <<
" is out of range");
200 GMM_WARNING1(
"Solve with MUMPS failed: matrix is singular");
203 GMM_ASSERT1(
false,
"Solve with MUMPS failed: error "
204 << INFO1 <<
", increase ICNTL(14)");
207 GMM_ASSERT1(
false,
"Solve with MUMPS failed: not enough memory");
210 GMM_ASSERT1(
false,
"Solve with MUMPS failed with error "
218 template <
typename MUMPS_STRUCT>
219 [[deprecated(
"Use updated error handling mechanism")]]
220 static inline bool mumps_error_check(MUMPS_STRUCT &
id) {
221 return mumps_error_check(
id.info[0],
id.info[1]);
264 template <
typename T>
265 class mumps_context {
266 typedef typename mumps_interf<T>::value_type MUMPS_T;
267 typedef typename number_traits<T>::magnitude_type MUMPS_R;
268 typedef typename mumps_interf<T>::MUMPS_STRUC_C MUMPS_STRUC;
270 std::unique_ptr<ij_sparse_matrix<T> > pK;
271 std::vector<T> rhs_or_sol;
277 inline void run_job(
int job) {
279 mumps_interf<T>::mumps_c(
id);
282 mumps_context(
int sym=0) : id(), rank(0), nrows_(0) {
284 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
289 id.comm_fortran = -987654;
293 ~mumps_context() { run_job(-2); }
295 inline int nrows()
const {
return nrows_; }
296 inline int &ICNTL(
int I) {
return id.icntl[I-1]; }
297 inline MUMPS_R &CNTL(
int I) {
return id.cntl[I-1]; }
298 inline const int &INFO(
int I) {
return id.info[I-1]; }
299 inline const int &INFOG(
int I) {
return id.infog[I-1]; }
300 inline const MUMPS_R &RINFO(
int I) {
return id.rinfo[I-1]; }
301 inline const MUMPS_R &RINFOG(
int I) {
return id.rinfog[I-1]; }
306 template <
typename MAT>
307 inline void set_matrix(
const MAT &K,
bool distributed,
308 const std::vector<size_type> &
309 rows=ij_sparse_matrix<T>::no_sel,
310 const std::vector<size_type> &
311 cols=ij_sparse_matrix<T>::no_sel) {
312 static_assert(std::is_same<
typename linalg_traits<MAT>::value_type,
314 "value_type of MAT and T must be the same");
315 GMM_ASSERT2(gmm::mat_nrows(K) == gmm::mat_ncols(K),
"Non-square matrix");
316 nrows_ = int(gmm::mat_nrows(K));
317 if (!distributed && rank != 0)
320 pK = std::make_unique< ij_sparse_matrix<T> >(K,
id.sym > 0, rows, cols);
322 id.nz_loc = int(pK->irn.size());
323 id.irn_loc = &(pK->irn[0]);
324 id.jcn_loc = &(pK->jcn[0]);
325 id.a_loc = (MUMPS_T*)(&(pK->a[0]));
327 id.nz = int(pK->irn.size());
328 id.irn = &(pK->irn[0]);
329 id.jcn = &(pK->jcn[0]);
330 id.a = (MUMPS_T *)(&(pK->a[0]));
334 template <
typename VEC>
335 inline void set_vector(
const VEC &rhs) {
336 static_assert(std::is_same<
typename linalg_traits<VEC>::value_type,
338 "value_type of MAT and T must be the same");
339 GMM_ASSERT2(nrows() > 0,
340 "System size not defined, need to call set_matrix first.");
341 const int nrhs = int(gmm::vect_size(rhs)/nrows());
342 GMM_ASSERT2(
size_type(nrhs*nrows()) == gmm::vect_size(rhs),
343 "Size of rhs (" << gmm::vect_size(rhs) <<
") must be an "
344 "integer multiple of the matrix size (" <<
id.n <<
")");
345 rhs_or_sol.resize(gmm::vect_size(rhs));
349 id.rhs = (MUMPS_T*)(&rhs_or_sol[0]);
354 const std::vector<T> &vector()
const {
return rhs_or_sol; }
356 inline void analyze() { run_job(1); }
357 inline void factorize() { run_job(2); }
358 inline void analyze_and_factorize() { run_job(4); }
359 inline void solve() { run_job(3); }
360 inline void factorize_and_solve() { run_job(5); }
361 inline void analyze_factorize_and_solve() { run_job(6); }
362 inline bool error_check() {
return mumps_error_check(INFO(1), INFO(2)); }
364 inline void mpi_broadcast() {
366 MPI_Bcast(&(rhs_or_sol[0]),
int(rhs_or_sol.size()),
367 gmm::mpi_type(T()), 0, MPI_COMM_WORLD);
376 template <
typename MAT,
typename VECTX,
typename VECTB>
377 bool MUMPS_solve(
const MAT &A, VECTX &X,
const VECTB &B,
378 bool sym =
false,
bool distributed =
false) {
380 typedef typename linalg_traits<MAT>::value_type T;
384 mumps_context<T> mumps_ctx(sym ? 2 : 0);
385 mumps_ctx.set_matrix(A, distributed);
386 mumps_ctx.set_vector(B);
387 mumps_ctx.ICNTL(1) = -1;
388 mumps_ctx.ICNTL(2) = -1;
389 mumps_ctx.ICNTL(3) = -1;
390 mumps_ctx.ICNTL(4) = 0;
392 mumps_ctx.ICNTL(5) = 0;
393 mumps_ctx.ICNTL(14) += 80;
397 mumps_ctx.ICNTL(18) = 3;
399 mumps_ctx.analyze_factorize_and_solve();
400 ok = mumps_ctx.error_check();
401 mumps_ctx.mpi_broadcast();
411 template <
typename MAT,
typename VECTX,
typename VECTB>
412 bool MUMPS_distributed_matrix_solve(
const MAT &A, VECTX &X_,
413 const VECTB &B,
bool sym=
false) {
414 return MUMPS_solve(A, X_, B, sym,
true);
419 inline T real_or_complex(std::complex<T> a) {
return a.real(); }
421 inline T real_or_complex(T &a) {
return a; }
427 template <typename MAT, typename T=typename linalg_traits<MAT>::value_type>
428 T MUMPS_determinant(
const MAT &A,
int &exponent,
429 bool sym=
false,
bool distributed=
false) {
431 typedef typename number_traits<T>::magnitude_type R;
433 mumps_context<T> mumps_ctx(sym ? 2 : 0);
434 mumps_ctx.set_matrix(A, distributed);
435 mumps_ctx.ICNTL(4) = 0;
437 mumps_ctx.ICNTL(5) = 0;
438 mumps_ctx.ICNTL(14) += 80;
440 mumps_ctx.ICNTL(18) = 3;
441 mumps_ctx.ICNTL(31) = 1;
442 mumps_ctx.ICNTL(33) = 1;
444 mumps_ctx.analyze_and_factorize();
446 T det = real_or_complex(std::complex<R>(mumps_ctx.RINFOG(12),
447 mumps_ctx.RINFOG(13)));
448 exponent = mumps_ctx.INFOG(34);
void copy(const L1 &l1, L2 &l2)
*/
Include the base gmm files.
size_t size_type
used as the common size type in the library