spbenchsolver.h 18 KB

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