MOAB: Mesh Oriented datABase
(version 5.4.1)
|
00001 /* ***************************************************************** 00002 MESQUITE -- The Mesh Quality Improvement Toolkit 00003 00004 Copyright 2006 Sandia National Laboratories. Developed at the 00005 University of Wisconsin--Madison under SNL contract number 00006 624796. The U.S. Government and the University of Wisconsin 00007 retian certain rights to this software. 00008 00009 This library is free software; you can redistribute it and/or 00010 modify it under the terms of the GNU Lesser General Public 00011 License as published by the Free Software Foundation; either 00012 version 2.1 of the License, or (at your option) any later version. 00013 00014 This library is distributed in the hope that it will be useful, 00015 but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 Lesser General Public License for more details. 00018 00019 You should have received a copy of the GNU Lesser General Public License 00020 (lgpl.txt) along with this library; if not, write to the Free Software 00021 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00022 00023 (2006) [email protected] 00024 00025 ***************************************************************** */ 00026 00027 /** \file IdealElementTest.cpp 00028 * \brief Test the ExtraData functionality of the PatchData class 00029 * \author Jason Kraftcheck 00030 */ 00031 00032 #include "Mesquite.hpp" 00033 #include "IdealElements.hpp" 00034 #include "TopologyInfo.hpp" 00035 #include "MsqError.hpp" 00036 #include "Vector3D.hpp" 00037 #include "cppunit/extensions/HelperMacros.h" 00038 00039 using namespace MBMesquite; 00040 00041 class IdealElementTest : public CppUnit::TestFixture 00042 { 00043 private: 00044 CPPUNIT_TEST_SUITE( IdealElementTest ); 00045 CPPUNIT_TEST( test_unit_tri ); 00046 CPPUNIT_TEST( test_unit_quad ); 00047 CPPUNIT_TEST( test_unit_tet ); 00048 CPPUNIT_TEST( test_unit_pyr ); 00049 CPPUNIT_TEST( test_unit_wdg ); 00050 CPPUNIT_TEST( test_unit_hex ); 00051 CPPUNIT_TEST( test_side_height_pyr ); 00052 CPPUNIT_TEST( test_unit_edge_tri ); 00053 CPPUNIT_TEST( test_unit_edge_quad ); 00054 CPPUNIT_TEST( test_unit_edge_tet ); 00055 CPPUNIT_TEST( test_unit_edge_pyr ); 00056 CPPUNIT_TEST( test_unit_edge_wdg ); 00057 CPPUNIT_TEST( test_unit_edge_hex ); 00058 CPPUNIT_TEST( test_unit_height_pyr ); 00059 CPPUNIT_TEST_SUITE_END(); 00060 00061 public: 00062 void test_unit_tri(); 00063 void test_unit_quad(); 00064 void test_unit_tet(); 00065 void test_unit_pyr(); 00066 void test_unit_wdg(); 00067 void test_unit_hex(); 00068 void test_unit_edge_tri(); 00069 void test_unit_edge_quad(); 00070 void test_unit_edge_tet(); 00071 void test_unit_edge_pyr(); 00072 void test_unit_edge_wdg(); 00073 void test_unit_edge_hex(); 00074 void test_side_height_pyr(); 00075 void test_unit_height_pyr(); 00076 }; 00077 00078 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( IdealElementTest, "IdealElementTest" ); 00079 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( IdealElementTest, "Unit" ); 00080 00081 static double distance_from_origin( unsigned n, const Vector3D* vtx ); 00082 static bool unit_edge_lengths( EntityTopology type, const Vector3D* coords ); 00083 static bool equal_edge_lengths( EntityTopology type, const Vector3D* coords ); 00084 00085 void IdealElementTest::test_unit_tri() 00086 { 00087 const Vector3D* coords = unit_element( TRIANGLE ); 00088 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.0, distance_from_origin( 3, coords ), 1e-6 ); 00089 CPPUNIT_ASSERT( equal_edge_lengths( TRIANGLE, coords ) ); 00090 00091 Vector3D v1 = coords[1] - coords[0]; 00092 Vector3D v2 = coords[2] - coords[0]; 00093 double area = 0.5 * ( v1 * v2 ).length(); 00094 CPPUNIT_ASSERT_DOUBLES_EQUAL( 1.0, area, 1e-6 ); 00095 } 00096 00097 void IdealElementTest::test_unit_quad() 00098 { 00099 const Vector3D* coords = unit_element( QUADRILATERAL ); 00100 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.0, distance_from_origin( 4, coords ), 1e-6 ); 00101 CPPUNIT_ASSERT( equal_edge_lengths( QUADRILATERAL, coords ) ); 00102 00103 Vector3D p1 = 0.5 * ( coords[0] + coords[1] ); 00104 Vector3D p2 = 0.5 * ( coords[1] + coords[2] ); 00105 Vector3D p3 = 0.5 * ( coords[2] + coords[3] ); 00106 Vector3D p4 = 0.5 * ( coords[3] + coords[0] ); 00107 Vector3D v1 = p1 - p3; 00108 Vector3D v2 = p2 - p4; 00109 double area = ( v1 * v2 ).length(); 00110 CPPUNIT_ASSERT_DOUBLES_EQUAL( 1.0, area, 1e-6 ); 00111 } 00112 00113 void IdealElementTest::test_unit_tet() 00114 { 00115 const Vector3D* coords = unit_element( TETRAHEDRON ); 00116 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.0, distance_from_origin( 4, coords ), 1e-6 ); 00117 CPPUNIT_ASSERT( equal_edge_lengths( TETRAHEDRON, coords ) ); 00118 00119 Vector3D v1 = coords[1] - coords[0]; 00120 Vector3D v2 = coords[2] - coords[0]; 00121 Vector3D v3 = coords[3] - coords[0]; 00122 double vol = ( v3 % ( v1 * v2 ) ) / 6.0; 00123 CPPUNIT_ASSERT_DOUBLES_EQUAL( 1.0, vol, 1e-6 ); 00124 } 00125 00126 void IdealElementTest::test_unit_pyr() 00127 { 00128 const Vector3D* coords = unit_element( PYRAMID ); 00129 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.0, distance_from_origin( 5, coords ), 1e-6 ); 00130 CPPUNIT_ASSERT( equal_edge_lengths( PYRAMID, coords ) ); 00131 00132 Vector3D p1 = 0.5 * ( coords[0] + coords[1] ); 00133 Vector3D p2 = 0.5 * ( coords[1] + coords[2] ); 00134 Vector3D p3 = 0.5 * ( coords[2] + coords[3] ); 00135 Vector3D p4 = 0.5 * ( coords[3] + coords[0] ); 00136 Vector3D v1 = p1 - p3; 00137 Vector3D v2 = p2 - p4; 00138 double area = ( v1 * v2 ).length(); 00139 00140 Vector3D n = ( v1 * v2 ); 00141 n.normalize(); 00142 Vector3D c = 0.25 * ( coords[0] + coords[1] + coords[2] + coords[3] ); 00143 double height = n % ( coords[4] - c ); 00144 double vol = area * height / 3.0; 00145 CPPUNIT_ASSERT_DOUBLES_EQUAL( 1.0, vol, 1e-6 ); 00146 } 00147 00148 void IdealElementTest::test_unit_wdg() 00149 { 00150 const Vector3D* coords = unit_element( PRISM ); 00151 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.0, distance_from_origin( 6, coords ), 1e-6 ); 00152 CPPUNIT_ASSERT( equal_edge_lengths( PRISM, coords ) ); 00153 00154 Vector3D v1 = coords[1] - coords[0]; 00155 Vector3D v2 = coords[2] - coords[0]; 00156 Vector3D v3 = coords[3] - coords[0]; 00157 double vol = 0.5 * v3 % ( v1 * v2 ); 00158 CPPUNIT_ASSERT_DOUBLES_EQUAL( 1.0, vol, 1e-6 ); 00159 } 00160 00161 void IdealElementTest::test_unit_hex() 00162 { 00163 const Vector3D* coords = unit_element( HEXAHEDRON ); 00164 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.0, distance_from_origin( 8, coords ), 1e-6 ); 00165 CPPUNIT_ASSERT( equal_edge_lengths( HEXAHEDRON, coords ) ); 00166 00167 Vector3D p1 = 0.25 * ( coords[0] + coords[1] + coords[2] + coords[3] ); 00168 Vector3D p2 = 0.25 * ( coords[4] + coords[5] + coords[6] + coords[7] ); 00169 Vector3D p3 = 0.25 * ( coords[0] + coords[1] + coords[5] + coords[4] ); 00170 Vector3D p4 = 0.25 * ( coords[7] + coords[6] + coords[6] + coords[7] ); 00171 Vector3D p5 = 0.25 * ( coords[0] + coords[3] + coords[4] + coords[7] ); 00172 Vector3D p6 = 0.25 * ( coords[1] + coords[2] + coords[6] + coords[5] ); 00173 Vector3D v1 = p1 - p2; 00174 Vector3D v2 = p3 - p4; 00175 Vector3D v3 = p5 - p6; 00176 double vol = v3 % ( v1 * v2 ); 00177 CPPUNIT_ASSERT_DOUBLES_EQUAL( 1.0, vol, 1e-6 ); 00178 } 00179 00180 void IdealElementTest::test_side_height_pyr() 00181 { 00182 const Vector3D* coords = unit_element( PYRAMID, true ); 00183 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.0, distance_from_origin( 5, coords ), 1e-6 ); 00184 CPPUNIT_ASSERT( equal_edge_lengths( QUADRILATERAL, coords ) ); 00185 00186 Vector3D p1 = 0.5 * ( coords[0] + coords[1] ); 00187 Vector3D p2 = 0.5 * ( coords[1] + coords[2] ); 00188 Vector3D p3 = 0.5 * ( coords[2] + coords[3] ); 00189 Vector3D p4 = 0.5 * ( coords[3] + coords[0] ); 00190 Vector3D v1 = p1 - p3; 00191 Vector3D v2 = p2 - p4; 00192 double area = ( v1 * v2 ).length(); 00193 00194 Vector3D n = ( v1 * v2 ); 00195 n.normalize(); 00196 Vector3D c = 0.25 * ( coords[0] + coords[1] + coords[2] + coords[3] ); 00197 double height = n % ( coords[4] - c ); 00198 double vol = area * height / 3.0; 00199 CPPUNIT_ASSERT_DOUBLES_EQUAL( 1.0, vol, 1e-6 ); 00200 CPPUNIT_ASSERT_DOUBLES_EQUAL( height, ( coords[0] - coords[1] ).length(), 1e-6 ); 00201 } 00202 00203 void IdealElementTest::test_unit_edge_tri() 00204 { 00205 const Vector3D* coords = unit_edge_element( TRIANGLE ); 00206 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.0, distance_from_origin( 3, coords ), 1e-6 ); 00207 CPPUNIT_ASSERT( unit_edge_lengths( TRIANGLE, coords ) ); 00208 } 00209 00210 void IdealElementTest::test_unit_edge_quad() 00211 { 00212 const Vector3D* coords = unit_edge_element( QUADRILATERAL ); 00213 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.0, distance_from_origin( 4, coords ), 1e-6 ); 00214 CPPUNIT_ASSERT( unit_edge_lengths( QUADRILATERAL, coords ) ); 00215 } 00216 00217 void IdealElementTest::test_unit_edge_tet() 00218 { 00219 const Vector3D* coords = unit_edge_element( TETRAHEDRON ); 00220 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.0, distance_from_origin( 4, coords ), 1e-6 ); 00221 CPPUNIT_ASSERT( unit_edge_lengths( TETRAHEDRON, coords ) ); 00222 } 00223 00224 void IdealElementTest::test_unit_edge_pyr() 00225 { 00226 const Vector3D* coords = unit_edge_element( PYRAMID ); 00227 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.0, distance_from_origin( 5, coords ), 1e-6 ); 00228 CPPUNIT_ASSERT( unit_edge_lengths( PYRAMID, coords ) ); 00229 } 00230 00231 void IdealElementTest::test_unit_edge_wdg() 00232 { 00233 const Vector3D* coords = unit_edge_element( PRISM ); 00234 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.0, distance_from_origin( 6, coords ), 1e-6 ); 00235 CPPUNIT_ASSERT( unit_edge_lengths( PRISM, coords ) ); 00236 } 00237 00238 void IdealElementTest::test_unit_edge_hex() 00239 { 00240 const Vector3D* coords = unit_edge_element( HEXAHEDRON ); 00241 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.0, distance_from_origin( 8, coords ), 1e-6 ); 00242 CPPUNIT_ASSERT( unit_edge_lengths( HEXAHEDRON, coords ) ); 00243 } 00244 00245 void IdealElementTest::test_unit_height_pyr() 00246 { 00247 const Vector3D* coords = unit_edge_element( PYRAMID, true ); 00248 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.0, distance_from_origin( 5, coords ), 1e-6 ); 00249 CPPUNIT_ASSERT( unit_edge_lengths( QUADRILATERAL, coords ) ); 00250 00251 Vector3D p1 = 0.5 * ( coords[0] + coords[1] ); 00252 Vector3D p2 = 0.5 * ( coords[1] + coords[2] ); 00253 Vector3D p3 = 0.5 * ( coords[2] + coords[3] ); 00254 Vector3D p4 = 0.5 * ( coords[3] + coords[0] ); 00255 Vector3D v1 = p1 - p3; 00256 Vector3D v2 = p2 - p4; 00257 00258 Vector3D n = ( v1 * v2 ); 00259 n.normalize(); 00260 Vector3D c = 0.25 * ( coords[0] + coords[1] + coords[2] + coords[3] ); 00261 double height = n % ( coords[4] - c ); 00262 CPPUNIT_ASSERT_DOUBLES_EQUAL( height, ( coords[0] - coords[1] ).length(), 1e-6 ); 00263 } 00264 00265 static void get_edge_lengths( EntityTopology type, const Vector3D* coords, double& min, double& max ) 00266 { 00267 MsqError err; 00268 unsigned n = TopologyInfo::edges( type ); 00269 min = HUGE_VAL; 00270 max = -HUGE_VAL; 00271 for( unsigned j = 0; j < n; ++j ) 00272 { 00273 const unsigned* edge = TopologyInfo::edge_vertices( type, j, err ); 00274 CPPUNIT_ASSERT( !err ); 00275 double len = ( coords[edge[0]] - coords[edge[1]] ).length(); 00276 if( min > len ) min = len; 00277 if( max < len ) max = len; 00278 } 00279 } 00280 00281 static bool unit_edge_lengths( EntityTopology type, const Vector3D* coords ) 00282 { 00283 double min, max; 00284 get_edge_lengths( type, coords, min, max ); 00285 return fabs( 1.0 - min ) < 1e-6 && fabs( 1.0 - max ) < 1e-6; 00286 } 00287 00288 static bool equal_edge_lengths( EntityTopology type, const Vector3D* coords ) 00289 { 00290 double min, max; 00291 get_edge_lengths( type, coords, min, max ); 00292 return ( max - min ) < 1e-6; 00293 } 00294 00295 static double distance_from_origin( unsigned n, const Vector3D* vtx ) 00296 { 00297 Vector3D sum( 0, 0, 0 ); 00298 for( unsigned i = 0; i < n; ++i ) 00299 sum += vtx[i]; 00300 if( n == 5 ) // pyrmid centroid is not mean of corners 00301 sum += ( vtx[4] / 3.0 ); 00302 00303 return sum.length(); 00304 }