Rheolef  7.1
an efficient C++ finite element environment
solver_option.cc
Go to the documentation of this file.
1 // direct solver interface
22 //
23 #include "rheolef/solver_option.h"
24 #include <unordered_set>
25 namespace rheolef {
26 
27 // -----------------------------------------------------------------------------
28 // default preferred direct solver library manager
29 // -----------------------------------------------------------------------------
30 // rule:
31 // 1) when distributed: only mumps
32 // 2) otherwise:
33 // 2a) when symmetry: eigen, mumps, cholmod(sdp)
34 // 2b) when no-symmetry: umfpack, mumps, eigen
35 // TODO: check stokes with eigen for indefinite sym pbs !
36 // --------------------------------------------------------------------------
37 // mumps note: for best performance in both distributed and sequential modes
38 // mumps requires to be compiled with a good numbering library (scotch or metis)
39 // such as within the libdmumps_scotch debian package
40 std::string
41 solver_option::_default_preferred_library (size_t dis_ext_nnz, bool is_sym, bool is_dp)
42 {
43  // for a given matrix a:
44  // dis_ext_nnz = number of non-block diagonal coefs on distributed matrix
45  // = 0 in sequential mode or block-diagonal matrix
46  // sequential libraries are not able to manage dis_ext_nnz != 0
47  if (dis_ext_nnz != 0) {
48  return "mumps"; // yet, the only supported distributed direct solver
49  }
50  // here, we can use some sequential libs, depending on the configuration:
51 #if defined(_RHEOLEF_HAVE_MUMPS)
52 #if defined(_RHEOLEF_HAVE_MUMPS_WITH_METIS) || \
53  defined(_RHEOLEF_HAVE_MUMPS_WITH_PARMETIS) || \
54  defined(_RHEOLEF_HAVE_MUMPS_WITH_SCOTCH) || \
55  defined(_RHEOLEF_HAVE_MUMPS_WITH_PTSCOTCH)
56  constexpr bool have_mumps_scotch = true,
57  have_mumps_no_scotch = false;
58 #else
59  constexpr bool have_mumps_scotch = false,
60  have_mumps_no_scotch = true;
61 #endif
62 #else
63  constexpr bool have_mumps_scotch = false,
64  have_mumps_no_scotch = false;
65 #endif
66  constexpr bool have_mumps = have_mumps_scotch || have_mumps_no_scotch;
67 #ifdef _RHEOLEF_HAVE_CHOLMOD
68  constexpr bool have_cholmod = true;
69 #else
70  constexpr bool have_cholmod = false;
71 #endif
72 #ifdef _RHEOLEF_HAVE_UMFPACK
73  constexpr bool have_umfpack = true;
74 #else
75  constexpr bool have_umfpack = false;
76 #endif
77 
78  // the best choice depends upon the symmetry of the matrix
79  std::string default_preferred_library;
80  if (is_sym) {
81  // if sdp, eigen is faster
82  // if not sdp, mumps is better when compiled with scotch
83  if (is_dp) default_preferred_library += " eigen";
84  if (have_mumps) default_preferred_library += " mumps";
85  if (!is_dp) default_preferred_library += " eigen";
86  if (have_cholmod && is_dp) default_preferred_library += " suitesparse";
87  if (!is_dp) default_preferred_library += " suitesparse";
88  } else {
89  // umfpack is best than mumps and eigen
90  if (have_umfpack) default_preferred_library += " suitesparse";
91  if (have_mumps) default_preferred_library += " mumps";
92  default_preferred_library += " eigen";
93  }
95 }
96 static
97 std::string
98 strip_white (std::string x)
99 {
100  using namespace std;
101  size_t first = 0;
102  while (first < x.length() && (x[first] == ' ' || x[first] == ',')) ++first;
103  return x.substr(first);
104 }
105 static
106 void
107 split_options (std::string o, std::vector<std::string>& o_table)
108 {
109  using namespace std;
110  size_t first = 0;
111  while (first < o.length()) {
112  while (first < o.length() && (o[first] == ' ' || o[first] == ',')) ++first;
113  size_t last = first;
114  while ( last < o.length() && !(o[last] == ' ' || o[last] == ',')) ++last;
115  if (last - first != 0) {
116  string x = strip_white (string(o, first, last-first));
117  o_table.push_back (x);
118  }
119  first = last;
120  }
121 }
122 static
123 void
124 split_options (std::string o, std::unordered_set<std::string>& o_table)
125 {
126  using namespace std;
127  size_t first = 0;
128  while (first < o.length()) {
129  while (first < o.length() && (o[first] == ' ' || o[first] == ',')) ++first;
130  size_t last = first;
131  while ( last < o.length() && !(o[last] == ' ' || o[last] == ',')) ++last;
132  if (last - first != 0) {
133  string x = o.substr (first, last-first);
134  o_table.insert (x);
135  }
136  first = last;
137  }
138 }
139 static
140 std::string
141 try_choice (
142  const std::vector<std::string>& preferred,
143  const std::unordered_set<std::string>& available)
144 {
145  using namespace std;
146  string choice;
147  for (size_t i = 0; i < preferred.size(); ++i) {
148  string x = strip_white(preferred[i]);
149  if (available.find (x) != available.end()) {
150  choice = x;
151  break;
152  }
153  }
154  return choice;
155 }
156 std::string
157 solver_option::_used_library (std::string init_preferred_library, size_t dis_ext_nnz, bool is_sym, bool is_dp)
158 {
159  using namespace std;
160  string available_library = _default_preferred_library (dis_ext_nnz, is_sym, is_dp);
161  string preferred_library = (init_preferred_library != "") ? init_preferred_library : available_library;
162  vector<string> preferred;
163  unordered_set<string> available;
164  split_options (available_library, available);
165  split_options (preferred_library, preferred);
166  string choice = try_choice (preferred, available);
167  if (choice == "") {
168  if (dis_ext_nnz == 0) { // when dis_ext_nnz != 0: distributed and only mumps is available
169  dis_warning_macro ("preferred_library=\""<<init_preferred_library<<"\" not available, use default=\""<<available_library<<"\"");
170  }
171  vector<string> available_as_vector;
172  split_options (available_library, available_as_vector);
173  choice = try_choice (available_as_vector, available); // now, will get the fist available
174  }
175  return choice;
176 }
177 
178 } // namespace rheolef
static std::string default_preferred_library(const csr< T, M > &a)
std::string preferred_library
static std::string _default_preferred_library(size_t dis_ext_nnz, bool is_sym, bool is_dp)
static std::string _used_library(std::string init_preferred_library, size_t dis_ext_nnz, bool is_sym, bool is_dp)
#define dis_warning_macro(message)
Definition: dis_macros.h:29
This file is part of Rheolef.