MOAB: Mesh Oriented datABase  (version 5.2.1)
PatchDataTest.cpp
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines