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); }
// 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 main( int argc, char* argv[] ) { const char* deformed_file = 0; const char* smoothed_file = 0; const char* tag_file = 0; struct { const char* flag; const char** name_ptr; } flags[] = { { "-d", &deformed_file }, { "-t", &tag_file }, { "-f", &smoothed_file }, { 0, 0 } }; for (int i = 1; i < argc; ++i) { int j; for (j = 0; flags[j].flag && strcmp( flags[j].flag, argv[i] ); ++j); if (!flags[j].flag) { std::cerr << "Invalid argument: \"" << argv[i] << '"' << std::endl; usage(argv[0]); } else if (++i == argc) { std::cerr << "Expected argument following \"" << argv[i-1] << '"' << std::endl; usage(argv[0]); } *(flags[j].name_ptr) = argv[i]; } // load mesh MsqPrintError err(std::cerr); MeshImpl mesh; mesh.read_vtk( INPUT_FILE, err ); if (MSQ_CHKERR(err)) return 1; // find boundary vertices std::vector<Mesh::VertexHandle> curves[4]; Mesh::VertexHandle corners[4]; classify_boundary( &mesh, corners, curves, err ); if (MSQ_CHKERR(err)) return 1; // new, "deformed" domain will be an 2HDx2HD planar square const double corner_coords[][3] = { {-HD,-HD, Z}, { HD,-HD, Z}, { HD, HD, Z}, {-HD, HD, Z} }; LineDomain lines[4] = { LineDomain( Vector3D(corner_coords[0]), Vector3D( 1, 0, 0) ), LineDomain( Vector3D(corner_coords[1]), Vector3D( 0, 1, 0) ), LineDomain( Vector3D(corner_coords[2]), Vector3D(-1, 0, 0) ), LineDomain( Vector3D(corner_coords[3]), Vector3D( 0,-1, 0) ) }; PlanarDomain surface( PlanarDomain::XY, Z ); // save initial mesh state DeformingCurveSmoother curve_tool; for (int i = 0; i < 4; ++i) { curve_tool.store_initial_mesh( &mesh, &curves[i][0], curves[i].size(), &lines[i], err ); if (MSQ_CHKERR(err)) return 1; } DeformingDomainWrapper wrapper; wrapper.store_initial_mesh( &mesh, err ); if (MSQ_CHKERR(err)) return 1; cond_write_file( mesh, tag_file ); // move corner vertices to new location for (int i = 0; i < 4; ++i) { Vector3D vect(corner_coords[i]); mesh.vertex_set_coordinates( corners[i], vect, err ); if (MSQ_CHKERR(err)) return 1; } std::vector<bool> fixed(4,true); mesh.vertices_set_fixed_flag( corners, fixed, 4, err ); if (MSQ_CHKERR(err)) return 1; // smooth curves for (int i = 0; i < 4; ++i) { curve_tool.smooth_curve( &mesh, &curves[i][0], curves[i].size(), &lines[i], DeformingCurveSmoother::PROPORTIONAL, err ); if (MSQ_CHKERR(err)) return 1; fixed.resize(curves[i].size(),true); mesh.vertices_set_fixed_flag( &curves[i][0], fixed, curves[i].size(), err ); if (MSQ_CHKERR(err)) return 1; } cond_write_file( mesh, deformed_file ); // smooth surface mesh MeshDomainAssoc mesh_and_domain = MeshDomainAssoc(&mesh, &surface); wrapper.run_instructions( &mesh_and_domain, err ); if (MSQ_CHKERR(err)) return 1; cond_write_file( mesh, smoothed_file ); return wrapper.quality_assessor().invalid_elements(); }
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 ); }