void TagVertexMeshTest::test_alternate_name() { MsqPrintError err( std::cerr ); Vector3D new_coords(5, 5, 5); MsqVertex get_coords; std::vector<Mesh::VertexHandle> vertices; realMesh->get_all_vertices( vertices, err ); ASSERT_NO_ERROR(err); Mesh::VertexHandle vertex = vertices[0]; realMesh->vertices_get_coordinates( &vertex, &get_coords, 1, err ); ASSERT_NO_ERROR(err); Vector3D orig_coords = get_coords; // modify a vertex in the tag interface and save it { TagVertexMesh tag_mesh( err, realMesh, false, "foobar" ); ASSERT_NO_ERROR(err); tag_mesh.vertex_set_coordinates( vertex, new_coords, err ); ASSERT_NO_ERROR(err); } // verify that it is modified in the new interface { TagVertexMesh tag_mesh( err, realMesh, false, "foobar" ); ASSERT_NO_ERROR(err); tag_mesh.vertices_get_coordinates( &vertex, &get_coords, 1, err ); ASSERT_NO_ERROR(err); CPPUNIT_ASSERT_VECTORS_EQUAL( new_coords, get_coords, DBL_EPSILON ); } }
void TagVertexMeshTest::test_cleanup() { MsqPrintError err( std::cerr ); Vector3D new_coords(5, 5, 5); MsqVertex get_coords; std::vector<Mesh::VertexHandle> vertices; realMesh->get_all_vertices( vertices, err ); ASSERT_NO_ERROR(err); Mesh::VertexHandle vertex = vertices[0]; realMesh->vertices_get_coordinates( &vertex, &get_coords, 1, err ); ASSERT_NO_ERROR(err); Vector3D orig_coords = get_coords; // modify a vertex in the tag interface { TagVertexMesh tag_mesh( err, realMesh, true ); ASSERT_NO_ERROR(err); tag_mesh.vertex_set_coordinates( vertex, new_coords, err ); ASSERT_NO_ERROR(err); } // check that values were cleaned up when previous instance was destroyed { TagVertexMesh tag_mesh( err, realMesh, false ); ASSERT_NO_ERROR(err); tag_mesh.vertices_get_coordinates( &vertex, &get_coords, 1, err ); ASSERT_NO_ERROR(err); CPPUNIT_ASSERT_VECTORS_EQUAL( orig_coords, get_coords, DBL_EPSILON ); } }
void DomainClassifierTest::check_domain( DomainClassifier& domain ) { std::vector<Mesh::VertexHandle> vertices, cverts; std::vector<Mesh::ElementHandle> elements, celems; // Check that, for each entity with a domain, the // DomainClassifier instance returns that domain. // Also, put all entities with domains into cverts and // celems for later. for (unsigned i = 0; i < myDomains.size(); ++i) { for (unsigned j = 0; j < myDomains[i].vertices.size(); ++j) { Mesh::VertexHandle v = myDomains[i].vertices[j]; const MeshDomain* ptr = domain.find_vertex_domain( v ); CPPUNIT_ASSERT( myDomains[i].domain == ptr ); cverts.push_back( v ); } for (unsigned k = 0; k < myDomains[i].elements.size(); ++k) { Mesh::ElementHandle e = myDomains[i].elements[k]; const MeshDomain* ptr = domain.find_element_domain( e ); CPPUNIT_ASSERT( myDomains[i].domain == ptr ); celems.push_back( e ); } } // sort cverts and celems so we can do binary_search later std::sort( cverts.begin(), cverts.end() ); std::sort( celems.begin(), celems.end() ); // get all vertices and elements in mesh MsqPrintError err(std::cerr); myMesh.get_all_vertices( vertices, err ); CPPUNIT_ASSERT(!err); myMesh.get_all_elements( elements, err ); CPPUNIT_ASSERT(!err); // For each vertex not in a domain (not in cverts), make sure // that the domain is NULL. for (size_t i = 0; i < vertices.size(); ++i) { if (std::binary_search( cverts.begin(), cverts.end(), vertices[i] )) continue; const MeshDomain* ptr = domain.find_vertex_domain( vertices[i] ); CPPUNIT_ASSERT( NULL == ptr ); } // For each element not in a domain (not in celems), make sure // that the domain is NULL. for (size_t i = 0; i < elements.size(); ++i) { if (std::binary_search( celems.begin(), celems.end(), elements[i] )) continue; const MeshDomain* ptr = domain.find_element_domain( elements[i] ); CPPUNIT_ASSERT( NULL == ptr ); } }
void get_planar_example( const char* filename, DomainClassifier& geom, MeshImpl& mesh, MsqError& err ) { static PlanarDomain z(PlanarDomain::XY); mesh.read_vtk(filename, err); MSQ_ERRRTN(err); mesh.mark_skin_fixed(err); MSQ_ERRRTN(err); DomainClassifier::DomainSet set(&z); mesh.get_all_vertices( set.vertices, err ); MSQ_ERRRTN(err); mesh.get_all_elements( set.elements, err ); MSQ_ERRRTN(err); DomainClassifier::classify_by_handle( geom, &mesh, &set, 1, err ); MSQ_ERRRTN(err); }
void TagVertexMeshTest::test_reference_mesh() { MsqPrintError err( std::cerr ); TagVertexMesh tag_mesh( err, realMesh, true ); ASSERT_NO_ERROR(err); std::vector<Mesh::VertexHandle> vertices; realMesh->get_all_vertices( vertices, err ); ASSERT_NO_ERROR(err); // copy real mesh coordinates into tag data in TagVertexMesh InstructionQueue q; q.add_tag_vertex_mesh( &tag_mesh, err ); ASSERT_NO_ERROR(err); q.run_instructions( realMesh, err ); ASSERT_NO_ERROR(err); // Check that initial position for vertex matches that of real mesh Mesh::VertexHandle vertex = vertices[0]; MsqVertex get_coords; Vector3D orig_coords, real_coords, tag_coords; realMesh->vertices_get_coordinates( &vertex, &get_coords, 1, err ); ASSERT_NO_ERROR(err); orig_coords = get_coords; tag_mesh.vertices_get_coordinates( &vertex, &get_coords, 1, err ); ASSERT_NO_ERROR(err); tag_coords = get_coords; CPPUNIT_ASSERT_VECTORS_EQUAL( orig_coords, tag_coords, DBL_EPSILON ); // Check that modified vertex coords show up in real mesh but not // tag mesh. realMesh->vertices_get_coordinates( &vertex, &get_coords, 1, err ); ASSERT_NO_ERROR(err); orig_coords = get_coords; Vector3D new_coords(5,5,5); realMesh->vertex_set_coordinates( vertex, new_coords, err ); ASSERT_NO_ERROR(err); tag_mesh.vertices_get_coordinates( &vertex, &get_coords, 1, err ); ASSERT_NO_ERROR(err); tag_coords = get_coords; CPPUNIT_ASSERT_VECTORS_EQUAL( orig_coords, tag_coords, DBL_EPSILON ); // restore realMesh to initial state realMesh->vertex_set_coordinates( vertex, orig_coords, err ); ASSERT_NO_ERROR(err); }
void TagVertexMeshTest::test_vertex_coordinates() { MsqPrintError err( std::cerr ); TagVertexMesh tag_mesh( err, realMesh, true ); ASSERT_NO_ERROR(err); std::vector<Mesh::VertexHandle> vertices; realMesh->get_all_vertices( vertices, err ); ASSERT_NO_ERROR(err); // Check that initial position for vertex matches that of real mesh Mesh::VertexHandle vertex = vertices[0]; MsqVertex get_coords; Vector3D orig_coords, real_coords, tag_coords; realMesh->vertices_get_coordinates( &vertex, &get_coords, 1, err ); ASSERT_NO_ERROR(err); orig_coords = get_coords; tag_mesh.vertices_get_coordinates( &vertex, &get_coords, 1, err ); ASSERT_NO_ERROR(err); tag_coords = get_coords; CPPUNIT_ASSERT_VECTORS_EQUAL( orig_coords, tag_coords, DBL_EPSILON ); // Check that modified vertex coords show up in tag mesh but not // real mesh. Vector3D new_coords(5,5,5); tag_mesh.vertex_set_coordinates( vertex, new_coords, err ); ASSERT_NO_ERROR(err); tag_mesh.vertices_get_coordinates( &vertex, &get_coords, 1, err ); ASSERT_NO_ERROR(err); tag_coords = get_coords; CPPUNIT_ASSERT_VECTORS_EQUAL( new_coords, tag_coords, DBL_EPSILON ); realMesh->vertices_get_coordinates( &vertex, &get_coords, 1, err ); ASSERT_NO_ERROR(err); real_coords = get_coords; CPPUNIT_ASSERT_VECTORS_EQUAL( orig_coords, real_coords, DBL_EPSILON ); }
// 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; }
int uwt( bool skip, UntangleWrapper::UntangleMetric metric, const char* input_file_base, int expected, bool flip_domain ) { if (skip) return 0; if (!brief_output) std::cout << std::endl << "**********************************************" << std::endl; std::cout << "Running \"" << input_file_base << "\" for " << tostr(metric) << std::endl; if (!brief_output) std::cout << "**********************************************" << std::endl << std::endl; // get mesh MsqError err; MeshImpl mesh; std::string input_file( VTK_2D_DIR ); input_file += input_file_base; mesh.read_vtk( input_file.c_str(), err ); if (err) { std::cerr << err << std::endl; std::cerr << "ERROR: " << input_file << " : failed to read file" << std::endl; return 1; } // get domain std::vector<Mesh::VertexHandle> verts; mesh.get_all_vertices( verts, err ); if (err || verts.empty()) abort(); MsqVertex coords; mesh.vertices_get_coordinates( arrptr(verts), &coords, 1, err ); if (err) abort(); Vector3D norm(0,0,flip_domain ? -1 : 1); PlanarDomain domain( norm, coords ); // run wrapper UntangleWrapper wrapper( metric ); wrapper.set_vertex_movement_limit_factor( 0.005 ); double constant = (metric == UntangleWrapper::BETA) ? beta : mu_sigma; if (constant > 0) wrapper.set_metric_constant( constant ); if (brief_output) wrapper.quality_assessor().disable_printing_results(); MeshDomainAssoc mesh_and_domain = MeshDomainAssoc(&mesh, &domain); wrapper.run_instructions( &mesh_and_domain, err ); if (err) { std::cerr << err << std::endl; std::cerr << "ERROR: optimization failed" << std::endl; return 1; } // write output file if (write_output) { std::string result_file(tostr(metric)); result_file += "-"; result_file += input_file_base; mesh.write_vtk( result_file.c_str(), err ); if (err) { std::cerr << err << std::endl; std::cerr << "ERROR: " << result_file << " : failed to write file" << std::endl; err.clear(); } else { std::cerr << "Wrote file: " << result_file << std::endl; } } // test number of inverted elements int count, junk; wrapper.quality_assessor().get_inverted_element_count( count, junk, err ); if (err) abort(); if (count < expected) { std::cout << "WARNING: expected " << expected << " inverted elements but finished with only " << count << std::endl << "Test needs to be updated?" << std::endl << std::endl; return 0; } else if (count == expected) { std::cout << "Completed with " << count << " inverted elements remaining" << std::endl << std::endl; return 0; } else { std::cerr << "ERROR: expected " << expected << " inverted elements but finished with " << count << std::endl << std::endl; return 1; } }
double run( QualityMetric* metric, Solver solver_type, const char* input_file, double& seconds_out, int& iterations_out ) { MsqPrintError err(cerr); IdealWeightInverseMeanRatio qa_metric; TerminationCriterion inner, outer; outer.add_iteration_limit( 1 ); inner.add_absolute_vertex_movement( 1e-4 ); inner.add_iteration_limit( 100 ); PMeanPTemplate of( 1.0, metric ); QualityAssessor qa( &qa_metric ); qa.add_quality_assessment( metric ); InstructionQueue q; SteepestDescent steep(&of); QuasiNewton quasi(&of); ConjugateGradient conj(&of); VertexMover* solver = 0; switch (solver_type) { case STEEP_DESCENT: solver = &steep; break; case QUASI_NEWT:solver = &quasi;break; case CONJ_GRAD: solver = &conj; break; } q.set_master_quality_improver( solver, err ); q.add_quality_assessor( &qa, err ); solver->set_inner_termination_criterion(&inner); solver->set_outer_termination_criterion(&outer); if (plot_file) inner.write_iterations( plot_file, err ); MeshImpl mesh; mesh.read_vtk( input_file, err ); if (err) { cerr << "Failed to read input file: \"" << input_file << '"' << endl; exit(1); } std::vector<Mesh::VertexHandle> handles; mesh.get_all_vertices( handles, err ); if (handles.empty()) { cerr << "no veritces in mesh" << endl; exit(1); } std::vector<MsqVertex> coords(handles.size()); mesh.vertices_get_coordinates( arrptr(handles), arrptr(coords), handles.size(), err ); Vector3D min(HUGE_VAL), max(-HUGE_VAL); for (size_t i = 0; i < coords.size(); ++i) { for (int j = 0; j < 3; ++j) { if (coords[i][j] < min[j]) min[j] = coords[i][j]; if (coords[i][j] > max[j]) max[j] = coords[i][j]; } } Vector3D size = max - min; PlanarDomain* domain = 0; if (size[0] < 1e-4) domain = new PlanarDomain( PlanarDomain::YZ, min[0] ); else if (size[1] < 1e-4) domain = new PlanarDomain( PlanarDomain::XZ, min[1] ); else if (size[2] < 1e-4) domain = new PlanarDomain( PlanarDomain::XY, min[2] ); Timer timer; q.run_instructions( &mesh, domain, err ); seconds_out = timer.since_birth(); if (err) { cerr << "Optimization failed." << endl << err << endl; abort(); } if (vtk_file) { MeshWriter::write_vtk( &mesh, vtk_file, err ); if (err) cerr << vtk_file << ": failed to write file." << endl; } if (gpt_file) { MeshWriter::write_gnuplot( &mesh, gpt_file, err ); if (err) cerr << gpt_file << ": failed to write file." << endl; } if (eps_file) { PlanarDomain xy(PlanarDomain::XY); MeshWriter::Projection proj( domain ? domain : &xy ); MeshWriter::write_eps( &mesh, eps_file, proj, err ); if (err) cerr << eps_file << ": failed to write file." << endl; } delete domain; iterations_out = inner.get_iteration_count(); const QualityAssessor::Assessor* a = qa.get_results( &qa_metric ); return a->get_average(); }
void DomainClassifierTest::setUp() { myMesh.clear(); myDomains.clear(); domainDims.clear(); // vertex coodinates const char vertex_data[] = "POINTS 64 float\n" "0 0 0 1 0 0 2 0 0 3 0 0\n" "0 1 0 1 1 0 2 1 0 3 1 0\n" "0 2 0 1 2 0 2 2 0 3 2 0\n" "0 3 0 1 3 0 2 3 0 3 3 0\n" "\n" "0 0 1 1 0 1 2 0 1 3 0 1\n" "0 1 1 1 1 1 2 1 1 3 1 1\n" "0 2 1 1 2 1 2 2 1 3 2 1\n" "0 3 1 1 3 1 2 3 1 3 3 1\n" "\n" "0 0 2 1 0 2 2 0 2 3 0 2\n" "0 1 2 1 1 2 2 1 2 3 1 2\n" "0 2 2 1 2 2 2 2 2 3 2 2\n" "0 3 2 1 3 2 2 3 2 3 3 2\n" "\n" "0 0 3 1 0 3 2 0 3 3 0 3\n" "0 1 3 1 1 3 2 1 3 3 1 3\n" "0 2 3 1 2 3 2 2 3 3 2 3\n" "0 3 3 1 3 3 2 3 3 3 3 3\n" "\n"; // quad connectivity for quads on mesh skin const int num_quads = 9*6; // nine per side const char quad_data[] = "4 1 0 4 5\n" // -z face (z == 0) "4 2 1 5 6\n" "4 3 2 6 7\n" "4 5 4 8 9\n" "4 6 5 9 10\n" "4 7 6 10 11\n" "4 9 8 12 13\n" "4 10 9 13 14\n" "4 11 10 14 15\n" "\n" "4 48 49 53 52\n" // +z face (z == 3) "4 49 50 54 53\n" "4 50 51 55 54\n" "4 52 53 57 56\n" "4 53 54 58 57\n" "4 54 55 59 58\n" "4 56 57 61 60\n" "4 57 58 62 61\n" "4 58 59 63 62\n" "\n" "4 0 1 17 16\n" // -y face (y == 0) "4 1 2 18 17\n" "4 2 3 19 18\n" "4 16 17 33 32\n" "4 17 18 34 33\n" "4 18 19 35 34\n" "4 32 33 49 48\n" "4 33 34 50 49\n" "4 34 35 51 50\n" "\n" "4 13 12 28 29\n" // +y face (y == 3) "4 14 13 29 30\n" "4 15 14 30 31\n" "4 29 28 44 45\n" "4 30 29 45 46\n" "4 31 30 46 47\n" "4 45 44 60 61\n" "4 46 45 61 62\n" "4 47 46 62 63\n" "\n" "4 4 0 16 20\n" // -x face (x == 0) "4 8 4 20 24\n" "4 12 8 24 28\n" "4 20 16 32 36\n" "4 24 20 36 40\n" "4 28 24 40 44\n" "4 36 32 48 52\n" "4 40 36 52 56\n" "4 44 40 56 60\n" "\n" "4 3 7 23 19\n" // +x face (x == 3) "4 7 11 27 23\n" "4 11 15 31 27\n" "4 19 23 39 35\n" "4 23 27 43 39\n" "4 27 31 47 43\n" "4 35 39 55 51\n" "4 39 43 59 55\n" "4 43 47 63 59\n" "\n"; // hexahedron connectivity const int num_hexes = 3*3*3; const char hex_data[] = "8 0 1 5 4 16 17 21 20\n" "8 1 2 6 5 17 18 22 21\n" "8 2 3 7 6 18 19 23 22\n" "8 4 5 9 8 20 21 25 24\n" "8 5 6 10 9 21 22 26 25\n" "8 6 7 11 10 22 23 27 26\n" "8 8 9 13 12 24 25 29 28\n" "8 9 10 14 13 25 26 30 29\n" "8 10 11 15 14 26 27 31 30\n" "\n" "8 16 17 21 20 32 33 37 36\n" "8 17 18 22 21 33 34 38 37\n" "8 18 19 23 22 34 35 39 38\n" "8 20 21 25 24 36 37 41 40\n" "8 21 22 26 25 37 38 42 41\n" "8 22 23 27 26 38 39 43 42\n" "8 24 25 29 28 40 41 45 44\n" "8 25 26 30 29 41 42 46 45\n" "8 26 27 31 30 42 43 47 46\n" "\n" "8 32 33 37 36 48 49 53 52\n" "8 33 34 38 37 49 50 54 53\n" "8 34 35 39 38 50 51 55 54\n" "8 36 37 41 40 52 53 57 56\n" "8 37 38 42 41 53 54 58 57\n" "8 38 39 43 42 54 55 59 58\n" "8 40 41 45 44 56 57 61 60\n" "8 41 42 46 45 57 58 62 61\n" "8 42 43 47 46 58 59 63 62\n" "\n"; // a few interior quads const int num_interior_quads = 3; const char interior_quad_data[] = "4 1 5 25 17\n" "4 4 5 25 24\n" "4 16 17 25 24\n" "\n"; const char filename[] = "dctest.vtk"; FILE* file = fopen( filename, "w" ); fputs( "# vtk DataFile Version 2.0\n", file ); fputs( "Mesquite Mesh\n", file ); fputs( "ASCII\n", file ); fputs( "DATASET UNSTRUCTURED_GRID\n", file ); fputs( vertex_data, file ); int num_elem = num_quads + num_hexes + num_interior_quads; int num_elem_data = 5*num_quads + 9*num_hexes * 5*num_interior_quads; fprintf( file, "CELLS %d %d\n", num_elem, num_elem_data ); fputs( quad_data, file ); fputs( hex_data, file ); fputs( interior_quad_data, file ); fprintf( file, "CELL_TYPES %d\n", num_elem ); for (int i = 0; i < num_quads; ++i) fputs( "9\n", file ); for (int i = 0; i < num_hexes; ++i) fputs( "12\n", file ); for (int i = 0; i < num_interior_quads; ++i) fputs( "9\n", file ); fclose( file ); MsqPrintError err(std::cerr); myMesh.read_vtk( filename, err ); remove( filename ); CPPUNIT_ASSERT(!err); std::vector<Mesh::VertexHandle> verts; std::vector<Mesh::ElementHandle> elems; myMesh.get_all_vertices(verts, err); CPPUNIT_ASSERT(!err); CPPUNIT_ASSERT_EQUAL( (size_t)64, verts.size() ); myMesh.get_all_elements(elems, err); CPPUNIT_ASSERT(!err); CPPUNIT_ASSERT_EQUAL( (size_t)num_elem, elems.size() ); // define point domains PointDomain* pdom[8]; pdom[0] = new PointDomain( Vector3D(0,0,0) ); pdom[1] = new PointDomain( Vector3D(3,0,0) ); pdom[2] = new PointDomain( Vector3D(0,3,0) ); pdom[3] = new PointDomain( Vector3D(3,3,0) ); pdom[4] = new PointDomain( Vector3D(0,0,3) ); pdom[5] = new PointDomain( Vector3D(3,0,3) ); pdom[6] = new PointDomain( Vector3D(0,3,3) ); pdom[7] = new PointDomain( Vector3D(3,3,3) ); size_t pdidx[8] = { 0, 3, 12, 15, 48, 51, 60, 63 }; for (unsigned i = 0; i < 8; ++i) { MsqVertex coords; Mesh::VertexHandle h = verts[pdidx[i]]; myMesh.vertices_get_coordinates( &h, &coords, 1, err ); CPPUNIT_ASSERT(!err); CPPUNIT_ASSERT_VECTORS_EQUAL( pdom[i]->geom(), coords, 1e-6 ); DomSet set; set.domain = pdom[i]; set.vertices.push_back( h ); myDomains.push_back( set ); domainDims.push_back( 0 ); } // define line domains LineDomain* ldom[12]; ldom[0] = new LineDomain( Vector3D(0,0,0), Vector3D(1,0,0) ); // y=0,z=0 ldom[1] = new LineDomain( Vector3D(0,3,0), Vector3D(1,0,0) ); // y=3,z=0 ldom[2] = new LineDomain( Vector3D(0,0,3), Vector3D(1,0,0) ); // y=0,z=3 ldom[3] = new LineDomain( Vector3D(0,3,3), Vector3D(1,0,0) ); // y=3,z=3 ldom[4] = new LineDomain( Vector3D(0,0,0), Vector3D(0,1,0) ); // x=0,z=0 ldom[5] = new LineDomain( Vector3D(3,0,0), Vector3D(0,1,0) ); // x=3,z=0 ldom[6] = new LineDomain( Vector3D(0,0,3), Vector3D(0,1,0) ); // x=0,z=3 ldom[7] = new LineDomain( Vector3D(3,0,3), Vector3D(0,1,0) ); // x=3,z=3 ldom[8] = new LineDomain( Vector3D(0,0,0), Vector3D(0,0,1) ); // x=0,y=0 ldom[9] = new LineDomain( Vector3D(3,0,0), Vector3D(0,0,1) ); // x=3,y=0 ldom[10]= new LineDomain( Vector3D(0,3,0), Vector3D(0,0,1) ); // x=0,y=3 ldom[11]= new LineDomain( Vector3D(3,3,0), Vector3D(0,0,1) ); // x=3,y=3 size_t ldidx[12][2] = { { 1, 2 }, { 13, 14 }, { 49, 50 }, { 61, 62 }, { 4, 8 }, { 7, 11 }, { 52, 56 }, { 55, 59 }, { 16, 32 }, { 19, 35 }, { 28, 44 }, { 31, 47 } }; for (unsigned i = 0; i < 12; ++i) { Mesh::VertexHandle v[2]; v[0] = verts[ldidx[i][0]]; v[1] = verts[ldidx[i][1]]; MsqVertex coords[2]; myMesh.vertices_get_coordinates( v, coords, 2, err ); CPPUNIT_ASSERT(!err); CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.0, ldom[i]->geom().distance( coords[0] ), 1e-6 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.0, ldom[i]->geom().distance( coords[1] ), 1e-6 ); DomSet set; set.domain = ldom[i]; set.vertices.push_back(v[0]); set.vertices.push_back(v[1]); myDomains.push_back( set ); domainDims.push_back( 1 ); } // define planar domains PlanarDomain* sdom[6]; sdom[0] = new PlanarDomain( Vector3D( 0, 0,-1), Vector3D(0,0,0) ); sdom[1] = new PlanarDomain( Vector3D( 0, 0, 1), Vector3D(0,0,3) ); sdom[2] = new PlanarDomain( Vector3D( 0,-1, 0), Vector3D(0,0,0) ); sdom[3] = new PlanarDomain( Vector3D( 0, 1, 0), Vector3D(0,3,0) ); sdom[4] = new PlanarDomain( Vector3D(-1, 0, 0), Vector3D(0,0,0) ); sdom[5] = new PlanarDomain( Vector3D( 1, 0, 0), Vector3D(3,0,0) ); size_t sdidx[6][4] = { { 5, 6, 9, 10 }, { 53, 54, 57, 58 }, { 17, 18, 33, 34 }, { 29, 30, 45, 46 }, { 20, 24, 36, 40 }, { 23, 27, 39, 43 } }; for (unsigned i = 0; i < 6; ++i) { DomSet set; set.domain = sdom[i]; for (unsigned j = 0; j < 4; ++j) set.vertices.push_back( verts[sdidx[i][j]] ); for (unsigned j = 0; j < 9; ++j) set.elements.push_back( elems[9*i+j] ); myDomains.push_back( set ); domainDims.push_back( 2 ); } // for (unsigned i = 0; i < myDomains.size(); ++i) // print_domain( i, myDomains[i] ); }
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 ); } } }
void BCDTest::compare_bcd( ObjectiveFunction* OF, string name, const char* mesh_file ) { MsqPrintError err(cout); size_t i; vector<MsqVertex> initial_coords, global_coords, bcd_coords; vector<Mesh::VertexHandle> vertex_list; // set up a smoother TerminationCriterion iterations, vertex_movement; iterations.add_iteration_limit( 2 ); vertex_movement.add_absolute_vertex_movement( 1e-3 ); SolverType global_solver( OF ); SolverType bcd_solver( OF ); global_solver.use_global_patch(); bcd_solver.use_element_on_vertex_patch(); bcd_solver.do_block_coordinate_descent_optimization(); global_solver.set_inner_termination_criterion( &vertex_movement ); bcd_solver.set_inner_termination_criterion( &iterations ); bcd_solver.set_outer_termination_criterion( &vertex_movement ); QualityAssessor qa; qa.add_quality_assessment( &mMetric ); InstructionQueue global_q, bcd_q; global_q.add_quality_assessor( &qa, err ); global_q.set_master_quality_improver( &global_solver, err ); global_q.add_quality_assessor( &qa, err ); bcd_q.set_master_quality_improver( &bcd_solver, err ); bcd_q.add_quality_assessor( &qa, err ); // read mesh MeshImpl mesh; mesh.read_vtk( mesh_file, err ); ASSERT_NO_ERROR(err); mesh.get_all_vertices( vertex_list, err ); ASSERT_NO_ERROR(err); CPPUNIT_ASSERT(!vertex_list.empty()); initial_coords.resize( vertex_list.size() ); mesh.vertices_get_coordinates( arrptr(vertex_list), arrptr(initial_coords), vertex_list.size(), err ); ASSERT_NO_ERROR(err); // run global smoother global_q.run_instructions( &mesh, err ); ASSERT_NO_ERROR(err); mesh.write_vtk( (name + "-gbl.vtk").c_str(), err ); global_coords.resize( vertex_list.size() ); mesh.vertices_get_coordinates( arrptr(vertex_list), arrptr(global_coords), vertex_list.size(), err ); ASSERT_NO_ERROR(err); // restore initial vertex positions for (i = 0; i < vertex_list.size(); ++i) { mesh.vertex_set_coordinates( vertex_list[i], initial_coords[i], err ); ASSERT_NO_ERROR(err); } // run local smoother bcd_q.run_instructions( &mesh, err ); ASSERT_NO_ERROR(err); mesh.write_vtk( (name + "-bcd.vtk").c_str(), err ); bcd_coords.resize( vertex_list.size() ); mesh.vertices_get_coordinates( arrptr(vertex_list), arrptr(bcd_coords), vertex_list.size(), err ); ASSERT_NO_ERROR(err); // compare results for (i = 0; i < bcd_coords.size(); ++i) CPPUNIT_ASSERT_VECTORS_EQUAL( global_coords[i], bcd_coords[i], 1e-2 ); }