xref: /aosp_15_r20/external/eigen/bench/spbench/spbenchsolver.h (revision bf2c37156dfe67e5dfebd6d394bad8b2ab5804d4)
1*bf2c3715SXin Li // This file is part of Eigen, a lightweight C++ template library
2*bf2c3715SXin Li // for linear algebra.
3*bf2c3715SXin Li //
4*bf2c3715SXin Li // Copyright (C) 2012 Désiré Nuentsa-Wakam <[email protected]>
5*bf2c3715SXin Li //
6*bf2c3715SXin Li // This Source Code Form is subject to the terms of the Mozilla
7*bf2c3715SXin Li // Public License v. 2.0. If a copy of the MPL was not distributed
8*bf2c3715SXin Li // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9*bf2c3715SXin Li 
10*bf2c3715SXin Li 
11*bf2c3715SXin Li #include <iostream>
12*bf2c3715SXin Li #include <fstream>
13*bf2c3715SXin Li #include <Eigen/SparseCore>
14*bf2c3715SXin Li #include <bench/BenchTimer.h>
15*bf2c3715SXin Li #include <cstdlib>
16*bf2c3715SXin Li #include <string>
17*bf2c3715SXin Li #include <Eigen/Cholesky>
18*bf2c3715SXin Li #include <Eigen/Jacobi>
19*bf2c3715SXin Li #include <Eigen/Householder>
20*bf2c3715SXin Li #include <Eigen/IterativeLinearSolvers>
21*bf2c3715SXin Li #include <unsupported/Eigen/IterativeSolvers>
22*bf2c3715SXin Li #include <Eigen/LU>
23*bf2c3715SXin Li #include <unsupported/Eigen/SparseExtra>
24*bf2c3715SXin Li #include <Eigen/SparseLU>
25*bf2c3715SXin Li 
26*bf2c3715SXin Li #include "spbenchstyle.h"
27*bf2c3715SXin Li 
28*bf2c3715SXin Li #ifdef EIGEN_METIS_SUPPORT
29*bf2c3715SXin Li #include <Eigen/MetisSupport>
30*bf2c3715SXin Li #endif
31*bf2c3715SXin Li 
32*bf2c3715SXin Li #ifdef EIGEN_CHOLMOD_SUPPORT
33*bf2c3715SXin Li #include <Eigen/CholmodSupport>
34*bf2c3715SXin Li #endif
35*bf2c3715SXin Li 
36*bf2c3715SXin Li #ifdef EIGEN_UMFPACK_SUPPORT
37*bf2c3715SXin Li #include <Eigen/UmfPackSupport>
38*bf2c3715SXin Li #endif
39*bf2c3715SXin Li 
40*bf2c3715SXin Li #ifdef EIGEN_KLU_SUPPORT
41*bf2c3715SXin Li #include <Eigen/KLUSupport>
42*bf2c3715SXin Li #endif
43*bf2c3715SXin Li 
44*bf2c3715SXin Li #ifdef EIGEN_PARDISO_SUPPORT
45*bf2c3715SXin Li #include <Eigen/PardisoSupport>
46*bf2c3715SXin Li #endif
47*bf2c3715SXin Li 
48*bf2c3715SXin Li #ifdef EIGEN_SUPERLU_SUPPORT
49*bf2c3715SXin Li #include <Eigen/SuperLUSupport>
50*bf2c3715SXin Li #endif
51*bf2c3715SXin Li 
52*bf2c3715SXin Li #ifdef EIGEN_PASTIX_SUPPORT
53*bf2c3715SXin Li #include <Eigen/PaStiXSupport>
54*bf2c3715SXin Li #endif
55*bf2c3715SXin Li 
56*bf2c3715SXin Li // CONSTANTS
57*bf2c3715SXin Li #define EIGEN_UMFPACK  10
58*bf2c3715SXin Li #define EIGEN_KLU  11
59*bf2c3715SXin Li #define EIGEN_SUPERLU  20
60*bf2c3715SXin Li #define EIGEN_PASTIX  30
61*bf2c3715SXin Li #define EIGEN_PARDISO  40
62*bf2c3715SXin Li #define EIGEN_SPARSELU_COLAMD 50
63*bf2c3715SXin Li #define EIGEN_SPARSELU_METIS 51
64*bf2c3715SXin Li #define EIGEN_BICGSTAB  60
65*bf2c3715SXin Li #define EIGEN_BICGSTAB_ILUT  61
66*bf2c3715SXin Li #define EIGEN_GMRES 70
67*bf2c3715SXin Li #define EIGEN_GMRES_ILUT 71
68*bf2c3715SXin Li #define EIGEN_SIMPLICIAL_LDLT  80
69*bf2c3715SXin Li #define EIGEN_CHOLMOD_LDLT  90
70*bf2c3715SXin Li #define EIGEN_PASTIX_LDLT  100
71*bf2c3715SXin Li #define EIGEN_PARDISO_LDLT  110
72*bf2c3715SXin Li #define EIGEN_SIMPLICIAL_LLT  120
73*bf2c3715SXin Li #define EIGEN_CHOLMOD_SUPERNODAL_LLT  130
74*bf2c3715SXin Li #define EIGEN_CHOLMOD_SIMPLICIAL_LLT  140
75*bf2c3715SXin Li #define EIGEN_PASTIX_LLT  150
76*bf2c3715SXin Li #define EIGEN_PARDISO_LLT  160
77*bf2c3715SXin Li #define EIGEN_CG  170
78*bf2c3715SXin Li #define EIGEN_CG_PRECOND  180
79*bf2c3715SXin Li 
80*bf2c3715SXin Li using namespace Eigen;
81*bf2c3715SXin Li using namespace std;
82*bf2c3715SXin Li 
83*bf2c3715SXin Li 
84*bf2c3715SXin Li // Global variables for input parameters
85*bf2c3715SXin Li int MaximumIters; // Maximum number of iterations
86*bf2c3715SXin Li double RelErr; // Relative error of the computed solution
87*bf2c3715SXin Li double best_time_val; // Current best time overall solvers
88*bf2c3715SXin Li int best_time_id; //  id of the best solver for the current system
89*bf2c3715SXin Li 
test_precision()90*bf2c3715SXin Li template<typename T> inline typename NumTraits<T>::Real test_precision() { return NumTraits<T>::dummy_precision(); }
91*bf2c3715SXin Li template<> inline float test_precision<float>() { return 1e-3f; }
92*bf2c3715SXin Li template<> inline double test_precision<double>() { return 1e-6; }
93*bf2c3715SXin Li template<> inline float test_precision<std::complex<float> >() { return test_precision<float>(); }
94*bf2c3715SXin Li template<> inline double test_precision<std::complex<double> >() { return test_precision<double>(); }
95*bf2c3715SXin Li 
printStatheader(std::ofstream & out)96*bf2c3715SXin Li void printStatheader(std::ofstream& out)
97*bf2c3715SXin Li {
98*bf2c3715SXin Li   // Print XML header
99*bf2c3715SXin Li   // NOTE It would have been much easier to write these XML documents using external libraries like tinyXML or Xerces-C++.
100*bf2c3715SXin Li 
101*bf2c3715SXin Li   out << "<?xml version='1.0' encoding='UTF-8'?> \n";
102*bf2c3715SXin Li   out << "<?xml-stylesheet type='text/xsl' href='#stylesheet' ?> \n";
103*bf2c3715SXin Li   out << "<!DOCTYPE BENCH  [\n<!ATTLIST xsl:stylesheet\n id\t ID  #REQUIRED>\n]>";
104*bf2c3715SXin Li   out << "\n\n<!-- Generated by the Eigen library -->\n";
105*bf2c3715SXin Li 
106*bf2c3715SXin Li   out << "\n<BENCH> \n" ; //root XML element
107*bf2c3715SXin Li   // Print the xsl style section
108*bf2c3715SXin Li   printBenchStyle(out);
109*bf2c3715SXin Li   // List all available solvers
110*bf2c3715SXin Li   out << " <AVAILSOLVER> \n";
111*bf2c3715SXin Li #ifdef EIGEN_UMFPACK_SUPPORT
112*bf2c3715SXin Li   out <<"  <SOLVER ID='" << EIGEN_UMFPACK << "'>\n";
113*bf2c3715SXin Li   out << "   <TYPE> LU </TYPE> \n";
114*bf2c3715SXin Li   out << "   <PACKAGE> UMFPACK </PACKAGE> \n";
115*bf2c3715SXin Li   out << "  </SOLVER> \n";
116*bf2c3715SXin Li #endif
117*bf2c3715SXin Li #ifdef EIGEN_KLU_SUPPORT
118*bf2c3715SXin Li   out <<"  <SOLVER ID='" << EIGEN_KLU << "'>\n";
119*bf2c3715SXin Li   out << "   <TYPE> LU </TYPE> \n";
120*bf2c3715SXin Li   out << "   <PACKAGE> KLU </PACKAGE> \n";
121*bf2c3715SXin Li   out << "  </SOLVER> \n";
122*bf2c3715SXin Li #endif
123*bf2c3715SXin Li #ifdef EIGEN_SUPERLU_SUPPORT
124*bf2c3715SXin Li   out <<"  <SOLVER ID='" << EIGEN_SUPERLU << "'>\n";
125*bf2c3715SXin Li   out << "   <TYPE> LU </TYPE> \n";
126*bf2c3715SXin Li   out << "   <PACKAGE> SUPERLU </PACKAGE> \n";
127*bf2c3715SXin Li   out << "  </SOLVER> \n";
128*bf2c3715SXin Li #endif
129*bf2c3715SXin Li #ifdef EIGEN_CHOLMOD_SUPPORT
130*bf2c3715SXin Li   out <<"  <SOLVER ID='" << EIGEN_CHOLMOD_SIMPLICIAL_LLT << "'>\n";
131*bf2c3715SXin Li   out << "   <TYPE> LLT SP</TYPE> \n";
132*bf2c3715SXin Li   out << "   <PACKAGE> CHOLMOD </PACKAGE> \n";
133*bf2c3715SXin Li   out << "  </SOLVER> \n";
134*bf2c3715SXin Li 
135*bf2c3715SXin Li   out <<"  <SOLVER ID='" << EIGEN_CHOLMOD_SUPERNODAL_LLT << "'>\n";
136*bf2c3715SXin Li   out << "   <TYPE> LLT</TYPE> \n";
137*bf2c3715SXin Li   out << "   <PACKAGE> CHOLMOD </PACKAGE> \n";
138*bf2c3715SXin Li   out << "  </SOLVER> \n";
139*bf2c3715SXin Li 
140*bf2c3715SXin Li   out <<"  <SOLVER ID='" << EIGEN_CHOLMOD_LDLT << "'>\n";
141*bf2c3715SXin Li   out << "   <TYPE> LDLT </TYPE> \n";
142*bf2c3715SXin Li   out << "   <PACKAGE> CHOLMOD </PACKAGE> \n";
143*bf2c3715SXin Li   out << "  </SOLVER> \n";
144*bf2c3715SXin Li #endif
145*bf2c3715SXin Li #ifdef EIGEN_PARDISO_SUPPORT
146*bf2c3715SXin Li   out <<"  <SOLVER ID='" << EIGEN_PARDISO << "'>\n";
147*bf2c3715SXin Li   out << "   <TYPE> LU </TYPE> \n";
148*bf2c3715SXin Li   out << "   <PACKAGE> PARDISO </PACKAGE> \n";
149*bf2c3715SXin Li   out << "  </SOLVER> \n";
150*bf2c3715SXin Li 
151*bf2c3715SXin Li   out <<"  <SOLVER ID='" << EIGEN_PARDISO_LLT << "'>\n";
152*bf2c3715SXin Li   out << "   <TYPE> LLT </TYPE> \n";
153*bf2c3715SXin Li   out << "   <PACKAGE> PARDISO </PACKAGE> \n";
154*bf2c3715SXin Li   out << "  </SOLVER> \n";
155*bf2c3715SXin Li 
156*bf2c3715SXin Li   out <<"  <SOLVER ID='" << EIGEN_PARDISO_LDLT << "'>\n";
157*bf2c3715SXin Li   out << "   <TYPE> LDLT </TYPE> \n";
158*bf2c3715SXin Li   out << "   <PACKAGE> PARDISO </PACKAGE> \n";
159*bf2c3715SXin Li   out << "  </SOLVER> \n";
160*bf2c3715SXin Li #endif
161*bf2c3715SXin Li #ifdef EIGEN_PASTIX_SUPPORT
162*bf2c3715SXin Li   out <<"  <SOLVER ID='" << EIGEN_PASTIX << "'>\n";
163*bf2c3715SXin Li   out << "   <TYPE> LU </TYPE> \n";
164*bf2c3715SXin Li   out << "   <PACKAGE> PASTIX </PACKAGE> \n";
165*bf2c3715SXin Li   out << "  </SOLVER> \n";
166*bf2c3715SXin Li 
167*bf2c3715SXin Li   out <<"  <SOLVER ID='" << EIGEN_PASTIX_LLT << "'>\n";
168*bf2c3715SXin Li   out << "   <TYPE> LLT </TYPE> \n";
169*bf2c3715SXin Li   out << "   <PACKAGE> PASTIX </PACKAGE> \n";
170*bf2c3715SXin Li   out << "  </SOLVER> \n";
171*bf2c3715SXin Li 
172*bf2c3715SXin Li   out <<"  <SOLVER ID='" << EIGEN_PASTIX_LDLT << "'>\n";
173*bf2c3715SXin Li   out << "   <TYPE> LDLT </TYPE> \n";
174*bf2c3715SXin Li   out << "   <PACKAGE> PASTIX </PACKAGE> \n";
175*bf2c3715SXin Li   out << "  </SOLVER> \n";
176*bf2c3715SXin Li #endif
177*bf2c3715SXin Li 
178*bf2c3715SXin Li   out <<"  <SOLVER ID='" << EIGEN_BICGSTAB << "'>\n";
179*bf2c3715SXin Li   out << "   <TYPE> BICGSTAB </TYPE> \n";
180*bf2c3715SXin Li   out << "   <PACKAGE> EIGEN </PACKAGE> \n";
181*bf2c3715SXin Li   out << "  </SOLVER> \n";
182*bf2c3715SXin Li 
183*bf2c3715SXin Li   out <<"  <SOLVER ID='" << EIGEN_BICGSTAB_ILUT << "'>\n";
184*bf2c3715SXin Li   out << "   <TYPE> BICGSTAB_ILUT </TYPE> \n";
185*bf2c3715SXin Li   out << "   <PACKAGE> EIGEN </PACKAGE> \n";
186*bf2c3715SXin Li   out << "  </SOLVER> \n";
187*bf2c3715SXin Li 
188*bf2c3715SXin Li   out <<"  <SOLVER ID='" << EIGEN_GMRES_ILUT << "'>\n";
189*bf2c3715SXin Li   out << "   <TYPE> GMRES_ILUT </TYPE> \n";
190*bf2c3715SXin Li   out << "   <PACKAGE> EIGEN </PACKAGE> \n";
191*bf2c3715SXin Li   out << "  </SOLVER> \n";
192*bf2c3715SXin Li 
193*bf2c3715SXin Li   out <<"  <SOLVER ID='" << EIGEN_SIMPLICIAL_LDLT << "'>\n";
194*bf2c3715SXin Li   out << "   <TYPE> LDLT </TYPE> \n";
195*bf2c3715SXin Li   out << "   <PACKAGE> EIGEN </PACKAGE> \n";
196*bf2c3715SXin Li   out << "  </SOLVER> \n";
197*bf2c3715SXin Li 
198*bf2c3715SXin Li   out <<"  <SOLVER ID='" << EIGEN_SIMPLICIAL_LLT << "'>\n";
199*bf2c3715SXin Li   out << "   <TYPE> LLT </TYPE> \n";
200*bf2c3715SXin Li   out << "   <PACKAGE> EIGEN </PACKAGE> \n";
201*bf2c3715SXin Li   out << "  </SOLVER> \n";
202*bf2c3715SXin Li 
203*bf2c3715SXin Li   out <<"  <SOLVER ID='" << EIGEN_CG << "'>\n";
204*bf2c3715SXin Li   out << "   <TYPE> CG </TYPE> \n";
205*bf2c3715SXin Li   out << "   <PACKAGE> EIGEN </PACKAGE> \n";
206*bf2c3715SXin Li   out << "  </SOLVER> \n";
207*bf2c3715SXin Li 
208*bf2c3715SXin Li   out <<"  <SOLVER ID='" << EIGEN_SPARSELU_COLAMD << "'>\n";
209*bf2c3715SXin Li   out << "   <TYPE> LU_COLAMD </TYPE> \n";
210*bf2c3715SXin Li   out << "   <PACKAGE> EIGEN </PACKAGE> \n";
211*bf2c3715SXin Li   out << "  </SOLVER> \n";
212*bf2c3715SXin Li 
213*bf2c3715SXin Li #ifdef EIGEN_METIS_SUPPORT
214*bf2c3715SXin Li   out <<"  <SOLVER ID='" << EIGEN_SPARSELU_METIS << "'>\n";
215*bf2c3715SXin Li   out << "   <TYPE> LU_METIS </TYPE> \n";
216*bf2c3715SXin Li   out << "   <PACKAGE> EIGEN </PACKAGE> \n";
217*bf2c3715SXin Li   out << "  </SOLVER> \n";
218*bf2c3715SXin Li #endif
219*bf2c3715SXin Li   out << " </AVAILSOLVER> \n";
220*bf2c3715SXin Li 
221*bf2c3715SXin Li }
222*bf2c3715SXin Li 
223*bf2c3715SXin Li 
224*bf2c3715SXin Li template<typename Solver, typename Scalar>
call_solver(Solver & solver,const int solver_id,const typename Solver::MatrixType & A,const Matrix<Scalar,Dynamic,1> & b,const Matrix<Scalar,Dynamic,1> & refX,std::ofstream & statbuf)225*bf2c3715SXin Li void call_solver(Solver &solver, const int solver_id, const typename Solver::MatrixType& A, const Matrix<Scalar, Dynamic, 1>& b, const Matrix<Scalar, Dynamic, 1>& refX,std::ofstream& statbuf)
226*bf2c3715SXin Li {
227*bf2c3715SXin Li 
228*bf2c3715SXin Li   double total_time;
229*bf2c3715SXin Li   double compute_time;
230*bf2c3715SXin Li   double solve_time;
231*bf2c3715SXin Li   double rel_error;
232*bf2c3715SXin Li   Matrix<Scalar, Dynamic, 1> x;
233*bf2c3715SXin Li   BenchTimer timer;
234*bf2c3715SXin Li   timer.reset();
235*bf2c3715SXin Li   timer.start();
236*bf2c3715SXin Li   solver.compute(A);
237*bf2c3715SXin Li   if (solver.info() != Success)
238*bf2c3715SXin Li   {
239*bf2c3715SXin Li     std::cerr << "Solver failed ... \n";
240*bf2c3715SXin Li     return;
241*bf2c3715SXin Li   }
242*bf2c3715SXin Li   timer.stop();
243*bf2c3715SXin Li   compute_time = timer.value();
244*bf2c3715SXin Li   statbuf << "    <TIME>\n";
245*bf2c3715SXin Li   statbuf << "     <COMPUTE> " << timer.value() << "</COMPUTE>\n";
246*bf2c3715SXin Li   std::cout<< "COMPUTE TIME : " << timer.value() <<std::endl;
247*bf2c3715SXin Li 
248*bf2c3715SXin Li   timer.reset();
249*bf2c3715SXin Li   timer.start();
250*bf2c3715SXin Li   x = solver.solve(b);
251*bf2c3715SXin Li   if (solver.info() == NumericalIssue)
252*bf2c3715SXin Li   {
253*bf2c3715SXin Li     std::cerr << "Solver failed ... \n";
254*bf2c3715SXin Li     return;
255*bf2c3715SXin Li   }
256*bf2c3715SXin Li   timer.stop();
257*bf2c3715SXin Li   solve_time = timer.value();
258*bf2c3715SXin Li   statbuf << "     <SOLVE> " << timer.value() << "</SOLVE>\n";
259*bf2c3715SXin Li   std::cout<< "SOLVE TIME : " << timer.value() <<std::endl;
260*bf2c3715SXin Li 
261*bf2c3715SXin Li   total_time = solve_time + compute_time;
262*bf2c3715SXin Li   statbuf << "     <TOTAL> " << total_time << "</TOTAL>\n";
263*bf2c3715SXin Li   std::cout<< "TOTAL TIME : " << total_time <<std::endl;
264*bf2c3715SXin Li   statbuf << "    </TIME>\n";
265*bf2c3715SXin Li 
266*bf2c3715SXin Li   // Verify the relative error
267*bf2c3715SXin Li   if(refX.size() != 0)
268*bf2c3715SXin Li     rel_error = (refX - x).norm()/refX.norm();
269*bf2c3715SXin Li   else
270*bf2c3715SXin Li   {
271*bf2c3715SXin Li     // Compute the relative residual norm
272*bf2c3715SXin Li     Matrix<Scalar, Dynamic, 1> temp;
273*bf2c3715SXin Li     temp = A * x;
274*bf2c3715SXin Li     rel_error = (b-temp).norm()/b.norm();
275*bf2c3715SXin Li   }
276*bf2c3715SXin Li   statbuf << "    <ERROR> " << rel_error << "</ERROR>\n";
277*bf2c3715SXin Li   std::cout<< "REL. ERROR : " << rel_error << "\n\n" ;
278*bf2c3715SXin Li   if ( rel_error <= RelErr )
279*bf2c3715SXin Li   {
280*bf2c3715SXin Li     // check the best time if convergence
281*bf2c3715SXin Li     if(!best_time_val || (best_time_val > total_time))
282*bf2c3715SXin Li     {
283*bf2c3715SXin Li       best_time_val = total_time;
284*bf2c3715SXin Li       best_time_id = solver_id;
285*bf2c3715SXin Li     }
286*bf2c3715SXin Li   }
287*bf2c3715SXin Li }
288*bf2c3715SXin Li 
289*bf2c3715SXin Li template<typename Solver, typename Scalar>
call_directsolver(Solver & solver,const int solver_id,const typename Solver::MatrixType & A,const Matrix<Scalar,Dynamic,1> & b,const Matrix<Scalar,Dynamic,1> & refX,std::string & statFile)290*bf2c3715SXin Li void call_directsolver(Solver& solver, const int solver_id, const typename Solver::MatrixType& A, const Matrix<Scalar, Dynamic, 1>& b, const Matrix<Scalar, Dynamic, 1>& refX, std::string& statFile)
291*bf2c3715SXin Li {
292*bf2c3715SXin Li     std::ofstream statbuf(statFile.c_str(), std::ios::app);
293*bf2c3715SXin Li     statbuf << "   <SOLVER_STAT ID='" << solver_id <<"'>\n";
294*bf2c3715SXin Li     call_solver(solver, solver_id, A, b, refX,statbuf);
295*bf2c3715SXin Li     statbuf << "   </SOLVER_STAT>\n";
296*bf2c3715SXin Li     statbuf.close();
297*bf2c3715SXin Li }
298*bf2c3715SXin Li 
299*bf2c3715SXin Li template<typename Solver, typename Scalar>
call_itersolver(Solver & solver,const int solver_id,const typename Solver::MatrixType & A,const Matrix<Scalar,Dynamic,1> & b,const Matrix<Scalar,Dynamic,1> & refX,std::string & statFile)300*bf2c3715SXin Li void call_itersolver(Solver &solver, const int solver_id, const typename Solver::MatrixType& A, const Matrix<Scalar, Dynamic, 1>& b, const Matrix<Scalar, Dynamic, 1>& refX, std::string& statFile)
301*bf2c3715SXin Li {
302*bf2c3715SXin Li   solver.setTolerance(RelErr);
303*bf2c3715SXin Li   solver.setMaxIterations(MaximumIters);
304*bf2c3715SXin Li 
305*bf2c3715SXin Li   std::ofstream statbuf(statFile.c_str(), std::ios::app);
306*bf2c3715SXin Li   statbuf << " <SOLVER_STAT ID='" << solver_id <<"'>\n";
307*bf2c3715SXin Li   call_solver(solver, solver_id, A, b, refX,statbuf);
308*bf2c3715SXin Li   statbuf << "   <ITER> "<< solver.iterations() << "</ITER>\n";
309*bf2c3715SXin Li   statbuf << " </SOLVER_STAT>\n";
310*bf2c3715SXin Li   std::cout << "ITERATIONS : " << solver.iterations() <<"\n\n\n";
311*bf2c3715SXin Li 
312*bf2c3715SXin Li }
313*bf2c3715SXin Li 
314*bf2c3715SXin Li 
315*bf2c3715SXin Li template <typename Scalar>
SelectSolvers(const SparseMatrix<Scalar> & A,unsigned int sym,Matrix<Scalar,Dynamic,1> & b,const Matrix<Scalar,Dynamic,1> & refX,std::string & statFile)316*bf2c3715SXin Li void SelectSolvers(const SparseMatrix<Scalar>&A, unsigned int sym, Matrix<Scalar, Dynamic, 1>& b, const Matrix<Scalar, Dynamic, 1>& refX, std::string& statFile)
317*bf2c3715SXin Li {
318*bf2c3715SXin Li   typedef SparseMatrix<Scalar, ColMajor> SpMat;
319*bf2c3715SXin Li   // First, deal with Nonsymmetric and symmetric matrices
320*bf2c3715SXin Li   best_time_id = 0;
321*bf2c3715SXin Li   best_time_val = 0.0;
322*bf2c3715SXin Li   //UMFPACK
323*bf2c3715SXin Li   #ifdef EIGEN_UMFPACK_SUPPORT
324*bf2c3715SXin Li   {
325*bf2c3715SXin Li     cout << "Solving with UMFPACK LU ... \n";
326*bf2c3715SXin Li     UmfPackLU<SpMat> solver;
327*bf2c3715SXin Li     call_directsolver(solver, EIGEN_UMFPACK, A, b, refX,statFile);
328*bf2c3715SXin Li   }
329*bf2c3715SXin Li   #endif
330*bf2c3715SXin Li   //KLU
331*bf2c3715SXin Li   #ifdef EIGEN_KLU_SUPPORT
332*bf2c3715SXin Li   {
333*bf2c3715SXin Li     cout << "Solving with KLU LU ... \n";
334*bf2c3715SXin Li     KLU<SpMat> solver;
335*bf2c3715SXin Li     call_directsolver(solver, EIGEN_KLU, A, b, refX,statFile);
336*bf2c3715SXin Li   }
337*bf2c3715SXin Li   #endif
338*bf2c3715SXin Li     //SuperLU
339*bf2c3715SXin Li   #ifdef EIGEN_SUPERLU_SUPPORT
340*bf2c3715SXin Li   {
341*bf2c3715SXin Li     cout << "\nSolving with SUPERLU ... \n";
342*bf2c3715SXin Li     SuperLU<SpMat> solver;
343*bf2c3715SXin Li     call_directsolver(solver, EIGEN_SUPERLU, A, b, refX,statFile);
344*bf2c3715SXin Li   }
345*bf2c3715SXin Li   #endif
346*bf2c3715SXin Li 
347*bf2c3715SXin Li    // PaStix LU
348*bf2c3715SXin Li   #ifdef EIGEN_PASTIX_SUPPORT
349*bf2c3715SXin Li   {
350*bf2c3715SXin Li     cout << "\nSolving with PASTIX LU ... \n";
351*bf2c3715SXin Li     PastixLU<SpMat> solver;
352*bf2c3715SXin Li     call_directsolver(solver, EIGEN_PASTIX, A, b, refX,statFile) ;
353*bf2c3715SXin Li   }
354*bf2c3715SXin Li   #endif
355*bf2c3715SXin Li 
356*bf2c3715SXin Li    //PARDISO LU
357*bf2c3715SXin Li   #ifdef EIGEN_PARDISO_SUPPORT
358*bf2c3715SXin Li   {
359*bf2c3715SXin Li     cout << "\nSolving with PARDISO LU ... \n";
360*bf2c3715SXin Li     PardisoLU<SpMat>  solver;
361*bf2c3715SXin Li     call_directsolver(solver, EIGEN_PARDISO, A, b, refX,statFile);
362*bf2c3715SXin Li   }
363*bf2c3715SXin Li   #endif
364*bf2c3715SXin Li 
365*bf2c3715SXin Li   // Eigen SparseLU METIS
366*bf2c3715SXin Li   cout << "\n Solving with Sparse LU AND COLAMD ... \n";
367*bf2c3715SXin Li   SparseLU<SpMat, COLAMDOrdering<int> >   solver;
368*bf2c3715SXin Li   call_directsolver(solver, EIGEN_SPARSELU_COLAMD, A, b, refX, statFile);
369*bf2c3715SXin Li   // Eigen SparseLU METIS
370*bf2c3715SXin Li   #ifdef EIGEN_METIS_SUPPORT
371*bf2c3715SXin Li   {
372*bf2c3715SXin Li     cout << "\n Solving with Sparse LU AND METIS ... \n";
373*bf2c3715SXin Li     SparseLU<SpMat, MetisOrdering<int> >   solver;
374*bf2c3715SXin Li     call_directsolver(solver, EIGEN_SPARSELU_METIS, A, b, refX, statFile);
375*bf2c3715SXin Li   }
376*bf2c3715SXin Li   #endif
377*bf2c3715SXin Li 
378*bf2c3715SXin Li   //BiCGSTAB
379*bf2c3715SXin Li   {
380*bf2c3715SXin Li     cout << "\nSolving with BiCGSTAB ... \n";
381*bf2c3715SXin Li     BiCGSTAB<SpMat> solver;
382*bf2c3715SXin Li     call_itersolver(solver, EIGEN_BICGSTAB, A, b, refX,statFile);
383*bf2c3715SXin Li   }
384*bf2c3715SXin Li   //BiCGSTAB+ILUT
385*bf2c3715SXin Li   {
386*bf2c3715SXin Li     cout << "\nSolving with BiCGSTAB and ILUT ... \n";
387*bf2c3715SXin Li     BiCGSTAB<SpMat, IncompleteLUT<Scalar> > solver;
388*bf2c3715SXin Li     call_itersolver(solver, EIGEN_BICGSTAB_ILUT, A, b, refX,statFile);
389*bf2c3715SXin Li   }
390*bf2c3715SXin Li 
391*bf2c3715SXin Li 
392*bf2c3715SXin Li   //GMRES
393*bf2c3715SXin Li //   {
394*bf2c3715SXin Li //     cout << "\nSolving with GMRES ... \n";
395*bf2c3715SXin Li //     GMRES<SpMat> solver;
396*bf2c3715SXin Li //     call_itersolver(solver, EIGEN_GMRES, A, b, refX,statFile);
397*bf2c3715SXin Li //   }
398*bf2c3715SXin Li   //GMRES+ILUT
399*bf2c3715SXin Li   {
400*bf2c3715SXin Li     cout << "\nSolving with GMRES and ILUT ... \n";
401*bf2c3715SXin Li     GMRES<SpMat, IncompleteLUT<Scalar> > solver;
402*bf2c3715SXin Li     call_itersolver(solver, EIGEN_GMRES_ILUT, A, b, refX,statFile);
403*bf2c3715SXin Li   }
404*bf2c3715SXin Li 
405*bf2c3715SXin Li   // Hermitian and not necessarily positive-definites
406*bf2c3715SXin Li   if (sym != NonSymmetric)
407*bf2c3715SXin Li   {
408*bf2c3715SXin Li     // Internal Cholesky
409*bf2c3715SXin Li     {
410*bf2c3715SXin Li       cout << "\nSolving with Simplicial LDLT ... \n";
411*bf2c3715SXin Li       SimplicialLDLT<SpMat, Lower> solver;
412*bf2c3715SXin Li       call_directsolver(solver, EIGEN_SIMPLICIAL_LDLT, A, b, refX,statFile);
413*bf2c3715SXin Li     }
414*bf2c3715SXin Li 
415*bf2c3715SXin Li     // CHOLMOD
416*bf2c3715SXin Li     #ifdef EIGEN_CHOLMOD_SUPPORT
417*bf2c3715SXin Li     {
418*bf2c3715SXin Li       cout << "\nSolving with CHOLMOD LDLT ... \n";
419*bf2c3715SXin Li       CholmodDecomposition<SpMat, Lower> solver;
420*bf2c3715SXin Li       solver.setMode(CholmodLDLt);
421*bf2c3715SXin Li        call_directsolver(solver,EIGEN_CHOLMOD_LDLT, A, b, refX,statFile);
422*bf2c3715SXin Li     }
423*bf2c3715SXin Li     #endif
424*bf2c3715SXin Li 
425*bf2c3715SXin Li     //PASTIX LLT
426*bf2c3715SXin Li     #ifdef EIGEN_PASTIX_SUPPORT
427*bf2c3715SXin Li     {
428*bf2c3715SXin Li       cout << "\nSolving with PASTIX LDLT ... \n";
429*bf2c3715SXin Li       PastixLDLT<SpMat, Lower> solver;
430*bf2c3715SXin Li       call_directsolver(solver,EIGEN_PASTIX_LDLT, A, b, refX,statFile);
431*bf2c3715SXin Li     }
432*bf2c3715SXin Li     #endif
433*bf2c3715SXin Li 
434*bf2c3715SXin Li     //PARDISO LLT
435*bf2c3715SXin Li     #ifdef EIGEN_PARDISO_SUPPORT
436*bf2c3715SXin Li     {
437*bf2c3715SXin Li       cout << "\nSolving with PARDISO LDLT ... \n";
438*bf2c3715SXin Li       PardisoLDLT<SpMat, Lower> solver;
439*bf2c3715SXin Li       call_directsolver(solver,EIGEN_PARDISO_LDLT, A, b, refX,statFile);
440*bf2c3715SXin Li     }
441*bf2c3715SXin Li     #endif
442*bf2c3715SXin Li   }
443*bf2c3715SXin Li 
444*bf2c3715SXin Li    // Now, symmetric POSITIVE DEFINITE matrices
445*bf2c3715SXin Li   if (sym == SPD)
446*bf2c3715SXin Li   {
447*bf2c3715SXin Li 
448*bf2c3715SXin Li     //Internal Sparse Cholesky
449*bf2c3715SXin Li     {
450*bf2c3715SXin Li       cout << "\nSolving with SIMPLICIAL LLT ... \n";
451*bf2c3715SXin Li       SimplicialLLT<SpMat, Lower> solver;
452*bf2c3715SXin Li       call_directsolver(solver,EIGEN_SIMPLICIAL_LLT, A, b, refX,statFile);
453*bf2c3715SXin Li     }
454*bf2c3715SXin Li 
455*bf2c3715SXin Li     // CHOLMOD
456*bf2c3715SXin Li     #ifdef EIGEN_CHOLMOD_SUPPORT
457*bf2c3715SXin Li     {
458*bf2c3715SXin Li       // CholMOD SuperNodal LLT
459*bf2c3715SXin Li       cout << "\nSolving with CHOLMOD LLT (Supernodal)... \n";
460*bf2c3715SXin Li       CholmodDecomposition<SpMat, Lower> solver;
461*bf2c3715SXin Li       solver.setMode(CholmodSupernodalLLt);
462*bf2c3715SXin Li        call_directsolver(solver,EIGEN_CHOLMOD_SUPERNODAL_LLT, A, b, refX,statFile);
463*bf2c3715SXin Li       // CholMod Simplicial LLT
464*bf2c3715SXin Li       cout << "\nSolving with CHOLMOD LLT (Simplicial) ... \n";
465*bf2c3715SXin Li       solver.setMode(CholmodSimplicialLLt);
466*bf2c3715SXin Li       call_directsolver(solver,EIGEN_CHOLMOD_SIMPLICIAL_LLT, A, b, refX,statFile);
467*bf2c3715SXin Li     }
468*bf2c3715SXin Li     #endif
469*bf2c3715SXin Li 
470*bf2c3715SXin Li     //PASTIX LLT
471*bf2c3715SXin Li     #ifdef EIGEN_PASTIX_SUPPORT
472*bf2c3715SXin Li     {
473*bf2c3715SXin Li       cout << "\nSolving with PASTIX LLT ... \n";
474*bf2c3715SXin Li       PastixLLT<SpMat, Lower> solver;
475*bf2c3715SXin Li       call_directsolver(solver,EIGEN_PASTIX_LLT, A, b, refX,statFile);
476*bf2c3715SXin Li     }
477*bf2c3715SXin Li     #endif
478*bf2c3715SXin Li 
479*bf2c3715SXin Li     //PARDISO LLT
480*bf2c3715SXin Li     #ifdef EIGEN_PARDISO_SUPPORT
481*bf2c3715SXin Li     {
482*bf2c3715SXin Li       cout << "\nSolving with PARDISO LLT ... \n";
483*bf2c3715SXin Li       PardisoLLT<SpMat, Lower> solver;
484*bf2c3715SXin Li       call_directsolver(solver,EIGEN_PARDISO_LLT, A, b, refX,statFile);
485*bf2c3715SXin Li     }
486*bf2c3715SXin Li     #endif
487*bf2c3715SXin Li 
488*bf2c3715SXin Li     // Internal CG
489*bf2c3715SXin Li     {
490*bf2c3715SXin Li       cout << "\nSolving with CG ... \n";
491*bf2c3715SXin Li       ConjugateGradient<SpMat, Lower> solver;
492*bf2c3715SXin Li       call_itersolver(solver,EIGEN_CG, A, b, refX,statFile);
493*bf2c3715SXin Li     }
494*bf2c3715SXin Li     //CG+IdentityPreconditioner
495*bf2c3715SXin Li //     {
496*bf2c3715SXin Li //       cout << "\nSolving with CG and IdentityPreconditioner ... \n";
497*bf2c3715SXin Li //       ConjugateGradient<SpMat, Lower, IdentityPreconditioner> solver;
498*bf2c3715SXin Li //       call_itersolver(solver,EIGEN_CG_PRECOND, A, b, refX,statFile);
499*bf2c3715SXin Li //     }
500*bf2c3715SXin Li   } // End SPD matrices
501*bf2c3715SXin Li }
502*bf2c3715SXin Li 
503*bf2c3715SXin Li /* Browse all the matrices available in the specified folder
504*bf2c3715SXin Li  * and solve the associated linear system.
505*bf2c3715SXin Li  * The results of each solve are printed in the standard output
506*bf2c3715SXin Li  * and optionally in the provided html file
507*bf2c3715SXin Li  */
508*bf2c3715SXin Li template <typename Scalar>
Browse_Matrices(const string folder,bool statFileExists,std::string & statFile,int maxiters,double tol)509*bf2c3715SXin Li void Browse_Matrices(const string folder, bool statFileExists, std::string& statFile, int maxiters, double tol)
510*bf2c3715SXin Li {
511*bf2c3715SXin Li   MaximumIters = maxiters; // Maximum number of iterations, global variable
512*bf2c3715SXin Li   RelErr = tol;  //Relative residual error  as stopping criterion for iterative solvers
513*bf2c3715SXin Li   MatrixMarketIterator<Scalar> it(folder);
514*bf2c3715SXin Li   for ( ; it; ++it)
515*bf2c3715SXin Li   {
516*bf2c3715SXin Li     //print the infos for this linear system
517*bf2c3715SXin Li     if(statFileExists)
518*bf2c3715SXin Li     {
519*bf2c3715SXin Li       std::ofstream statbuf(statFile.c_str(), std::ios::app);
520*bf2c3715SXin Li       statbuf << "<LINEARSYSTEM> \n";
521*bf2c3715SXin Li       statbuf << "   <MATRIX> \n";
522*bf2c3715SXin Li       statbuf << "     <NAME> " << it.matname() << " </NAME>\n";
523*bf2c3715SXin Li       statbuf << "     <SIZE> " << it.matrix().rows() << " </SIZE>\n";
524*bf2c3715SXin Li       statbuf << "     <ENTRIES> " << it.matrix().nonZeros() << "</ENTRIES>\n";
525*bf2c3715SXin Li       if (it.sym()!=NonSymmetric)
526*bf2c3715SXin Li       {
527*bf2c3715SXin Li         statbuf << "     <SYMMETRY> Symmetric </SYMMETRY>\n" ;
528*bf2c3715SXin Li         if (it.sym() == SPD)
529*bf2c3715SXin Li           statbuf << "     <POSDEF> YES </POSDEF>\n";
530*bf2c3715SXin Li         else
531*bf2c3715SXin Li           statbuf << "     <POSDEF> NO </POSDEF>\n";
532*bf2c3715SXin Li 
533*bf2c3715SXin Li       }
534*bf2c3715SXin Li       else
535*bf2c3715SXin Li       {
536*bf2c3715SXin Li         statbuf << "     <SYMMETRY> NonSymmetric </SYMMETRY>\n" ;
537*bf2c3715SXin Li         statbuf << "     <POSDEF> NO </POSDEF>\n";
538*bf2c3715SXin Li       }
539*bf2c3715SXin Li       statbuf << "   </MATRIX> \n";
540*bf2c3715SXin Li       statbuf.close();
541*bf2c3715SXin Li     }
542*bf2c3715SXin Li 
543*bf2c3715SXin Li     cout<< "\n\n===================================================== \n";
544*bf2c3715SXin Li     cout<< " ======  SOLVING WITH MATRIX " << it.matname() << " ====\n";
545*bf2c3715SXin Li     cout<< " =================================================== \n\n";
546*bf2c3715SXin Li     Matrix<Scalar, Dynamic, 1> refX;
547*bf2c3715SXin Li     if(it.hasrefX()) refX = it.refX();
548*bf2c3715SXin Li     // Call all suitable solvers for this linear system
549*bf2c3715SXin Li     SelectSolvers<Scalar>(it.matrix(), it.sym(), it.rhs(), refX, statFile);
550*bf2c3715SXin Li 
551*bf2c3715SXin Li     if(statFileExists)
552*bf2c3715SXin Li     {
553*bf2c3715SXin Li       std::ofstream statbuf(statFile.c_str(), std::ios::app);
554*bf2c3715SXin Li       statbuf << "  <BEST_SOLVER ID='"<< best_time_id
555*bf2c3715SXin Li               << "'></BEST_SOLVER>\n";
556*bf2c3715SXin Li       statbuf << " </LINEARSYSTEM> \n";
557*bf2c3715SXin Li       statbuf.close();
558*bf2c3715SXin Li     }
559*bf2c3715SXin Li   }
560*bf2c3715SXin Li }
561*bf2c3715SXin Li 
562*bf2c3715SXin Li bool get_options(int argc, char **args, string option, string* value=0)
563*bf2c3715SXin Li {
564*bf2c3715SXin Li   int idx = 1, found=false;
565*bf2c3715SXin Li   while (idx<argc && !found){
566*bf2c3715SXin Li     if (option.compare(args[idx]) == 0){
567*bf2c3715SXin Li       found = true;
568*bf2c3715SXin Li       if(value) *value = args[idx+1];
569*bf2c3715SXin Li     }
570*bf2c3715SXin Li     idx+=2;
571*bf2c3715SXin Li   }
572*bf2c3715SXin Li   return found;
573*bf2c3715SXin Li }
574