MOAB: Mesh Oriented datABase
(version 5.4.1)
|
00001 /* ***************************************************************** 00002 MESQUITE -- The Mesh Quality Improvement Toolkit 00003 00004 Copyright 2004 Sandia Corporation and Argonne National 00005 Laboratory. Under the terms of Contract DE-AC04-94AL85000 00006 with Sandia Corporation, the U.S. Government retains certain 00007 rights in 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 [email protected], [email protected], [email protected], 00024 [email protected], [email protected], [email protected] 00025 00026 ***************************************************************** */ 00027 // 00028 // AUTHOR: Thomas Leurent <[email protected]> 00029 // ORG: Argonne National Laboratory 00030 // E-MAIL: [email protected] 00031 // 00032 // ORIG-DATE: 13-Nov-02 at 18:05:56 00033 // LAST-MOD: 9-Jun-04 at 14:50:51 by Thomas Leurent 00034 // 00035 // DESCRIPTION: 00036 // ============ 00037 /*! \file PatchDataTest.cpp 00038 00039 Unit testing of various functions in the PatchData class. 00040 00041 */ 00042 // DESCRIP-END. 00043 // 00044 00045 #include "Mesquite.hpp" 00046 #include "PatchData.hpp" 00047 #include "PatchDataInstances.hpp" 00048 #include "UnitUtil.hpp" 00049 #include "Settings.hpp" 00050 #include "Instruction.hpp" 00051 00052 #include "ArrayMesh.hpp" 00053 #include "DomainClassifier.hpp" 00054 #include "PlanarDomain.hpp" 00055 #include "MeshDomain1D.hpp" 00056 #include "MeshDecorator.hpp" 00057 00058 //#include "TriLagrangeShape.hpp" 00059 00060 #include "cppunit/extensions/HelperMacros.h" 00061 00062 #include <algorithm> 00063 #include <set> 00064 #include <map> 00065 00066 using namespace MBMesquite; 00067 00068 using std::cerr; 00069 using std::cout; 00070 using std::endl; 00071 00072 class PatchDataTest : public CppUnit::TestFixture 00073 { 00074 private: 00075 CPPUNIT_TEST_SUITE( PatchDataTest ); 00076 CPPUNIT_TEST( test_num_corners ); 00077 CPPUNIT_TEST( test_get_element_vertex_indices ); 00078 CPPUNIT_TEST( test_get_vertex_element_indices ); 00079 CPPUNIT_TEST( test_get_element_vertex_coordinates ); 00080 CPPUNIT_TEST( test_move_free_vertices_constrained ); 00081 CPPUNIT_TEST( test_movement_function ); 00082 CPPUNIT_TEST( test_get_adj_elems_2d ); 00083 CPPUNIT_TEST( test_get_minmax_element_area ); 00084 CPPUNIT_TEST( test_sub_patch ); 00085 CPPUNIT_TEST( test_fill ); 00086 CPPUNIT_TEST( test_reorder ); 00087 CPPUNIT_TEST( test_update_slave_node_coords ); 00088 CPPUNIT_TEST( test_patch_data_fill_slaved_ho_nodes ); 00089 CPPUNIT_TEST( test_patch_reorder_ho_nodes ); 00090 CPPUNIT_TEST( test_patch_data_fill_free_ho_nodes ); 00091 CPPUNIT_TEST( test_patch_data_mesh_slaved_ho_nodes ); 00092 CPPUNIT_TEST( test_patch_data_mesh_free_ho_nodes ); 00093 CPPUNIT_TEST( test_patch_data_mesh_calcualted_ho_nodes ); 00094 CPPUNIT_TEST( test_patch_data_mesh_flagged_ho_nodes ); 00095 CPPUNIT_TEST( test_vertex_verts_fixed ); 00096 CPPUNIT_TEST( test_curve_verts_fixed ); 00097 CPPUNIT_TEST( test_surf_verts_fixed ); 00098 CPPUNIT_TEST_SUITE_END(); 00099 00100 private: 00101 MsqVertex vtx_0_0; 00102 MsqVertex vtx_0_1; 00103 MsqVertex vtx_1_0; 00104 MsqVertex vtx_1_1; 00105 MsqVertex vtx_2_0; 00106 MsqVertex vtx_2_1; 00107 00108 MsqMeshEntity tri1; 00109 MsqMeshEntity tri2; 00110 MsqMeshEntity quad1; 00111 00112 PatchData mPatch2D; 00113 00114 void test_quad8_patch( bool reorder, bool ho_nodes_slaved ); 00115 void get_quad8_mesh( Mesh*& mesh_out ); 00116 void get_quad8_mesh_and_domain( Mesh*& mesh_out, MeshDomain*& domain_out ); 00117 void get_higher_order_vertices( Mesh* mesh, 00118 std::map< Mesh::VertexHandle, bool >& ho_verts, 00119 bool initial_value = false, 00120 bool non_fixed_only = true ); 00121 void check_higher_order_vertices_slaved( Mesh* mesh, 00122 Settings::HigherOrderSlaveMode mode, 00123 const std::map< Mesh::VertexHandle, bool >& expected ); 00124 00125 public: 00126 void setUp() 00127 { 00128 MsqPrintError err( cout ); 00129 00130 /* our 2D set up: 2 triangles and one quad are available 00131 1___3___5 00132 |\1| | 00133 |0\| 2 | 00134 0---2---4 00135 */ 00136 vtx_0_0.set( 0, 0, 0 ); 00137 vtx_0_1.set( 0, 1, 0 ); 00138 vtx_1_0.set( 1, 0, 0 ); 00139 vtx_1_1.set( 1, 1, 0 ); 00140 vtx_2_0.set( 2, 0, 0 ); 00141 vtx_2_1.set( 2, 1, 0 ); 00142 00143 double coords[] = { 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 2, 0, 0, 2, 1, 0 }; 00144 00145 EntityTopology types[] = { TRIANGLE, TRIANGLE, QUADRILATERAL }; 00146 00147 size_t connectivity[] = { 0, 2, 1, 1, 2, 3, 3, 2, 4, 5 }; 00148 00149 size_t counts[] = { 3, 3, 4 }; 00150 00151 mPatch2D.fill( 6, coords, 3, types, counts, connectivity, 0, err ); 00152 } 00153 00154 void tearDown() {} 00155 00156 public: 00157 PatchDataTest() {} 00158 00159 void test_num_corners() 00160 { 00161 MsqPrintError err( cout ); 00162 size_t n = mPatch2D.num_corners(); 00163 CPPUNIT_ASSERT( n == 10 ); 00164 } 00165 00166 void test_get_element_vertex_indices() 00167 { 00168 00169 MsqPrintError err( cout ); 00170 00171 std::vector< size_t > vtx_ind; 00172 std::vector< size_t > res; 00173 00174 // test we get the right vertices for element 1 (tri) 00175 mPatch2D.get_element_vertex_indices( 1, vtx_ind, err ); 00176 CPPUNIT_ASSERT( !err ); 00177 res.push_back( 1 ); 00178 res.push_back( 2 ); 00179 res.push_back( 3 ); 00180 CPPUNIT_ASSERT( vtx_ind == res ); 00181 00182 // test we get the right vertices for element 2 (quad) 00183 vtx_ind.clear(); 00184 res.clear(); 00185 mPatch2D.get_element_vertex_indices( 2, vtx_ind, err ); 00186 CPPUNIT_ASSERT( !err ); 00187 res.push_back( 3 ); 00188 res.push_back( 2 ); 00189 res.push_back( 4 ); 00190 res.push_back( 5 ); 00191 CPPUNIT_ASSERT( vtx_ind == res ); 00192 } 00193 00194 void test_get_vertex_element_indices() 00195 { 00196 /* 1___3___5 00197 |\1| | 00198 |0\| 2 | 00199 0---2---4 */ 00200 MsqPrintError err( cout ); 00201 00202 std::vector< size_t > elem_ind; 00203 std::vector< size_t > res; 00204 00205 mPatch2D.generate_vertex_to_element_data(); 00206 00207 // test we get the elements contiguous to vertex 3 00208 mPatch2D.get_vertex_element_indices( 3, elem_ind, err ); 00209 CPPUNIT_ASSERT( !err ); 00210 res.push_back( 2 ); 00211 res.push_back( 1 ); 00212 CPPUNIT_ASSERT( res == elem_ind ); 00213 00214 // test we get the elements contiguous to vertex 2 00215 elem_ind.clear(); 00216 res.clear(); 00217 mPatch2D.get_vertex_element_indices( 2, elem_ind, err ); 00218 CPPUNIT_ASSERT( !err ); 00219 res.push_back( 2 ); 00220 res.push_back( 1 ); 00221 res.push_back( 0 ); 00222 CPPUNIT_ASSERT( res == elem_ind ); 00223 } 00224 00225 void test_get_element_vertex_coordinates() 00226 { 00227 MsqPrintError err( cout ); 00228 00229 std::vector< Vector3D > coords; 00230 mPatch2D.get_element_vertex_coordinates( 1, coords, err ); 00231 CPPUNIT_ASSERT( !err ); 00232 00233 CPPUNIT_ASSERT( coords[0] == vtx_0_1 ); 00234 CPPUNIT_ASSERT( coords[1] == vtx_1_0 ); 00235 CPPUNIT_ASSERT( coords[2] == vtx_1_1 ); 00236 } 00237 00238 /* This tests the move_vertices() function as well as the 00239 PatchDataCoordsMemento functionality 00240 */ 00241 void test_move_free_vertices_constrained() 00242 { 00243 MsqPrintError err( cout ); 00244 00245 // gets a memento of the patch coordinates. 00246 PatchDataVerticesMemento* coords_mem = mPatch2D.create_vertices_memento( err ); 00247 CPPUNIT_ASSERT( !err ); 00248 00249 // Move the two first vertices in direction dk by step size s; 00250 Vector3D dk[6]; 00251 dk[0].set( -1, -2, 0 ); 00252 dk[1].set( -1, 2, 0 ); 00253 double s = 0.3; 00254 mPatch2D.move_free_vertices_constrained( dk, 6, s, err ); 00255 CPPUNIT_ASSERT( !err ); 00256 00257 // gets the new coordinates and checks the vertices were displaced as expected. 00258 std::vector< Vector3D > coords; 00259 mPatch2D.get_element_vertex_coordinates( 0, coords, err ); 00260 Vector3D new_vtx_0_0 = vtx_0_0 + s * dk[0]; 00261 Vector3D new_vtx_0_1 = vtx_0_1 + s * dk[1]; 00262 CPPUNIT_ASSERT( coords[0] == new_vtx_0_0 ); 00263 CPPUNIT_ASSERT( coords[2] == new_vtx_0_1 ); 00264 00265 // restore the PatchData to previous coords. 00266 mPatch2D.set_to_vertices_memento( coords_mem, err ); 00267 CPPUNIT_ASSERT( !err ); 00268 00269 // gets the new coordinates and checks the vertices are back to original. 00270 coords.clear(); 00271 mPatch2D.get_element_vertex_coordinates( 0, coords, err ); 00272 CPPUNIT_ASSERT( coords[0] == vtx_0_0 ); 00273 CPPUNIT_ASSERT( coords[2] == vtx_0_1 ); 00274 00275 delete coords_mem; 00276 } 00277 00278 void test_movement_function() 00279 { 00280 MsqPrintError err( cout ); 00281 // gets a memento of the patch coordinates. 00282 PatchDataVerticesMemento* coords_mem = mPatch2D.create_vertices_memento( err ); 00283 CPPUNIT_ASSERT( !err ); 00284 00285 // Move the two first vertices in direction dk by step size s; 00286 Vector3D dk[6]; 00287 dk[0].set( 0, -2, 0 ); 00288 dk[1].set( -1, 0, 0 ); 00289 double s = 1; 00290 mPatch2D.move_free_vertices_constrained( dk, 6, 1, err ); 00291 CPPUNIT_ASSERT( !err ); 00292 // gets the new coordinates and checks the vertices were displaced as expected. 00293 std::vector< Vector3D > coords; 00294 mPatch2D.get_element_vertex_coordinates( 0, coords, err ); 00295 Vector3D new_vtx_0_0 = vtx_0_0 + s * dk[0]; 00296 Vector3D new_vtx_0_1 = vtx_0_1 + s * dk[1]; 00297 CPPUNIT_ASSERT( coords[0] == new_vtx_0_0 ); 00298 CPPUNIT_ASSERT( coords[2] == new_vtx_0_1 ); 00299 double m_dist = mPatch2D.get_max_vertex_movement_squared( coords_mem, err ); 00300 CPPUNIT_ASSERT( m_dist == 4.0 ); 00301 // restore the PatchData to previous coords. 00302 mPatch2D.set_to_vertices_memento( coords_mem, err ); 00303 CPPUNIT_ASSERT( !err ); 00304 // gets the new coordinates and checks the vertices are back to original. 00305 coords.clear(); 00306 mPatch2D.get_element_vertex_coordinates( 0, coords, err ); 00307 CPPUNIT_ASSERT( coords[0] == vtx_0_0 ); 00308 CPPUNIT_ASSERT( coords[2] == vtx_0_1 ); 00309 00310 delete coords_mem; 00311 } 00312 00313 /*Tests the function PatchData::get_adjacent_entities_via_n_dim() 00314 which finds the elements adjacent to a given element. If 'n' 00315 equals 0 the elements must share a vertex; if 'n' equals 1 the 00316 elements must share an edge; and if 'n' equals 2 the elements 00317 must share a face.*/ 00318 void test_get_adj_elems_2d() 00319 { 00320 MsqPrintError err( cout ); 00321 std::vector< size_t > elems_0; 00322 // find elements sharing an edge with oth elem (should be 1) 00323 mPatch2D.get_adjacent_entities_via_n_dim( 1, 0, elems_0, err ); 00324 CPPUNIT_ASSERT( !err ); 00325 CPPUNIT_ASSERT( elems_0.back() == 1 ); 00326 std::vector< size_t > elems_1; 00327 // find elements sharing an edge with 1st elem (should be 0 and 2) 00328 mPatch2D.get_adjacent_entities_via_n_dim( 1, 1, elems_1, err ); 00329 CPPUNIT_ASSERT( !err ); 00330 CPPUNIT_ASSERT( elems_1.size() == 2 ); 00331 std::vector< size_t > elems_2; 00332 // find elements sharing an vert with 0th elem (should be 1 and 2). 00333 mPatch2D.get_adjacent_entities_via_n_dim( 0, 0, elems_2, err ); 00334 CPPUNIT_ASSERT( !err ); 00335 CPPUNIT_ASSERT( elems_2.size() == 2 ); 00336 std::vector< size_t > elems_3; 00337 // find elements sharing an face with 0th elem (should be empty). 00338 mPatch2D.get_adjacent_entities_via_n_dim( 2, 0, elems_3, err ); 00339 CPPUNIT_ASSERT( !err ); 00340 CPPUNIT_ASSERT( elems_3.size() == 0 ); 00341 } 00342 00343 void test_get_minmax_element_area() 00344 { 00345 MsqPrintError err( cout ); 00346 double min, max; 00347 mPatch2D.get_minmax_element_unsigned_area( min, max, err ); 00348 CPPUNIT_ASSERT( !err ); 00349 00350 CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.5, min, 0.0001 ); 00351 CPPUNIT_ASSERT_DOUBLES_EQUAL( 1.0, max, 0.0001 ); 00352 } 00353 00354 void check_sub_patch( unsigned vtx, unsigned layers, PatchData& pd, PatchData& sub ); 00355 00356 void test_sub_patch(); 00357 00358 void test_patch_contents( bool reorder ); 00359 00360 void test_fill() 00361 { 00362 test_patch_contents( false ); 00363 } 00364 void test_reorder() 00365 { 00366 test_patch_contents( true ); 00367 } 00368 00369 void test_update_slave_node_coords(); 00370 void test_patch_data_fill_slaved_ho_nodes() 00371 { 00372 test_quad8_patch( false, true ); 00373 } 00374 void test_patch_reorder_ho_nodes() 00375 { 00376 test_quad8_patch( true, true ); 00377 } 00378 void test_patch_data_fill_free_ho_nodes() 00379 { 00380 test_quad8_patch( false, false ); 00381 } 00382 00383 void test_patch_data_mesh_slaved_ho_nodes(); 00384 void test_patch_data_mesh_free_ho_nodes(); 00385 void test_patch_data_mesh_calcualted_ho_nodes(); 00386 void test_patch_data_mesh_flagged_ho_nodes(); 00387 00388 void test_fixed_by_geom_dim( unsigned dim ); 00389 void test_vertex_verts_fixed() 00390 { 00391 test_fixed_by_geom_dim( 0 ); 00392 } 00393 void test_curve_verts_fixed() 00394 { 00395 test_fixed_by_geom_dim( 1 ); 00396 } 00397 void test_surf_verts_fixed() 00398 { 00399 test_fixed_by_geom_dim( 2 ); 00400 } 00401 }; 00402 00403 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( PatchDataTest, "PatchDataTest" ); 00404 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( PatchDataTest, "Unit" ); 00405 00406 void PatchDataTest::check_sub_patch( unsigned vtx, unsigned layers, PatchData& pd, PatchData& sub ) 00407 { 00408 unsigned i, j; 00409 std::set< size_t > seen; 00410 std::vector< size_t > vtx_map, elem_map; 00411 00412 // test vertex list consistency 00413 vtx_map.resize( sub.num_nodes() ); 00414 for( i = 0; i < sub.num_nodes(); ++i ) 00415 { 00416 // get index in old patch for this vertex 00417 Mesh::VertexHandle h = sub.get_vertex_handles_array()[i]; 00418 Mesh::VertexHandle* end = pd.get_vertex_handles_array() + pd.num_nodes(); 00419 Mesh::VertexHandle* ptr = std::find( pd.get_vertex_handles_array(), end, h ); 00420 CPPUNIT_ASSERT( ptr != end ); 00421 size_t idx = ptr - pd.get_vertex_handles_array(); 00422 CPPUNIT_ASSERT( idx < pd.num_nodes() ); 00423 // put handle in map 00424 vtx_map[i] = idx; 00425 // make sure we don't have duplicates of vertices 00426 CPPUNIT_ASSERT( seen.insert( idx ).second ); 00427 // make sure vertices have same coords 00428 CPPUNIT_ASSERT_VECTORS_EQUAL( pd.vertex_by_index( idx ), sub.vertex_by_index( i ), 1e-12 ); 00429 } 00430 00431 // test element list consistency 00432 seen.clear(); 00433 elem_map.resize( sub.num_elements() ); 00434 for( i = 0; i < sub.num_elements(); ++i ) 00435 { 00436 // get index in old patch for element 00437 Mesh::ElementHandle h = sub.get_element_handles_array()[i]; 00438 Mesh::ElementHandle* end = pd.get_element_handles_array() + pd.num_nodes(); 00439 Mesh::ElementHandle* ptr = std::find( pd.get_element_handles_array(), end, h ); 00440 CPPUNIT_ASSERT( ptr != end ); 00441 size_t idx = ptr - pd.get_element_handles_array(); 00442 CPPUNIT_ASSERT( idx < pd.num_elements() ); 00443 // put handle in map 00444 elem_map[i] = idx; 00445 // make sure we don't have duplicate elements 00446 CPPUNIT_ASSERT( seen.insert( idx ).second ); 00447 // get elements 00448 MsqMeshEntity& elem1 = pd.element_by_index( idx ); 00449 MsqMeshEntity& elem2 = sub.element_by_index( i ); 00450 // compare element data 00451 CPPUNIT_ASSERT_EQUAL( elem1.get_element_type(), elem2.get_element_type() ); 00452 CPPUNIT_ASSERT_EQUAL( elem1.node_count(), elem2.node_count() ); 00453 // get connectivity for elements 00454 std::vector< size_t > vtx1, vtx2; 00455 elem1.get_node_indices( vtx1 ); 00456 elem2.get_node_indices( vtx2 ); 00457 CPPUNIT_ASSERT_EQUAL( vtx1.size(), vtx2.size() ); 00458 // compare connectivity 00459 for( j = 0; j < vtx1.size(); ++j ) 00460 { 00461 CPPUNIT_ASSERT( vtx1[j] < pd.num_nodes() ); 00462 CPPUNIT_ASSERT( vtx2[j] < sub.num_nodes() ); 00463 CPPUNIT_ASSERT_EQUAL( vtx1[j], vtx_map[vtx2[j]] ); 00464 } 00465 } 00466 00467 // test that the subpatch has the elements adjacent to the specified 00468 // vertex. 00469 00470 // first get list of adjacent elements in original patch 00471 seen.clear(); 00472 for( i = 0; i < pd.num_elements(); ++i ) 00473 { 00474 std::vector< size_t > vtx_list; 00475 pd.element_by_index( i ).get_node_indices( vtx_list ); 00476 if( std::find( vtx_list.begin(), vtx_list.end(), vtx ) != vtx_list.end() ) seen.insert( i ); 00477 } 00478 00479 // if 1 layer, then should match element count 00480 if( layers == 1 ) 00481 { 00482 CPPUNIT_ASSERT_EQUAL( seen.size(), sub.num_elements() ); 00483 } 00484 00485 // remove from the set each element in the subpatch 00486 for( i = 0; i < sub.num_elements(); ++i ) 00487 { 00488 size_t idx = elem_map[i]; 00489 std::set< size_t >::iterator it = seen.find( idx ); 00490 if( it != seen.end() ) 00491 { 00492 seen.erase( it ); 00493 } 00494 else 00495 { 00496 CPPUNIT_ASSERT( layers > 1 ); 00497 } 00498 } 00499 CPPUNIT_ASSERT( seen.empty() ); 00500 } 00501 00502 void PatchDataTest::test_sub_patch() 00503 { 00504 MsqPrintError err( std::cout ); 00505 PatchData pd, sub; 00506 create_twelve_hex_patch( pd, err ); 00507 CPPUNIT_ASSERT( !err ); 00508 00509 for( unsigned i = 0; i < pd.num_free_vertices(); ++i ) 00510 { 00511 unsigned layers = i % 2 ? 2 : 1; 00512 pd.get_subpatch( i, layers, sub, err ); 00513 CPPUNIT_ASSERT( !err ); 00514 00515 check_sub_patch( i, layers, pd, sub ); 00516 } 00517 } 00518 00519 void PatchDataTest::test_patch_contents( bool reorder ) 00520 { 00521 const unsigned NUM_VERTEX = 15; 00522 const unsigned NUM_ELEMENT = 9; 00523 00524 // Mesh data used to populate patch 00525 // Use a relatively randomized order for verices 00526 // so patch reordering will result in a changed 00527 // vertex ordering. 00528 double coords[3 * NUM_VERTEX] = { 6, 6, 3, // 0 00529 0, 0, 0, 0, 6, 3, 4, 2, 2, 2, 4, 2, 4, 4, 2, // 5 00530 0, 6, 3, 2, 2, 1, 2, 6, 3, 4, 0, 2, 6, 3, 3, // 10 00531 0, 4, 2, 2, 0, 1, 6, 2, 2, 0, 2, 1 }; // 14 00532 size_t conn[] = { 3, 5, 4, 7, 7, 4, 11, 14, 5, 0, 8, 11, 5, 8, 13, 3, 9, 00533 6, 10, 5, 3, 13, 12, 7, 14, 1, 10, 0, 5, 7, 12, 9, 3 }; 00534 size_t conn_len[NUM_ELEMENT] = { 4, 4, 3, 3, 4, 4, 4, 3, 4 }; 00535 EntityTopology types[NUM_ELEMENT] = { QUADRILATERAL, QUADRILATERAL, TRIANGLE, TRIANGLE, QUADRILATERAL, 00536 QUADRILATERAL, QUADRILATERAL, TRIANGLE, QUADRILATERAL }; 00537 // mark vertices along X and Y axis as fixed 00538 bool fixed[NUM_VERTEX] = { false, true, true, false, false, false, true, false, 00539 false, true, false, true, true, false, false }; 00540 00541 // populate patch data 00542 PatchData pd; 00543 MsqPrintError err( std::cout ); 00544 pd.fill( NUM_VERTEX, coords, NUM_ELEMENT, types, conn_len, conn, fixed, err ); 00545 CPPUNIT_ASSERT( !MSQ_CHKERR( err ) ); 00546 00547 if( reorder ) pd.reorder(); 00548 00549 // count free vertices 00550 unsigned i, j; 00551 size_t num_free = 0; 00552 for( i = 0; i < NUM_VERTEX; ++i ) 00553 if( !fixed[i] ) ++num_free; 00554 CPPUNIT_ASSERT_EQUAL( num_free, pd.num_free_vertices() ); 00555 00556 // NOTE: PatchData will reorder contents either because reorder() 00557 // was called or to group vertices by fixed/free status. 00558 // We will assume that the handles arrays for vertices and 00559 // elements contain the initial positions in the input 00560 // arrays used to populate the patch data. 00561 00562 // Test vertex handles 00563 std::vector< bool > seen( NUM_VERTEX, false ); 00564 for( i = 0; i < pd.num_nodes(); ++i ) 00565 { 00566 size_t h = (size_t)( pd.get_vertex_handles_array()[i] ); 00567 CPPUNIT_ASSERT( h < NUM_VERTEX ); 00568 CPPUNIT_ASSERT( !seen[h] ); 00569 seen[h] = true; 00570 } 00571 00572 // Test vertex coordinates 00573 for( i = 0; i < pd.num_nodes(); ++i ) 00574 { 00575 size_t h = (size_t)( pd.get_vertex_handles_array()[i] ); 00576 MsqVertex vtx = pd.vertex_by_index( i ); 00577 CPPUNIT_ASSERT_DOUBLES_EQUAL( vtx[0], coords[3 * h], DBL_EPSILON ); 00578 CPPUNIT_ASSERT_DOUBLES_EQUAL( vtx[1], coords[3 * h + 1], DBL_EPSILON ); 00579 CPPUNIT_ASSERT_DOUBLES_EQUAL( vtx[2], coords[3 * h + 2], DBL_EPSILON ); 00580 } 00581 00582 // Test vertex fixed flags 00583 for( i = 0; i < pd.num_nodes(); ++i ) 00584 { 00585 size_t h = (size_t)( pd.get_vertex_handles_array()[i] ); 00586 if( fixed[h] ) 00587 { 00588 CPPUNIT_ASSERT( i >= pd.num_free_vertices() ); 00589 CPPUNIT_ASSERT( !pd.vertex_by_index( i ).is_free_vertex() ); 00590 } 00591 else 00592 { 00593 CPPUNIT_ASSERT( i < pd.num_free_vertices() ); 00594 CPPUNIT_ASSERT( pd.vertex_by_index( i ).is_free_vertex() ); 00595 } 00596 } 00597 00598 // Test element handles 00599 seen.clear(); 00600 seen.resize( NUM_ELEMENT, false ); 00601 for( i = 0; i < pd.num_elements(); ++i ) 00602 { 00603 size_t h = (size_t)( pd.get_element_handles_array()[i] ); 00604 CPPUNIT_ASSERT( h < NUM_ELEMENT ); 00605 CPPUNIT_ASSERT( !seen[h] ); 00606 seen[h] = true; 00607 } 00608 00609 // Test element types 00610 for( i = 0; i < pd.num_elements(); ++i ) 00611 { 00612 size_t h = (size_t)( pd.get_element_handles_array()[i] ); 00613 CPPUNIT_ASSERT_EQUAL( types[h], pd.element_by_index( i ).get_element_type() ); 00614 } 00615 00616 // Test element connectivity 00617 for( i = 0; i < pd.num_elements(); ++i ) 00618 { 00619 size_t h = (size_t)( pd.get_element_handles_array()[i] ); 00620 MsqMeshEntity& elem = pd.element_by_index( i ); 00621 CPPUNIT_ASSERT_EQUAL( conn_len[h], elem.vertex_count() ); 00622 CPPUNIT_ASSERT_EQUAL( conn_len[h], elem.node_count() ); 00623 00624 // calculate offset in input list for element connectivity 00625 unsigned conn_pos = 0; 00626 for( j = 0; j < h; ++j ) 00627 conn_pos += conn_len[j]; 00628 00629 const size_t* elem_conn = elem.get_vertex_index_array(); 00630 for( unsigned j = 0; j < elem.vertex_count(); ++j ) 00631 { 00632 size_t vh = (size_t)( pd.get_vertex_handles_array()[elem_conn[j]] ); 00633 CPPUNIT_ASSERT_EQUAL( vh, conn[conn_pos] ); 00634 ++conn_pos; 00635 } 00636 } 00637 } 00638 00639 void PatchDataTest::test_update_slave_node_coords() 00640 { 00641 MsqPrintError err( std::cerr ); 00642 00643 // create a patch containing a single 6-node triangle 00644 // with a) two mid-edge nodes marked as slave vertices and 00645 // b) with all mid-edge nodes moved away from the center 00646 // of their corresponding edge. 00647 const double coords[] = { 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, -0.1, -0.1, 0.6, 0.6, 0.1, -0.1, 0.5, 0.0 }; 00648 const size_t init_conn[] = { 0, 1, 2, 3, 4, 5 }; 00649 const bool fixed[] = { false, false, false, false, true, false }; 00650 PatchData pd; 00651 EntityTopology type = TRIANGLE; 00652 size_t node_per_tri = 6; 00653 pd.fill( 6, coords, 1, &type, &node_per_tri, init_conn, fixed, err ); 00654 ASSERT_NO_ERROR( err ); 00655 00656 // update_slave_node_coords requires a mapping function 00657 Settings settings; 00658 // TriLagrangeShape tri_func; 00659 // settings.set_mapping_function( &tri_func ); 00660 pd.attach_settings( &settings ); 00661 00662 // call the function we're trying to test. 00663 pd.update_slave_node_coordinates( err ); 00664 ASSERT_NO_ERROR( err ); 00665 00666 // get vertex coordinates in the same order that we passed them in 00667 MsqMeshEntity elem = pd.element_by_index( 0 ); 00668 const size_t* conn = elem.get_vertex_index_array(); 00669 Vector3D vtx_coords[6]; 00670 for( size_t i = 0; i < 6; ++i ) 00671 vtx_coords[i] = pd.vertex_by_index( conn[i] ); 00672 00673 // check that corner vertex coordinates are unchanged 00674 CPPUNIT_ASSERT_VECTORS_EQUAL( Vector3D( coords ), vtx_coords[0], 1e-12 ); 00675 CPPUNIT_ASSERT_VECTORS_EQUAL( Vector3D( coords + 3 ), vtx_coords[1], 1e-12 ); 00676 CPPUNIT_ASSERT_VECTORS_EQUAL( Vector3D( coords + 6 ), vtx_coords[2], 1e-12 ); 00677 // check that fixed HO node is unchanged 00678 CPPUNIT_ASSERT_VECTORS_EQUAL( Vector3D( coords + 12 ), vtx_coords[4], 1e-12 ); 00679 // check that slave HO nodes were updated 00680 const Vector3D mid1 = 0.5 * ( Vector3D( coords ) + Vector3D( coords + 3 ) ); 00681 const Vector3D mid2 = 0.5 * ( Vector3D( coords ) + Vector3D( coords + 6 ) ); 00682 CPPUNIT_ASSERT_VECTORS_EQUAL( mid1, vtx_coords[3], 1e-6 ); 00683 CPPUNIT_ASSERT_VECTORS_EQUAL( mid2, vtx_coords[5], 1e-6 ); 00684 } 00685 00686 /* This is the input mesh topology 00687 (0)------(16)-----(1)------(17)-----(2)------(18)-----(3) 00688 | | | | 00689 | | | | 00690 | | | | 00691 | | | | 00692 (19) 0 (20) 1 (21) 2 (22) 00693 | | | | 00694 | | | | 00695 | | | | 00696 | | | | 00697 (4)------(23)-----(5)------(24)-----(6)------(25)-----(7) 00698 | | | | 00699 | | | | 00700 | | | | 00701 | | | | 00702 (26) 3 (27) 4 (28) 5 (29) 00703 | | | | 00704 | | | | 00705 | | | | 00706 | | | | 00707 (8)------(30)-----(9)------(31)-----(10)-----(32)-----(11) 00708 | | | | 00709 | | | | 00710 | | | | 00711 | | | | 00712 (33) 6 (34) 7 (35) 8 (36) 00713 | | | | 00714 | | | | 00715 | | | | 00716 | | | | 00717 (12)-----(37)-----(13)-----(38)-----(14)-----(39)-----(15) 00718 */ 00719 // input mesh definition 00720 const int NUM_VTX = 40, NUM_ELEM = 9, NUM_CORNER = 16; 00721 const double input_coords[3 * NUM_VTX] = { -3.0, 3.0, 0, -1.0, 3.0, 0, 1.0, 3.0, 0, 3.0, 3.0, 0, -3.0, 1.0, 0, 00722 -1.0, 1.0, 0, 1.0, 1.0, 0, 3.0, 1.0, 0, -3.0, -1.0, 0, -1.0, -1.0, 0, 00723 1.0, -1.0, 0, 3.0, -1.0, 0, -3.0, -3.0, 0, -1.0, -3.0, 0, 1.0, -3.0, 0, 00724 3.0, -3.0, 0, -2.0, 3.0, 0, 0.0, 3.0, 0, 2.0, 3.0, 0, -3.0, 2.0, 0, 00725 -1.0, 2.0, 0, 1.0, 2.0, 0, 3.0, 2.0, 0, -2.0, 1.0, 0, 0.0, 1.0, 0, 00726 2.0, 1.0, 0, -3.0, 0.0, 0, -1.0, 0.0, 0, 1.0, 0.0, 0, 3.0, 0.0, 0, 00727 -2.0, -1.0, 0, 0.0, -1.0, 0, 2.0, -1.0, 0, -3.0, -2.0, 0, -1.0, -2.0, 0, 00728 1.0, -2.0, 0, 3.0, -2.0, 0, -2.0, -3.0, 0, 0.0, -3.0, 0, 2.0, -3.0, 0 }; 00729 const bool fixed[NUM_VTX] = { true, true, true, true, true, false, false, true, true, false, false, true, true, 00730 true, true, true, true, true, true, true, false, false, true, false, false, false, 00731 true, false, false, true, false, false, false, true, false, false, true }; 00732 const size_t input_conn[8 * NUM_ELEM] = { 1, 0, 4, 5, 16, 19, 23, 20, 2, 1, 5, 6, 17, 20, 24, 21, 3, 2, 00733 6, 7, 18, 21, 25, 22, 5, 4, 8, 9, 23, 26, 30, 27, 6, 5, 9, 10, 00734 24, 27, 31, 28, 7, 6, 10, 11, 25, 28, 32, 29, 9, 8, 12, 13, 30, 33, 00735 37, 34, 10, 9, 13, 14, 31, 34, 38, 35, 11, 10, 14, 15, 32, 35, 39, 36 }; 00736 00737 const size_t node_per_elem[NUM_ELEM] = { 8, 8, 8, 8, 8, 8, 8, 8, 8 }; 00738 const EntityTopology elem_types[NUM_ELEM] = { QUADRILATERAL, QUADRILATERAL, QUADRILATERAL, QUADRILATERAL, QUADRILATERAL, 00739 QUADRILATERAL, QUADRILATERAL, QUADRILATERAL, QUADRILATERAL }; 00740 00741 void PatchDataTest::test_quad8_patch( bool reorder, bool slaved ) 00742 { 00743 // create PatchData 00744 MsqPrintError err( std::cerr ); 00745 PatchData pd; 00746 Settings settings; 00747 settings.set_slaved_ho_node_mode( Settings::SLAVE_NONE ); 00748 if( !slaved ) // default is slaved, so only change settings if no slaved 00749 pd.attach_settings( &settings ); 00750 pd.fill( NUM_VTX, input_coords, NUM_ELEM, elem_types, node_per_elem, input_conn, fixed, err ); 00751 ASSERT_NO_ERROR( err ); 00752 00753 // reorder if testing that 00754 if( reorder ) pd.reorder(); 00755 00756 // Check sizes. Assume that all non-fixed HO nodes are slave vertices 00757 // unless 'slaved' is false. 00758 00759 CPPUNIT_ASSERT_EQUAL( NUM_VTX, (int)pd.num_nodes() ); 00760 CPPUNIT_ASSERT_EQUAL( NUM_ELEM, (int)pd.num_elements() ); 00761 int num_free = 0, num_slave = 0, num_fixed = 0; 00762 for( int i = 0; i < NUM_VTX; ++i ) 00763 { 00764 if( fixed[i] ) 00765 ++num_fixed; 00766 else if( i < NUM_CORNER ) 00767 ++num_free; 00768 else if( slaved ) 00769 ++num_slave; 00770 else 00771 ++num_free; 00772 } 00773 CPPUNIT_ASSERT_EQUAL( num_free, (int)pd.num_free_vertices() ); 00774 CPPUNIT_ASSERT_EQUAL( num_slave, (int)pd.num_slave_vertices() ); 00775 CPPUNIT_ASSERT_EQUAL( num_fixed, (int)pd.num_fixed_vertices() ); 00776 00777 // Check that vertex handles and vertex coords are correct. 00778 // Assume that handles array contains input vertex indices. 00779 00780 for( int i = 0; i < NUM_VTX; ++i ) 00781 { 00782 const MsqVertex& vtx = pd.vertex_by_index( i ); 00783 Mesh::VertexHandle hdl = pd.get_vertex_handles_array()[i]; 00784 size_t idx = (size_t)hdl; 00785 Vector3D exp_coords( input_coords + 3 * idx ); 00786 if( ( exp_coords - vtx ).length_squared() > 1e-16 ) 00787 { 00788 std::cerr << "Input Index: " << idx << std::endl; 00789 std::cerr << "Patch Index: " << i << std::endl; 00790 } 00791 CPPUNIT_ASSERT_VECTORS_EQUAL( exp_coords, vtx, 1e-16 ); 00792 } 00793 00794 // Check that vertex flags are correct. 00795 // Assume all non-fixed HO noes are slave vertices unless 'slaved' is false. 00796 // Assume that handles array contains input vertex indices. 00797 00798 for( int i = 0; i < NUM_VTX; ++i ) 00799 { 00800 const MsqVertex& vtx = pd.vertex_by_index( i ); 00801 Mesh::VertexHandle hdl = pd.get_vertex_handles_array()[i]; 00802 size_t idx = (size_t)hdl; 00803 if( fixed[idx] ) 00804 { 00805 CPPUNIT_ASSERT( vtx.is_flag_set( MsqVertex::MSQ_HARD_FIXED ) ); 00806 } 00807 else if( slaved && idx >= (size_t)NUM_CORNER ) 00808 { 00809 CPPUNIT_ASSERT( vtx.is_flag_set( MsqVertex::MSQ_DEPENDENT ) ); 00810 } 00811 else 00812 { 00813 CPPUNIT_ASSERT( !vtx.is_flag_set( MsqVertex::MSQ_HARD_FIXED ) ); 00814 CPPUNIT_ASSERT( !vtx.is_flag_set( MsqVertex::MSQ_DEPENDENT ) ); 00815 } 00816 } 00817 00818 // Check that element connectivity is correct. 00819 // Assume that handles array contains input vertex and element indices. 00820 00821 for( int i = 0; i < NUM_ELEM; ++i ) 00822 { 00823 MsqMeshEntity& elem = pd.element_by_index( i ); 00824 CPPUNIT_ASSERT_EQUAL( QUADRILATERAL, elem.get_element_type() ); 00825 CPPUNIT_ASSERT_EQUAL( (size_t)4, elem.vertex_count() ); 00826 CPPUNIT_ASSERT_EQUAL( (size_t)8, elem.node_count() ); 00827 CPPUNIT_ASSERT_EQUAL( (size_t)4, elem.corner_count() ); 00828 std::vector< std::size_t > conn; 00829 elem.get_node_indices( conn ); 00830 CPPUNIT_ASSERT_EQUAL( elem.node_count(), conn.size() ); 00831 for( int j = 0; j < 8; ++j ) 00832 conn[j] = (size_t)pd.get_vertex_handles_array()[conn[j]]; 00833 size_t idx = (size_t)pd.get_element_handles_array()[i]; 00834 ASSERT_ARRAYS_EQUAL( input_conn + 8 * idx, arrptr( conn ), 8 ); 00835 } 00836 } 00837 00838 void PatchDataTest::get_quad8_mesh( Mesh*& mesh_out ) 00839 { 00840 static std::vector< int > fixed_flags( fixed, fixed + NUM_VTX ); 00841 static std::vector< double > coords( input_coords, input_coords + 3 * NUM_VTX ); 00842 static std::vector< unsigned long > conn( input_conn, input_conn + 8 * NUM_ELEM ); 00843 mesh_out = new ArrayMesh( 3, NUM_VTX, arrptr( coords ), arrptr( fixed_flags ), NUM_ELEM, QUADRILATERAL, 00844 arrptr( conn ), false, 8 ); 00845 } 00846 00847 void PatchDataTest::get_quad8_mesh_and_domain( Mesh*& mesh_out, MeshDomain*& domain_out ) 00848 { 00849 MsqPrintError err( std::cerr ); 00850 00851 get_quad8_mesh( mesh_out ); 00852 DomainClassifier geom; 00853 Vector3D corners[4] = { Vector3D( -3, 3, 0 ), Vector3D( 3, 3, 0 ), Vector3D( -3, -3, 0 ), Vector3D( 3, -3, 0 ) }; 00854 MeshDomain* geomarr[] = { new PointDomain( corners[0] ), 00855 new PointDomain( corners[1] ), 00856 new PointDomain( corners[2] ), 00857 new PointDomain( corners[3] ), 00858 new LineDomain( corners[0], corners[1] - corners[0] ), 00859 new LineDomain( corners[1], corners[2] - corners[1] ), 00860 new LineDomain( corners[2], corners[3] - corners[2] ), 00861 new LineDomain( corners[3], corners[0] - corners[3] ), 00862 new PlanarDomain( PlanarDomain::XY ) }; 00863 int dimarr[] = { 0, 0, 0, 0, 1, 1, 1, 1, 2 }; 00864 00865 DomainClassifier* domain; 00866 domain_out = domain = new DomainClassifier; 00867 DomainClassifier::classify_geometrically( *domain, mesh_out, 1e-6, geomarr, dimarr, 9, err ); 00868 domain->delete_sub_domains( true ); 00869 ASSERT_NO_ERROR( err ); 00870 } 00871 00872 void PatchDataTest::test_fixed_by_geom_dim( unsigned dim ) 00873 { 00874 MsqPrintError err( std::cerr ); 00875 00876 Settings settings; 00877 switch( dim ) 00878 { 00879 case 0: 00880 settings.set_fixed_vertex_mode( Settings::FIXED_VERTEX ); 00881 break; 00882 case 1: 00883 settings.set_fixed_vertex_mode( Settings::FIXED_CURVE ); 00884 break; 00885 case 2: 00886 settings.set_fixed_vertex_mode( Settings::FIXED_SURFACE ); 00887 break; 00888 default: 00889 CPPUNIT_ASSERT( false ); 00890 } 00891 00892 Mesh* mesh = 0; 00893 MeshDomain* domain = 0; 00894 get_quad8_mesh_and_domain( mesh, domain ); 00895 MeshDomainAssoc mesh_and_domain = MeshDomainAssoc( mesh, domain ); 00896 Instruction::initialize_vertex_byte( &mesh_and_domain, &settings, err ); 00897 ASSERT_NO_ERROR( err ); 00898 00899 PatchData pd; 00900 pd.attach_settings( &settings ); 00901 pd.set_mesh( mesh ); 00902 pd.set_domain( domain ); 00903 00904 std::vector< Mesh::ElementHandle > elems; 00905 std::vector< Mesh::VertexHandle > verts; 00906 mesh->get_all_elements( elems, err ); 00907 ASSERT_NO_ERROR( err ); 00908 mesh->get_all_vertices( verts, err ); 00909 ASSERT_NO_ERROR( err ); 00910 pd.set_mesh_entities( elems, verts, err ); 00911 ASSERT_NO_ERROR( err ); 00912 CPPUNIT_ASSERT( !elems.empty() ); 00913 00914 std::vector< unsigned short > dims( verts.size() ); 00915 domain->domain_DoF( arrptr( verts ), arrptr( dims ), verts.size(), err ); 00916 ASSERT_NO_ERROR( err ); 00917 00918 for( size_t i = 0; i < pd.num_free_vertices(); ++i ) 00919 { 00920 Mesh::VertexHandle handle = pd.get_vertex_handles_array()[i]; 00921 unsigned short d; 00922 domain->domain_DoF( &handle, &d, 1, err ); 00923 ASSERT_NO_ERROR( err ); 00924 CPPUNIT_ASSERT( d > dim ); 00925 } 00926 for( size_t i = 0; i < pd.num_fixed_vertices(); ++i ) 00927 { 00928 size_t j = i + pd.num_free_vertices() + pd.num_slave_vertices(); 00929 Mesh::VertexHandle handle = pd.get_vertex_handles_array()[j]; 00930 unsigned short d; 00931 domain->domain_DoF( &handle, &d, 1, err ); 00932 ASSERT_NO_ERROR( err ); 00933 CPPUNIT_ASSERT( d <= dim ); 00934 } 00935 00936 delete mesh; 00937 delete domain; 00938 } 00939 00940 void PatchDataTest::get_higher_order_vertices( Mesh* mesh, 00941 std::map< Mesh::VertexHandle, bool >& ho_verts, 00942 bool initial_value, 00943 bool non_fixed_only ) 00944 { 00945 // get mesh data 00946 MsqPrintError err( std::cerr ); 00947 std::vector< Mesh::ElementHandle > elems; 00948 std::vector< Mesh::VertexHandle > verts; 00949 std::vector< size_t > offsets; 00950 mesh->get_all_elements( elems, err ); 00951 ASSERT_NO_ERROR( err ); 00952 CPPUNIT_ASSERT( !elems.empty() ); 00953 mesh->elements_get_attached_vertices( arrptr( elems ), elems.size(), verts, offsets, err ); 00954 CPPUNIT_ASSERT_EQUAL( elems.size() + 1, offsets.size() ); 00955 ASSERT_NO_ERROR( err ); 00956 std::vector< EntityTopology > types( elems.size() ); 00957 mesh->elements_get_topologies( arrptr( elems ), arrptr( types ), elems.size(), err ); 00958 ASSERT_NO_ERROR( err ); 00959 00960 // clear initial state 00961 ho_verts.clear(); 00962 00963 // for each element, add ho nodes 00964 for( size_t i = 0; i < elems.size(); ++i ) 00965 for( size_t j = offsets[i] + TopologyInfo::corners( types[i] ); j < offsets[i + 1]; ++j ) 00966 ho_verts[verts[j]] = initial_value; 00967 00968 if( non_fixed_only ) 00969 { 00970 std::map< Mesh::VertexHandle, bool >::iterator p; 00971 std::sort( verts.begin(), verts.end() ); 00972 verts.erase( std::unique( verts.begin(), verts.end() ), verts.end() ); 00973 std::vector< bool > fixed; 00974 mesh->vertices_get_fixed_flag( arrptr( verts ), fixed, verts.size(), err ); 00975 ASSERT_NO_ERROR( err ); 00976 for( size_t i = 0; i < verts.size(); ++i ) 00977 { 00978 if( fixed[i] ) 00979 { 00980 p = ho_verts.find( verts[i] ); 00981 if( p != ho_verts.end() ) ho_verts.erase( p ); 00982 } 00983 } 00984 } 00985 } 00986 00987 void PatchDataTest::check_higher_order_vertices_slaved( Mesh* mesh, 00988 Settings::HigherOrderSlaveMode mode, 00989 const std::map< Mesh::VertexHandle, bool >& expected ) 00990 { 00991 MsqPrintError err( std::cerr ); 00992 00993 Settings settings; 00994 settings.set_slaved_ho_node_mode( mode ); 00995 MeshDomainAssoc mesh_and_domain = MeshDomainAssoc( mesh, 0 ); 00996 Instruction::initialize_vertex_byte( &mesh_and_domain, &settings, err ); 00997 ASSERT_NO_ERROR( err ); 00998 00999 PatchData pd; 01000 pd.attach_settings( &settings ); 01001 pd.set_mesh( mesh ); 01002 01003 std::vector< Mesh::ElementHandle > elements; 01004 std::vector< Mesh::VertexHandle > vertices; 01005 mesh->get_all_elements( elements, err ); 01006 ASSERT_NO_ERROR( err ); 01007 pd.set_mesh_entities( elements, vertices, err ); 01008 ASSERT_NO_ERROR( err ); 01009 01010 std::map< Mesh::VertexHandle, bool >::const_iterator p; 01011 for( size_t i = 0; i < pd.num_nodes(); ++i ) 01012 { 01013 p = expected.find( pd.get_vertex_handles_array()[i] ); 01014 bool found = ( p != expected.end() ); 01015 bool exp = found && p->second; 01016 bool act = pd.vertex_by_index( i ).is_flag_set( MsqVertex::MSQ_DEPENDENT ); 01017 CPPUNIT_ASSERT_EQUAL( exp, act ); 01018 } 01019 } 01020 01021 void PatchDataTest::test_patch_data_mesh_slaved_ho_nodes() 01022 { 01023 Mesh* mesh = 0; 01024 get_quad8_mesh( mesh ); 01025 01026 std::map< Mesh::VertexHandle, bool > ho_verts; 01027 get_higher_order_vertices( mesh, ho_verts, true, false ); 01028 01029 check_higher_order_vertices_slaved( mesh, Settings::SLAVE_ALL, ho_verts ); 01030 delete mesh; 01031 } 01032 01033 void PatchDataTest::test_patch_data_mesh_free_ho_nodes() 01034 { 01035 Mesh* mesh = 0; 01036 get_quad8_mesh( mesh ); 01037 01038 std::map< Mesh::VertexHandle, bool > ho_verts; 01039 get_higher_order_vertices( mesh, ho_verts, false ); 01040 01041 check_higher_order_vertices_slaved( mesh, Settings::SLAVE_NONE, ho_verts ); 01042 delete mesh; 01043 } 01044 01045 void PatchDataTest::test_patch_data_mesh_calcualted_ho_nodes() 01046 { 01047 Mesh* mesh = 0; 01048 get_quad8_mesh( mesh ); 01049 01050 std::map< Mesh::VertexHandle, bool > ho_verts; 01051 get_higher_order_vertices( mesh, ho_verts, false ); 01052 01053 // set bit on every other higher-order vertex 01054 std::map< Mesh::VertexHandle, bool >::iterator i = ho_verts.end(); 01055 std::vector< Mesh::VertexHandle > slaved; 01056 std::vector< unsigned char > bytes; 01057 while( i != ho_verts.end() ) 01058 { 01059 slaved.push_back( i->first ); 01060 bytes.push_back( MsqVertex::MSQ_DEPENDENT ); 01061 i->second = true; 01062 if( ++i == ho_verts.end() ) 01063 ; 01064 break; 01065 ++i; 01066 } 01067 01068 if( !slaved.empty() ) 01069 { 01070 MsqPrintError err( std::cerr ); 01071 mesh->vertices_set_byte( arrptr( slaved ), arrptr( bytes ), slaved.size(), err ); 01072 ASSERT_NO_ERROR( err ); 01073 } 01074 01075 check_higher_order_vertices_slaved( mesh, Settings::SLAVE_CALCULATED, ho_verts ); 01076 delete mesh; 01077 } 01078 01079 //! create a wrapper around the real mesh that returns what we 01080 //! want from vertices_get_slaved_flag. 01081 class HoSlavedMesh : public MeshDecorator 01082 { 01083 public: 01084 typedef std::map< Mesh::VertexHandle, bool > SMap; 01085 HoSlavedMesh( Mesh* real_mesh, SMap& slaved ) : MeshDecorator( real_mesh ), slavedVerts( slaved ) {} 01086 01087 virtual void vertices_get_slaved_flag( const VertexHandle vert_array[], 01088 std::vector< bool >& slaved_flag_array, 01089 size_t num_vtx, 01090 MsqError& err ); 01091 01092 private: 01093 SMap slavedVerts; 01094 }; 01095 void HoSlavedMesh::vertices_get_slaved_flag( const VertexHandle vert_array[], 01096 std::vector< bool >& slaved_flag_array, 01097 size_t num_vtx, 01098 MsqError& err ) 01099 { 01100 slaved_flag_array.resize( num_vtx ); 01101 for( size_t i = 0; i < num_vtx; ++i ) 01102 { 01103 SMap::iterator j = slavedVerts.find( vert_array[i] ); 01104 slaved_flag_array[i] = ( j != slavedVerts.end() ) && j->second; 01105 } 01106 } 01107 01108 void PatchDataTest::test_patch_data_mesh_flagged_ho_nodes() 01109 { 01110 Mesh* mesh = 0; 01111 get_quad8_mesh( mesh ); 01112 01113 std::map< Mesh::VertexHandle, bool > ho_verts; 01114 get_higher_order_vertices( mesh, ho_verts, false ); 01115 01116 // set every other higher-order vertex as slaved 01117 std::map< Mesh::VertexHandle, bool >::iterator i = ho_verts.end(); 01118 while( i != ho_verts.end() ) 01119 { 01120 if( ++i == ho_verts.end() ) 01121 ; 01122 break; 01123 i->second = true; 01124 ++i; 01125 } 01126 01127 // create a wrapper mesh that returns what we want 01128 // from vertices_get_slaved_flag 01129 HoSlavedMesh wrapper( mesh, ho_verts ); 01130 01131 check_higher_order_vertices_slaved( &wrapper, Settings::SLAVE_FLAG, ho_verts ); 01132 delete mesh; 01133 }