20#ifndef B2MUMPS_SOLVER_H_
21#define B2MUMPS_SOLVER_H_
25#include "b2sparse_solver.H"
26#include "utils/b2timing.H"
28#ifdef HAVE_UPMUMPS_DMUMPS_C_H
29#include "MUMPS/dmumps_c.h"
31#ifdef HAVE_MUMPS_DMUMPS_C_H
32#include "mumps/dmumps_c.h"
40#ifdef HAVE_UPMUMPS_ZMUMPS_C_H
41#include "MUMPS/zmumps_c.h"
43#ifdef HAVE_MUMPS_ZMUMPS_C_H
44#include "mumps/zmumps_c.h"
52#include "b2blaslapack.H"
53#include "b2linalg_solver_slave.H"
63namespace b2000 {
namespace b2linalg {
70 MUMPS_ErrStream = 1 - 1,
71 MUMPS_DiagStream = 2 - 1,
72 MUMPS_GlobStream = 3 - 1,
73 MUMPS_LogLevel = 4 - 1,
74 MUMPS_MatrixForm = 5 - 1,
75 MUMPS_ZeroFreeScale = 6 - 1,
76 MUMPS_SymPerm = 7 - 1,
77 MUMPS_Scaling = 8 - 1,
78 MUMPS_Transposed = 9 - 1,
79 MUMPS_MaxIterRefine = 10 - 1,
80 MUMPS_ErrStats = 11 - 1,
81 MUMPS_OrdStrategy = 12 - 1,
82 MUMPS_RootParallel = 13 - 1,
83 MUMPS_WsIncrease = 14 - 1,
84 MUMPS_nThreads = 16 - 1,
85 MUMPS_MatrixDist = 18 - 1,
86 MUMPS_SchurComp = 19 - 1,
87 MUMPS_RhsForm = 20 - 1,
88 MUMPS_SolDist = 21 - 1,
90 MUMPS_MaxWorkMem = 23 - 1,
91 MUMPS_NullPivotRows = 24 - 1,
92 MUMPS_Deficient = 25 - 1,
93 MUMPS_SchurPhase = 26 - 1,
94 MUMPS_RhsBlockSize = 27 - 1,
95 MUMPS_SeqOrPar = 28 - 1,
96 MUMPS_ParOrderTool = 29 - 1,
97 MUMPS_Subset = 30 - 1,
98 MUMPS_DiscardFacts = 31 - 1,
99 MUMPS_ForwardInFact = 32 - 1,
100 MUMPS_Determinant = 33 - 1,
101 MUMPS_DelFiles = 34 - 1,
103 MUMPS_BlrVariant = 36 - 1,
104 MUMPS_Compression = 38 - 1,
127 using type = DMUMPS_STRUC_C;
128 using numtype = DMUMPS_REAL;
132 using type = ZMUMPS_STRUC_C;
133 using numtype = mumps_double_complex;
137 using type = ZMUMPS_STRUC_C;
138 using numtype = mumps_double_complex;
166 const int error = info[0];
168 if (!autospc && info[27] > 0) {
169 SingularMatrixError e;
170 e.null_space_size = info[27];
171 e <<
"Numerically singular matrix: " << info[27] <<
" null pivot found\n";
172 e <<
"Note: You may want to reduce the threshold for null pivots\n";
173 e <<
" by adding a mumps_cntl(3) statement to your case definition.\n";
174 e <<
" Try `mumps_cntl '3:1.1e-21'`.\n";
175 e <<
"See the section on the mumps_cntl parameter in the user guide for\n";
176 e <<
"further reference.\n";
179 }
else if (error > 0) {
181 logging ::get_logger(
"linear_algebra.sparse_symmetric_solver.mumps");
183 if (error & 1) { logger <<
"Index (in IRN or JCN) out of range. "; }
185 logger <<
"During error analysis the max-norm of the computed "
186 "solution was found to be zero. ";
189 logger <<
"User data JCN has been modified (internally) by the"
192 if (error & 8) { logger <<
"More than ICNTL(10) iterations refinement are required."; }
193 logger << logging::LOGFLUSH;
196 e <<
"error code " << error <<
": ";
199 e <<
"Matrix is singular in structure.";
202 e <<
"Numerically singular matrix.";
205 e <<
"out of memory error";
208 e <<
"The matrix was indicated to be positive definite but a"
209 " negative or null pivot was encountered";
228template <
typename MUMPS_STRUC_C>
230 std::string icntl = d.get_string(
"MUMPS_ICNTL",
"");
232 std::istringstream iss(icntl);
236 if (iss >> k && iss >> c && iss >> v) {
237 if (c !=
':' || (k < 1 || k > 33)) {
238 Exception() <<
"Cannot parse the MUMPS_ICNTL analysis directive " << icntl
241 if (MUMPS_MatrixForm == k - 1) {
242 Exception() <<
"Not allowed to modify the Matrix form "
243 "(5) in MUMPS_ICNTL: "
246 if (MUMPS_MatrixDist == k - 1) {
247 Exception() <<
"Not allowed to modify the Matrix "
248 "distribution (18) in MUMPS_ICNTL: "
251 mumps_struct.icntl[k - 1] = v;
253 Exception() <<
"Cannot parse the MUMPS_ICNTL analysis directive " << icntl <<
THROW;
258 Exception() <<
"Cannot parse the MUMPS_ICNTL analysis directive " << icntl <<
THROW;
262 std::string cntl = d.get_string(
"MUMPS_CNTL",
"");
264 std::istringstream dss(cntl);
269 if (dss >> k && dss >> c && dss >> v) {
270 if (c !=
':' || (k < 1 || k > 5)) {
271 Exception() <<
"Cannot parse the MUMPS_CNTL analysis directive " << cntl
274 mumps_struct.cntl[k - 1] = v;
276 Exception() <<
"Cannot parse the MUMPS_CNTL analysis directive " << cntl <<
THROW;
281 Exception() <<
"Cannot parse the MUMPS_CNTL analysis directive " << cntl <<
THROW;
293template <
typename MUMPS_STRUC_C>
295 MUMPS_STRUC_C& mumps_struct,
MUMPSACTION action = MUMPSACTION::Continued) {
296 constexpr bool is_dmumps = std::is_same<MUMPS_STRUC_C, DMUMPS_STRUC_C>::value;
297 constexpr unsigned int numtype = is_dmumps ? 0 : 1;
299 unsigned int act =
static_cast<unsigned int>(action);
300 unsigned int sym_job = 1 == act ? mumps_struct.sym : mumps_struct.job;
302 (*mumpstimer).second.start();
303 SolverSlave::MumpsSend(act, numtype, &mumps_struct, sym_job);
304 if constexpr (is_dmumps) {
305 dmumps_c(&mumps_struct);
307 zmumps_c(&mumps_struct);
309 (*mumpstimer).second.stop();
325template <
typename MUMPS_STRUC_C>
327 mumps_struct.sym = sym;
328 mumps_struct.par = 1;
329 mumps_struct.job = -1;
330 mumps_struct.comm_fortran = (MUMPS_INT)SolverSlave::GetFcomm();
333 mumps_struct.irn = 0;
334 mumps_struct.jcn = 0;
338 mumps_struct.icntl[MUMPS_LogLevel] = 3;
339 mumps_struct.icntl[MUMPS_ErrStream] = 6;
340 mumps_struct.icntl[MUMPS_DiagStream] = 6;
341 mumps_struct.icntl[MUMPS_GlobStream] = 6;
342 mumps_struct.icntl[MUMPS_ErrStats] = 1;
344 mumps_struct.icntl[MUMPS_LogLevel] = 0;
345 mumps_struct.icntl[MUMPS_ErrStream] = 0;
346 mumps_struct.icntl[MUMPS_DiagStream] = 0;
347 mumps_struct.icntl[MUMPS_GlobStream] = 0;
357template <
typename MUMPS_STRUC_C>
359 mumps_struct.job = -2;
362 delete[] mumps_struct.irn;
363 delete[] mumps_struct.jcn;
372template <
typename MUMPS_STRUC_C>
377 if (mumps_struct.infog[0] == -8 || mumps_struct.infog[0] == -9) {
378 mumps_struct.icntl[MUMPS_WsIncrease] *= 2;
379 if (4 == mumps_struct.job) { mumps_struct.job = 2; }
380 logger <<
"resolve: work array is too small, increasing size "
381 "of work array and retrying resolution."
382 << logging::LOGFLUSH;
415 const size_t*
const colind,
const size_t*
const rowind,
const T*
const value,
417 autospc = dictionary.
get_bool(
"AUTOSPC",
false);
418 mumps_struct.icntl[MUMPS_NullPivotRows] = 1;
419 mumps_struct.icntl[MUMPS_OOC] = dictionary.
get_bool(
"MUMPS_OOC", 0);
420 mumps_struct.icntl[MUMPS_Scaling] = dictionary.
get_int(
"MUMPS_SCALING", 77);
421 mumps_struct.icntl[MUMPS_MaxIterRefine] =
422 dictionary.
get_int(
"MUMPS_MAX_ITERATIVE_REFINEMENT", 0);
423 mumps_struct.cntl[2] = dictionary.
get_double(
"AUTOSPC_THRESHOLD", 0.0);
424 mumps_struct.cntl[4] = dictionary.
get_double(
"AUTOSPC_VALUE", 0.0);
427 if (mumps_struct.icntl[MUMPS_OOC] != 0) {
428 std::string tmp = dictionary.
get_string(
"MUMPS_OOC_TMPDIR",
"");
430 if (tmp.size() > 255) {
431 Exception() <<
"The MUMPS_OOC_TMPDIR string is limited to 255"
435 strncpy(mumps_struct.ooc_tmpdir, tmp.c_str(), 256);
437 tmp = dictionary.
get_string(
"MUMPS_OOC_PREFIX",
"");
439 if (tmp.size() > 63) {
440 Exception() <<
"The MUMPS_OOC_PREFIX string is limited to 63"
444 strncpy(mumps_struct.ooc_prefix, tmp.c_str(), 64);
448 mumps_struct.job = 4;
450 mumps_struct.nz = nnz;
451 mumps_struct.irn =
new int[nnz];
452 mumps_struct.jcn =
new int[nnz];
453 if (s == 0) {
return; }
454 size_t ptr = colind[0];
455 for (
size_t j = 1; j <= s; ++j) {
456 const size_t ptr_end = colind[j];
457 for (; ptr != ptr_end; ++ptr) {
458 mumps_struct.irn[ptr] = rowind[ptr] + 1;
459 mumps_struct.jcn[ptr] = j;
465 if ((mumps_struct.sym > 0) && (mumps_struct.infog[0] == -6)) {
466 std::vector<bool> dof_nn(s,
false);
467 size_t r = colind[0];
468 for (
size_t j = 0; j != s; ++j) {
469 for (
size_t r_end = colind[j + 1]; r != r_end; ++r) {
470 dof_nn[j] = dof_nn[rowind[r]] = (value[r] != T{0.0});
473 SingularMatrixError e;
474 for (
size_t j = 0; j != s; ++j) {
475 if (!dof_nn[j]) { e.singular_dofs.push_back(j); }
477 e <<
"Matrix is singular in structure. The involved " << e.singular_dofs.size()
478 <<
" dof's can be visualized by means of the DISP_NS dataset." <<
THROW;
505 const T*
const b,
size_t ldb, T*
const x,
size_t ldx) {
506 if (s == 0) {
return; }
507 mumps_.job = updated_value ? 5 : 3;
508 updated_value =
false;
510 if (nrhs == 1 || mumps_.icntl[MUMPS_ErrStats] == 0) {
515 for (
size_t i = 0; i != nrhs; ++i) {
516 std::copy(b + i * ldb, b + i * ldb + s, x + i * ldx);
526 for (
size_t i = 0; i != nrhs; ++i) {
528 if (b != x) { std::copy(b + i * ldb, b + i * ldb + s, x + i * ldx); }
558 size_t s,
size_t nnz,
const size_t* colind,
const size_t* rowind,
const T* value,
559 const int connectivity,
const Dictionary& dictionary)
override {
561 mumps_, autospc, updated_value, s, nnz, colind, rowind, value, dictionary);
564 void update_value()
override { updated_value =
true; }
567 size_t s,
size_t nrhs,
const T* b,
size_t ldb, T* x,
size_t ldx,
568 char left_or_right =
' ')
override {
569 mumps_solve(mumps_, updated_value, autospc, s, nrhs, b, ldb, x, ldx);
572 size_t get_null_space_size()
override {
return mumps_.infog[27]; }
574 void get_null_space(
size_t s,
size_t nv, T* m,
size_t lm)
override {
575 if (s == 0) {
return; }
577 mumps_.job = updated_value ? 5 : 3;
578 updated_value =
false;
579 mumps_.icntl[MUMPS_NullPivotRows] = 1;
580 mumps_.icntl[MUMPS_Deficient] = nv == 1 ? 1 : -1;
581 mumps_.rhs =
reinterpret_cast<B2MUMPS_NUM_t<T>*
>(m);
585 mumps_.icntl[MUMPS_Deficient] = 0;
590 bool updated_value =
false;
591 bool autospc =
false;
592 B2MUMPS_STRUC_t<T> mumps_;
598 :
public LDLt_extension_sparse_solver<T>,
612 size_t size_,
size_t nnz_,
const size_t* colind_,
const size_t* rowind_,
const T* value_,
613 size_t size_ext_,
const int connectivity,
const Dictionary& dictionary)
override {
617 size_, nnz_, colind_, rowind_, value_, connectivity, dictionary);
618 m_ab.resize(size_ * 2);
621 void update_value()
override { MUMPS_LDLt_seq_sparse_direct_solver<T>::update_value(); }
624 size_t s,
size_t nrhs,
const T* b,
size_t ldb, T* x,
size_t ldx,
const T* ma_ = 0,
625 const T* mb_ = 0,
const T* mc_ = 0,
char left_or_right =
' ')
override {
627 std::copy(ma_, ma_ + s - 1, &m_ab[0]);
628 std::copy(mb_, mb_ + s - 1, &m_ab[s - 1]);
629 MUMPS_LDLt_seq_sparse_direct_solver<T>::resolve(
630 s - 1, 2, &m_ab[0], s - 1, &m_ab[0], s - 1);
631 m_div = T{1.0} / (*mc_ - blas::dot(s - 1, ma_, 1, &m_ab[s - 1], 1));
634 for (
size_t i = 0; i != nrhs; ++i) {
635 const T x2 = x[ldx * i + s - 1] =
636 m_div * (b[ldb * i + s - 1] - blas::dot(s - 1, b + ldb * i, 1, &m_ab[s - 1], 1));
637 MUMPS_LDLt_seq_sparse_direct_solver<T>::resolve(
638 s - 1, 1, b + ldb * i, ldb, x + ldx * i, ldx);
639 blas::axpy(s - 1, -x2, &m_ab[0], 1, x + ldx * i, 1);
643 size_t get_null_space_size()
override {
644 return MUMPS_LDLt_seq_sparse_direct_solver<T>::get_null_space_size();
647 void get_null_space(
size_t s,
size_t nv, T* m,
size_t lm)
override {
648 MUMPS_LDLt_seq_sparse_direct_solver<T>::get_null_space(s, nv, m, lm);
672 size_t s,
size_t nnz,
const size_t* colind,
const size_t* rowind,
const T* value,
673 const int connectivity,
const Dictionary& dictionary)
override {
675 mumps_, autospc, updated_value, s, nnz, colind, rowind, value, dictionary);
678 void update_value()
override { updated_value =
true; }
681 size_t s,
size_t nrhs,
const T* b,
size_t ldb, T* x,
size_t ldx,
682 char left_or_right =
' ')
override {
683 mumps_solve(mumps_, updated_value, autospc, s, nrhs, b, ldb, x, ldx);
687 bool updated_value =
false;
688 bool autospc =
false;
689 B2MUMPS_STRUC_t<T> mumps_;
698 size_t size_,
size_t nnz_,
const size_t* colind_,
const size_t* rowind_,
const T* value_,
699 size_t size_ext_,
const int connectivity,
const Dictionary& dictionary)
override {
703 size_, nnz_, colind_, rowind_, value_, connectivity, dictionary);
704 m_ab.resize(size_ * 2);
710 size_t s,
size_t nrhs,
const T* b,
size_t ldb, T* x,
size_t ldx,
const T* ma_ = 0,
711 const T* mb_ = 0,
const T* mc_ = 0,
char left_or_right =
' ')
override {
713 std::copy(ma_, ma_ + s - 1, &m_ab[0]);
714 std::copy(mb_, mb_ + s - 1, &m_ab[s - 1]);
716 s - 1, 2, &m_ab[0], s - 1, &m_ab[0], s - 1);
717 m_div = T{1.0} / (*mc_ - blas::dot(s - 1, ma_, 1, &m_ab[s - 1], 1));
720 for (
size_t i = 0; i != nrhs; ++i) {
721 const T x2 = x[ldx * i + s - 1] =
722 m_div * (b[ldb * i + s - 1] - blas::dot(s - 1, b + ldb * i, 1, &m_ab[s - 1], 1));
724 s - 1, 1, b + ldb * i, s - 1, x + ldx * i, s - 1);
725 blas::axpy(s - 1, -x2, &m_ab[0], 1, x + ldx * i, 1);
#define THROW
Definition b2exception.H:198
MUMPSICNTL
MUMPS control constants for icntl.
Definition b2mumps_solver.H:69
void b2_mumps_init_struct(B2MUMPS_STRUC_t< T > &mumps_struct, bool &autospc, bool &updated, size_t s, size_t nnz, const size_t *const colind, const size_t *const rowind, const T *const value, const Dictionary &dictionary)
Complete the MUMPS interface and define the matrix structure.
Definition b2mumps_solver.H:413
void mumps_solve(B2MUMPS_STRUC_t< T > &mumps_, bool &updated_value, bool autospc, size_t s, size_t nrhs, const T *const b, size_t ldb, T *const x, size_t ldx)
Solving the equation system with MUMPS.
Definition b2mumps_solver.H:503
void b2_mumps_delete(MUMPS_STRUC_C &mumps_struct)
Delete the MUMPS object.
Definition b2mumps_solver.H:358
void mumps_error_handler(const int *const info, bool autospc=false)
Handling errors that may occur during the execution of MUMPS.
Definition b2mumps_solver.H:165
typename B2MUMPS_STRUC< T >::type B2MUMPS_STRUC_t
Convenience alias to refer to the B2MUMPS_STRUC type trait.
Definition b2mumps_solver.H:143
typename B2MUMPS_STRUC< T >::numtype B2MUMPS_NUM_t
Convenience alias to refer to the B2MUMPS_STRUC numtype trait.
Definition b2mumps_solver.H:147
void b2_mumps_call(MUMPS_STRUC_C &mumps_struct, MUMPSACTION action=MUMPSACTION::Continued)
Encapsulate calls to MUMPS.
Definition b2mumps_solver.H:294
MUMPSACTION
Actions to take when running a MUMPS call.
Definition b2mumps_solver.H:111
void decode_mumps_cntl(const Dictionary &d, MUMPS_STRUC_C &mumps_struct)
Decode user configurations for cntl and icntl.
Definition b2mumps_solver.H:229
void b2_mumps_new(MUMPS_STRUC_C &mumps_struct, MUMPS_INT sym)
Initialize a new MUMPS interface structure.
Definition b2mumps_solver.H:326
void b2_mumps_call_wsgrow(MUMPS_STRUC_C &mumps_struct)
Calling MUMPS with MUMPSACTION::Continued and grow its workspace as needed.
Definition b2mumps_solver.H:373
Definition b2dictionary.H:48
virtual bool get_bool(const std::string &key) const =0
virtual std::string get_string(const std::string &key) const =0
virtual double get_double(const std::string &key) const =0
virtual int get_int(const std::string &key) const =0
Definition b2exception.H:131
Implementation of the LDLt extension sparse solver interface with MUMPS.
Definition b2mumps_solver.H:599
MUMPS_LDLt_seq_extension_sparse_direct_solver(bool definit_positive=false)
The constructor creates a new MUMPS interface datastructure.
Definition b2mumps_solver.H:608
Implementation of the LDLt sparse solver interface with MUMPS.
Definition b2mumps_solver.H:541
MUMPS_LDLt_seq_sparse_direct_solver(bool definit_positive=false)
The constructor creates a new MUMPS interface datastructure.
Definition b2mumps_solver.H:550
~MUMPS_LDLt_seq_sparse_direct_solver() override
The destructor instructs MUMPS to close down on all processes.
Definition b2mumps_solver.H:555
Implementation of the LU extension sparse solver interface with MUMPS.
Definition b2mumps_solver.H:695
Implementation of the LU sparse solver interface with MUMPS.
Definition b2mumps_solver.H:662
~MUMPS_LU_seq_sparse_direct_solver() override
The destructor instructs MUMPS to close down on all processes.
Definition b2mumps_solver.H:669
MUMPS_LU_seq_sparse_direct_solver()
Definition b2mumps_solver.H:666
Definition b2logging.H:495
Logger & get_logger(const std::string &logger_name="")
Definition b2logging.H:829
Contains the base classes for implementing Finite Elements.
Definition b2boundary_condition.H:32
timer_map_t::iterator obtain_timer(std::string name)
Definition b2timing.H:139
GenericException< UnimplementedError_name > UnimplementedError
Definition b2exception.H:314
Definition b2mumps_solver.H:123