// Test reading Vtk vector attribute void VtkTest::test_read_vector_attrib() { MeshImpl mesh; MsqPrintError err(cout); FILE* file = fopen( temp_file_name, "w+" ); fputs( structured_3d_points_data, file ); fputs( simple_vector_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 ); void* th = mesh.tag_get( "hexvect", err ); CPPUNIT_ASSERT( !err ); std::string name; Mesh::TagType type; unsigned tagsize; mesh.tag_properties( th, name, type, tagsize, err ); CPPUNIT_ASSERT( !err && type == Mesh::DOUBLE && tagsize == 3 ); double elem_data[24]; mesh.tag_get_element_data( th, 8, arrptr(elems), elem_data, err ); CPPUNIT_ASSERT( !err ); for (int i = 0; i < 8; ++i) CPPUNIT_ASSERT( Vector3D( elem_data+3*i ) == Vector3D( i+1, i+1, i+1 ) ); }
void VtkTest::check_field_attrib( const char* temp_file_name ) { MeshImpl mesh; MsqPrintError err(cout); 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::string name; Mesh::TagType type; unsigned tagsize; void* th = mesh.tag_get( "test_field elem_vects", err ); CPPUNIT_ASSERT( !err ); mesh.tag_properties( th, name, type, tagsize, err ); CPPUNIT_ASSERT( !err && type == Mesh::DOUBLE && tagsize == 3 ); double elem_data[24]; mesh.tag_get_element_data( th, 8, arrptr(elems), elem_data, err ); CPPUNIT_ASSERT( !err ); for (int i = 0; i < 8; ++i) CPPUNIT_ASSERT( Vector3D( elem_data+3*i ) == Vector3D( i+1, i+1, i+1 ) ); th = mesh.tag_get( "test_field elem_ids", err ); CPPUNIT_ASSERT( !err ); mesh.tag_properties( th, name, type, tagsize, err ); CPPUNIT_ASSERT( !err && type == Mesh::INT && tagsize == 1 ); int elem_ids[8]; mesh.tag_get_element_data( th, 8, arrptr(elems), elem_ids, err ); CPPUNIT_ASSERT( !err ); for (int i = 0; i < 8; ++i) CPPUNIT_ASSERT( elem_ids[i] == i+1 ); th = mesh.tag_get( "field1", err ); CPPUNIT_ASSERT( !err ); mesh.tag_properties( th, name, type, tagsize, err ); CPPUNIT_ASSERT( !err && type == Mesh::INT && tagsize == 1 ); int values[8]; mesh.tag_get_element_data( th, 8, arrptr(elems), values, err ); CPPUNIT_ASSERT( !err ); for (int i = 0; i < 8; ++i) CPPUNIT_ASSERT( values[i] == 8-i ); }
void TagVertexMeshTest::setUp() { const char vtk_data[] = "# vtk DataFile Version 2.0\n" "test mesh\n" "ASCII\n" "DATASET UNSTRUCTURED_GRID\n" "POINTS 3 float\n" "0 0 0\n" "1 0 0\n" "0 1 0\n" "CELLS 1 4\n" "3 0 1 2\n" "CELL_TYPES 1\n" "5\n"; FILE* file = fopen( TEMP_FILE_NAME, "w" ); CPPUNIT_ASSERT( !!file ); size_t r = fwrite( vtk_data, sizeof(vtk_data)-1, 1, file ); fclose( file ); CPPUNIT_ASSERT( r == 1 ); MsqPrintError err( std::cerr ); realMesh = new MeshImpl; realMesh->read_vtk( TEMP_FILE_NAME, err ); remove( TEMP_FILE_NAME ); ASSERT_NO_ERROR(err); }
void SlaveBoundaryVerticesTest::make_mesh( MeshImpl& mesh, DomainClassifier& domain, const int intervals ) { MsqPrintError err(std::cerr); const char input_file[] = MESH_FILES_DIR "3D/VTK/6x6x6-hex20.vtk"; const Vector3D min( -3, -3, -3 ); const Vector3D max( 3, 3, 3 ); const Vector3D space = (max - min) * 1.0/(intervals); mesh.clear(); mesh.read_vtk( input_file, err ); ASSERT_NO_ERROR(err); const Vector3D corners[8] = { Vector3D(min[0],min[1],min[2]), Vector3D(max[0],min[1],min[2]), Vector3D(max[0],max[1],min[2]), Vector3D(min[0],max[1],min[2]), Vector3D(min[0],min[1],max[2]), Vector3D(max[0],min[1],max[2]), Vector3D(max[0],max[1],max[2]), Vector3D(min[0],max[1],max[2]) }; MeshDomain* subdomains[26] = { new PlanarDomain( PlanarDomain::XZ, min[1] ), new PlanarDomain( PlanarDomain::YZ, max[0] ), new PlanarDomain( PlanarDomain::XZ, max[1] ), new PlanarDomain( PlanarDomain::YZ, min[0] ), new PlanarDomain( PlanarDomain::XY, min[2] ), new PlanarDomain( PlanarDomain::XY, max[2] ), new LineDomain( corners[0], corners[1] - corners[0] ), new LineDomain( corners[1], corners[2] - corners[1] ), new LineDomain( corners[2], corners[3] - corners[2] ), new LineDomain( corners[3], corners[0] - corners[3] ), new LineDomain( corners[0], corners[4] - corners[0] ), new LineDomain( corners[1], corners[5] - corners[1] ), new LineDomain( corners[2], corners[6] - corners[0] ), new LineDomain( corners[3], corners[7] - corners[1] ), new LineDomain( corners[4], corners[5] - corners[4] ), new LineDomain( corners[5], corners[6] - corners[5] ), new LineDomain( corners[6], corners[7] - corners[6] ), new LineDomain( corners[7], corners[4] - corners[7] ), new PointDomain( corners[0] ), new PointDomain( corners[1] ), new PointDomain( corners[2] ), new PointDomain( corners[3] ), new PointDomain( corners[4] ), new PointDomain( corners[5] ), new PointDomain( corners[6] ), new PointDomain( corners[7] ) }; const int subdims[26] = { 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 }; DomainClassifier::classify_skin_geometrically( domain, &mesh, 1e-6, subdomains, subdims, 26, err ); domain.delete_sub_domains(true); ASSERT_NO_ERROR(err); }
// Test reading Vtk simple (one-component) scalar attribute void VtkTest::test_read_simple_scalar_attrib() { MeshImpl mesh; MsqPrintError err(cout); FILE* file = fopen( temp_file_name, "w+" ); fputs( structured_3d_points_data, file ); fputs( simple_scalar_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 ); void* th = mesh.tag_get( "global_id", err ); CPPUNIT_ASSERT( !err ); std::string name; Mesh::TagType type; unsigned tagsize; mesh.tag_properties( th, name, type, tagsize, err ); CPPUNIT_ASSERT( !err && type == Mesh::INT && tagsize == 1 ); int elem_data[8]; mesh.tag_get_element_data( th, 8, arrptr(elems), elem_data, err ); CPPUNIT_ASSERT( !err ); for (int i = 0; i < 8; ++i) CPPUNIT_ASSERT( elem_data[i] == (1+i) ); }
// Test writing VTK unstructured mesh void VtkTest::test_write() { MeshImpl mesh; MsqPrintError err(cout); // Create file containing unstructured mesh test case FILE* file = fopen( temp_file_name, "w+" ); CPPUNIT_ASSERT(file); int rval = fputs( mixed_unstructured_data, file ); fclose( file ); if (rval == EOF) remove(temp_file_name); CPPUNIT_ASSERT(rval != EOF); // Read unstructured mesh file mesh.read_vtk( temp_file_name, err ); remove(temp_file_name); ASSERT_NO_ERROR(err); // Write unstructured mesh file back out mesh.write_vtk( temp_file_name, err ); if (err) remove( temp_file_name ); ASSERT_NO_ERROR(err); // Check if file contained expected mesh test_read_unstructured( temp_file_name ); remove( temp_file_name ); }
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); }
// Test reading 3D Vtk rectilinear-grid mesh void VtkTest::test_read_rectilinear_grid() { MeshImpl mesh; MsqPrintError err(cout); FILE* file = fopen( temp_file_name, "w+" ); fputs( rectilinear_grid_data, file ); fclose( file ); mesh.read_vtk( temp_file_name, err ); remove( temp_file_name ); ASSERT_NO_ERROR(err); check_8hex_structured( mesh ); }
// Test reading 2D Vtk structured-points mesh void VtkTest::test_read_structured_2d_points() { MeshImpl mesh; MsqPrintError err(cout); FILE* file = fopen( temp_file_name, "w+" ); fputs( structured_2d_points_data, file ); fclose( file ); mesh.read_vtk( temp_file_name, err ); remove( temp_file_name ); ASSERT_NO_ERROR(err); check_4quad_structured( mesh ); }
void VtkTest::test_elements() { Mesquite::MsqPrintError err(cout); MeshImpl mMesh; mMesh.read_vtk(MESH_FILES_DIR "2D/vtk/tris/untangled/equil_tri2.vtk", err); ASSERT_NO_ERROR(err); Mesquite::MeshDomainAssoc mesh_and_domain = Mesquite::MeshDomainAssoc(&mMesh, 0); Mesquite::Instruction::initialize_vertex_byte( &mesh_and_domain, 0, err ); ASSERT_NO_ERROR(err); // Retrieve a patch Mesquite::PatchData pd; pd.set_mesh( &mMesh ); VertexPatches patch_set; patch_set.set_mesh( &mMesh ); PatchIterator patches( &patch_set ); patches.get_next_patch( pd, err ); ASSERT_NO_ERROR(err); int free_vtx = pd.num_free_vertices(); // std::cout << "nb of free vertices: " << free_vtx << std::endl; CPPUNIT_ASSERT( free_vtx == 1 ); Mesquite::MsqMeshEntity* element_array = pd.get_element_array(err); ASSERT_NO_ERROR(err); size_t num_elements = pd.num_elements(); CPPUNIT_ASSERT( num_elements == 6 ); const Mesquite::MsqVertex* vtx_array = pd.get_vertex_array(err); ASSERT_NO_ERROR(err); size_t num_vertices = pd.num_nodes(); CPPUNIT_ASSERT( num_vertices == 7 ); CPPUNIT_ASSERT( tri_check_validity(element_array, num_elements, vtx_array, num_vertices) == 1 ); patches.get_next_patch( pd, err ); ASSERT_NO_ERROR(err); element_array = pd.get_element_array(err); ASSERT_NO_ERROR(err); num_elements = pd.num_elements(); CPPUNIT_ASSERT( num_elements == 6 ); vtx_array = pd.get_vertex_array(err); ASSERT_NO_ERROR(err); num_vertices = pd.num_nodes(); CPPUNIT_ASSERT( num_vertices == 7 ); CPPUNIT_ASSERT( tri_check_validity(element_array, num_elements, vtx_array, num_vertices) == 1 ); }
// 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] ); } }
std::string get_sphere_cylinder_example( DomainClassifier& geom, MeshImpl& mesh, MsqError& err ) { const char filename[] = SRCDIR "sphereCylinder_1194_inv.vtk"; const Vector3D vec_k(0,0,8), vec_nk(0,0,-8); const Vector3D vec_c(0,0,5); //++ 0D domains ++ //++ 1D domains ++ //top circle static CircleDomain cr_to(vec_k,vec_k,8.0), cr_ti(vec_k,vec_k,4.0); //bottom circle static CircleDomain cr_bo(vec_nk,vec_nk,8.0); //++ 2D domains ++ static PlanarDomain sf_t(vec_k,vec_k), sf_b(vec_nk,vec_nk); static CylinderDomain cy(8.0,vec_k,vec_k); static SphericalDomain sp(vec_c,5.0); MeshDomain* base_domains[] = { &cr_to, &cr_ti, &cr_bo, &sf_t, &sf_b, &cy, &sp }; const int NDOM = sizeof(base_domains)/sizeof(base_domains[0]); int dim_array[NDOM] = { 1, 1, 1, 2, 2, 2, 2 }; //++ MESH & DOMAIN ++ mesh.read_vtk(filename, err); MSQ_ERRZERO(err); DomainClassifier::classify_skin_geometrically (geom, &mesh, 0.001, base_domains, dim_array, NDOM, err); MSQ_ERRZERO(err); mesh.set_skin_flags( false, false, true, err ); MSQ_ERRZERO(err); return filename; }
void create_input_mesh( const MeshParams& p, bool all_fixed, MeshImpl& mesh, MsqError& err ) { const double z = 0; const int F = all_fixed; std::ofstream vtkfile( temp_file ); double bx = all_fixed ? 0.5 * p.w : p.x; double by = all_fixed ? 0.5 * p.h : p.y; vtkfile << "# vtk DataFile Version 3.0" << std::endl << "Mesquite High Aspect Ratio test" << std::endl << "ASCII" << std::endl << "DATASET UNSTRUCTURED_GRID" << std::endl << "POINTS 9 float" << std::endl << 0.0 << ' ' << 0.0 << ' ' << z << std::endl << bx << ' ' << 0.0 << ' ' << z << std::endl << p.w << ' ' << 0.0 << ' ' << z << std::endl << 0.0 << ' ' << by << ' ' << z << std::endl << p.x << ' ' << p.y << ' ' << z << std::endl << p.w << ' ' << by << ' ' << z << std::endl << 0.0 << ' ' << p.h << ' ' << z << std::endl << bx << ' ' << p.h << ' ' << z << std::endl << p.w << ' ' << p.h << ' ' << z << std::endl << "CELLS 4 20" << std::endl << "4 0 1 4 3" << std::endl << "4 1 2 5 4" << std::endl << "4 4 5 8 7" << std::endl << "4 3 4 7 6" << std::endl << "CELL_TYPES 4" << std::endl << "9 9 9 9" << std::endl << "POINT_DATA 9" << std::endl << "SCALARS fixed int" << std::endl << "LOOKUP_TABLE default" << std::endl << "1 " << F << " 1" << std::endl << F << " 0 " << F << std::endl << "1 " << F << " 1" << std::endl ; vtkfile.close(); mesh.read_vtk( temp_file, err ); std::remove( temp_file ); MSQ_CHKERR(err); }
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 ); }
void create_input_mesh( double mid_x , MeshImpl& mesh, MsqError& err ) { std::ofstream vtkfile( temp_file ); vtkfile << "# vtk DataFile Version 3.0" << std::endl << "Mesquite Syncronous Boundary test" << std::endl << "ASCII" << std::endl << "DATASET UNSTRUCTURED_GRID" << std::endl << "POINTS 9 float" << std::endl << min_x << ' ' << max_y << ' ' << z << std::endl << mid_x << ' ' << max_y << ' ' << z << std::endl << max_x << ' ' << max_y << ' ' << z << std::endl << min_x << ' ' << mid_y << ' ' << z << std::endl << mid_x << ' ' << mid_y << ' ' << z << std::endl << max_x << ' ' << mid_y << ' ' << z << std::endl << min_x << ' ' << min_y << ' ' << z << std::endl << mid_x << ' ' << min_y << ' ' << z << std::endl << max_x << ' ' << min_y << ' ' << z << std::endl << "CELLS 4 20" << std::endl << "4 1 0 3 4" << std::endl << "4 2 1 4 5" << std::endl << "4 4 3 6 7" << std::endl << "4 5 4 7 8" << std::endl << "CELL_TYPES 4" << std::endl << "9 9 9 9" << std::endl << "POINT_DATA 9" << std::endl << "SCALARS fixed int" << std::endl << "LOOKUP_TABLE default" << std::endl << "1 0 1" << std::endl << "1 0 1" << std::endl << "1 0 1" << std::endl ; vtkfile.close(); mesh.read_vtk( temp_file, err ); remove( temp_file ); }
// Test writing quadtratic elements void VtkTest::test_write_field_attrib() { MeshImpl mesh; MsqPrintError err(cout); // Create file containing unstructured mesh test case FILE* file = fopen( temp_file_name, "w+" ); fputs( structured_3d_points_data, file ); fputs( simple_field_attrib, file ); fclose( file ); // Read unstructured mesh file mesh.read_vtk( temp_file_name, err ); remove(temp_file_name); ASSERT_NO_ERROR(err); // Write unstructured mesh file back out mesh.write_vtk( temp_file_name, err ); if (err) remove( temp_file_name ); ASSERT_NO_ERROR(err); // Check if file contained expected mesh check_field_attrib( temp_file_name ); }
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; } }
static int test(std::string filename_prefix, std::string mesh_topology_name, MeshDomain *domain=0) { int rank, nprocs; MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &nprocs); if (nprocs > 2) { cerr << "parallel_untangle_shape::test(" << mesh_topology_name << " can only be run with 1 or 2 processors" << std::endl; return 0; } /* create processor-specific file names */ ostringstream in_name, out_name, gold_name; in_name << filename_prefix << "par_untangle_original_" << mesh_topology_name << "_mesh." << nprocs << "." << rank << ".vtk"; gold_name << filename_prefix << "par_untangle_smoothed_" << mesh_topology_name << "_mesh." << nprocs << "." << rank << ".vtk"; out_name << "par_untangle_smoothed_" << mesh_topology_name << "_mesh." << nprocs << "." << rank << ".vtk"; cout << "in_name= " << in_name.str() << " gold_name= " << gold_name.str() << " out_name= " << out_name.str() << std::endl; /* load different mesh files on each processor */ MsqError err; MeshImpl mesh; mesh.read_vtk(in_name.str().c_str(), err); if (err) {cerr << err << endl; return 1;} /* create parallel mesh instance, specifying tags * containing parallel data */ ParallelMeshImpl parallel_mesh(&mesh, "GLOBAL_ID", "PROCESSOR_ID"); ParallelHelperImpl helper; helper.set_communicator(MPI_COMM_WORLD); helper.set_parallel_mesh(¶llel_mesh); parallel_mesh.set_parallel_helper(&helper); /* do Laplacian smooth */ //LaplaceWrapper optimizer; //optimizer.run_instructions(¶llel_mesh, err); int msq_debug = 0; // 1,2,3 for more debug info bool always_smooth = true; int innerIter = 100; double gradNorm = 1.e-9; ParShapeImprover si(innerIter, gradNorm); //Mesh *pmesh = ¶llel_mesh; si.run(parallel_mesh, domain, err, always_smooth, msq_debug); if (err) {cerr << err << endl; return 1; } /* write mesh */ mesh.write_vtk(out_name.str().c_str(),err); if (err) {cerr << err << endl; return 1;} //std::cout << "P[ " << rank <<"] reading gold..." << std::endl; /* compare mesh with gold copy */ MeshImpl gold; gold.read_vtk(gold_name.str().c_str(),err); if (err) {cerr << err << endl; return 1;} //std::cout << "P[ " << rank <<"] read gold, checking mesh diff..." << std::endl; bool do_print=true; double tol = 1.e-4; bool diff = MeshUtil::meshes_are_different(mesh, gold, err, tol, do_print); if (err) {cerr << err << endl; return 1;} //std::cout << "P[ " << rank <<"] read gold, checking mesh diff...done" << std::endl; if (diff) {cerr << "Error, computed mesh different from gold copy" << std::endl; return 1;} print_timing_diagnostics(cout); return 0; }
std::string get_hex_3d_part_example( DomainClassifier& geom, MeshImpl& mesh, MsqError& err ) { const char filename[] = SRCDIR "hex3Dpart.vtk"; //2D domains const Vector3D vec_i(1,0,0), vec_j(0,1,0), vec_k(0,0,1); const Vector3D vec_ni(-1,0,0), vec_nj(0,-1,0), vec_nk(0,0,-1); const Vector3D vec_left(-11.5,0,0), vec_right(11.5,0,0); const Vector3D vec_top(0,5,0), vec_bottom(0,-5,0); const Vector3D vec_front(0,0,5), vec_back(0,0,-5); //1D domains const Vector3D pt_top_front(0,5,5),pt_top_back(0,5,-5); const Vector3D pt_bottom_front(0,-5,5),pt_bottom_back(0,-5,-5); const Vector3D pt_top_left(-11.5,5,0),pt_top_right(11.5,5,0); const Vector3D pt_bottom_left(-11.5,-5,0),pt_bottom_right(11.5,-5,0); const Vector3D pt_left_front(-11.5,0,5),pt_left_back(-11.5,0,-5); const Vector3D pt_right_front(11.5,0,5),pt_right_back(11.5,0,-5); const Vector3D cpt_top_left(-1.5,5,0),cpt_top_right(1.5,5,0); const Vector3D cpt_bottom_left(-1.5,-5,0),cpt_bottom_right(1.5,-5,0); //0D domains const Vector3D pt_tlf(-11.5,5,5), pt_tlb(-11.5,5,-5); const Vector3D pt_trf(11.5,5,5), pt_trb(11.5,5,-5); const Vector3D pt_blf(-11.5,-5,5), pt_blb(-11.5,-5,-5); const Vector3D pt_brf(11.5,-5,5), pt_brb(11.5,-5,-5); const Vector3D pt_c_tlf(-1.5,5,5), pt_c_tlb(-1.5,5,-5); const Vector3D pt_c_trf(1.5,5,5), pt_c_trb(1.5,5,-5); const Vector3D pt_c_blf(-1.5,-5,5), pt_c_blb(-1.5,-5,-5); const Vector3D pt_c_brf(1.5,-5,5), pt_c_brb(1.5,-5,-5); static PointDomain p00(pt_tlf); static PointDomain p01(pt_tlb); static PointDomain p02(pt_trf); static PointDomain p03(pt_trb); static PointDomain p04(pt_blf); static PointDomain p05(pt_blb); static PointDomain p06(pt_brf); static PointDomain p07(pt_brb); static PointDomain p08(pt_c_tlf); static PointDomain p09(pt_c_tlb); static PointDomain p10(pt_c_trf); static PointDomain p11(pt_c_trb); static PointDomain p12(pt_c_blf); static PointDomain p13(pt_c_blb); static PointDomain p14(pt_c_brf); static PointDomain p15(pt_c_brb); static CircleDomain c00(pt_top_front,vec_k,1.5); static CircleDomain c01(pt_top_back,vec_k,1.5); static CircleDomain c02(pt_bottom_front,vec_k,1.5); static CircleDomain c03(pt_bottom_back,vec_k,1.5); static LineDomain l00(cpt_top_left,vec_k); static LineDomain l01(cpt_top_right,vec_k); static LineDomain l02(cpt_bottom_left,vec_k); static LineDomain l03(cpt_bottom_right,vec_k); static LineDomain l04(pt_top_front,vec_i); static LineDomain l05(pt_top_back,vec_i); static LineDomain l06(pt_bottom_front,vec_i); static LineDomain l07(pt_bottom_back,vec_i); static LineDomain l08(pt_top_left,vec_k); static LineDomain l09(pt_top_right,vec_k); static LineDomain l10(pt_bottom_left,vec_k); static LineDomain l11(pt_bottom_right,vec_k); static LineDomain l12(pt_left_front,vec_j); static LineDomain l13(pt_left_back,vec_j); static LineDomain l14(pt_right_front,vec_j); static LineDomain l15(pt_right_back,vec_j); static CylinderDomain C00(1.5,vec_k,vec_top,false); static CylinderDomain C01(1.5,vec_k,vec_bottom,false); static PlanarDomain P00(vec_ni,vec_left); static PlanarDomain P01(vec_i,vec_right); static PlanarDomain P02(vec_j,vec_top); static PlanarDomain P03(vec_nj,vec_bottom); static PlanarDomain P04(vec_k,vec_front); static PlanarDomain P05(vec_nk,vec_back); const int NDOM = 44; MeshDomain* base_domains[NDOM] = { &p00, &p01, &p02, &p03, &p04, &p05, &p06, &p07, &p08, &p09, &p10, &p11, &p12, &p13, &p14, &p15, &c00, &c01, &c02, &c03, &l00, &l01, &l02, &l03, &l04, &l05, &l06, &l07, &l08, &l09, &l10, &l11, &l12, &l13, &l14, &l15, &C00, &C01, &P00, &P01, &P02, &P03, &P04, &P05 }; int dim_array[NDOM] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2 }; //++ MESH & DOMAIN ++ mesh.read_vtk(filename, err); MSQ_ERRZERO(err); DomainClassifier::classify_skin_geometrically (geom, &mesh, 0.1, base_domains, dim_array, NDOM, err); MSQ_ERRZERO(err); mesh.set_skin_flags( false, false, true, err ); MSQ_ERRZERO(err); return filename; }
std::string get_cut_cube_example( DomainClassifier& geom, MeshImpl& mesh, MsqError& err ) { const char filename[] = SRCDIR "cutCube.vtk"; const Vector3D vec_i(5,0,0), vec_ni(-5,0,0); const Vector3D vec_j(0,5,0), vec_nj(0,-5,0); const Vector3D vec_k(0,0,5), vec_nk(0,0,-5); const Vector3D vec_tfl(5,-5,5), vec_tfr(5,5,5); const Vector3D vec_tbl(-5,-5,5), vec_tbr(-5,5,5); const Vector3D vec_bfl(5,-5,-5), vec_bfr(5,5,-5); const Vector3D vec_bbl(-5,-5,-5), vec_bbr(-5,5,-5); const Vector3D vec_ts(5,0,2), vec_bs(5,0,-2); //++ 0D domains ++ static PointDomain pt_tfl(vec_tfl), pt_tfr(vec_tfr); static PointDomain pt_tbl(vec_tbl), pt_tbr(vec_tbr); static PointDomain pt_bfl(vec_bfl), pt_bfr(vec_bfr); static PointDomain pt_bbl(vec_bbl), pt_bbr(vec_bbr); //++ 1D domains ++ //top square static LineDomain ln_tf(vec_tfl,vec_j), lin_tb(vec_tbr,vec_nj); static LineDomain ln_tl(vec_tfl,vec_ni), lin_tr(vec_tbr,vec_i); //bottom square static LineDomain ln_bf(vec_bfl,vec_j), lin_bb(vec_bbr,vec_nj); static LineDomain ln_bl(vec_bfl,vec_ni), lin_br(vec_bbr,vec_i); //sides static LineDomain ln_lf(vec_bfl,vec_k), lin_rf(vec_bfr,vec_k); static LineDomain ln_lb(vec_bbl,vec_k), lin_rb(vec_bbr,vec_k); //top sphere static CircleDomain cr_tf(vec_ts,vec_i,1.0), cr_tn(vec_ts,vec_k,1.0); //bottom sphere static CircleDomain cr_bf(vec_bs,vec_i,1.0), cr_bn(vec_bs,vec_k,1.0); //++ 2D domains ++ //cube static PlanarDomain sf_i(vec_i,vec_i), sf_ni(vec_ni,vec_ni); static PlanarDomain sf_j(vec_j,vec_j), sf_nj(vec_nj,vec_nj); static PlanarDomain sf_k(vec_k,vec_k), sf_nk(vec_nk,vec_nk); //cut static CylinderDomain cy(1.0,vec_k,vec_bs); static SphericalDomain sp_t(vec_ts,1.0), sp_b(vec_bs,1.0); MeshDomain* base_domains[] = { &pt_tfl, &pt_tfr, &pt_tbl, &pt_tbr, &pt_bfl, &pt_bfr, &pt_bbl, &pt_bbr, &ln_tf, &lin_tb, &ln_tl, &lin_tr, &ln_bf, &lin_bb, &ln_bl, &lin_br, &ln_lf, &lin_rf, &ln_lb, &lin_rb, &cr_tf, &cr_tn, &cr_bf, &cr_bn, &sf_i, &sf_ni, &sf_j, &sf_nj, &sf_k, &sf_nk, &cy, &sp_t, &sp_b }; const int NDOM = sizeof(base_domains)/sizeof(base_domains[0]); int dim_array[NDOM] = { 0,0,0,0,0,0,0,0, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 2,2,2,2,2,2,2,2,2 }; //++ MESH & DOMAIN ++ mesh.read_vtk(filename, err); MSQ_ERRZERO(err); DomainClassifier::classify_skin_geometrically (geom, &mesh, 0.1, base_domains, dim_array, NDOM, err); MSQ_ERRZERO(err); mesh.set_skin_flags( false, false, true, err ); MSQ_ERRZERO(err); return filename; }
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(); }
int main( int argc, char* argv[] ) { const char* input_file = 0; const char* output_file = 0; for (int i = 1; i < argc; ++i) { if (!strcmp("-h", argv[i])) usage(argv[0],true); else if (!input_file) input_file = argv[i]; else if (!output_file) output_file = argv[i]; else usage(argv[0]); } if (!input_file) input_file = DEFAULT_INPUT; MsqError err; MeshImpl mesh; mesh.read_vtk( input_file, err ); if (err) { std::cerr << err << std::endl << input_file << ": failed to read file" << std::endl; return 3; } PlanarDomain plane(PlanarDomain::XY); #ifdef TEST_OLD_WRAPPER ShapeImprovementWrapper smoother; #else ShapeImprover smoother; #endif IdealWeightInverseMeanRatio extra_metric; smoother.quality_assessor().add_quality_assessment(&extra_metric); MeshDomainAssoc mesh_and_domain = MeshDomainAssoc(&mesh, &plane); smoother.run_instructions( &mesh_and_domain, err ); if (err) { std::cerr << err << std::endl << input_file << ": smoother failed" << std::endl; return 2; } if (output_file) { mesh.write_vtk( output_file, err ); if (err) { std::cerr << err << std::endl << output_file << ": failed to write file" << std::endl; return 3; } } if (smoother.quality_assessor().invalid_elements()) { std::cerr << "Resulting mesh contains invalid elements: untangler did not succeed" << std::endl; return 4; } const QualityAssessor::Assessor* quality = smoother.quality_assessor().get_results(&extra_metric); if (!quality) { std::cerr << "Failed to get quality stats for IMR metric" << std::endl; return 2; } if (fabs(1 - quality->get_average()) > 1e-3) { std::cerr << "Average quality is not optimal." << std::endl; return 4; } if (quality->get_stddev() > 1e-3) { std::cerr << "Not all elements have optimal quality." << std::endl; return 4; } 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; } } }
int main( int argc, char* argv[] ) { MeshTransform xform; RotateArg rotate_arg( &xform ); ScaleArg scale_arg( &xform ); TranslateArg translate_arg( &xform ); CLArgs::ToggleArg freeonly, skin; CLArgs args( "vtkxform", "Transform a mesh", "Apply one or more transformations to vertex coordinates " "in a mesh read from a VTK file." ); const char* ROTATE_VALS[] = { "a", "i", "j", "k" }; args.double_list_flag( ROTATE_FLAG, "Specify a rotation as an angle in degrees counter-clockwise about a vector", &rotate_arg ); args.limit_list_flag( ROTATE_FLAG, 4, ROTATE_VALS ); const char* SCALE_VALS[] = { "s", "sx", "sy", "sz" }; args.double_list_flag( SCALE_FLAG, "Specify factor(s) by which to scale mesh about origin", &scale_arg ); args.limit_list_flag( SCALE_FLAG, 1, SCALE_VALS ); args.limit_list_flag( SCALE_FLAG, 3, SCALE_VALS + 1 ); const char* TRANSLATE_VALS[] = { "dx", "dy", "dz" }; args.double_list_flag( TRANSLATE_FLAG, "Specify translation of vertex coordinates.", &translate_arg ); args.limit_list_flag( TRANSLATE_FLAG, 3, TRANSLATE_VALS ); args.toggle_flag( 'f', "Do not move fixed vertices.", &freeonly ); args.toggle_flag( 'k', "Mark boundary vertices as fixed", &skin ); args.add_required_arg( "input_file" ); args.add_required_arg( "output_file" ); std::vector<std::string> files; if (!args.parse_options( argc, argv, files, std::cerr )) { args.print_usage( std::cerr ); exit(1); } std::string input_file = files[0]; std::string output_file = files[1]; MeshImpl mesh; MsqError err; mesh.read_vtk( input_file.c_str(), err ); if (err) { std::cerr << err << std::endl << "Failed to read file: " << input_file << std::endl; return 1; } if (skin.value()) { mesh.mark_skin_fixed( err, false ); if (err) { std::cerr << err << std::endl << "Failed to skin mesh from file: " << input_file << std::endl; return 1; } } xform.skip_fixed_vertices( freeonly.value() ); MeshDomainAssoc mesh_and_domain = MeshDomainAssoc(&mesh, 0); xform.loop_over_mesh( &mesh_and_domain, 0, err ); if (err) { std::cerr << err << std::endl ; return 2; } mesh.write_vtk( output_file.c_str(), err ); if (err) { std::cerr << err << std::endl << "Failed to write file: " << output_file << std::endl; return 1; } return 0; }
// 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 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] ); }
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(); }
int main( int argc, char* argv[] ) { /* init MPI */ int rank, nprocs; if (MPI_SUCCESS != MPI_Init(&argc, &argv)) { cerr << "MPI_Init failed." << endl; return 2; } MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &nprocs); if (nprocs > 2) { cerr << "parallel_laplace_smooth test can only be run with 1 or 2 processors" << std::endl; return 0; } const int debug=0; // 1,2,3 for more debug info if (debug) { MsqDebug::enable(1); if (debug > 1) MsqDebug::enable(2); if (debug > 2) MsqDebug::enable(3); } /* create processor-specific file names */ ostringstream in_name, out_name, gold_name; in_name << VTK_3D_DIR << "par_original_hex_mesh." << nprocs << "." << rank << ".vtk"; gold_name << VTK_3D_DIR << "par_smoothed_hex_mesh." << nprocs << "." << rank << ".vtk"; out_name << "par_smoothed_hex_mesh." << nprocs << "." << rank << ".vtk"; /* load different mesh files on each processor */ Mesquite::MsqError err; Mesquite::MeshImpl mesh; mesh.read_vtk(in_name.str().c_str(), err); if (err) {cerr << err << endl; return 1;} /* create parallel mesh instance, specifying tags * containing parallel data */ Mesquite::ParallelMeshImpl parallel_mesh(&mesh, "GLOBAL_ID", "PROCESSOR_ID"); Mesquite::ParallelHelperImpl helper; helper.set_communicator(MPI_COMM_WORLD); helper.set_parallel_mesh(¶llel_mesh); parallel_mesh.set_parallel_helper(&helper); /* do Laplacian smooth */ LaplaceWrapper optimizer; optimizer.set_vertex_movement_limit_factor(1.e-10); optimizer.set_iteration_limit(2000); optimizer.enable_culling(false); optimizer.run_instructions(¶llel_mesh, err); if (err) {cerr << err << endl; return 1; } /* write mesh */ mesh.write_vtk(out_name.str().c_str(),err); if (err) {cerr << err << endl; return 1;} /* compare mesh with gold copy */ MeshImpl gold; gold.read_vtk(gold_name.str().c_str(),err); if (err) {cerr << err << endl; return 1;} bool do_print=true; double tol = 1.e-4; bool diff = MeshUtil::meshes_are_different(mesh, gold, err, tol, do_print); if (err) {cerr << err << endl; return 1;} if (diff) {cerr << "Error, computed mesh different from gold copy" << std::endl; return 1;} print_timing_diagnostics(cout); MPI_Finalize(); return 0; }
static int do_smoother( const char* input_file, const char* output_file, const char* ref_mesh_file, double of_power, unsigned metric_idx, AveragingScheme avg_scheme ) { MsqPrintError err(cerr); TMetric *const target_metric = metrics[metric_idx].u; cout << "Input file: " << input_file << endl; cout << "Metric: "; if (avg_scheme != NONE) cout << averaging_names[avg_scheme] << " average of "; cout << metrics[metric_idx].n << endl; cout << "Of Power: " << of_power << endl; auto_ptr<TargetCalculator> tc; auto_ptr<MeshImpl> ref_mesh_impl; auto_ptr<ReferenceMesh> ref_mesh; if (ref_mesh_file) { ref_mesh_impl.reset(new MeshImpl); ref_mesh_impl->read_vtk( ref_mesh_file, err ); if (MSQ_CHKERR(err)) return 2; ref_mesh.reset( new ReferenceMesh( ref_mesh_impl.get() )); tc.reset( new RefMeshTargetCalculator( ref_mesh.get() ) ); } else { tc.reset( new IdealShapeTarget( ) ); } TQualityMetric jacobian_metric( tc.get(), target_metric ); ElementPMeanP elem_avg( of_power, &jacobian_metric ); VertexPMeanP vtx_avg( of_power, &jacobian_metric ); QualityMetric* mmetrics[] = { &jacobian_metric, &elem_avg, &vtx_avg, &jacobian_metric }; QualityMetric* metric = mmetrics[avg_scheme]; TerminationCriterion outer, inner; outer.add_iteration_limit( 1 ); inner.add_absolute_vertex_movement( 1e-4 ); inner.add_iteration_limit( 100 ); PMeanPTemplate obj1( of_power, metric ); PatchPowerMeanP obj2( of_power, metric ); ObjectiveFunction& objective = *((avg_scheme == PATCH) ? (ObjectiveFunction*)&obj2 : (ObjectiveFunction*)&obj1); ConjugateGradient solver( &objective, err ); if (MSQ_CHKERR(err)) return 1; solver.set_inner_termination_criterion( &inner ); solver.set_outer_termination_criterion( &outer ); solver.use_global_patch(); ConditionNumberQualityMetric qm_metric; QualityAssessor before_assessor; QualityAssessor after_assessor; before_assessor.add_quality_assessment( metric, 10); before_assessor.add_quality_assessment( &qm_metric ); after_assessor.add_quality_assessment( metric, 10 ); InstructionQueue q; q.add_quality_assessor( &before_assessor, err ); q.set_master_quality_improver( &solver, err ); q.add_quality_assessor( &after_assessor, err ); MeshImpl mesh; mesh.read_vtk( input_file, err ); if (MSQ_CHKERR(err)) return 2; PlanarDomain geom = make_domain( &mesh, err ); if (MSQ_CHKERR(err)) return 1; q.run_instructions( &mesh, &geom, err ); if (MSQ_CHKERR(err)) return 3; mesh.write_vtk( output_file, err ); if (MSQ_CHKERR(err)) return 2; cout << "Wrote: " << output_file << endl; before_assessor.scale_histograms(&after_assessor); return 0; }
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 ); }