HArD::Core3D
Hybrid Arbitrary Degree::Core 3D - Library to implement 3D schemes with vertex, edge, face 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@monash.edu)
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#include <boost/algorithm/string.hpp>
27
28namespace HArDCore3D
29{
37
38 // Types of Eigen wrappers for each solver (if the module is not available, we define bools just to have a name of that type)
39 template<typename MatrixType>
40 using EigenLUType = Eigen::SparseLU<MatrixType>;
41 template<typename MatrixType>
42 using EigenBiCGStabType = Eigen::BiCGSTAB<MatrixType, Eigen::IncompleteLUT<double> >;
43
44 template<typename MatrixType>
45 #ifdef WITH_MKL
46 using PardisoLUType = Eigen::PardisoLU<MatrixType>;
47 #else
49 #endif
50
51 template<typename MatrixType>
52 #ifdef WITH_UMFPACK
53 using UMFPACKType = Eigen::UmfPackLU<MatrixType>;
54 #else
56 #endif
57
58 #ifdef WITH_PASTIX
61 #else
64 #endif
65
66
68
69 std::map<std::string, SolverName> map_solver = {{"eigenlu",EigenLU},
70 {"eigenbicgstab",EigenBiCGStab},
71 {"pardisolu",PardisoLU},
72 {"umfpack",UMFPACK},
73 {"pastixlu",PaStiXLU},
74 {"pastixllt",PaStiXLLT},};
75
77 std::map<SolverName, std::string> map_realname = {{EigenLU,"Eigen LU"},
78 {EigenBiCGStab,"Eigen BiCGStab"},
79 {PardisoLU,"Pardiso LU"},
80 {UMFPACK,"UMFPACK"},
81 {PaStiXLU,"PaStiX LU"},
82 {PaStiXLLT,"PaStiX LLT"}};
83
84 std::map<SolverName, size_t> map_id = {{EigenLU,0},
85 {EigenBiCGStab,1},
86 {PardisoLU,2},
87 {UMFPACK,3},
88 {PaStiXLU,4},
89 {PaStiXLLT,5}};
90
91
92 // A tuple of unique pointers to list all available pointers (or "int" as a placeholder in case a pointer is not available),
93 // in the order in which they appear in SolverName. If "name" is a SolverName, a get<name> accesses the pointer corresponding to that solver.
94 template<typename MatrixType>
95 using ListSolvers = std::tuple<std::unique_ptr<EigenLUType<MatrixType>>,
96 std::unique_ptr<EigenBiCGStabType<MatrixType>>,
97 std::unique_ptr<PardisoLUType<MatrixType>>,
98 std::unique_ptr<UMFPACKType<MatrixType>>,
99 std::unique_ptr<PastixLUType>,
100 std::unique_ptr<PastixLLTType>>;
101
102
104 template<typename MatrixType>
106 {
107 public:
109
111 LinearSolver(const std::string & namesolver)
113 {
114 // We adjust the solver if the selected one was not available
115 #ifndef WITH_MKL
116 if (m_name == PardisoLU){
117 m_name = EigenLU;
118 std::cout << "[linearsolver] Pardiso not available, reverting to Eigen LU" << std::endl;
119 };
120 #endif
121 #ifndef WITH_UMFPACK
122 if (m_name == UMFPACK){
123 m_name = EigenLU;
124 std::cout << "[linearsolver] UMFPACK not available, reverting to Eigen LU" << std::endl;
125 };
126 #endif
127 #ifndef WITH_PASTIX
128 if (m_name == PaStiXLU || m_name == PaStiXLLT){
129 m_name = EigenLU;
130 std::cout << "[linearsolver] PaStiX not available, reverting to Eigen LU" << std::endl;
131 };
132 #endif
133
134 // Instantiate selected solver, put all other pointers to NULL
135 switch(m_name){
136 case EigenLU:
137 {
138 std::get<0>(m_list_solvers).reset( new EigenLUType<MatrixType> );
139 break;
140 }
141 case EigenBiCGStab:
142 {
143 std::get<1>(m_list_solvers).reset( new EigenBiCGStabType<MatrixType> );
144 break;
145 }
146 #ifdef WITH_MKL
147 case PardisoLU:
148 {
149 unsigned nb_threads_hint = std::thread::hardware_concurrency();
152 std::get<2>(m_list_solvers).reset( new PardisoLUType<MatrixType> );
153 break;
154 }
155 #endif
156 #ifdef WITH_UMFPACK
157 case UMFPACK:
158 {
159 std::get<3>(m_list_solvers).reset( new UMFPACKType<MatrixType>);
160 break;
161 }
162 #endif
163 #ifdef WITH_PASTIX
164 case PaStiXLU:
165 {
166 std::get<4>(m_list_solvers).reset( new PastixLUType );
167 // std::get<4>(m_list_solvers).get()->init(1e-3,1e-3); // Does not seem to work in 3D
168 break;
169 }
170 case PaStiXLLT:
171 {
172 std::get<5>(m_list_solvers).reset( new PastixLLTType );
173 break;
174 }
175 #endif
176 default:
177 break;
178 } // end switch
179 }; // end constructor
180
182 std::string name() const
183 {
184 return map_realname[m_name];
185 }
186
188 Eigen::ComputationInfo info_factorize() const
189 {
190 return m_info_factorize;
191 }
192
194 Eigen::ComputationInfo info_solve() const
195 {
196 return m_info_solve;
197 }
198
200 void analyzePattern(MatrixType & A
201 )
202 {
203 switch(m_name){
204 case EigenLU:
205 {
206 std::get<0>(m_list_solvers).get()->analyzePattern(A);
207 break;
208 }
209 case EigenBiCGStab:
210 {
211 std::get<1>(m_list_solvers).get()->analyzePattern(A);
212 break;
213 }
214 #ifdef WITH_MKL
215 case PardisoLU:
216 {
217 std::get<2>(m_list_solvers).get()->analyzePattern(A);
218 break;
219 }
220 #endif
221
222 #ifdef WITH_UMFPACK
223 case UMFPACK:
224 {
225 std::get<3>(m_list_solvers).get()->analyzePattern(A);
226 break;
227 }
228 #endif
229
230 #ifdef WITH_PASTIX
231 case PaStiXLU:
232 {
233 std::get<4>(m_list_solvers).get()->analyzePattern(A);
234 break;
235 }
236
237 case PaStiXLLT:
238 {
239 std::get<5>(m_list_solvers).get()->analyzePattern(A);
240 break;
241 }
242 #endif
243
244 default:
245 break;
246 } // end switch for m_name
247
248 }
249
251 void factorize(MatrixType & A
252 )
253 {
254 switch(m_name){
255 case EigenLU:
256 {
257 std::get<0>(m_list_solvers).get()->factorize(A);
258 m_info_factorize = std::get<0>(m_list_solvers).get()->info();
259 break;
260 }
261 case EigenBiCGStab:
262 {
263 std::get<1>(m_list_solvers).get()->factorize(A);
264 m_info_factorize = std::get<1>(m_list_solvers).get()->info();
265 break;
266 }
267 #ifdef WITH_MKL
268 case PardisoLU:
269 {
270 std::get<2>(m_list_solvers).get()->factorize(A);
271 m_info_factorize = std::get<2>(m_list_solvers).get()->info();
272 break;
273 }
274 #endif
275
276 #ifdef WITH_UMFPACK
277 case UMFPACK:
278 {
279 std::get<3>(m_list_solvers).get()->factorize(A);
280 m_info_factorize = std::get<3>(m_list_solvers).get()->info();
281 break;
282 }
283 #endif
284
285 #ifdef WITH_PASTIX
286 case PaStiXLU:
287 {
288 std::get<4>(m_list_solvers).get()->factorize(A);
289 m_info_factorize = std::get<4>(m_list_solvers).get()->info();
290 break;
291 }
292
293 case PaStiXLLT:
294 {
295 std::get<5>(m_list_solvers).get()->factorize(A);
296 m_info_factorize = std::get<5>(m_list_solvers).get()->info();
297 break;
298 }
299 #endif
300
301 default:
302 break;
303 } // end switch for m_name
304
305 _check_info(m_info_factorize, "factorize");
306
307 }
308
310 void compute(MatrixType & A
311 )
312 {
314 factorize(A);
315 }
316
318 template<typename VectorType>
320 )
321 {
322 VectorType x;
323
324 switch(m_name){
325 case EigenLU:
326 {
327 x = std::get<0>(m_list_solvers).get()->solve(b);
328 m_info_solve = std::get<0>(m_list_solvers).get()->info();
329 break;
330 }
331 case EigenBiCGStab:
332 {
333 x = std::get<1>(m_list_solvers).get()->solve(b);
334 m_info_solve = std::get<1>(m_list_solvers).get()->info();
335 break;
336 }
337 #ifdef WITH_MKL
338 case PardisoLU:
339 {
340 x = std::get<2>(m_list_solvers).get()->solve(b);
341 m_info_solve = std::get<2>(m_list_solvers).get()->info();
342 break;
343 }
344 #endif
345
346 #ifdef WITH_UMFPACK
347 case UMFPACK:
348 {
349 x = std::get<3>(m_list_solvers).get()->solve(b);
350 m_info_solve = std::get<3>(m_list_solvers).get()->info();
351 break;
352 }
353 #endif
354
355 #ifdef WITH_PASTIX
356 case PaStiXLU:
357 {
358 x = std::get<4>(m_list_solvers).get()->solve(b);
359 m_info_solve = std::get<4>(m_list_solvers).get()->info();
360 break;
361 }
362
363 case PaStiXLLT:
364 {
365 x = std::get<5>(m_list_solvers).get()->solve(b);
366 m_info_solve = std::get<5>(m_list_solvers).get()->info();
367 break;
368 }
369 #endif
370
371 default:
372 break;
373 } // end switch for m_name
374
375 _check_info(m_info_solve, "solve");
376
377 return x;
378 };
379
381 template<typename VectorType>
383 VectorType & b
384 )
385 {
387 factorize(A);
388 return solve(b);
389 }
390
392 template <typename VectorType>
393 inline double residual(MatrixType & A, VectorType & b, VectorType & x)
394 { return (A*x - b).template lpNorm<Eigen::Infinity>() / (b.template lpNorm<Eigen::Infinity>()+1e-8); };
395
396 private:
397
398 // Checks an info, and stop the execution if there is an error
399 void _check_info(Eigen::ComputationInfo const & info, std::string step) const
400 {
401 if (info != Eigen::Success) {
402 std::cerr << "[linearsolver] ERROR in step: " << step << std::endl;
403 std::cerr << "[linearsolver] Info: " << info << " (see Eigen::ComputationInfo for the meaning)" << std::endl;
404 exit(1);
405 }
406 }
407
408 // Members
409 SolverName m_name;
410 ListSolvers<MatrixType> m_list_solvers;
411 Eigen::ComputationInfo m_info_factorize;
412 Eigen::ComputationInfo m_info_solve;
413 }; // end definition class
414
415
417
418} // end namespace HArDCore3D
419
420
421#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:106
@ Matrix
Definition basis.hpp:67
Eigen::BiCGSTAB< MatrixType, Eigen::IncompleteLUT< double > > EigenBiCGStabType
Definition linearsolver.hpp:42
std::map< SolverName, std::string > map_realname
Map to associate to each solver its proper name.
Definition linearsolver.hpp:77
Eigen::SparseLU< MatrixType > EigenLUType
Definition linearsolver.hpp:40
void factorize(MatrixType &A)
Factorize the matrix.
Definition linearsolver.hpp:251
void compute(MatrixType &A)
Analyze and factorize the matrix.
Definition linearsolver.hpp:310
bool PardisoLUType
Definition linearsolver.hpp:48
bool UMFPACKType
Definition linearsolver.hpp:55
void analyzePattern(MatrixType &A)
Analyze the pattern of the matrix.
Definition linearsolver.hpp:200
SolverName
Enumeration of all available solvers.
Definition linearsolver.hpp:36
std::map< std::string, SolverName > map_solver
Map to associate to each lowercase name a solver.
Definition linearsolver.hpp:69
std::string name() const
Returns the name of the solver.
Definition linearsolver.hpp:182
VectorType compute_and_solve(MatrixType &A, VectorType &b)
Perform all operators to solve Ax=b.
Definition linearsolver.hpp:382
bool PastixLUType
Definition linearsolver.hpp:62
double residual(MatrixType &A, VectorType &b, VectorType &x)
Check relative infinity norm of residual: ||Ax-b||/||b||.
Definition linearsolver.hpp:393
VectorType solve(VectorType &b)
Solve the system Ax=b using the selected solver (after analysis of pattern and computation of matrix)
Definition linearsolver.hpp:319
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 > > ListSolvers
Definition linearsolver.hpp:100
std::map< SolverName, size_t > map_id
Definition linearsolver.hpp:84
Eigen::ComputationInfo info_solve() const
Returns the information message after the "solve" step.
Definition linearsolver.hpp:194
LinearSolver(const std::string &namesolver)
Constructor.
Definition linearsolver.hpp:111
Eigen::ComputationInfo info_factorize() const
Returns the information message after the "factorize" step.
Definition linearsolver.hpp:188
bool PastixLLTType
Definition linearsolver.hpp:63
@ EigenLU
Definition linearsolver.hpp:36
@ PaStiXLLT
Definition linearsolver.hpp:36
@ PardisoLU
Definition linearsolver.hpp:36
@ PaStiXLU
Definition linearsolver.hpp:36
@ UMFPACK
Definition linearsolver.hpp:36
@ EigenBiCGStab
Definition linearsolver.hpp:36
Definition ddr-magnetostatics.hpp:41