MyraMath
rldlt2_solver


Source: tests/multifrontal/rldlt/rldlt2_solver.cpp

1 // ========================================================================= //
2 // This file is part of MyraMath, copyright (c) 2014-2019 by Ryan A Chilton //
3 // and distributed by MyraCore, LLC. See LICENSE.txt for license terms. //
4 // ========================================================================= //
5 
11 // Containers.
13 #include <myramath/dense/Matrix.h>
15 #include <myramath/dense/Vector.h>
20 
21 // Algorithms.
23 #include <myramath/sparse/gemm.h>
24 #include <myramath/sparse/gemv.h>
26 
27 // Solver under test.
29 
30 // For testing serialization roundtrip.
32 
33 // Reporting.
35 #include <tests/myratest.h>
36 
37 using namespace myra;
38 using namespace myra_stlprint;
39 
40 namespace {
41 
42 template<class Precision> void test(int I, int J, Precision tolerance)
43  {
44  myra::out() << typestring<Precision>() << std::endl;
45  int N = I*J;
46  // Make laplacian matrix A, shift it to make it indefinite.
47  SparseMatrix<Precision> A = laplacian2<Precision>(I,J);
48  Precision shift = 5.5;
49  for (int n = 0; n < N; ++n)
50  A(n,n) -= shift;
51  // Factor A = L*L'
52  typedef SparseRLDLTSolver<Precision> Solver;
53  Solver solver(A);
54  myra::out() << "inertia = " << solver.inertia() << std::endl;
55  // Note that this indefinite solver is not very accurate in
56  // single precision, so we only check/throw residual errors
57  // when we're using backwards refinement with them. Note this
58  // refinement is baked into SparseRLDLT.refine() automatically.
59  // Test A*x = b, no refinement.
60  {
61  auto b = Vector<Precision>::random(N);
62  auto x = b;
63  solver.solve(x.column(),'L','N');
64  Precision residual = frobenius(A*x-b) / frobenius(b);
65  myra::out() << " |A*x-b| (solve) = " << residual << std::endl;
66  // Note, we don't check the residual on this one.
67  // REQUIRE(residual < tolerance);
68  }
69  // Test A*x = b, using refine()
70  {
71  auto b = Vector<Precision>::random(N);
72  auto x = b;
73  auto history = solver.refine(x.column(),'L','N');
74  Precision residual = frobenius(A*x-b) / frobenius(b);
75  myra::out() << " |A*x-b| (refine) = " << residual << std::endl;
76  myra::out() << " history = " << history << std::endl;
77  // Note, we do check the residual on this one (and all the rest)
78  REQUIRE(residual < tolerance);
79  }
80  // Test x*A = b, using refine()
81  {
82  auto b = Vector<Precision>::random(N);
83  auto x = b;
84  auto history = solver.refine(x.row(),'R','N');
85  Precision residual = frobenius(x*A-b) / frobenius(b);
86  myra::out() << " |x*A-b| (refine) = " << residual << std::endl;
87  REQUIRE(residual < tolerance);
88  }
89  // Make a deep copy of solver, test A*x = b again.
90  {
91  Solver copy = solver;
92  auto b = Vector<Precision>::random(N);
93  auto x = b;
94  auto history = solver.refine(x.column(),'L','N');
95  Precision residual = frobenius(A*x-b) / frobenius(b);
96  myra::out() << " |inv(A)*b-x| (copy) = " << residual << std::endl;
97  REQUIRE(residual < tolerance);
98  }
99  // Roundtrip solver to file, test A*x = b again.
100  {
101  VectorStream inout;
102  solver.write(inout);
103  Solver saved(inout);
104  auto b = Vector<Precision>::random(N);
105  auto x = b;
106  auto history = saved.refine(x.column(),'L','N');
107  Precision residual = frobenius(A*x-b) / frobenius(b);
108  myra::out() << " |A*x-b| (saved) = " << residual << std::endl;
109  REQUIRE(residual < tolerance);
110  }
111  }
112 
113 } // namespace
114 
115 ADD_TEST("rldlt2_solver","[multifrontal][parallel]")
116  {
117  // Define problem size.
118  int I = 64;
119  int J = 64;
120  int N = I*J;
121  // Run tests.
122  test<float >(I,J,1.0e-4f);
123  test<double>(I,J,1.0e-8);
124  }
Interface class for representing subranges of dense Matrix&#39;s.
Interface class for representing subranges of dense Vector&#39;s.
Variety of routines for mixed dense*sparse or dense*sparse matrix multiplies. The dense*dense case is...
Routines for computing Frobenius norms of various algebraic containers.
Sparse direct solver suitable for real symmetric indefinite systems.
Definition: SparseRLDLTSolver.h:61
Wraps a std::vector<char>, presents it as both an InputStream and OutputStream. Useful for hygienic u...
Definition: VectorStream.h:22
General purpose compressed-sparse-column (CSC) container.
static Vector< Number > random(int N)
Generates a random Vector of specified size.
Definition: Vector.cpp:276
Definition: syntax.dox:1
Definition: stlprint.h:32
Routines for printing the contents of various std::container&#39;s to a std::ostream using operator <<...
Various utility functions/classes related to scalar Number types.
Signatures for sparse matrix * dense vector multiplies. All delegate to gemm() under the hood...
A stream that serialize/deserializes to std::vector<char> buffer.
General purpose dense matrix container, O(i*j) storage.
Container for either a column vector or row vector (depends upon the usage context) ...
Aggregates a (perm, iperm, swaps) triple into a vocabulary type.
Sparse direct solver suitable for real symmetric indefinite systems.
Stores an IxJ matrix A in compressed sparse column format.
Definition: bothcat.h:23
Helper routines for reordering/filling 2D structured grids. Used by many unit tests.
Range/Iterator types associated with SparseMatrix.


Results: [PASS]

float
inertia = {1531,2565}
|A*x-b| (solve) = 0.00093264
|A*x-b| (refine) = 1.24751e-05
history = [ 0.00300359 1.25741e-05 ] (2)
|x*A-b| (refine) = 5.98628e-06
|inv(A)*b-x| (copy) = 3.85729e-06
|A*x-b| (saved) = 8.37572e-06
double
inertia = {1531,2565}
|A*x-b| (solve) = 4.18021e-13
|A*x-b| (refine) = 4.91717e-15
history = [ 2.30188e-13 4.88419e-15 ] (2)
|x*A-b| (refine) = 1.23369e-14
|inv(A)*b-x| (copy) = 1.14628e-14
|A*x-b| (saved) = 1.33477e-14


Go back to Summary of /test programs.