MOAB: Mesh Oriented datABase
(version 5.4.1)
|
00001 #include <vector> 00002 #include <cassert> 00003 #include "moab/Matrix3.hpp" 00004 #include "moab/Core.hpp" 00005 #include "moab/CartVect.hpp" 00006 #include "TestUtil.hpp" 00007 00008 using namespace moab; 00009 00010 #define ACOS( x ) acos( std::min( std::max( x, -1.0 ), 1.0 ) ) 00011 00012 double find_angle( const moab::CartVect& A, const moab::CartVect& B ) 00013 { 00014 const double lA = A.length(), lB = B.length(); 00015 assert( lA > 0.0 ); 00016 assert( lB > 0.0 ); 00017 const double dPI = 3.14159265; 00018 const double dot = ( A[0] * B[0] + A[1] * B[1] + A[2] * B[2] ); 00019 return ACOS( dot / ( lA * lB ) ) * 180.0 / dPI; 00020 } 00021 00022 #define CHECK_EIGVECREAL_EQUAL( EXP, ACT, EPS ) \ 00023 check_equal_eigvect( ( EXP ), ( ACT ), ( EPS ), #EXP, #ACT, __LINE__, __FILE__ ) 00024 void check_equal_eigvect( const moab::CartVect& A, 00025 const moab::CartVect& B, 00026 double eps, 00027 const char* sA, 00028 const char* sB, 00029 int line, 00030 const char* file ) 00031 { 00032 check_equal( A.length(), B.length(), eps, sA, sB, line, file ); 00033 00034 double angle = find_angle( A, B ); 00035 00036 if( ( fabs( A[0] - B[0] ) <= eps || fabs( A[0] + B[0] ) <= eps ) && 00037 ( fabs( A[1] - B[1] ) <= eps || fabs( A[1] + B[1] ) <= eps ) && 00038 ( fabs( A[2] - B[2] ) <= eps || fabs( A[2] + B[2] ) <= eps ) && 00039 ( angle <= eps || fabs( angle - 180.0 ) <= eps ) ) 00040 return; 00041 00042 std::cout << "Equality Test Failed: " << sA << " == " << sB << std::endl; 00043 std::cout << " at line " << line << " of '" << file << "'" << std::endl; 00044 00045 std::cout << " Expected: "; 00046 std::cout << A << std::endl; 00047 00048 std::cout << " Actual: "; 00049 std::cout << B << std::endl; 00050 00051 std::cout << "Angle between vectors := " << angle << std::endl; 00052 00053 flag_error(); 00054 } 00055 00056 void test_EigenDecomp(); 00057 00058 int main() 00059 { 00060 00061 int result = 0; 00062 00063 result += RUN_TEST( test_EigenDecomp ); 00064 00065 return result; 00066 } 00067 00068 // test to ensure the Eigenvalues/vectors are calculated correctly and returned properly 00069 // from the Matrix3 class for a simple case 00070 void test_EigenDecomp() 00071 { 00072 // Create a matrix 00073 moab::Matrix3 mat; 00074 00075 mat( 0 ) = 2; 00076 mat( 1 ) = -1; 00077 mat( 2 ) = 0; 00078 mat( 3 ) = -1; 00079 mat( 4 ) = 2; 00080 mat( 5 ) = -1; 00081 mat( 6 ) = 0; 00082 mat( 7 ) = -1; 00083 mat( 8 ) = 2; 00084 00085 // now do the Eigen Decomposition of this Matrix 00086 00087 CartVect lamda; 00088 Matrix3 vectors; 00089 moab::ErrorCode rval = mat.eigen_decomposition( lamda, vectors );CHECK_ERR( rval ); 00090 for( int i = 0; i < 3; ++i ) 00091 vectors.col( i ).normalize(); 00092 00093 // Hardcoded check values for the results 00094 double lamda_check[3]; 00095 lamda_check[0] = 0.585786; 00096 lamda_check[1] = 2.0; 00097 lamda_check[2] = 3.41421; 00098 00099 moab::CartVect vec0_check( 0.5, 0.707107, 0.5 ); 00100 moab::CartVect vec1_check( 0.707107, 3.37748e-17, -0.707107 ); 00101 moab::CartVect vec2_check( 0.5, -0.707107, 0.5 ); 00102 00103 // now verfy that the returns Eigenvalues and Eigenvectors are correct (within some tolerance) 00104 double tol = 1e-04; 00105 00106 // use a deprecated constructor 00107 Matrix3 mat3( CartVect( 2, -1, 0 ), CartVect( -1, 2, -1 ), CartVect( 0, -1, 2 ), true ); 00108 CHECK_REAL_EQUAL( mat( 1 ), mat3( 1 ), tol ); 00109 00110 vec0_check.normalize(); 00111 vec1_check.normalize(); 00112 vec2_check.normalize(); 00113 00114 // check that the correct Eigenvalues are returned correctly (in order) 00115 CHECK_REAL_EQUAL( lamda[0], lamda_check[0], tol ); 00116 CHECK_REAL_EQUAL( lamda[1], lamda_check[1], tol ); 00117 CHECK_REAL_EQUAL( lamda[2], lamda_check[2], tol ); 00118 00119 // check the Eigenvector values (order should correspond to the Eigenvalues) 00120 // first vector 00121 CHECK_EIGVECREAL_EQUAL( vectors.col( 0 ), vec0_check, tol ); 00122 00123 // sceond vector 00124 CHECK_EIGVECREAL_EQUAL( vectors.col( 1 ), vec1_check, tol ); 00125 00126 // third vector 00127 CHECK_EIGVECREAL_EQUAL( vectors.col( 2 ), vec2_check, tol ); 00128 00129 // another check to ensure the result is valid (AM-kM = 0) 00130 for( unsigned i = 0; i < 3; ++i ) 00131 { 00132 moab::CartVect v = moab::Matrix::matrix_vector( mat, vectors.col( i ) ) - lamda[i] * vectors.col( i ); 00133 CHECK_REAL_EQUAL( v.length(), 0, tol ); 00134 } 00135 00136 // for a real, symmetric matrix the Eigenvectors should be orthogonal 00137 CHECK_REAL_EQUAL( vectors.col( 0 ) % vectors.col( 1 ), 0, tol ); 00138 CHECK_REAL_EQUAL( vectors.col( 0 ) % vectors.col( 2 ), 0, tol ); 00139 00140 return; 00141 }