MOAB: Mesh Oriented datABase  (version 5.5.0)
test_Matrix3.cpp
Go to the documentation of this file.
1 #include <vector>
2 #include <cassert>
3 #include "moab/Matrix3.hpp"
4 #include "moab/Core.hpp"
5 #include "moab/CartVect.hpp"
6 #include "TestUtil.hpp"
7 
8 using namespace moab;
9 
10 #define ACOS( x ) acos( std::min( std::max( x, -1.0 ), 1.0 ) )
11 
12 double find_angle( const moab::CartVect& A, const moab::CartVect& B )
13 {
14  const double lA = A.length(), lB = B.length();
15  assert( lA > 0.0 );
16  assert( lB > 0.0 );
17  const double dPI = 3.14159265;
18  const double dot = ( A[0] * B[0] + A[1] * B[1] + A[2] * B[2] );
19  return ACOS( dot / ( lA * lB ) ) * 180.0 / dPI;
20 }
21 
22 #define CHECK_EIGVECREAL_EQUAL( EXP, ACT, EPS ) \
23  check_equal_eigvect( ( EXP ), ( ACT ), ( EPS ), #EXP, #ACT, __LINE__, __FILE__ )
25  const moab::CartVect& B,
26  double eps,
27  const char* sA,
28  const char* sB,
29  int line,
30  const char* file )
31 {
32  check_equal( A.length(), B.length(), eps, sA, sB, line, file );
33 
34  double angle = find_angle( A, B );
35 
36  if( ( fabs( A[0] - B[0] ) <= eps || fabs( A[0] + B[0] ) <= eps ) &&
37  ( fabs( A[1] - B[1] ) <= eps || fabs( A[1] + B[1] ) <= eps ) &&
38  ( fabs( A[2] - B[2] ) <= eps || fabs( A[2] + B[2] ) <= eps ) &&
39  ( angle <= eps || fabs( angle - 180.0 ) <= eps ) )
40  return;
41 
42  std::cout << "Equality Test Failed: " << sA << " == " << sB << std::endl;
43  std::cout << " at line " << line << " of '" << file << "'" << std::endl;
44 
45  std::cout << " Expected: ";
46  std::cout << A << std::endl;
47 
48  std::cout << " Actual: ";
49  std::cout << B << std::endl;
50 
51  std::cout << "Angle between vectors := " << angle << std::endl;
52 
53  flag_error();
54 }
55 
56 void test_EigenDecomp();
57 
58 int main()
59 {
60 
61  int result = 0;
62 
63  result += RUN_TEST( test_EigenDecomp );
64 
65  return result;
66 }
67 
68 // test to ensure the Eigenvalues/vectors are calculated correctly and returned properly
69 // from the Matrix3 class for a simple case
71 {
72  // Create a matrix
73  moab::Matrix3 mat;
74 
75  mat( 0 ) = 2;
76  mat( 1 ) = -1;
77  mat( 2 ) = 0;
78  mat( 3 ) = -1;
79  mat( 4 ) = 2;
80  mat( 5 ) = -1;
81  mat( 6 ) = 0;
82  mat( 7 ) = -1;
83  mat( 8 ) = 2;
84 
85  // now do the Eigen Decomposition of this Matrix
86 
87  CartVect lamda;
88  Matrix3 vectors;
89  moab::ErrorCode rval = mat.eigen_decomposition( lamda, vectors );CHECK_ERR( rval );
90  for( int i = 0; i < 3; ++i )
91  vectors.col( i ).normalize();
92 
93  // Hardcoded check values for the results
94  double lamda_check[3];
95  lamda_check[0] = 0.585786;
96  lamda_check[1] = 2.0;
97  lamda_check[2] = 3.41421;
98 
99  moab::CartVect vec0_check( 0.5, 0.707107, 0.5 );
100  moab::CartVect vec1_check( 0.707107, 3.37748e-17, -0.707107 );
101  moab::CartVect vec2_check( 0.5, -0.707107, 0.5 );
102 
103  // now verfy that the returns Eigenvalues and Eigenvectors are correct (within some tolerance)
104  double tol = 1e-04;
105 
106  // use a deprecated constructor
107  Matrix3 mat3( CartVect( 2, -1, 0 ), CartVect( -1, 2, -1 ), CartVect( 0, -1, 2 ), true );
108  CHECK_REAL_EQUAL( mat( 1 ), mat3( 1 ), tol );
109 
110  vec0_check.normalize();
111  vec1_check.normalize();
112  vec2_check.normalize();
113 
114  // check that the correct Eigenvalues are returned correctly (in order)
115  CHECK_REAL_EQUAL( lamda[0], lamda_check[0], tol );
116  CHECK_REAL_EQUAL( lamda[1], lamda_check[1], tol );
117  CHECK_REAL_EQUAL( lamda[2], lamda_check[2], tol );
118 
119  // check the Eigenvector values (order should correspond to the Eigenvalues)
120  // first vector
121  CHECK_EIGVECREAL_EQUAL( vectors.col( 0 ), vec0_check, tol );
122 
123  // sceond vector
124  CHECK_EIGVECREAL_EQUAL( vectors.col( 1 ), vec1_check, tol );
125 
126  // third vector
127  CHECK_EIGVECREAL_EQUAL( vectors.col( 2 ), vec2_check, tol );
128 
129  // another check to ensure the result is valid (AM-kM = 0)
130  for( unsigned i = 0; i < 3; ++i )
131  {
132  moab::CartVect v = moab::Matrix::matrix_vector( mat, vectors.col( i ) ) - lamda[i] * vectors.col( i );
133  CHECK_REAL_EQUAL( v.length(), 0, tol );
134  }
135 
136  // for a real, symmetric matrix the Eigenvectors should be orthogonal
137  CHECK_REAL_EQUAL( vectors.col( 0 ) % vectors.col( 1 ), 0, tol );
138  CHECK_REAL_EQUAL( vectors.col( 0 ) % vectors.col( 2 ), 0, tol );
139 
140  return;
141 }