MyraMath
stationary


Source: tests/iterative/stationary.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>
15 #include <myramath/dense/Matrix.h>
19 
20 // Algorithms.
23 #include <myramath/sparse/gemv.h>
27 
28 // Reporting.
29 #include <tests/myratest.h>
30 
31 using namespace myra;
32 
33 namespace {
34 
35 template<class Precision> void test(int I, int J, Precision tol)
36  {
37  // Setup A and b for two-dimensional laplacian operator, div(grad(phi)) = 0 ..
38  int N = I*J;
39  auto A = laplacian2<Precision>(I,J);
40  auto b = Vector<Precision>::zeros(I*J);
41  // .. subjecting A and b to phi=1 boundary conditions
42  Precision one(1);
43  Natural2D ordering(I,J);
44  for (int n = 0; n < I*J; ++n)
45  A(n,n) -= one;
46  // .. along j=0 and j=1 walls
47  for (int i = 0; i < I; ++i)
48  {
49  int n0 = ordering(i,0);
50  b(n0) += one;
51  A(n0,n0) += one;
52  int n1 = ordering(i,J-1);
53  b(n1) += one;
54  A(n1,n1) += one;
55  }
56  // .. along i=0 and i=1 walls
57  for (int j = 0; j < J; ++j)
58  {
59  int n0 = ordering(0,j);
60  b(n0) += one;
61  A(n0,n0) += one;
62  int n1 = ordering(I-1,j);
63  b(n1) += one;
64  A(n1,n1) += one;
65  }
66 
67  // Verify A is symmetric.
68  myra::out() << "|A-A'| = " << frobenius(A-transpose(A)) << std::endl;
69 
70  // Verify exact solution, A*ones = b
71  auto y = Vector<Precision>::ones(N);
72  myra::out() << "|A*ones-b| = " << euclidean(A*y-b) << std::endl;
73 
74  // Solve A*x=b using jacobi()
75  auto x1 = Vector<Precision>::zeros(N);
76  auto output1 = jacobi(A,b,x1,tol,1000);
77  Precision error1 = euclidean(A*x1-b) / euclidean(b);
78  myra::out() << "jacobi |A*x-b|/|b| = " << error1 << ", iterations = " << output1.history.size() << std::endl;
79  REQUIRE(error1 < tol);
80 
81  // Solve A*x=b using seidel()
82  auto x2 = Vector<Precision>::zeros(N);
83  auto output2 = seidel(A,b,x2,tol,1000);
84  Precision error2 = euclidean(A*x2-b) / euclidean(b);
85  myra::out() << "seidel |A*x-b|/|b| = " << error2 << ", iterations = " << output2.history.size() << std::endl;
86  REQUIRE(error2 < tol);
87 
88  // Solve A*x=b using seidel()
89  auto x3 = Vector<Precision>::zeros(N);
90  auto output3 = sseidel(A,b,x3,tol,1000);
91  Precision error3 = euclidean(A*x3-b) / euclidean(b);
92  myra::out() << "sseidel |A*x-b|/|b| = " << error3 << ", iterations = " << output3.history.size() << std::endl;
93  REQUIRE(error3 < tol);
94 
95  // Solve A*x = b using sor()
96  Precision omega(1.5);
97  auto x4 = Vector<Precision>::zeros(N);
98  auto output4 = sor(A,b,x4,omega,tol,1000);
99  Precision error4 = euclidean(A*x4-b) / euclidean(b);
100  myra::out() << "sor |A*x-b|/|b| = " << error4 << ", iterations = " << output4.history.size() << std::endl;
101  REQUIRE(error4 < tol);
102 
103  // Solve A*x = b using ssor()
104  auto x5 = Vector<Precision>::zeros(N);
105  auto output5 = ssor(A,b,x5,omega,tol,1000);
106  Precision error5 = euclidean(A*x5-b) / euclidean(b);
107  myra::out() << "ssor |A*x-b|/|b| = " << error5 << ", iterations = " << output5.history.size() << std::endl;
108  REQUIRE(error5 < tol);
109 
110  }
111 
112 } // namespace
113 
114 ADD_TEST("stationary","[iterative]")
115  {
116  test<float>(20,20,1.0e-4f);
117  test<double>(20,20,1.0e-4);
118  }
119 
int size() const
Returns size of underlying system A (it&#39;s square).
Definition: ICholeskySolver.cpp:220
Routines for computing euclidean norm of a Vector/VectorRange, or normalizing a Vector/VectorRange to...
Returns a transposed copy of a SparseMatrix.
Interface class for representing subranges of dense Matrix&#39;s.
Implementations of classical stationary iterations: jacobi(), seidel(), sor() and ssor() ...
static Vector< Number > ones(int N)
Generates a ones Vector of specified size.
Definition: Vector.cpp:284
Interface class for representing subranges of dense Vector&#39;s.
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...
static Vector< Number > zeros(int N)
Generates a zeros Vector of specified size.
Definition: Vector.cpp:280
General purpose dense matrix container, O(i*j) storage.
Container for either a column vector or row vector (depends upon the usage context) ...
A helper class that generates a natural ordering on a 2D structured grid of size IxJ.
Definition: laplacian2.h:43
Returns frobenius norm of a SparseMatrix.
Helper routines for reordering/filling 2D structured grids. Used by many unit tests.
Range/Iterator types associated with SparseMatrix.


Results: [PASS]

|A-A'| = 0
|A*ones-b| = 0
jacobi |A*x-b|/|b| = 9.99893e-05, iterations = 597
seidel |A*x-b|/|b| = 9.81902e-05, iterations = 300
sseidel |A*x-b|/|b| = 6.78522e-05, iterations = 160
sor |A*x-b|/|b| = 9.50828e-05, iterations = 99
ssor |A*x-b|/|b| = 8.15185e-05, iterations = 56
|A-A'| = 0
|A*ones-b| = 0
jacobi |A*x-b|/|b| = 9.99856e-05, iterations = 597
seidel |A*x-b|/|b| = 9.819e-05, iterations = 300
sseidel |A*x-b|/|b| = 6.78542e-05, iterations = 160
sor |A*x-b|/|b| = 9.50743e-05, iterations = 99
ssor |A*x-b|/|b| = 8.15192e-05, iterations = 56


Go back to Summary of /test programs.