MyraMath
lu2_solver


Source: tests/multifrontal/lu/lu2_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>
22 
23 // Algorithms.
25 #include <myramath/sparse/gemm.h>
26 #include <myramath/sparse/gemv.h>
31 
32 // Solver under test.
34 
35 // For testing serialization roundtrip.
37 
38 // Reporting.
39 #include <tests/myratest.h>
40 
41 using namespace myra;
42 
43 namespace {
44 
45 template<class Number> void test(int I, int J, typename ReflectPrecision<Number>::type tolerance)
46  {
47  myra::out() << typestring<Number>() << std::endl;
48  typedef typename ReflectPrecision<Number>::type Precision;
49  int N = I*J;
50  // Make symmetric pattern, stuff with random values.
51  Pattern P = stencil2(I,J);
52  auto A = SparseMatrix<Number>::random(P);
53  // Factor A = L*U
54  typedef SparseLUSolver<Number> Solver;
55  Solver solver(A);
56  // Test A*x = b
57  {
58  auto b = Matrix<Number>::random(N,3);
59  auto x = b;
60  solver.refine(x,'L','N');
61  Precision residual = frobenius(A*x-b) / frobenius(b);
62  myra::out() << " |A*b-x| = " << residual << std::endl;
63  REQUIRE(residual < tolerance);
64  }
65  // Test transpose(A)*x = b
66  {
67  auto b = Matrix<Number>::random(N,3);
68  auto x = b;
69  solver.refine(x,'L','T');
70  Precision residual = frobenius(transpose(A)*x-b) / frobenius(b);
71  myra::out() << " |A^T*x-b| = " << residual << std::endl;
72  REQUIRE(residual < tolerance);
73  }
74  // Test hermitian(A)*x = b
75  {
76  auto b = Matrix<Number>::random(N,3);
77  auto x = b;
78  solver.refine(x,'L','H');
79  Precision residual = frobenius(hermitian(A)*x-b) / frobenius(b);
80  myra::out() << " |A^H*x-b| = " << residual << std::endl;
81  REQUIRE(residual < tolerance);
82  }
83  // Test conjugate(A)*x = b
84  {
85  auto b = Matrix<Number>::random(N,3);
86  auto x = b;
87  solver.refine(x,'L','C');
88  Precision residual = frobenius(conjugate(A)*x-b) / frobenius(b);
89  myra::out() << " |A^C*b-x| = " << residual << std::endl;
90  REQUIRE(residual < tolerance);
91  }
92  // Test x*A = b
93  {
94  auto b = Matrix<Number>::random(3,N);
95  auto x = b;
96  solver.refine(x,'R','N');
97  Precision residual = frobenius(x*A-b) / frobenius(b);
98  myra::out() << " |x*A-b| = " << residual << std::endl;
99  REQUIRE(residual < tolerance);
100  }
101  // Test x*transpose(A) = b
102  {
103  auto b = Matrix<Number>::random(3,N);
104  auto x = b;
105  solver.refine(x,'R','T');
106  Precision residual = frobenius(x*transpose(A)-b) / frobenius(b);
107  myra::out() << " |x*A^T-b| = " << residual << std::endl;
108  REQUIRE(residual < tolerance);
109  }
110  // Test x*hermitian(A) = b
111  {
112  auto b = Matrix<Number>::random(3,N);
113  auto x = b;
114  solver.refine(x,'R','H');
115  Precision residual = frobenius(x*hermitian(A)-b) / frobenius(b);
116  myra::out() << " |x*A^H-b| = " << residual << std::endl;
117  REQUIRE(residual < tolerance);
118  }
119  // Test x*conjugate(A) = b
120  {
121  auto b = Matrix<Number>::random(3,N);
122  auto x = b;
123  solver.refine(x,'R','C');
124  Precision residual = frobenius(x*conjugate(A)-b) / frobenius(b);
125  myra::out() << " |x*A^C-b| = " << residual << std::endl;
126  REQUIRE(residual < tolerance);
127  }
128  // Make a deep copy of solver, test A*x = b again.
129  {
130  Solver copy = solver;
131  auto b = Matrix<Number>::random(N,3);
132  auto x = b;
133  solver.refine(x,'L','N');
134  Precision residual = frobenius(A*x-b) / frobenius(b);
135  myra::out() << " |inv(A)*b-x| (copy) = " << residual << std::endl;
136  REQUIRE(residual < tolerance);
137  }
138  // Roundtrip solver to file, test A*x = b again.
139  {
140  VectorStream inout;
141  solver.write(inout);
142  Solver saved(inout);
143  auto b = Matrix<Number>::random(N,3);
144  auto x = b;
145  saved.refine(x,'L','N');
146  Precision residual = frobenius(A*x-b) / frobenius(b);
147  myra::out() << " |A*x-b| (saved) = " << residual << std::endl;
148  REQUIRE(residual < tolerance);
149  }
150  }
151 
152 } // namespace
153 
154 ADD_TEST("lu2_solver","[multifrontal][parallel]")
155  {
156  // Define problem size.
157  int I = 64;
158  int J = 64;
159  int N = I*J;
160  // Run tests.
161  test<NumberD>(I,J,1.0e-8);
162  test<NumberZ>(I,J,1.0e-8);
163  }
Returns a transposed copy of a SparseMatrix.
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.
static Matrix< Number > random(int I, int J)
Generates a random Matrix of specified size.
Definition: Matrix.cpp:353
static SparseMatrix< Number > random(int I, int J, int N)
Generates a random SparseMatrix with size IxJ and (approximately) N nonzeros.
Definition: SparseMatrix.cpp:493
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.
Definition: syntax.dox:1
Various utility functions/classes related to scalar Number types.
Signatures for sparse matrix * dense vector multiplies. All delegate to gemm() under the hood...
Sparse direct solver suitable for symmetric-pattern nonsymmetric-value A.
A stream that serialize/deserializes to std::vector<char> buffer.
General purpose dense matrix container, O(i*j) storage.
Range/Iterator types associated with Pattern.
Container for either a column vector or row vector (depends upon the usage context) ...
Sparse direct solver suitable for symmetric-pattern nonsymmetric-valued A.
Definition: SparseLUSolver.h:57
Holds the nonzero pattern of a sparse matrix.
Definition: Pattern.h:55
Reflects Precision trait for a Number, scalar Number types should specialize it.
Definition: Number.h:33
Container class for a sparse nonzero pattern, used in reordering/symbolic analysis.
Aggregates a (perm, iperm, swaps) triple into a vocabulary type.
Returns a conjugated copy of a SparseMatrix.
Returns a hermitian copy of a SparseMatrix.
Helper routines for reordering/filling 2D structured grids. Used by many unit tests.
Range/Iterator types associated with SparseMatrix.


Results: [PASS]

double
|A*b-x| = 3.3134e-13
|A^T*x-b| = 9.94901e-12
|A^H*x-b| = 1.09132e-11
|A^C*b-x| = 6.26222e-12
|x*A-b| = 2.06765e-13
|x*A^T-b| = 3.69549e-12
|x*A^H-b| = 6.07387e-12
|x*A^C-b| = 1.38604e-11
|inv(A)*b-x| (copy) = 8.48731e-12
|A*x-b| (saved) = 6.47891e-12
std::complex<double>
|A*b-x| = 3.83262e-13
|A^T*x-b| = 2.95353e-13
|A^H*x-b| = 4.38668e-13
|A^C*b-x| = 2.86627e-13
|x*A-b| = 3.07921e-13
|x*A^T-b| = 5.08965e-13
|x*A^H-b| = 3.42837e-13
|x*A^C-b| = 2.88567e-13
|inv(A)*b-x| (copy) = 5.57157e-13
|A*x-b| (saved) = 4.20228e-13


Go back to Summary of /test programs.