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