MyraMath
zldlh2_solver


Source: tests/multifrontal/zldlh/zldlh2_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 #include <myramath/sparse/phasor.h>
28 
29 // Solver type under test.
31 
32 // For testing serialization roundtrip.
34 
35 // Reporting.
37 #include <tests/myratest.h>
38 
39 using namespace myra;
40 using namespace myra_stlprint;
41 
42 namespace {
43 
44 template<class Precision> void test(int I, int J, Precision tolerance)
45  {
46  myra::out() << typestring<Precision>() << std::endl;
47  typedef std::complex<Precision> Number;
48  int N = I*J;
49  // Make laplacian A, shift it indefinite, phase shift to make it nontrivially hermitian.
50  SparseMatrix<Number> A = laplacian2<Number>(I,J);
51  Number shift = 5.5;
52  for (int n = 0; n < N; ++n)
53  A(n,n) -= shift;
54  phasor_hermitian(A);
55  // Factor A = L*L'
56  typedef SparseZLDLHSolver<Precision> Solver;
57  Solver solver(A);
58  myra::out() << "inertia = " << solver.inertia() << std::endl;
59  // Note that this indefinite solver is not very accurate in
60  // single precision, so we only check/throw residual errors
61  // when we're using backwards refinement with them. Note this
62  // refinement is baked into SparseZLDLH.refine() automatically.
63  // Test A*x = b, no refinement.
64  {
65  auto b = Vector<Number>::random(N);
66  auto x = b;
67  solver.solve(x.column(),'L','N');
68  Precision residual = frobenius(A*x-b) / frobenius(b);
69  myra::out() << " |A*x-b| (solve) = " << residual << std::endl;
70  // Note, we don't check the residual on this one.
71  // REQUIRE(residual < tolerance);
72  }
73  // Test A*x = b, using refine()
74  {
75  auto b = Vector<Number>::random(N);
76  auto x = b;
77  auto history = solver.refine(x.column(),'L','N');
78  Precision residual = frobenius(A*x-b) / frobenius(b);
79  myra::out() << " |A*x-b| (refine) = " << residual << std::endl;
80  myra::out() << " history = " << history << std::endl;
81  // Note, we do check the residual on this one (and all the rest)
82  REQUIRE(residual < tolerance);
83  }
84  // Test transpose(A)*x = b, using refine()
85  {
86  auto b = Vector<Number>::random(N);
87  auto x = b;
88  auto history = solver.refine(x.column(),'L','T');
89  Precision residual = frobenius(transpose(A)*x-b) / frobenius(b);
90  myra::out() << " |A^T*x-b| (refine) = " << residual << std::endl;
91  myra::out() << " history = " << history << std::endl;
92  REQUIRE(residual < tolerance);
93  }
94  // Test x*A = b, using refine()
95  {
96  auto b = Vector<Number>::random(N);
97  auto x = b;
98  auto history = solver.refine(x.row(),'R','N');
99  Precision residual = frobenius(x*A-b) / frobenius(b);
100  myra::out() << " |x*A-b| (refine) = " << residual << std::endl;
101  REQUIRE(residual < tolerance);
102  }
103  // Test x*tranpose(A) = b, using refine()
104  {
105  auto b = Vector<Number>::random(N);
106  auto x = b;
107  auto history = solver.refine(x.row(),'R','T');
108  Precision residual = frobenius(x*transpose(A)-b) / frobenius(b);
109  myra::out() << " |x*A^T-b| (refine) = " << residual << std::endl;
110  REQUIRE(residual < tolerance);
111  }
112  // Make a deep copy of solver, test A*x = b again.
113  {
114  Solver copy = solver;
115  auto b = Vector<Number>::random(N);
116  auto x = b;
117  auto history = solver.refine(x.column(),'L','N');
118  Precision residual = frobenius(A*x-b) / frobenius(b);
119  myra::out() << " |inv(A)*b-x| (copy) = " << residual << std::endl;
120  REQUIRE(residual < tolerance);
121  }
122  // Roundtrip solver to file, test A*x = b again.
123  {
124  VectorStream inout;
125  solver.write(inout);
126  Solver saved(inout);
127  auto b = Vector<Number>::random(N);
128  auto x = b;
129  auto history = saved.refine(x.column(),'L','N');
130  Precision residual = frobenius(A*x-b) / frobenius(b);
131  myra::out() << " |A*x-b| (saved) = " << residual << std::endl;
132  REQUIRE(residual < tolerance);
133  }
134  }
135 
136 } // namespace
137 
138 ADD_TEST("zldlh2_solver","[multifrontal][parallel]")
139  {
140  // Define problem size.
141  int I = 64;
142  int J = 64;
143  int N = I*J;
144  // Run tests.
145  test<float >(I,J,1.0e-4f);
146  test<double>(I,J,1.0e-8);
147  }
Returns a transposed copy of a SparseMatrix.
Interface class for representing subranges of dense Matrix&#39;s.
Sparse direct solver suitable for complex hermitian indefinite systems.
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.
Wraps a std::vector<char>, presents it as both an InputStream and OutputStream. Useful for hygienic u...
Definition: VectorStream.h:22
Sparse direct solver suitable for complex hermitian indefinite systems.
Definition: SparseZLDLHSolver.h:60
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.
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.
Applies random phase shifts to a complex square SparseMatrix.
Range/Iterator types associated with SparseMatrix.


Results: [PASS]

float
inertia = {1531,2565}
|A*x-b| (solve) = 0.000508248
|A*x-b| (refine) = 8.13978e-06
history = [ 0.000293949 6.34765e-06 ] (2)
|A^T*x-b| (refine) = 7.67395e-06
history = [ 0.000383531 5.95696e-06 ] (2)
|x*A-b| (refine) = 9.24975e-06
|x*A^T-b| (refine) = 6.34025e-06
|inv(A)*b-x| (copy) = 8.43896e-06
|A*x-b| (saved) = 7.02306e-06
double
inertia = {1531,2565}
|A*x-b| (solve) = 1.03828e-12
|A*x-b| (refine) = 1.82741e-14
history = [ 1.12802e-12 1.40342e-14 ] (2)
|A^T*x-b| (refine) = 2.68098e-14
history = [ 1.92368e-12 2.13485e-14 ] (2)
|x*A-b| (refine) = 2.66673e-14
|x*A^T-b| (refine) = 2.94271e-14
|inv(A)*b-x| (copy) = 2.10389e-14
|A*x-b| (saved) = 2.44362e-14


Go back to Summary of /test programs.