// Test reading MeshImpl boundary-vertex bit // from Vtk scalar attribute. void VtkTest::test_read_fixed_attrib() { MeshImpl mesh; MsqPrintError err(cout); FILE* file = fopen( temp_file_name, "w+" ); fputs( structured_3d_points_data, file ); fputs( fixed_vertex_attrib, file ); fclose( file ); mesh.read_vtk( temp_file_name, err ); remove( temp_file_name ); ASSERT_NO_ERROR(err); std::vector<Mesh::ElementHandle> elems; mesh.get_all_elements( elems, err ); CPPUNIT_ASSERT( !err ); CPPUNIT_ASSERT_EQUAL( elems.size(), (size_t)8 ); std::vector<Mesh::VertexHandle> verts; std::vector<size_t> offsets; mesh.elements_get_attached_vertices( arrptr(elems), elems.size(), verts, offsets, err ); ASSERT_NO_ERROR(err); // get unique list of vertices std::vector<Mesh::VertexHandle>::iterator new_end; std::sort( verts.begin(), verts.end() ); new_end = std::unique( verts.begin(), verts.end() ); verts.resize( new_end - verts.begin() ); CPPUNIT_ASSERT_EQUAL( verts.size(), (size_t)27 ); // get fixed flag std::vector<bool> fixed; mesh.vertices_get_fixed_flag( arrptr(verts), fixed, verts.size(), err ); ASSERT_NO_ERROR(err); CPPUNIT_ASSERT_EQUAL( verts.size(), fixed.size() ); for (int i = 0; i < 27; ++i) { bool should_be_fixed = (i != 13); CPPUNIT_ASSERT_EQUAL( should_be_fixed, (bool)fixed[i] ); } }
void VtkTest::test_read_unstructured( const char* filename ) { MeshImpl mesh; MsqPrintError err(cout); mesh.read_vtk( filename, err ); ASSERT_NO_ERROR(err); // Get mesh data std::vector<Mesh::VertexHandle> conn; std::vector<Mesh::ElementHandle> elems(38); std::vector<size_t> offsets(39); mesh.get_all_elements( elems, err ); ASSERT_NO_ERROR(err); CPPUNIT_ASSERT_EQUAL( elems.size(), (size_t)38 ); mesh.elements_get_attached_vertices( arrptr(elems), elems.size(), conn, offsets, err ); ASSERT_NO_ERROR(err); unsigned i; struct meshdata { EntityTopology type; size_t nodes; size_t count; }; meshdata list[] = { { Mesquite::HEXAHEDRON, 8, 8 }, { Mesquite::QUADRILATERAL, 4, 4 }, { Mesquite::PYRAMID, 5, 4 }, { Mesquite::TETRAHEDRON, 4, 6 }, { Mesquite::TRIANGLE, 3, 14 }, { Mesquite::PRISM, 6, 2 }, { Mesquite::MIXED, 0, 0 } }; // Count expected lenght of connectivity list size_t conn_len = 0; for (i = 0; list[i].nodes; ++i) conn_len += list[i].nodes * list[i].count; CPPUNIT_ASSERT_EQUAL( conn_len, conn.size() ); check_8hex_block( mesh, conn.begin() ); check_4quad_block( mesh, conn.begin() + 64 ); }
// Routine to create initial mesh for test. // o Marks vertices at a greater topological depth than the specified // value as slaved. // o Perturbs higher-order vertices on skin towards element center // o Marks skin vertices as fixed int main( int argc, char* argv[] ) { if (argc != 4) usage(argv[0]); char* endptr = 0; const long n = strtol( argv[1], &endptr, 0 ); if (*endptr || n < 0) usage(argv[0]); // read input mesh MeshImpl mesh; MsqPrintError err(std::cerr); mesh.read_vtk( argv[2], err ); if (err) return 1; // get skin vertices mesh.mark_skin_fixed( err, true ); if (err) return 1; std::vector<Mesh::VertexHandle> verts; mesh.get_all_vertices( verts, err ); if (err) return 1; std::vector<bool> fixed; mesh.vertices_get_fixed_flag( arrptr(verts), fixed, verts.size(), err ); if (err) return 1; std::vector<Mesh::VertexHandle> skin; for (size_t i = 0; i < verts.size(); ++i) if (fixed[i]) skin.push_back( verts[i] ); // create map for vertex depth, and initialize to 0 for skin vertices std::map<Mesh::VertexHandle,int> depth; std::map<Mesh::VertexHandle,int>::iterator d_iter; for (size_t i = 0; i < skin.size(); ++i) depth[skin[i]] = 0; // get all elements std::vector<Mesh::ElementHandle> curr, next; std::vector<Mesh::ElementHandle> conn; std::vector<size_t> off; mesh.get_all_elements( next, err ); // build sorted list of higher-order vertices std::vector<Mesh::VertexHandle> higher_order; for (size_t i = 0; i < next.size(); ++i) { Mesh::ElementHandle elem = next[i]; conn.clear(); mesh.elements_get_attached_vertices( &elem, 1, conn, off, err ); if (err) return 1; EntityTopology type; mesh.elements_get_topologies( &elem, &type, 1, err ); std::copy( conn.begin() + TopologyInfo::corners(type), conn.end(), std::back_inserter( higher_order ) ); } std::sort( higher_order.begin(), higher_order.end() ); higher_order.erase( std::unique( higher_order.begin(), higher_order.end() ), higher_order.end() ); // build depth map for all vertices while (!next.empty()) { curr.swap( next ); next.clear(); while (!curr.empty()) { Mesh::ElementHandle elem = curr.back(); curr.pop_back(); conn.clear(); mesh.elements_get_attached_vertices( &elem, 1, conn, off, err ); if (err) return 1; int min = std::numeric_limits<int>::max(); for (size_t i = 0; i < conn.size(); ++i) { d_iter = depth.find( conn[i] ); if (d_iter != depth.end() && d_iter->second < min) min = d_iter->second; } if (min == std::numeric_limits<int>::max()) { next.push_back( elem ); continue; } for (size_t i = 0; i < conn.size(); ++i) { d_iter = depth.find( conn[i] ); if (d_iter == depth.end() || d_iter->second > min+1) depth[conn[i]] = min+1; } } } // write depth map to tag for debugging purposes std::vector<int> depth_vals(verts.size()); for (size_t i = 0; i < verts.size(); ++i) depth_vals[i] = depth[verts[i]]; TagHandle tag = mesh.tag_create( "depth", Mesh::INT, 1, 0, err ); if (err) return 1; mesh.tag_set_vertex_data( tag, verts.size(), arrptr(verts), arrptr(depth_vals), err ); if (err) return 1; // set tag specifying slaved vertices for (size_t i = 0; i < verts.size(); ++i) if (std::binary_search( higher_order.begin(), higher_order.end(), verts[i] )) depth_vals[i] = depth[verts[i]] > n; else depth_vals[i] = 0; tag = mesh.tag_create( "slaved", Mesh::INT, 1, 0, err ); if (err) return 1; mesh.tag_set_vertex_data( tag, verts.size(), arrptr(verts), arrptr(depth_vals), err ); if (err) return 1; // perturb mid-edge nodes along boundary std::vector<MsqVertex> coords; for (size_t i = 0; i < skin.size(); ++i) { if (!std::binary_search( higher_order.begin(), higher_order.end(), skin[i])) continue; curr.clear(); mesh.vertices_get_attached_elements( &skin[i], 1, curr, off, err ); if (err) return 1; assert(curr.size() == 1); conn.clear(); mesh.elements_get_attached_vertices( arrptr(curr), 1, conn, off, err ); if (err) return 1; // estimate element center coords.resize( conn.size() ); mesh.vertices_get_coordinates( arrptr(conn), arrptr(coords), conn.size(), err ); if (err) return 1; Vector3D mean(0.0); for (size_t j = 0; j < coords.size(); ++j) mean += coords[j]; mean /= coords.size(); size_t idx = std::find( conn.begin(), conn.end(), skin[i] ) - conn.begin(); assert(idx < conn.size()); Vector3D init = coords[idx]; Vector3D pos = (1 - PERTURB_FRACT) * init + PERTURB_FRACT * mean; mesh.vertex_set_coordinates( skin[i], pos, err ); if (err) return 1; } mesh.write_vtk( argv[3], err ); if (err) return 1; return 0; }
void VtkTest::test_read_quadratic( const char* filename ) { const size_t NUM_ELEM = 8; MeshImpl mesh; MsqPrintError err(cout); mesh.read_vtk( filename, err ); ASSERT_NO_ERROR(err); std::vector<Mesh::ElementHandle> elems(NUM_ELEM); mesh.get_all_elements( elems, err ); ASSERT_NO_ERROR(err); CPPUNIT_ASSERT_EQUAL(elems.size(), NUM_ELEM ); std::vector<Mesh::VertexHandle> conn; std::vector<size_t> offsets; mesh.elements_get_attached_vertices( arrptr(elems), elems.size(), conn, offsets, err ); ASSERT_NO_ERROR(err); CPPUNIT_ASSERT_EQUAL( conn.size(), (size_t)108 ); EntityTopology types[NUM_ELEM]; mesh.elements_get_topologies( arrptr(elems), types, NUM_ELEM, err ); ASSERT_NO_ERROR(err); static const double hex_corners[] = { 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0 }; static const double tet_corners[] = { 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 0.0, -1.0, 0.0, 0.0, 1.0 }; static const double pyr_corners[] = { 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 0.0, 0.0, 1.0 }; static const double pri_corners[] = { -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0 }; static const unsigned hex_edges[] = { 0, 1, 1, 2, 2, 3, 3, 0, 0, 4, 1, 5, 2, 6, 3, 7, 4, 5, 5, 6, 6, 7, 7, 4 }; static const unsigned tet_edges[] = { 0, 1, 1, 2, 2, 0, 0, 3, 1, 3, 2, 3 }; static const unsigned pri_edges[] = { 0, 1, 1, 2, 2, 0, 0, 3, 1, 4, 2, 5, 3, 4, 4, 5, 5, 3 }; static const unsigned pyr_edges[] = { 0, 1, 1, 2, 2, 3, 3, 0, 0, 4, 1, 4, 2, 4, 3, 4 }; static const unsigned hex_faces[] = { 4, 0, 1, 5, 4, 4, 1, 2, 6, 5, 4, 2, 3, 7, 6, 4, 3, 0, 4, 7, 4, 3, 2, 1, 0, 4, 4, 5, 6, 7 }; static const struct { EntityTopology topology; unsigned num_corners; unsigned num_edges; unsigned num_faces; // if non-zero expect mid-face nodes unsigned num_region; // if non-zero expect mid-region node const double* corners; const unsigned* edges; const unsigned* faces; } expected_elems[NUM_ELEM] = { { Mesquite::HEXAHEDRON, 8, 12, 0, 0, hex_corners, hex_edges, hex_faces }, { Mesquite::HEXAHEDRON, 8, 12, 6, 1, hex_corners, hex_edges, hex_faces }, { Mesquite::TETRAHEDRON, 4, 6, 0, 0, tet_corners, tet_edges, 0 }, { Mesquite::QUADRILATERAL, 4, 4, 0, 0, hex_corners, hex_edges, 0 }, { Mesquite::QUADRILATERAL, 4, 4, 0, 1, hex_corners, hex_edges, 0 }, { Mesquite::TRIANGLE, 3, 3, 0, 0, tet_corners, tet_edges, 0 }, { Mesquite::PRISM, 6, 9, 0, 0, pri_corners, pri_edges, 0 }, { Mesquite::PYRAMID, 5, 8, 0, 0, pyr_corners, pyr_edges, 0 } }; MsqVertex have; std::vector<Mesh::VertexHandle>::iterator v_it = conn.begin(); for (unsigned i = 0; i < NUM_ELEM; ++i) { CPPUNIT_ASSERT_EQUAL( expected_elems[i].topology, types[i] ); size_t vtx_start = offsets[i]; size_t vtx_end = offsets[i+1]; size_t conn_len = expected_elems[i].num_corners + expected_elems[i].num_edges + expected_elems[i].num_faces + expected_elems[i].num_region; CPPUNIT_ASSERT_EQUAL( conn_len, vtx_end - vtx_start ); for (unsigned c = 0; c < expected_elems[i].num_corners; ++c, ++v_it) { Vector3D expected(expected_elems[i].corners + 3*c); mesh.vertices_get_coordinates( &*v_it, &have, 1, err ); ASSERT_NO_ERROR(err); expected -= have; CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.0, expected.length(), DBL_EPSILON ); } for (unsigned m = 0; m < expected_elems[i].num_edges; ++m, ++v_it) { unsigned start_idx = expected_elems[i].edges[2*m]; unsigned end_idx = expected_elems[i].edges[2*m+1]; Vector3D start( expected_elems[i].corners + 3*start_idx ); Vector3D end( expected_elems[i].corners + 3*end_idx ); Vector3D expected = 0.5 * (start + end); mesh.vertices_get_coordinates( &*v_it, &have, 1, err ); ASSERT_NO_ERROR(err); expected -= have; CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.0, expected.length(), DBL_EPSILON ); } const unsigned* f_it = expected_elems[i].faces; for (unsigned m = 0; m < expected_elems[i].num_faces; ++m, ++v_it) { Vector3D expected(0,0,0); const unsigned face_size = *f_it; ++f_it; CPPUNIT_ASSERT( face_size == 3u || face_size == 4u ); for (unsigned f = 0; f < face_size; ++f, ++f_it) expected += Vector3D( expected_elems[i].corners + 3 * *f_it ); expected /= face_size; mesh.vertices_get_coordinates( &*v_it, &have, 1, err ); ASSERT_NO_ERROR(err); expected -= have; CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.0, expected.length(), DBL_EPSILON ); } if (expected_elems[i].num_region) { CPPUNIT_ASSERT_EQUAL( 1u, expected_elems[i].num_region ); Vector3D expected(0,0,0); for (unsigned m = 0; m < expected_elems[i].num_corners; ++m) expected += Vector3D( expected_elems[i].corners + 3*m ); expected /= expected_elems[i].num_corners; mesh.vertices_get_coordinates( &*v_it, &have, 1, err ); ASSERT_NO_ERROR(err); expected -= have; CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.0, expected.length(), DBL_EPSILON ); ++v_it; } } }
void SlaveBoundaryVerticesTest::test_slaved_common( unsigned depth, unsigned boundary ) { MeshImpl mesh; DomainClassifier domain; make_mesh( mesh, domain, 2*depth+2 ); MsqPrintError err(std::cerr); std::vector< std::vector<Mesh::VertexHandle> > depths(depth+1); std::set<Mesh::VertexHandle> non_slave; std::set<Mesh::VertexHandle>::iterator p; // find boundary vertices std::vector<Mesh::VertexHandle> verts; mesh.get_all_vertices( verts, err ); ASSERT_NO_ERROR(err); CPPUNIT_ASSERT(!verts.empty()); if (boundary >= 4) { std::vector<bool> flags; mesh.vertices_get_fixed_flag( arrptr(verts), flags, verts.size(), err ); ASSERT_NO_ERROR(err); for (size_t i = 0; i < verts.size(); ++i) if (flags[i]) { depths[0].push_back( verts[i] ); non_slave.insert( verts[i] ); } } else { std::vector<unsigned short> dim(verts.size()); domain.domain_DoF( arrptr(verts), arrptr(dim), verts.size(), err ); ASSERT_NO_ERROR(err); for (size_t i = 0; i < verts.size(); ++i) if (dim[i] <= boundary) { depths[0].push_back( verts[i] ); non_slave.insert( verts[i] ); } } // check that our input is usable for this test CPPUNIT_ASSERT( !verts.empty() ); // find all vertices up to specified depth for (unsigned d = 0; d < depth; ++d) { for (size_t i = 0; i < depths[d].size(); ++i) { std::vector<Mesh::ElementHandle> adj; std::vector<size_t> junk; mesh.vertices_get_attached_elements( &depths[d][i], 1, adj, junk, err ); ASSERT_NO_ERROR(err); for(size_t j = 0; j < adj.size(); ++j) { junk.clear(); std::vector<Mesh::VertexHandle> conn; mesh.elements_get_attached_vertices( &adj[j], 1, conn, junk, err ); ASSERT_NO_ERROR(err); for (size_t k = 0; k < conn.size(); ++k) { p = non_slave.find(conn[k]); if (p == non_slave.end()) { non_slave.insert( p, conn[k] ); depths[d+1].push_back( conn[k] ); } } } } } // Check that our input is usable for this test: // Should have some vertices that are not within the specified depth of // the boundary. CPPUNIT_ASSERT( non_slave.size() < verts.size() ); // Now build a map of all higher-order nodes in the mesh std::set<Mesh::VertexHandle> higher_order; std::vector<Mesh::ElementHandle> elems; mesh.get_all_elements( elems, err ); ASSERT_NO_ERROR(err); CPPUNIT_ASSERT(!elems.empty()); std::vector<EntityTopology> types(elems.size()); mesh.elements_get_topologies( arrptr(elems), arrptr(types), elems.size(), err ); ASSERT_NO_ERROR(err); for (size_t i = 0; i < elems.size(); ++i) { std::vector<Mesh::VertexHandle> conn; std::vector<size_t> junk; mesh.elements_get_attached_vertices( &elems[i], 1, conn, junk, err ); ASSERT_NO_ERROR(err); for (size_t j = TopologyInfo::corners( types[i] ); j < conn.size(); ++j) higher_order.insert( conn[j] ); } // Check that our input is usable for this test: // Should have some higher-order vertices CPPUNIT_ASSERT( !higher_order.empty() ); // Now build a map of all fixed vertices std::set<Mesh::VertexHandle> fixed_vertices; std::vector<bool> fixed; mesh.vertices_get_fixed_flag( arrptr(verts), fixed, verts.size(), err ); ASSERT_NO_ERROR(err); for (size_t i = 0; i < verts.size(); ++i) if (fixed[i]) fixed_vertices.insert( verts[i] ); // Now actually run the tool Settings settings; settings.set_slaved_ho_node_mode( Settings::SLAVE_CALCULATED ); SlaveBoundaryVertices tool( depth, boundary ); tool.loop_over_mesh( &mesh, &domain, &settings, err ); ASSERT_NO_ERROR(err); // Now verify the results std::vector<unsigned char> bytes( verts.size() ); mesh.vertices_get_byte( arrptr(verts), arrptr(bytes), verts.size(), err ); ASSERT_NO_ERROR(err); for (size_t i = 0; i < verts.size(); ++i) { bool in_non_slave = (non_slave.find( verts[i] ) != non_slave.end()); bool in_fixed = (fixed_vertices.find( verts[i] ) != fixed_vertices.end()); bool in_higher_order = (higher_order.find( verts[i] ) != higher_order.end()); if (bytes[i] & MsqVertex::MSQ_DEPENDENT) { // if slave node // must not be within 'depth' of boundary CPPUNIT_ASSERT( !in_non_slave ); // must be a higher-order vertex CPPUNIT_ASSERT( in_higher_order ); // must not be fixed CPPUNIT_ASSERT( !in_fixed ); } else { // there are three reasons that a vertex isn't slaved bool in_non_slave = (non_slave.find( verts[i] ) != non_slave.end()); bool in_fixed = (fixed_vertices.find( verts[i] ) != fixed_vertices.end()); bool in_higher_order = (higher_order.find( verts[i] ) != higher_order.end()); CPPUNIT_ASSERT( in_fixed || !in_higher_order || in_non_slave ); } } }