MOAB: Mesh Oriented datABase  (version 5.4.0)
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,
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines