solver_option.cc
Go to the documentation of this file.
// direct solver interface
//
#include "rheolef/solver_option.h"
#include <unordered_set>
namespace rheolef {
// -----------------------------------------------------------------------------
// default preferred direct solver library manager
// -----------------------------------------------------------------------------
// rule:
// 1) when distributed: only mumps
// 2) otherwise:
// 2a) when symmetry: eigen, mumps, cholmod(sdp)
// 2b) when no-symmetry: umfpack, mumps, eigen
// TODO: check stokes with eigen for indefinite sym pbs !
// --------------------------------------------------------------------------
// mumps note: for best performance in both distributed and sequential modes
// mumps requires to be compiled with a good numbering library (scotch or metis)
// such as within the libdmumps_scotch debian package
std::string
solver_option::_default_preferred_library (size_t dis_ext_nnz, bool is_sym, bool is_dp)
{
// for a given matrix a:
// dis_ext_nnz = number of non-block diagonal coefs on distributed matrix
// = 0 in sequential mode or block-diagonal matrix
// sequential libraries are not able to manage dis_ext_nnz != 0
if (dis_ext_nnz != 0) {
return "mumps"; // yet, the only supported distributed direct solver
}
// here, we can use some sequential libs, depending on the configuration:
#if defined(_RHEOLEF_HAVE_MUMPS)
#if defined(_RHEOLEF_HAVE_MUMPS_WITH_METIS) || \
defined(_RHEOLEF_HAVE_MUMPS_WITH_PARMETIS) || \
defined(_RHEOLEF_HAVE_MUMPS_WITH_SCOTCH) || \
defined(_RHEOLEF_HAVE_MUMPS_WITH_PTSCOTCH)
constexpr bool have_mumps_scotch = true,
have_mumps_no_scotch = false;
#else
constexpr bool have_mumps_scotch = false,
have_mumps_no_scotch = true;
#endif
#else
constexpr bool have_mumps_scotch = false,
have_mumps_no_scotch = false;
#endif
constexpr bool have_mumps = have_mumps_scotch || have_mumps_no_scotch;
#ifdef _RHEOLEF_HAVE_CHOLMOD
constexpr bool have_cholmod = true;
#else
constexpr bool have_cholmod = false;
#endif
#ifdef _RHEOLEF_HAVE_UMFPACK
constexpr bool have_umfpack = true;
#else
constexpr bool have_umfpack = false;
#endif
// the best choice depends upon the symmetry of the matrix
std::string default_preferred_library;
if (is_sym) {
// if sdp, eigen is faster
// if not sdp, mumps is better when compiled with scotch
if (is_dp) default_preferred_library += " eigen";
if (have_mumps) default_preferred_library += " mumps";
if (!is_dp) default_preferred_library += " eigen";
if (have_cholmod && is_dp) default_preferred_library += " suitesparse";
if (!is_dp) default_preferred_library += " suitesparse";
} else {
// umfpack is best than mumps and eigen
if (have_umfpack) default_preferred_library += " suitesparse";
if (have_mumps) default_preferred_library += " mumps";
default_preferred_library += " eigen";
}
return default_preferred_library;
}
static
std::string
strip_white (std::string x)
{
using namespace std;
size_t first = 0;
while (first < x.length() && (x[first] == ' ' || x[first] == ',')) ++first;
return x.substr(first);
}
static
void
split_options (std::string o, std::vector<std::string>& o_table)
{
using namespace std;
size_t first = 0;
while (first < o.length()) {
while (first < o.length() && (o[first] == ' ' || o[first] == ',')) ++first;
size_t last = first;
while ( last < o.length() && !(o[last] == ' ' || o[last] == ',')) ++last;
if (last - first != 0) {
string x = strip_white (string(o, first, last-first));
o_table.push_back (x);
}
first = last;
}
}
static
void
split_options (std::string o, std::unordered_set<std::string>& o_table)
{
using namespace std;
size_t first = 0;
while (first < o.length()) {
while (first < o.length() && (o[first] == ' ' || o[first] == ',')) ++first;
size_t last = first;
while ( last < o.length() && !(o[last] == ' ' || o[last] == ',')) ++last;
if (last - first != 0) {
string x = o.substr (first, last-first);
o_table.insert (x);
}
first = last;
}
}
static
std::string
try_choice (
const std::vector<std::string>& preferred,
const std::unordered_set<std::string>& available)
{
using namespace std;
string choice;
for (size_t i = 0; i < preferred.size(); ++i) {
string x = strip_white(preferred[i]);
if (available.find (x) != available.end()) {
choice = x;
break;
}
}
return choice;
}
std::string
solver_option::_used_library (std::string init_preferred_library, size_t dis_ext_nnz, bool is_sym, bool is_dp)
{
using namespace std;
string available_library = _default_preferred_library (dis_ext_nnz, is_sym, is_dp);
string preferred_library = (init_preferred_library != "") ? init_preferred_library : available_library;
vector<string> preferred;
unordered_set<string> available;
split_options (available_library, available);
split_options (preferred_library, preferred);
string choice = try_choice (preferred, available);
if (choice == "") {
if (dis_ext_nnz == 0) { // when dis_ext_nnz != 0: distributed and only mumps is available
dis_warning_macro ("preferred_library=\""<<init_preferred_library<<"\" not available, use default=\""<<available_library<<"\"");
}
vector<string> available_as_vector;
split_options (available_library, available_as_vector);
choice = try_choice (available_as_vector, available); // now, will get the fist available
}
return choice;
}
} // namespace rheolef
rheolef::solver_option::_default_preferred_library
static std::string _default_preferred_library(size_t dis_ext_nnz, bool is_sym, bool is_dp)
Definition: solver_option.cc:41
rheolef::solver_option::preferred_library
std::string preferred_library
Definition: solver_option.h:170
dis_warning_macro
#define dis_warning_macro(message)
Definition: dis_macros.h:66
rheolef
This file is part of Rheolef.
Definition: compiler_eigen.h:37
rheolef::solver_option::_used_library
static std::string _used_library(std::string init_preferred_library, size_t dis_ext_nnz, bool is_sym, bool is_dp)
Definition: solver_option.cc:157
rheolef::solver_option::default_preferred_library
static std::string default_preferred_library(const csr< T, M > &a)
Definition: solver_option.h:274
rheolef::std
Definition: vec_expr_v2.h:391