sparse_solver.h File Reference
#include "sparse.h"
#include <Eigen/SparseCore>
#include <Eigen/SparseLU>
#include <sstream>

Go to the source code of this file.

Classes

struct  prune_column
 

Functions

template<typename Solver , typename Rhs , typename Guess , typename Result >
void solve_with_guess (IterativeSolverBase< Solver > &solver, const MatrixBase< Rhs > &b, const Guess &g, Result &x)
 
template<typename Solver , typename Rhs , typename Guess , typename Result >
void solve_with_guess (SparseSolverBase< Solver > &solver, const MatrixBase< Rhs > &b, const Guess &, Result &x)
 
template<typename Solver , typename Rhs , typename Guess , typename Result >
void solve_with_guess (SparseSolverBase< Solver > &solver, const SparseMatrixBase< Rhs > &b, const Guess &, Result &x)
 
template<typename Solver , typename Rhs , typename DenseMat , typename DenseRhs >
void check_sparse_solving (Solver &solver, const typename Solver::MatrixType &A, const Rhs &b, const DenseMat &dA, const DenseRhs &db)
 
template<typename Scalar , typename Rhs , typename DenseMat , typename DenseRhs >
void check_sparse_solving (Eigen::SparseLU< Eigen::SparseMatrix< Scalar >> &solver, const typename Eigen::SparseMatrix< Scalar > &A, const Rhs &b, const DenseMat &dA, const DenseRhs &db)
 
template<typename Solver , typename Rhs >
void check_sparse_solving_real_cases (Solver &solver, const typename Solver::MatrixType &A, const Rhs &b, const typename Solver::MatrixType &fullA, const Rhs &refX)
 
template<typename Solver , typename DenseMat >
void check_sparse_determinant (Solver &solver, const typename Solver::MatrixType &A, const DenseMat &dA)
 
template<typename Solver , typename DenseMat >
void check_sparse_abs_determinant (Solver &solver, const typename Solver::MatrixType &A, const DenseMat &dA)
 
template<typename Solver , typename DenseMat >
int generate_sparse_spd_problem (Solver &, typename Solver::MatrixType &A, typename Solver::MatrixType &halfA, DenseMat &dA, int maxSize=300)
 
template<typename Solver >
void check_sparse_spd_solving (Solver &solver, int maxSize=(std::min)(300, EIGEN_TEST_MAX_SIZE), int maxRealWorldSize=100000)
 
template<typename Solver >
void check_sparse_spd_determinant (Solver &solver)
 
template<typename Solver , typename DenseMat >
int generate_sparse_nonhermitian_problem (Solver &, typename Solver::MatrixType &A, typename Solver::MatrixType &halfA, DenseMat &dA, int maxSize=300)
 
template<typename Solver >
void check_sparse_nonhermitian_solving (Solver &solver, int maxSize=(std::min)(300, EIGEN_TEST_MAX_SIZE), int maxRealWorldSize=100000)
 
template<typename Solver >
void check_sparse_nonhermitian_determinant (Solver &solver)
 
template<typename Solver >
void check_sparse_zero_matrix (Solver &solver)
 
template<typename Solver , typename DenseMat >
Index generate_sparse_square_problem (Solver &, typename Solver::MatrixType &A, DenseMat &dA, int maxSize=300, int options=ForceNonZeroDiag)
 
template<typename Solver >
void check_sparse_square_solving (Solver &solver, int maxSize=300, int maxRealWorldSize=100000, bool checkDeficient=false)
 
template<typename Solver >
void check_sparse_square_determinant (Solver &solver)
 
template<typename Solver >
void check_sparse_square_abs_determinant (Solver &solver)
 
template<typename Solver , typename DenseMat >
void generate_sparse_leastsquare_problem (Solver &, typename Solver::MatrixType &A, DenseMat &dA, int maxSize=300, int options=ForceNonZeroDiag)
 
template<typename Solver >
void check_sparse_leastsquare_solving (Solver &solver)
 

Function Documentation

◆ check_sparse_abs_determinant()

template<typename Solver , typename DenseMat >
void check_sparse_abs_determinant ( Solver &  solver,
const typename Solver::MatrixType A,
const DenseMat &  dA 
)
322  {
323  using std::abs;
324  typedef typename Solver::MatrixType Mat;
325  typedef typename Mat::Scalar Scalar;
326 
327  solver.compute(A);
328  if (solver.info() != Success) {
329  std::cerr << "WARNING | sparse solver testing: factorization failed (check_sparse_abs_determinant)\n";
330  return;
331  }
332 
333  Scalar refDet = abs(dA.determinant());
334  VERIFY_IS_APPROX(refDet, solver.absDeterminant());
335 }
AnnoyingScalar abs(const AnnoyingScalar &x)
Definition: AnnoyingScalar.h:135
BiCGSTAB< SparseMatrix< double > > solver
Definition: BiCGSTAB_simple.cpp:5
SCALAR Scalar
Definition: bench_gemm.cpp:45
MatrixXf MatrixType
Definition: benchmark-blocking-sizes.cpp:52
The matrix class, also used for vectors and row-vectors.
Definition: Eigen/Eigen/src/Core/Matrix.h:186
internal::traits< Derived >::Scalar Scalar
Definition: PlainObjectBase.h:127
Matrix< Scalar, Dynamic, Dynamic > Mat
Definition: gemm_common.h:15
@ Success
Definition: Constants.h:440
#define VERIFY_IS_APPROX(a, b)
Definition: integer_types.cpp:13

References abs(), solver, Eigen::Success, and VERIFY_IS_APPROX.

Referenced by check_sparse_square_abs_determinant().

◆ check_sparse_determinant()

template<typename Solver , typename DenseMat >
void check_sparse_determinant ( Solver &  solver,
const typename Solver::MatrixType A,
const DenseMat &  dA 
)
308  {
309  typedef typename Solver::MatrixType Mat;
310  typedef typename Mat::Scalar Scalar;
311 
312  solver.compute(A);
313  if (solver.info() != Success) {
314  std::cerr << "WARNING | sparse solver testing: factorization failed (check_sparse_determinant)\n";
315  return;
316  }
317 
318  Scalar refDet = dA.determinant();
319  VERIFY_IS_APPROX(refDet, solver.determinant());
320 }

References solver, Eigen::Success, and VERIFY_IS_APPROX.

Referenced by check_sparse_nonhermitian_determinant(), check_sparse_spd_determinant(), and check_sparse_square_determinant().

◆ check_sparse_leastsquare_solving()

template<typename Solver >
void check_sparse_leastsquare_solving ( Solver &  solver)
738  {
739  typedef typename Solver::MatrixType Mat;
740  typedef typename Mat::Scalar Scalar;
744 
745  int rhsCols = internal::random<int>(1, 16);
746 
747  Mat A;
748  DenseMatrix dA;
749  for (int i = 0; i < g_repeat; i++) {
751 
752  A.makeCompressed();
753  DenseVector b = DenseVector::Random(A.rows());
754  DenseMatrix dB(A.rows(), rhsCols);
755  SpMat B(A.rows(), rhsCols);
756  double density = (std::max)(8. / (A.rows() * rhsCols), 0.1);
757  initSparse<Scalar>(density, dB, B, ForceNonZeroDiag);
758  B.makeCompressed();
759  check_sparse_solving(solver, A, b, dA, b);
760  check_sparse_solving(solver, A, dB, dA, dB);
761  check_sparse_solving(solver, A, B, dA, dB);
762 
763  // check only once
764  if (i == 0) {
765  b = DenseVector::Zero(A.rows());
766  check_sparse_solving(solver, A, b, dA, b);
767  }
768  }
769 }
Matrix< Scalar, Dynamic, Dynamic > DenseMatrix
Definition: BenchSparseUtil.h:23
Matrix< Scalar, Dynamic, 1 > DenseVector
Definition: BenchSparseUtil.h:24
int i
Definition: BiCGSTAB_step_by_step.cpp:9
Eigen::SparseMatrix< double > SpMat
Definition: Tutorial_sparse_example.cpp:5
Scalar * b
Definition: benchVecAdd.cpp:17
Matrix< SCALARA, Dynamic, Dynamic, opt_A > A
Definition: bench_gemm.cpp:47
Matrix< SCALARB, Dynamic, Dynamic, opt_B > B
Definition: bench_gemm.cpp:48
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT
Definition: PlainObjectBase.h:191
A versatible sparse matrix representation.
Definition: SparseMatrix.h:121
Definition: matrices.h:74
#define max(a, b)
Definition: datatypes.h:23
static int g_repeat
Definition: main.h:191
density
Definition: UniformPSDSelfTest.py:19
double Zero
Definition: pseudosolid_node_update_elements.cc:35
@ ForceNonZeroDiag
Definition: sparse.h:32
void generate_sparse_leastsquare_problem(Solver &, typename Solver::MatrixType &A, DenseMat &dA, int maxSize=300, int options=ForceNonZeroDiag)
Definition: sparse_solver.h:722
void check_sparse_solving(Solver &solver, const typename Solver::MatrixType &A, const Rhs &b, const DenseMat &dA, const DenseRhs &db)
Definition: sparse_solver.h:40

References b, check_sparse_solving(), UniformPSDSelfTest::density, ForceNonZeroDiag, Eigen::g_repeat, generate_sparse_leastsquare_problem(), i, max, Eigen::PlainObjectBase< Derived >::rows(), solver, and oomph::PseudoSolidHelper::Zero.

Referenced by test_lscg_T().

◆ check_sparse_nonhermitian_determinant()

template<typename Solver >
void check_sparse_nonhermitian_determinant ( Solver &  solver)
561  {
562  typedef typename Solver::MatrixType Mat;
563  typedef typename Mat::Scalar Scalar;
565 
566  // generate the problem
567  Mat A, halfA;
568  DenseMatrix dA;
570 
571  for (int i = 0; i < g_repeat; i++) {
573  check_sparse_determinant(solver, halfA, dA);
574  }
575 }
int generate_sparse_nonhermitian_problem(Solver &, typename Solver::MatrixType &A, typename Solver::MatrixType &halfA, DenseMat &dA, int maxSize=300)
Definition: sparse_solver.h:488
void check_sparse_determinant(Solver &solver, const typename Solver::MatrixType &A, const DenseMat &dA)
Definition: sparse_solver.h:308

References check_sparse_determinant(), Eigen::g_repeat, generate_sparse_nonhermitian_problem(), i, and solver.

Referenced by test_simplicial_cholesky_T().

◆ check_sparse_nonhermitian_solving()

template<typename Solver >
void check_sparse_nonhermitian_solving ( Solver &  solver,
int  maxSize = (std::min)(300, EIGEN_TEST_MAX_SIZE),
int  maxRealWorldSize = 100000 
)
516  {
517  typedef typename Solver::MatrixType Mat;
518  typedef typename Mat::Scalar Scalar;
519  typedef typename Mat::StorageIndex StorageIndex;
524 
525  // generate the problem
526  Mat A, halfA;
527  DenseMatrix dA;
528  for (int i = 0; i < g_repeat; i++) {
529  int size = generate_sparse_nonhermitian_problem(solver, A, halfA, dA, maxSize);
530 
531  // generate the right hand sides
532  int rhsCols = internal::random<int>(1, 16);
533  double density = (std::max)(8. / static_cast<double>(size * rhsCols), 0.1);
534  SpMat B(size, rhsCols);
535  DenseVector b = DenseVector::Random(size);
536  DenseMatrix dB(size, rhsCols);
537  initSparse<Scalar>(density, dB, B, ForceNonZeroDiag);
538  SpVec c = B.col(0);
539  DenseVector dc = dB.col(0);
540 
542  CALL_SUBTEST(check_sparse_solving(solver, halfA, b, dA, b));
543  CALL_SUBTEST(check_sparse_solving(solver, A, dB, dA, dB));
544  CALL_SUBTEST(check_sparse_solving(solver, halfA, dB, dA, dB));
546  CALL_SUBTEST(check_sparse_solving(solver, halfA, B, dA, dB));
548  CALL_SUBTEST(check_sparse_solving(solver, halfA, c, dA, dc));
549 
550  // check only once
551  if (i == 0) {
553  check_sparse_solving(solver, A, b, dA, b);
554  }
555  }
556 
557  EIGEN_UNUSED_VARIABLE(maxRealWorldSize);
558 }
#define EIGEN_UNUSED_VARIABLE(var)
Definition: Macros.h:966
Scalar Scalar int size
Definition: benchVecAdd.cpp:17
a sparse vector class
Definition: SparseVector.h:62
#define CALL_SUBTEST(FUNC)
Definition: main.h:382
int c
Definition: calibrate.py:100

References b, calibrate::c, CALL_SUBTEST, check_sparse_solving(), UniformPSDSelfTest::density, EIGEN_UNUSED_VARIABLE, ForceNonZeroDiag, Eigen::g_repeat, generate_sparse_nonhermitian_problem(), i, max, size, solver, and oomph::PseudoSolidHelper::Zero.

Referenced by test_simplicial_cholesky_T().

◆ check_sparse_solving() [1/2]

template<typename Scalar , typename Rhs , typename DenseMat , typename DenseRhs >
void check_sparse_solving ( Eigen::SparseLU< Eigen::SparseMatrix< Scalar >> &  solver,
const typename Eigen::SparseMatrix< Scalar > &  A,
const Rhs &  b,
const DenseMat &  dA,
const DenseRhs &  db 
)
156  {
157  typedef typename Eigen::SparseMatrix<Scalar> Mat;
158  typedef typename Mat::StorageIndex StorageIndex;
159  typedef typename Eigen::SparseLU<Eigen::SparseMatrix<Scalar>> Solver;
160 
161  // reference solutions computed by dense QR solver
162  DenseRhs refX1 = dA.householderQr().solve(db); // solution of A x = db
163  DenseRhs refX2 = dA.transpose().householderQr().solve(db); // solution of A^T * x = db (use transposed matrix A^T)
164  DenseRhs refX3 = dA.adjoint().householderQr().solve(db); // solution of A^* * x = db (use adjoint matrix A^*)
165 
166  {
167  Rhs x1(A.cols(), b.cols());
168  Rhs x2(A.cols(), b.cols());
169  Rhs x3(A.cols(), b.cols());
170  Rhs oldb = b;
171 
172  solver.compute(A);
173  if (solver.info() != Success) {
174  std::cerr << "ERROR | sparse solver testing, factorization failed (" << typeid(Solver).name() << ")\n";
175  VERIFY(solver.info() == Success);
176  }
177  x1 = solver.solve(b);
178  if (solver.info() != Success) {
179  std::cerr << "WARNING | sparse solver testing: solving failed (" << typeid(Solver).name() << ")\n";
180  return;
181  }
182  VERIFY(oldb.isApprox(b, 0.0) && "sparse solver testing: the rhs should not be modified!");
183  VERIFY(x1.isApprox(refX1, test_precision<Scalar>()));
184 
185  // test solve with transposed
186  x2 = solver.transpose().solve(b);
187  VERIFY(oldb.isApprox(b) && "sparse solver testing: the rhs should not be modified!");
188  VERIFY(x2.isApprox(refX2, test_precision<Scalar>()));
189 
190  // test solve with adjoint
191  // solver.template _solve_impl_transposed<true>(b, x3);
192  x3 = solver.adjoint().solve(b);
193  VERIFY(oldb.isApprox(b, 0.0) && "sparse solver testing: the rhs should not be modified!");
194  VERIFY(x3.isApprox(refX3, test_precision<Scalar>()));
195 
196  x1.setZero();
198  VERIFY(solver.info() == Success && "solving failed when using analyzePattern/factorize API");
199  VERIFY(oldb.isApprox(b, 0.0) && "sparse solver testing: the rhs should not be modified!");
200  VERIFY(x1.isApprox(refX1, test_precision<Scalar>()));
201 
202  x1.setZero();
203  x2.setZero();
204  x3.setZero();
205  // test the analyze/factorize API
206  solver.analyzePattern(A);
207  solver.factorize(A);
208  VERIFY(solver.info() == Success && "factorization failed when using analyzePattern/factorize API");
209  x1 = solver.solve(b);
210  x2 = solver.transpose().solve(b);
211  x3 = solver.adjoint().solve(b);
212 
213  VERIFY(solver.info() == Success && "solving failed when using analyzePattern/factorize API");
214  VERIFY(oldb.isApprox(b, 0.0) && "sparse solver testing: the rhs should not be modified!");
215  VERIFY(x1.isApprox(refX1, test_precision<Scalar>()));
216  VERIFY(x2.isApprox(refX2, test_precision<Scalar>()));
217  VERIFY(x3.isApprox(refX3, test_precision<Scalar>()));
218 
219  x1.setZero();
220  // test with Map
222  A.rows(), A.cols(), A.nonZeros(), const_cast<StorageIndex*>(A.outerIndexPtr()),
223  const_cast<StorageIndex*>(A.innerIndexPtr()), const_cast<Scalar*>(A.valuePtr()));
224  solver.compute(Am);
225  VERIFY(solver.info() == Success && "factorization failed when using Map");
226  DenseRhs dx(refX1);
227  dx.setZero();
228  Map<DenseRhs> xm(dx.data(), dx.rows(), dx.cols());
229  Map<const DenseRhs> bm(db.data(), db.rows(), db.cols());
230  xm = solver.solve(bm);
231  VERIFY(solver.info() == Success && "solving failed when using Map");
232  VERIFY(oldb.isApprox(bm, 0.0) && "sparse solver testing: the rhs should not be modified!");
233  VERIFY(xm.isApprox(refX1, test_precision<Scalar>()));
234  }
235 
236  // if not too large, do some extra check:
237  if (A.rows() < 2000) {
238  // test initialization ctor
239  {
240  Rhs x(b.rows(), b.cols());
241  Solver solver2(A);
242  VERIFY(solver2.info() == Success);
243  x = solver2.solve(b);
244  VERIFY(x.isApprox(refX1, test_precision<Scalar>()));
245  }
246 
247  // test dense Block as the result and rhs:
248  {
249  DenseRhs x(refX1.rows(), refX1.cols());
250  DenseRhs oldb(db);
251  x.setZero();
252  x.block(0, 0, x.rows(), x.cols()) = solver.solve(db.block(0, 0, db.rows(), db.cols()));
253  VERIFY(oldb.isApprox(db, 0.0) && "sparse solver testing: the rhs should not be modified!");
254  VERIFY(x.isApprox(refX1, test_precision<Scalar>()));
255  }
256 
257  // test uncompressed inputs
258  {
259  Mat A2 = A;
260  A2.reserve((ArrayXf::Random(A.outerSize()) + 2).template cast<typename Mat::StorageIndex>().eval());
261  solver.compute(A2);
262  Rhs x = solver.solve(b);
263  VERIFY(x.isApprox(refX1, test_precision<Scalar>()));
264  }
265 
266  // test expression as input
267  {
268  solver.compute(0.5 * (A + A));
269  Rhs x = solver.solve(b);
270  VERIFY(x.isApprox(refX1, test_precision<Scalar>()));
271 
272  Solver solver2(0.5 * (A + A));
273  Rhs x2 = solver2.solve(b);
274  VERIFY(x2.isApprox(refX1, test_precision<Scalar>()));
275  }
276  }
277 }
A matrix or vector expression mapping an existing array of data.
Definition: Map.h:96
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT
Definition: PlainObjectBase.h:192
Sparse supernodal LU factorization for general matrices.
Definition: SparseLU.h:151
const Solve< Derived, Rhs > solve(const MatrixBase< Rhs > &b) const
Definition: SparseSolverBase.h:84
#define VERIFY(a)
Definition: main.h:362
@ Rhs
Definition: TensorContractionMapper.h:20
Vector< double > x1(const Vector< double > &coord)
Cartesian coordinates centered at the point (0.5,1)
Definition: poisson/poisson_with_singularity/two_d_poisson.cc:86
Vector< double > x2(const Vector< double > &coord)
Cartesian coordinates centered at the point (1.5,1)
Definition: poisson/poisson_with_singularity/two_d_poisson.cc:102
list x
Definition: plotDoE.py:28
string name
Definition: plotDoE.py:33
void solve_with_guess(IterativeSolverBase< Solver > &solver, const MatrixBase< Rhs > &b, const Guess &g, Result &x)
Definition: sparse_solver.h:16

References b, Eigen::PlainObjectBase< Derived >::cols(), plotDoE::name, Eigen::internal::Rhs, Eigen::PlainObjectBase< Derived >::rows(), Eigen::SparseSolverBase< Derived >::solve(), solve_with_guess(), solver, Eigen::Success, VERIFY, plotDoE::x, Global_parameters::x1(), and Global_parameters::x2().

◆ check_sparse_solving() [2/2]

template<typename Solver , typename Rhs , typename DenseMat , typename DenseRhs >
void check_sparse_solving ( Solver &  solver,
const typename Solver::MatrixType A,
const Rhs &  b,
const DenseMat &  dA,
const DenseRhs &  db 
)
41  {
42  typedef typename Solver::MatrixType Mat;
43  typedef typename Mat::Scalar Scalar;
44  typedef typename Mat::StorageIndex StorageIndex;
45 
46  DenseRhs refX = dA.householderQr().solve(db);
47  {
48  Rhs x(A.cols(), b.cols());
49  Rhs oldb = b;
50 
51  solver.compute(A);
52  if (solver.info() != Success) {
53  std::cerr << "ERROR | sparse solver testing, factorization failed (" << typeid(Solver).name() << ")\n";
54  VERIFY(solver.info() == Success);
55  }
56  x = solver.solve(b);
57  if (solver.info() != Success) {
58  std::cerr << "WARNING: sparse solver testing: solving failed (" << typeid(Solver).name() << ")\n";
59  // dump call stack:
60  g_test_level++;
61  VERIFY(solver.info() == Success);
62  g_test_level--;
63  return;
64  }
65  VERIFY(oldb.isApprox(b) && "sparse solver testing: the rhs should not be modified!");
66  VERIFY(x.isApprox(refX, test_precision<Scalar>()));
67 
68  x.setZero();
70  VERIFY(solver.info() == Success && "solving failed when using solve_with_guess API");
71  VERIFY(oldb.isApprox(b) && "sparse solver testing: the rhs should not be modified!");
72  VERIFY(x.isApprox(refX, test_precision<Scalar>()));
73 
74  x.setZero();
75  // test the analyze/factorize API
76  solver.analyzePattern(A);
77  solver.factorize(A);
78  VERIFY(solver.info() == Success && "factorization failed when using analyzePattern/factorize API");
79  x = solver.solve(b);
80  VERIFY(solver.info() == Success && "solving failed when using analyzePattern/factorize API");
81  VERIFY(oldb.isApprox(b) && "sparse solver testing: the rhs should not be modified!");
82  VERIFY(x.isApprox(refX, test_precision<Scalar>()));
83 
84  x.setZero();
85  // test with Map
87  A.rows(), A.cols(), A.nonZeros(), const_cast<StorageIndex*>(A.outerIndexPtr()),
88  const_cast<StorageIndex*>(A.innerIndexPtr()), const_cast<Scalar*>(A.valuePtr()));
89  solver.compute(Am);
90  VERIFY(solver.info() == Success && "factorization failed when using Map");
91  DenseRhs dx(refX);
92  dx.setZero();
93  Map<DenseRhs> xm(dx.data(), dx.rows(), dx.cols());
94  Map<const DenseRhs> bm(db.data(), db.rows(), db.cols());
95  xm = solver.solve(bm);
96  VERIFY(solver.info() == Success && "solving failed when using Map");
97  VERIFY(oldb.isApprox(bm) && "sparse solver testing: the rhs should not be modified!");
98  VERIFY(xm.isApprox(refX, test_precision<Scalar>()));
99 
100  // Test with a Map and non-unit stride.
101  Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> out(2 * xm.rows(), 2 * xm.cols());
102  out.setZero();
103  Eigen::Map<DenseRhs, 0, Stride<Eigen::Dynamic, 2>> outm(out.data(), xm.rows(), xm.cols(),
104  Stride<Eigen::Dynamic, 2>(2 * xm.rows(), 2));
105  outm = solver.solve(bm);
106  VERIFY(outm.isApprox(refX, test_precision<Scalar>()));
107  }
108 
109  // if not too large, do some extra check:
110  if (A.rows() < 2000) {
111  // test initialization ctor
112  {
113  Rhs x(b.rows(), b.cols());
114  Solver solver2(A);
115  VERIFY(solver2.info() == Success);
116  x = solver2.solve(b);
117  VERIFY(x.isApprox(refX, test_precision<Scalar>()));
118  }
119 
120  // test dense Block as the result and rhs:
121  {
122  DenseRhs x(refX.rows(), refX.cols());
123  DenseRhs oldb(db);
124  x.setZero();
125  x.block(0, 0, x.rows(), x.cols()) = solver.solve(db.block(0, 0, db.rows(), db.cols()));
126  VERIFY(oldb.isApprox(db) && "sparse solver testing: the rhs should not be modified!");
127  VERIFY(x.isApprox(refX, test_precision<Scalar>()));
128  }
129 
130  // test uncompressed inputs
131  {
132  Mat A2 = A;
133  A2.reserve((ArrayXf::Random(A.outerSize()) + 2).template cast<typename Mat::StorageIndex>().eval());
134  solver.compute(A2);
135  Rhs x = solver.solve(b);
136  VERIFY(x.isApprox(refX, test_precision<Scalar>()));
137  }
138 
139  // test expression as input
140  {
141  solver.compute(0.5 * (A + A));
142  Rhs x = solver.solve(b);
143  VERIFY(x.isApprox(refX, test_precision<Scalar>()));
144 
145  Solver solver2(0.5 * (A + A));
146  Rhs x2 = solver2.solve(b);
147  VERIFY(x2.isApprox(refX, test_precision<Scalar>()));
148  }
149  }
150 }
Holds strides information for Map.
Definition: Stride.h:55
static int g_test_level
Definition: main.h:190
std::ofstream out("Result.txt")

References b, Eigen::PlainObjectBase< Derived >::cols(), Eigen::g_test_level, plotDoE::name, out(), Eigen::internal::Rhs, Eigen::PlainObjectBase< Derived >::rows(), solve_with_guess(), solver, Eigen::Success, VERIFY, plotDoE::x, and Global_parameters::x2().

Referenced by check_sparse_leastsquare_solving(), check_sparse_nonhermitian_solving(), check_sparse_spd_solving(), and check_sparse_square_solving().

◆ check_sparse_solving_real_cases()

template<typename Solver , typename Rhs >
void check_sparse_solving_real_cases ( Solver &  solver,
const typename Solver::MatrixType A,
const Rhs &  b,
const typename Solver::MatrixType fullA,
const Rhs &  refX 
)
281  {
282  typedef typename Solver::MatrixType Mat;
283  typedef typename Mat::Scalar Scalar;
284  typedef typename Mat::RealScalar RealScalar;
285 
286  Rhs x(A.cols(), b.cols());
287 
288  solver.compute(A);
289  if (solver.info() != Success) {
290  std::cerr << "ERROR | sparse solver testing, factorization failed (" << typeid(Solver).name() << ")\n";
291  VERIFY(solver.info() == Success);
292  }
293  x = solver.solve(b);
294 
295  if (solver.info() != Success) {
296  std::cerr << "WARNING | sparse solver testing, solving failed (" << typeid(Solver).name() << ")\n";
297  return;
298  }
299 
300  RealScalar res_error = (fullA * x - b).norm() / b.norm();
301  VERIFY((res_error <= test_precision<Scalar>()) && "sparse solver failed without noticing it");
302 
303  if (refX.size() != 0 && (refX - x).norm() / refX.norm() > test_precision<Scalar>()) {
304  std::cerr << "WARNING | found solution is different from the provided reference one\n";
305  }
306 }
NumTraits< Scalar >::Real RealScalar
Definition: bench_gemm.cpp:46
NumTraits< Scalar >::Real RealScalar
Definition: PlainObjectBase.h:130

References b, Eigen::PlainObjectBase< Derived >::cols(), plotDoE::name, Eigen::internal::Rhs, solver, Eigen::Success, VERIFY, and plotDoE::x.

Referenced by check_sparse_spd_solving(), and check_sparse_square_solving().

◆ check_sparse_spd_determinant()

template<typename Solver >
void check_sparse_spd_determinant ( Solver &  solver)
471  {
472  typedef typename Solver::MatrixType Mat;
473  typedef typename Mat::Scalar Scalar;
475 
476  // generate the problem
477  Mat A, halfA;
478  DenseMatrix dA;
479  generate_sparse_spd_problem(solver, A, halfA, dA, 30);
480 
481  for (int i = 0; i < g_repeat; i++) {
483  check_sparse_determinant(solver, halfA, dA);
484  }
485 }
int generate_sparse_spd_problem(Solver &, typename Solver::MatrixType &A, typename Solver::MatrixType &halfA, DenseMat &dA, int maxSize=300)
Definition: sparse_solver.h:338

References check_sparse_determinant(), Eigen::g_repeat, generate_sparse_spd_problem(), i, and solver.

Referenced by test_cholmod_ST(), and test_simplicial_cholesky_T().

◆ check_sparse_spd_solving()

template<typename Solver >
void check_sparse_spd_solving ( Solver &  solver,
int  maxSize = (std::min)(300, EIGEN_TEST_MAX_SIZE),
int  maxRealWorldSize = 100000 
)
393  {
394  typedef typename Solver::MatrixType Mat;
395  typedef typename Mat::Scalar Scalar;
396  typedef typename Mat::StorageIndex StorageIndex;
401 
402  // generate the problem
403  Mat A, halfA;
404  DenseMatrix dA;
405  for (int i = 0; i < g_repeat; i++) {
406  int size = generate_sparse_spd_problem(solver, A, halfA, dA, maxSize);
407 
408  // generate the right hand sides
409  int rhsCols = internal::random<int>(1, 16);
410  double density = (std::max)(8. / static_cast<double>(size * rhsCols), 0.1);
411  SpMat B(size, rhsCols);
412  DenseVector b = DenseVector::Random(size);
413  DenseMatrix dB(size, rhsCols);
414  initSparse<Scalar>(density, dB, B, ForceNonZeroDiag);
415  SpVec c = B.col(0);
416  DenseVector dc = dB.col(0);
417 
419  CALL_SUBTEST(check_sparse_solving(solver, halfA, b, dA, b));
420  CALL_SUBTEST(check_sparse_solving(solver, A, dB, dA, dB));
421  CALL_SUBTEST(check_sparse_solving(solver, halfA, dB, dA, dB));
423  CALL_SUBTEST(check_sparse_solving(solver, halfA, B, dA, dB));
425  CALL_SUBTEST(check_sparse_solving(solver, halfA, c, dA, dc));
426 
427  // check only once
428  if (i == 0) {
430  check_sparse_solving(solver, A, b, dA, b);
431  }
432  }
433 
434  // First, get the folder
435 #ifdef TEST_REAL_CASES
436  // Test real problems with double precision only
437  if (internal::is_same<typename NumTraits<Scalar>::Real, double>::value) {
438  std::string mat_folder = get_matrixfolder<Scalar>();
439  MatrixMarketIterator<Scalar> it(mat_folder);
440  for (; it; ++it) {
441  if (it.sym() == SPD) {
442  A = it.matrix();
443  if (A.diagonal().size() <= maxRealWorldSize) {
444  DenseVector b = it.rhs();
445  DenseVector refX = it.refX();
447  halfA.resize(A.rows(), A.cols());
448  if (Solver::UpLo == (Lower | Upper))
449  halfA = A;
450  else
451  halfA.template selfadjointView<Solver::UpLo>() = A.template triangularView<Eigen::Lower>().twistedBy(pnull);
452 
453  std::cout << "INFO | Testing " << sym_to_string(it.sym()) << "sparse problem " << it.matname() << " ("
454  << A.rows() << "x" << A.cols() << ") using " << typeid(Solver).name() << "..." << std::endl;
456  std::string stats = solver_stats(solver);
457  if (stats.size() > 0) std::cout << "INFO | " << stats << std::endl;
459  } else {
460  std::cout << "INFO | Skip sparse problem \"" << it.matname() << "\" (too large)" << std::endl;
461  }
462  }
463  }
464  }
465 #else
466  EIGEN_UNUSED_VARIABLE(maxRealWorldSize);
467 #endif
468 }
Iterator to browse matrices from a specified folder.
Definition: MatrixMarketIterator.h:42
EIGEN_DEVICE_FUNC constexpr EIGEN_STRONG_INLINE void resize(Index rows, Index cols)
Definition: PlainObjectBase.h:294
@ Lower
Definition: Constants.h:211
@ Upper
Definition: Constants.h:213
squared absolute value
Definition: GlobalFunctions.h:87
@ SPD
Definition: MatrixMarketIterator.h:19
std::string string(const unsigned &i)
Definition: oomph_definitions.cc:286
void check_sparse_solving_real_cases(Solver &solver, const typename Solver::MatrixType &A, const Rhs &b, const typename Solver::MatrixType &fullA, const Rhs &refX)
Definition: sparse_solver.h:280
Holds information about the various numeric (i.e. scalar) types allowed by Eigen.
Definition: NumTraits.h:217

References b, calibrate::c, CALL_SUBTEST, check_sparse_solving(), check_sparse_solving_real_cases(), Eigen::PlainObjectBase< Derived >::cols(), UniformPSDSelfTest::density, EIGEN_UNUSED_VARIABLE, ForceNonZeroDiag, Eigen::g_repeat, generate_sparse_spd_problem(), i, Eigen::Lower, Eigen::MatrixMarketIterator< Scalar >::matname(), Eigen::MatrixMarketIterator< Scalar >::matrix(), max, plotDoE::name, Eigen::MatrixMarketIterator< Scalar >::refX(), Eigen::PlainObjectBase< Derived >::resize(), Eigen::MatrixMarketIterator< Scalar >::rhs(), Eigen::PlainObjectBase< Derived >::rows(), size, solver, Eigen::SPD, oomph::Global_string_for_annotation::string(), Eigen::MatrixMarketIterator< Scalar >::sym(), Eigen::Upper, Eigen::value, and oomph::PseudoSolidHelper::Zero.

Referenced by test_cholmod_ST(), test_conjugate_gradient_T(), test_incomplete_cholesky_T(), test_minres_T(), test_pardiso_T(), test_pastix_T(), and test_simplicial_cholesky_T().

◆ check_sparse_square_abs_determinant()

template<typename Solver >
void check_sparse_square_abs_determinant ( Solver &  solver)
706  {
707  typedef typename Solver::MatrixType Mat;
708  typedef typename Mat::Scalar Scalar;
710 
711  for (int i = 0; i < g_repeat; i++) {
712  // generate the problem
713  Mat A;
714  DenseMatrix dA;
716  A.makeCompressed();
718  }
719 }
Index generate_sparse_square_problem(Solver &, typename Solver::MatrixType &A, DenseMat &dA, int maxSize=300, int options=ForceNonZeroDiag)
Definition: sparse_solver.h:587
void check_sparse_abs_determinant(Solver &solver, const typename Solver::MatrixType &A, const DenseMat &dA)
Definition: sparse_solver.h:322

References check_sparse_abs_determinant(), Eigen::g_repeat, generate_sparse_square_problem(), i, and solver.

Referenced by test_sparselu_T().

◆ check_sparse_square_determinant()

template<typename Solver >
void check_sparse_square_determinant ( Solver &  solver)
683  {
684  typedef typename Solver::MatrixType Mat;
685  typedef typename Mat::Scalar Scalar;
687 
688  for (int i = 0; i < g_repeat; i++) {
689  // generate the problem
690  Mat A;
691  DenseMatrix dA;
692 
693  int size = internal::random<int>(1, 30);
694  dA.setRandom(size, size);
695 
696  dA = (dA.array().abs() < 0.3).select(0, dA);
697  dA.diagonal() = (dA.diagonal().array() == 0).select(1, dA.diagonal());
698  A = dA.sparseView();
699  A.makeCompressed();
700 
702  }
703 }
Derived & setRandom(Index size)
Definition: Random.h:147

References check_sparse_determinant(), Eigen::g_repeat, i, Eigen::PlainObjectBase< Derived >::setRandom(), size, and solver.

Referenced by EIGEN_DECLARE_TEST(), test_sparselu_T(), and test_umfpack_support_T().

◆ check_sparse_square_solving()

template<typename Solver >
void check_sparse_square_solving ( Solver &  solver,
int  maxSize = 300,
int  maxRealWorldSize = 100000,
bool  checkDeficient = false 
)
614  {
615  typedef typename Solver::MatrixType Mat;
616  typedef typename Mat::Scalar Scalar;
621 
622  int rhsCols = internal::random<int>(1, 16);
623 
624  Mat A;
625  DenseMatrix dA;
626  for (int i = 0; i < g_repeat; i++) {
628 
629  A.makeCompressed();
630  DenseVector b = DenseVector::Random(size);
631  DenseMatrix dB(size, rhsCols);
632  SpMat B(size, rhsCols);
633  double density = (std::max)(8. / double(size * rhsCols), 0.1);
634  initSparse<Scalar>(density, dB, B, ForceNonZeroDiag);
635  B.makeCompressed();
636  SpVec c = B.col(0);
637  DenseVector dc = dB.col(0);
639  CALL_SUBTEST(check_sparse_solving(solver, A, dB, dA, dB));
642 
643  // check only once
644  if (i == 0) {
646  }
647  // regression test for Bug 792 (structurally rank deficient matrices):
648  if (checkDeficient && size > 1) {
649  Index col = internal::random<int>(0, int(size - 1));
650  A.prune(prune_column(col));
651  solver.compute(A);
653  }
654  }
655 
656  // First, get the folder
657 #ifdef TEST_REAL_CASES
658  // Test real problems with double precision only
659  if (internal::is_same<typename NumTraits<Scalar>::Real, double>::value) {
660  std::string mat_folder = get_matrixfolder<Scalar>();
661  MatrixMarketIterator<Scalar> it(mat_folder);
662  for (; it; ++it) {
663  A = it.matrix();
664  if (A.diagonal().size() <= maxRealWorldSize) {
665  DenseVector b = it.rhs();
666  DenseVector refX = it.refX();
667  std::cout << "INFO | Testing " << sym_to_string(it.sym()) << "sparse problem " << it.matname() << " ("
668  << A.rows() << "x" << A.cols() << ") using " << typeid(Solver).name() << "..." << std::endl;
670  std::string stats = solver_stats(solver);
671  if (stats.size() > 0) std::cout << "INFO | " << stats << std::endl;
672  } else {
673  std::cout << "INFO | SKIP sparse problem \"" << it.matname() << "\" (too large)" << std::endl;
674  }
675  }
676  }
677 #else
678  EIGEN_UNUSED_VARIABLE(maxRealWorldSize);
679 #endif
680 }
m col(1)
@ NumericalIssue
Definition: Constants.h:442
#define VERIFY_IS_EQUAL(a, b)
Definition: main.h:367
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:83
Definition: sparse_solver.h:603

References b, calibrate::c, CALL_SUBTEST, check_sparse_solving(), check_sparse_solving_real_cases(), col(), Eigen::PlainObjectBase< Derived >::cols(), UniformPSDSelfTest::density, EIGEN_UNUSED_VARIABLE, ForceNonZeroDiag, Eigen::g_repeat, generate_sparse_square_problem(), i, Eigen::MatrixMarketIterator< Scalar >::matname(), Eigen::MatrixMarketIterator< Scalar >::matrix(), max, plotDoE::name, Eigen::NumericalIssue, Eigen::MatrixMarketIterator< Scalar >::refX(), Eigen::MatrixMarketIterator< Scalar >::rhs(), Eigen::PlainObjectBase< Derived >::rows(), size, solver, oomph::Global_string_for_annotation::string(), Eigen::MatrixMarketIterator< Scalar >::sym(), Eigen::value, VERIFY_IS_EQUAL, and oomph::PseudoSolidHelper::Zero.

Referenced by EIGEN_DECLARE_TEST(), test_bicgstab_T(), test_bicgstabl_T(), test_dgmres_T(), test_gmres_T(), test_idrs_T(), test_idrstabl_T(), test_klu_support_T(), test_lscg_T(), test_metis_T(), test_pardiso_T(), test_pastix_T(), test_pastix_T_LU(), test_sparselu_T(), and test_umfpack_support_T().

◆ check_sparse_zero_matrix()

template<typename Solver >
void check_sparse_zero_matrix ( Solver &  solver)
578  {
579  typedef typename Solver::MatrixType Mat;
580 
581  Mat A(1, 1);
582  solver.compute(A);
584 }

References Eigen::NumericalIssue, solver, and VERIFY_IS_EQUAL.

Referenced by test_cholmod_ST().

◆ generate_sparse_leastsquare_problem()

template<typename Solver , typename DenseMat >
void generate_sparse_leastsquare_problem ( Solver &  ,
typename Solver::MatrixType A,
DenseMat &  dA,
int  maxSize = 300,
int  options = ForceNonZeroDiag 
)
723  {
724  typedef typename Solver::MatrixType Mat;
725  typedef typename Mat::Scalar Scalar;
726 
727  int rows = internal::random<int>(1, maxSize);
728  int cols = internal::random<int>(1, rows);
729  double density = (std::max)(8. / (rows * cols), 0.01);
730 
731  A.resize(rows, cols);
732  dA.resize(rows, cols);
733 
734  initSparse<Scalar>(density, dA, A, options);
735 }
int rows
Definition: Tutorial_commainit_02.cpp:1
int cols
Definition: Tutorial_commainit_02.cpp:1

References cols, UniformPSDSelfTest::density, max, Eigen::PlainObjectBase< Derived >::resize(), and rows.

Referenced by check_sparse_leastsquare_solving().

◆ generate_sparse_nonhermitian_problem()

template<typename Solver , typename DenseMat >
int generate_sparse_nonhermitian_problem ( Solver &  ,
typename Solver::MatrixType A,
typename Solver::MatrixType halfA,
DenseMat &  dA,
int  maxSize = 300 
)
489  {
490  typedef typename Solver::MatrixType Mat;
491  typedef typename Mat::Scalar Scalar;
493 
494  int size = internal::random<int>(1, maxSize);
495  double density = (std::max)(8. / static_cast<double>(size * size), 0.01);
496 
497  Mat M(size, size);
498  DenseMatrix dM(size, size);
499 
500  initSparse<Scalar>(density, dM, M, ForceNonZeroDiag);
501 
502  A = M * M.transpose();
503  dA = dM * dM.transpose();
504 
505  halfA.resize(size, size);
506  if (Solver::UpLo == (Lower | Upper))
507  halfA = A;
508  else
509  halfA = A.template triangularView<Solver::UpLo>();
510 
511  return size;
512 }
Matrix< RealScalar, Dynamic, Dynamic > M
Definition: bench_gemm.cpp:50

References UniformPSDSelfTest::density, ForceNonZeroDiag, Eigen::Lower, max, Eigen::PlainObjectBase< Derived >::resize(), size, and Eigen::Upper.

Referenced by check_sparse_nonhermitian_determinant(), and check_sparse_nonhermitian_solving().

◆ generate_sparse_spd_problem()

template<typename Solver , typename DenseMat >
int generate_sparse_spd_problem ( Solver &  ,
typename Solver::MatrixType A,
typename Solver::MatrixType halfA,
DenseMat &  dA,
int  maxSize = 300 
)
339  {
340  typedef typename Solver::MatrixType Mat;
341  typedef typename Mat::Scalar Scalar;
343 
344  int size = internal::random<int>(1, maxSize);
345  double density = (std::max)(8. / static_cast<double>(size * size), 0.01);
346 
347  Mat M(size, size);
348  DenseMatrix dM(size, size);
349 
350  initSparse<Scalar>(density, dM, M, ForceNonZeroDiag);
351 
352  A = M * M.adjoint();
353  dA = dM * dM.adjoint();
354 
355  halfA.resize(size, size);
356  if (Solver::UpLo == (Lower | Upper))
357  halfA = A;
358  else
359  halfA.template selfadjointView<Solver::UpLo>().rankUpdate(M);
360 
361  return size;
362 }

References UniformPSDSelfTest::density, ForceNonZeroDiag, Eigen::Lower, max, Eigen::PlainObjectBase< Derived >::resize(), size, and Eigen::Upper.

Referenced by check_sparse_spd_determinant(), and check_sparse_spd_solving().

◆ generate_sparse_square_problem()

template<typename Solver , typename DenseMat >
Index generate_sparse_square_problem ( Solver &  ,
typename Solver::MatrixType A,
DenseMat &  dA,
int  maxSize = 300,
int  options = ForceNonZeroDiag 
)
588  {
589  typedef typename Solver::MatrixType Mat;
590  typedef typename Mat::Scalar Scalar;
591 
592  Index size = internal::random<int>(1, maxSize);
593  double density = (std::max)(8. / static_cast<double>(size * size), 0.01);
594 
595  A.resize(size, size);
596  dA.resize(size, size);
597 
598  initSparse<Scalar>(density, dA, A, options);
599 
600  return size;
601 }

References UniformPSDSelfTest::density, max, Eigen::PlainObjectBase< Derived >::resize(), and size.

Referenced by check_sparse_square_abs_determinant(), and check_sparse_square_solving().

◆ solve_with_guess() [1/3]

template<typename Solver , typename Rhs , typename Guess , typename Result >
void solve_with_guess ( IterativeSolverBase< Solver > &  solver,
const MatrixBase< Rhs > &  b,
const Guess &  g,
Result &  x 
)
16  {
17  if (internal::random<bool>()) {
18  // With a temporary through evaluator<SolveWithGuess>
19  x = solver.derived().solveWithGuess(b, g) + Result::Zero(x.rows(), x.cols());
20  } else {
21  // direct evaluation within x through Assignment<Result,SolveWithGuess>
22  x = solver.derived().solveWithGuess(b.derived(), g);
23  }
24 }

References b, solver, plotDoE::x, and oomph::PseudoSolidHelper::Zero.

Referenced by check_sparse_solving().

◆ solve_with_guess() [2/3]

template<typename Solver , typename Rhs , typename Guess , typename Result >
void solve_with_guess ( SparseSolverBase< Solver > &  solver,
const MatrixBase< Rhs > &  b,
const Guess &  ,
Result &  x 
)
27  {
28  if (internal::random<bool>())
29  x = solver.derived().solve(b) + Result::Zero(x.rows(), x.cols());
30  else
31  x = solver.derived().solve(b);
32 }

References b, solver, plotDoE::x, and oomph::PseudoSolidHelper::Zero.

◆ solve_with_guess() [3/3]

template<typename Solver , typename Rhs , typename Guess , typename Result >
void solve_with_guess ( SparseSolverBase< Solver > &  solver,
const SparseMatrixBase< Rhs > &  b,
const Guess &  ,
Result &  x 
)
35  {
36  x = solver.derived().solve(b);
37 }

References b, solver, and plotDoE::x.