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