HArD::Core2D
Hybrid Arbitrary Degree::Core 2D - Library to implement 2D schemes with edge and cell polynomials as unknowns
Loading...
Searching...
No Matches
linearsolver.hpp
Go to the documentation of this file.
1// Class to select and apply solver
2//
3//
4// Author: Jerome Droniou (jerome.droniou@umontpellier.fr)
5
6
7#ifndef LINEARSOLVER_HPP
8#define LINEARSOLVER_HPP
9
10#include <Eigen/Dense>
11#include <Eigen/Sparse>
12
13#ifdef WITH_UMFPACK
14#include <Eigen/UmfPackSupport>
15#endif
16
17#ifdef WITH_MKL
18#include <Eigen/PardisoSupport>
19#include <mkl.h>
20#endif
21
22#ifdef WITH_PASTIX
23#include <PastixInterface.hpp>
24#endif
25
26#ifdef WITH_SUPERLU
27#include <Eigen/SuperLUSupport>
28#endif
29
30#include <boost/algorithm/string.hpp>
31
32namespace HArDCore2D
33{
41
43 std::map<std::string, int> ParamName{
44 #ifdef WITH_PASTIX
45 {"eps_refinement",0},{"eps_ctrl",1}
46 #endif
47 };
48
50 std::vector<double> SolverParam{
51 #ifdef WITH_PASTIX
52 -1.0, -1.0 // eps_refinement, eps_ctrl with default values
53 #endif
54 };
55
57 const char *SolverParamHelper{
58 #ifdef WITH_PASTIX
59 "Set the solver parameters; Usage [with v1, v2 as doubles]: \n"
60 "--solver-parameters param1=v1 param2=v2\n"
61 "--solver-parameters param1=v1 --solver-parameters param2=v2 \n"
62 "-sparm param=v \n"
63 "Possible parameters are [all optionals]:\n eps_refinement \n eps_ctrl\n"
64 #else
65 "Set the solver parameters, not implemented with this solver, see src/Common/linearsolver.hpp for modifications\n"
66 #endif
67 };
68
69 // Types of Eigen wrappers for each solver (if the module is not available, we define bools just to have a name of that type)
70 template<typename MatrixType>
71 using EigenLUType = Eigen::SparseLU<MatrixType>;
72 template<typename MatrixType>
73 using EigenBiCGStabType = Eigen::BiCGSTAB<MatrixType, Eigen::IncompleteLUT<double> >;
74
75 template<typename MatrixType>
76 #ifdef WITH_MKL
77 using PardisoLUType = Eigen::PardisoLU<MatrixType>;
78 #else
79 using PardisoLUType = bool;
80 #endif
81
82 template<typename MatrixType>
83 #ifdef WITH_UMFPACK
84 using UMFPACKType = Eigen::UmfPackLU<MatrixType>;
85 #else
86 using UMFPACKType = bool;
87 #endif
88
89 #ifdef WITH_PASTIX
92 #else
93 using PastixLUType = bool;
94 using PastixLLTType = bool;
95 #endif
96
97 #ifdef WITH_SUPERLU
98 using SuperLUType = Eigen::SuperLU<Eigen::SparseMatrix<double>>;
99 #else
100 using SuperLUType = bool;
101 #endif
102
104
105 std::map<std::string, SolverName> map_solver = {{"eigenlu",EigenLU},
106 {"eigenbicgstab",EigenBiCGStab},
107 {"pardisolu",PardisoLU},
108 {"umfpack",UMFPACK},
109 {"pastixlu",PaStiXLU},
110 {"pastixllt",PaStiXLLT},
111 {"superlu",SuperLU}};
112
114 std::map<SolverName, std::string> map_realname = {{EigenLU,"Eigen LU"},
115 {EigenBiCGStab,"Eigen BiCGStab"},
116 {PardisoLU,"Pardiso LU"},
117 {UMFPACK,"UMFPACK"},
118 {PaStiXLU,"PaStiX LU"},
119 {PaStiXLLT,"PaStiX LLT"},
120 {SuperLU,"SuperLU"}};
121
122 std::map<SolverName, size_t> map_id = {{EigenLU,0},
123 {EigenBiCGStab,1},
124 {PardisoLU,2},
125 {UMFPACK,3},
126 {PaStiXLU,4},
127 {PaStiXLLT,5},
128 {SuperLU,6}};
129
130
131 // A tuple of unique pointers to list all available pointers (or "int" as a placeholder in case a pointer is not available),
132 // in the order in which they appear in SolverName. If "name" is a SolverName, a get<name> accesses the pointer corresponding to that solver.
133 template<typename MatrixType>
134 using ListSolvers = std::tuple<std::unique_ptr<EigenLUType<MatrixType>>,
135 std::unique_ptr<EigenBiCGStabType<MatrixType>>,
136 std::unique_ptr<PardisoLUType<MatrixType>>,
137 std::unique_ptr<UMFPACKType<MatrixType>>,
138 std::unique_ptr<PastixLUType>,
139 std::unique_ptr<PastixLLTType>,
140 std::unique_ptr<SuperLUType>>;
141
142
144 template<typename MatrixType>
146 {
147 public:
149
151 LinearSolver(const std::string & namesolver)
152 : m_name(map_solver[boost::algorithm::to_lower_copy(namesolver)])
153 {
154 // We adjust the solver if the selected one was not available
155 #ifndef WITH_MKL
156 if (m_name == PardisoLU){
157 m_name = EigenLU;
158 std::cout << "[linearsolver] Pardiso not available, reverting to Eigen LU" << std::endl;
159 };
160 #endif
161 #ifndef WITH_UMFPACK
162 if (m_name == UMFPACK){
163 m_name = EigenLU;
164 std::cout << "[linearsolver] UMFPACK not available, reverting to Eigen LU" << std::endl;
165 };
166 #endif
167 #ifndef WITH_PASTIX
168 if (m_name == PaStiXLU || m_name == PaStiXLLT){
169 m_name = EigenLU;
170 std::cout << "[linearsolver] PaStiX not available, reverting to Eigen LU" << std::endl;
171 };
172 #endif
173 #ifndef WITH_SUPERLU
174 if (m_name == SuperLU){
175 m_name = EigenLU;
176 std::cout << "[linearsolver] SuperLU not available, reverting to Eigen LU" << std::endl;
177 };
178 #endif
179
180 // Instantiate selected solver, put all other pointers to NULL
181 switch(m_name){
182 case EigenLU:
183 {
184 std::get<0>(m_list_solvers).reset( new EigenLUType<MatrixType> );
185 break;
186 }
187 case EigenBiCGStab:
188 {
189 std::get<1>(m_list_solvers).reset( new EigenBiCGStabType<MatrixType> );
190 break;
191 }
192 #ifdef WITH_MKL
193 case PardisoLU:
194 {
195 unsigned nb_threads_hint = std::thread::hardware_concurrency();
196 mkl_set_dynamic(0);
197 mkl_set_num_threads(nb_threads_hint);
198 std::get<2>(m_list_solvers).reset( new PardisoLUType<MatrixType> );
199 break;
200 }
201 #endif
202 #ifdef WITH_UMFPACK
203 case UMFPACK:
204 {
205 std::get<3>(m_list_solvers).reset( new UMFPACKType<MatrixType>);
206 break;
207 }
208 #endif
209 #ifdef WITH_PASTIX
210 case PaStiXLU:
211 {
212 std::get<4>(m_list_solvers).reset( new PastixLUType );
213 std::get<4>(m_list_solvers).get()->init(SolverParam[0],SolverParam[1]);
214 break;
215 }
216 case PaStiXLLT:
217 {
218 std::get<5>(m_list_solvers).reset( new PastixLLTType );
219 break;
220 }
221 #endif
222 #ifdef WITH_SUPERLU
223 case SuperLU:
224 {
225 std::get<6>(m_list_solvers).reset( new SuperLUType );
226 break;
227 }
228 #endif
229 default:
230 break;
231 } // end switch
232 }; // end constructor
233
235 std::string name() const
236 {
237 return map_realname[m_name];
238 }
239
241 Eigen::ComputationInfo info_factorize() const
242 {
243 return m_info_factorize;
244 }
245
247 Eigen::ComputationInfo info_solve() const
248 {
249 return m_info_solve;
250 }
251
253 void analyzePattern(MatrixType & A
254 )
255 {
256 // Only if the pattern hasn't been analyzed yet
257 if (m_is_pattern_analyzed == false){
258 switch(m_name){
259 case EigenLU:
260 {
261 std::get<0>(m_list_solvers).get()->analyzePattern(A);
262 break;
263 }
264 case EigenBiCGStab:
265 {
266 std::get<1>(m_list_solvers).get()->analyzePattern(A);
267 break;
268 }
269 #ifdef WITH_MKL
270 case PardisoLU:
271 {
272 std::get<2>(m_list_solvers).get()->analyzePattern(A);
273 break;
274 }
275 #endif
276
277 #ifdef WITH_UMFPACK
278 case UMFPACK:
279 {
280 std::get<3>(m_list_solvers).get()->analyzePattern(A);
281 break;
282 }
283 #endif
284
285 #ifdef WITH_PASTIX
286 case PaStiXLU:
287 {
288 std::get<4>(m_list_solvers).get()->analyzePattern(A);
289 break;
290 }
291
292 case PaStiXLLT:
293 {
294 std::get<5>(m_list_solvers).get()->analyzePattern(A);
295 break;
296 }
297 #endif
298
299 #ifdef WITH_SUPERLU
300 case SuperLU:
301 {
302 std::get<6>(m_list_solvers).get()->analyzePattern(A);
303 break;
304 }
305 #endif
306
307 default:
308 break;
309 } // end switch for m_name
310
311 m_is_pattern_analyzed = true;
312 }
313 }
314
316 void factorize(MatrixType & A
317 )
318 {
319 switch(m_name){
320 case EigenLU:
321 {
322 std::get<0>(m_list_solvers).get()->factorize(A);
323 m_info_factorize = std::get<0>(m_list_solvers).get()->info();
324 break;
325 }
326 case EigenBiCGStab:
327 {
328 std::get<1>(m_list_solvers).get()->factorize(A);
329 m_info_factorize = std::get<1>(m_list_solvers).get()->info();
330 break;
331 }
332 #ifdef WITH_MKL
333 case PardisoLU:
334 {
335 std::get<2>(m_list_solvers).get()->factorize(A);
336 m_info_factorize = std::get<2>(m_list_solvers).get()->info();
337 break;
338 }
339 #endif
340
341 #ifdef WITH_UMFPACK
342 case UMFPACK:
343 {
344 std::get<3>(m_list_solvers).get()->factorize(A);
345 m_info_factorize = std::get<3>(m_list_solvers).get()->info();
346 break;
347 }
348 #endif
349
350 #ifdef WITH_PASTIX
351 case PaStiXLU:
352 {
353 std::get<4>(m_list_solvers).get()->factorize(A);
354 m_info_factorize = std::get<4>(m_list_solvers).get()->info();
355 break;
356 }
357
358 case PaStiXLLT:
359 {
360 std::get<5>(m_list_solvers).get()->factorize(A);
361 m_info_factorize = std::get<5>(m_list_solvers).get()->info();
362 break;
363 }
364 #endif
365
366 #ifdef WITH_SUPERLU
367 case SuperLU:
368 {
369 std::get<6>(m_list_solvers).get()->factorize(A);
370 m_info_factorize = std::get<6>(m_list_solvers).get()->info();
371 break;
372 }
373 #endif
374
375 default:
376 break;
377 } // end switch for m_name
378
379 _check_info(m_info_factorize, "factorize");
380
381 }
382
384 void compute(MatrixType & A
385 )
386 {
388 factorize(A);
389 }
390
392 template<typename VectorType>
393 VectorType solve(VectorType & b
394 )
395 {
396 VectorType x;
397
398 switch(m_name){
399 case EigenLU:
400 {
401 x = std::get<0>(m_list_solvers).get()->solve(b);
402 m_info_solve = std::get<0>(m_list_solvers).get()->info();
403 break;
404 }
405 case EigenBiCGStab:
406 {
407 x = std::get<1>(m_list_solvers).get()->solve(b);
408 m_info_solve = std::get<1>(m_list_solvers).get()->info();
409 break;
410 }
411 #ifdef WITH_MKL
412 case PardisoLU:
413 {
414 x = std::get<2>(m_list_solvers).get()->solve(b);
415 m_info_solve = std::get<2>(m_list_solvers).get()->info();
416 break;
417 }
418 #endif
419
420 #ifdef WITH_UMFPACK
421 case UMFPACK:
422 {
423 x = std::get<3>(m_list_solvers).get()->solve(b);
424 m_info_solve = std::get<3>(m_list_solvers).get()->info();
425 break;
426 }
427 #endif
428
429 #ifdef WITH_PASTIX
430 case PaStiXLU:
431 {
432 x = std::get<4>(m_list_solvers).get()->solve(b);
433 m_info_solve = std::get<4>(m_list_solvers).get()->info();
434 break;
435 }
436
437 case PaStiXLLT:
438 {
439 x = std::get<5>(m_list_solvers).get()->solve(b);
440 m_info_solve = std::get<5>(m_list_solvers).get()->info();
441 break;
442 }
443 #endif
444
445 #ifdef WITH_SUPERLU
446 case SuperLU:
447 {
448 x = std::get<6>(m_list_solvers).get()->solve(b);
449 m_info_solve = std::get<6>(m_list_solvers).get()->info();
450 break;
451 }
452 #endif
453
454 default:
455 break;
456 } // end switch for m_name
457
458 _check_info(m_info_solve, "solve");
459
460 return x;
461 }
462
464 template<typename VectorType>
465 VectorType compute_and_solve(MatrixType & A,
466 VectorType & b
467 )
468 {
470 factorize(A);
471 return solve(b);
472 }
473
475 template <typename VectorType>
476 inline double residual(MatrixType & A, VectorType & b, VectorType & x)
477 { return (A*x - b).template lpNorm<Eigen::Infinity>() / (b.template lpNorm<Eigen::Infinity>()+1e-8); }
478
479 private:
480
481 // Checks an info, and stop the execution if there is an error
482 void _check_info(Eigen::ComputationInfo const & info, std::string step) const
483 {
484 if (info != Eigen::Success) {
485 std::cerr << "[linearsolver] ERROR in step: " << step << std::endl;
486 std::cerr << "[linearsolver] Info: " << info << " (see Eigen::ComputationInfo for the meaning)" << std::endl;
487 exit(1);
488 }
489 }
490
491 // Members
492 SolverName m_name;
493 ListSolvers<MatrixType> m_list_solvers;
494 Eigen::ComputationInfo m_info_factorize;
495 Eigen::ComputationInfo m_info_solve;
496 bool m_is_pattern_analyzed = false; // to avoid analyzing a pattern twice, Eigen does not like it
497 }; // end definition class
498
499
501
502} // end namespace HArDCore2D
503
504
505#endif
Class to invoke the Pastix LLT solver.
Definition PastixInterface.hpp:543
Class to invoke the Pastix LU solver.
Definition PastixInterface.hpp:424
This structure is a wrapper to allow a given code to select various linear solvers.
Definition linearsolver.hpp:146
bool PardisoLUType
Definition linearsolver.hpp:79
VectorType compute_and_solve(MatrixType &A, VectorType &b)
Perform all operators to solve Ax=b.
Definition linearsolver.hpp:465
SolverName
Enumeration of all available solvers.
Definition linearsolver.hpp:40
bool SuperLUType
Definition linearsolver.hpp:100
const char * SolverParamHelper
Create a solver specific description in boost::desc.options.
Definition linearsolver.hpp:57
LinearSolver(const std::string &namesolver)
Constructor.
Definition linearsolver.hpp:151
std::map< std::string, SolverName > map_solver
Map to associate to each lowercase name a solver.
Definition linearsolver.hpp:105
double residual(MatrixType &A, VectorType &b, VectorType &x)
Check relative infinity norm of residual: ||Ax-b||/||b||.
Definition linearsolver.hpp:476
Eigen::ComputationInfo info_solve() const
Returns the information message after the "solve" step.
Definition linearsolver.hpp:247
std::string name() const
Returns the name of the solver.
Definition linearsolver.hpp:235
Eigen::ComputationInfo info_factorize() const
Returns the information message after the "factorize" step.
Definition linearsolver.hpp:241
std::tuple< std::unique_ptr< EigenLUType< MatrixType > >, std::unique_ptr< EigenBiCGStabType< MatrixType > >, std::unique_ptr< PardisoLUType< MatrixType > >, std::unique_ptr< UMFPACKType< MatrixType > >, std::unique_ptr< PastixLUType >, std::unique_ptr< PastixLLTType >, std::unique_ptr< SuperLUType > > ListSolvers
Definition linearsolver.hpp:140
void analyzePattern(MatrixType &A)
Analyze the pattern of the matrix.
Definition linearsolver.hpp:253
std::map< std::string, int > ParamName
To parse optional Solver parameter from command line.
Definition linearsolver.hpp:43
std::vector< double > SolverParam
Create space and stores default values of optional solver parameters.
Definition linearsolver.hpp:50
Eigen::BiCGSTAB< MatrixType, Eigen::IncompleteLUT< double > > EigenBiCGStabType
Definition linearsolver.hpp:73
bool UMFPACKType
Definition linearsolver.hpp:86
std::map< SolverName, std::string > map_realname
Map to associate to each solver its proper name.
Definition linearsolver.hpp:114
Eigen::SparseLU< MatrixType > EigenLUType
Definition linearsolver.hpp:71
void compute(MatrixType &A)
Analyze and factorize the matrix.
Definition linearsolver.hpp:384
std::map< SolverName, size_t > map_id
Definition linearsolver.hpp:122
bool PastixLUType
Definition linearsolver.hpp:93
bool PastixLLTType
Definition linearsolver.hpp:94
VectorType solve(VectorType &b)
Solve the system Ax=b using the selected solver (after analysis of pattern and computation of matrix)
Definition linearsolver.hpp:393
void factorize(MatrixType &A)
Factorize the matrix.
Definition linearsolver.hpp:316
@ PaStiXLU
Definition linearsolver.hpp:40
@ UMFPACK
Definition linearsolver.hpp:40
@ EigenLU
Definition linearsolver.hpp:40
@ SuperLU
Definition linearsolver.hpp:40
@ PaStiXLLT
Definition linearsolver.hpp:40
@ PardisoLU
Definition linearsolver.hpp:40
@ EigenBiCGStab
Definition linearsolver.hpp:40
A
Definition mmread.m:102
Definition ddr-klplate.hpp:27