MyraMath
pcg


Source: tests/iterative/pcg.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/Vector.h>
18 
19 // Algorithms.
21 #include <myramath/sparse/gemv.h>
22 #include <myramath/sparse/phasor.h>
24 
25 // Iterative solve/action stuff.
30 #include <myramath/iterative/pcg.h>
31 
32 // Reporting.
34 #include <tests/myratest.h>
35 
36 using namespace myra;
37 using namespace myra_stlprint;
38 
39 namespace {
40 
41 template<class Precision> void test_real(int X, int Y, Precision tolerance)
42  {
43  myra::out() << typestring<Precision>() << std::endl;
44  // Construct 2D laplacian.
45  int N = X*Y;
46  auto A = laplacian2<Precision>(X,Y);
47  // Construct random x/b vectors.
48  auto x = Vector<Precision>::random(N);
49  auto b = A*x;
50  // Solve using pcg() - no preconditioner.
51  {
52  auto m = make_IdentityAction<Precision>(N);
53  auto a = make_GemmAction(A);
55  auto result = pcg(m,a,b,x,tolerance);
56  Precision error = euclidean(A*x-b) / euclidean(b);
57  myra::out() << " No preconditioner:" << std::endl;
58  myra::out() << " |Ax-b| = " << error << std::endl;
59  myra::out() << " iteration count = " << result.history.size() << std::endl;
60  //myra::out() << " history = " << result.history << std::endl;
61  REQUIRE(error < tolerance);
62  }
63  // Solve using pcg() - incomplete cholesky preconditioner.
64  {
66  auto m = make_SolveAction(M);
67  auto a = make_GemmAction(A);
69  auto result = pcg(m,a,b,x,tolerance);
70  Precision error = euclidean(A*x-b) / euclidean(b);
71  myra::out() << " IC preconditioner:" << std::endl;
72  myra::out() << " |Ax-b| = " << error << std::endl;
73  myra::out() << " iteration count = " << result.history.size() << std::endl;
74  //myra::out() << " history = " << result.history << std::endl;
75  REQUIRE(error < tolerance);
76  }
77  }
78 
79 // Tests complex pcg(), by solving a 2D graph laplacian (both with and without a preconditioner).
80 template<class Precision> void test_complex(int X, int Y, Precision tolerance)
81  {
82  typedef std::complex<Precision> Number;
83  myra::out() << typestring<Number>() << std::endl;
84  // Construct 2D laplacian.
85  int N = X*Y;
86  auto A = laplacian2<Number>(X,Y);
87  phasor_hermitian(A);
88  // Construct random x/b vectors.
89  auto x = Vector<Number>::random(N);
90  auto b = A*x;
91  // Solve using pcg() - no preconditioner.
92  {
93  auto m = make_IdentityAction<Number>(N);
94  auto a = make_GemmAction(A);
95  x = Vector<Number>::zeros(N);
96  auto result = pcg(m,a,b,x,tolerance);
97  Precision error = euclidean(A*x-b) / euclidean(b);
98  myra::out() << " No preconditioner:" << std::endl;
99  myra::out() << " |Ax-b| = " << error << std::endl;
100  myra::out() << " iteration count = " << result.history.size() << std::endl;
101  //myra::out() << " history = " << result.history << std::endl;
102  REQUIRE(error < tolerance);
103  }
104  // Solve using pcg() - incomplete cholesky preconditioner.
105  {
107  auto m = make_SolveAction(M);
108  auto a = make_GemmAction(A);
109  x = Vector<Number>::zeros(N);
110  auto result = pcg(m,a,b,x,tolerance);
111  Precision error = euclidean(A*x-b) / euclidean(b);
112  myra::out() << " No preconditioner:" << std::endl;
113  myra::out() << " |Ax-b| = " << error << std::endl;
114  myra::out() << " iteration count = " << result.history.size() << std::endl;
115  //myra::out() << " history = " << result.history << std::endl;
116  REQUIRE(error < tolerance);
117  }
118  }
119 
120 } // namespace
121 
122 ADD_TEST("pcg","[iterative]")
123  {
124  test_real<NumberS>(20,20,1.0e-4f);
125  test_real<NumberD>(20,20,1.0e-8);
126  test_complex<NumberS>(20,20,1.0e-4f);
127  test_complex<NumberD>(20,20,1.0e-8);
128  }
Routines for computing euclidean norm of a Vector/VectorRange, or normalizing a Vector/VectorRange to...
Interface class for representing subranges of dense Vector&#39;s.
Applies the "Action" of a linear operator, b := A*x, used in iterative solution algorithms.
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
An Action that is just the identity operator.
Definition: stlprint.h:32
Action< typename ReflectNumber< Solver >::type > make_SolveAction(const Solver &solver, char op='N')
Free function for making SolveAction&#39;s.
Definition: SolveAction.h:67
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...
static Vector< Number > zeros(int N)
Generates a zeros Vector of specified size.
Definition: Vector.cpp:280
Linear system solution via conjugate gradients (symmetric positive definite action A) ...
Container for either a column vector or row vector (depends upon the usage context) ...
Adapts a class with a .solve() method into an Action.
An Action for multiplying by a dense Matrix or SparseMatrix using gemm().
Incompletely factors A ~= L*L&#39;, presents approximate solve() method.
Definition: ICholeskySolver.h:28
Helper routines for reordering/filling 2D structured grids. Used by many unit tests.
Applies random phase shifts to a complex square SparseMatrix.
Incomplete Cholesky preconditioner. Presents a solve() function, but it&#39;s only approximate.
Range/Iterator types associated with SparseMatrix.


Results: [PASS]

float
No preconditioner:
|Ax-b| = 5.08343e-05
iteration count = 14
IC preconditioner:
|Ax-b| = 7.19519e-05
iteration count = 5
double
No preconditioner:
|Ax-b| = 9.18353e-09
iteration count = 26
IC preconditioner:
|Ax-b| = 1.31763e-09
iteration count = 10
std::complex<float>
No preconditioner:
|Ax-b| = 5.79116e-05
iteration count = 14
No preconditioner:
|Ax-b| = 6.91329e-05
iteration count = 5
std::complex<double>
No preconditioner:
|Ax-b| = 5.75304e-09
iteration count = 27
No preconditioner:
|Ax-b| = 1.32676e-09
iteration count = 10


Go back to Summary of /test programs.