int main(int argc, char* argv[]) { MsqError err; if (argc != 2) { std::cerr << "Expected mesh file names as single argument." << std::endl; exit (EXIT_FAILURE); } // new code starts here //... Mesquite::MeshImpl my_mesh; my_mesh.read_vtk(argv[1], err); if (err) { std::cout << err << std::endl; return 1; } my_mesh.write_vtk("original_mesh.vtk",err); Vector3D normal(0,0,-1); Vector3D point(0,0,-5); PlanarDomain my_mesh_plane(normal, point); // creates a mean ratio quality metric ... IdealWeightInverseMeanRatio inverse_mean_ratio(err); // sets the objective function template LPtoPTemplate obj_func(&inverse_mean_ratio, 2, err); // creates the optimization procedures SteepestDescent f_newton(&obj_func); //performs optimization globally f_newton.use_global_patch(); // creates a termination criterion and // add it to the optimization procedure // outer loop: default behavior: 1 iteration // inner loop: stop if gradient norm < eps TerminationCriterion tc_inner; tc_inner.add_absolute_gradient_L2_norm( 1e-4 ); f_newton.set_inner_termination_criterion(&tc_inner); // creates a quality assessor QualityAssessor m_ratio_qa(&inverse_mean_ratio); // creates an instruction queue InstructionQueue queue; queue.add_quality_assessor(&m_ratio_qa, err); queue.set_master_quality_improver(&f_newton, err); queue.add_quality_assessor(&m_ratio_qa, err); // do optimization of the mesh_set MeshDomainAssoc mesh_and_domain = MeshDomainAssoc(&my_mesh, &my_mesh_plane); queue.run_instructions(&mesh_and_domain, err); if (err) { std::cout << err << std::endl; return 2; } my_mesh.write_vtk("smoothed_mesh.vtk",err); return 0; }
int main( int argc, char* argv[] ) { parse_options( argv, argc ); MeshImpl mesh; XYRectangle domain( max_x - min_x, max_y - min_y, min_x, min_y ); MsqError err; create_input_mesh( input_x, mesh, err ); if (MSQ_CHKERR(err)) { std::cerr << err << std::endl; return 2; } domain.setup( &mesh, err ); if (MSQ_CHKERR(err)) { std::cerr << err << std::endl; return 2; } QualityMetric* metric = 0; if (mMetric == 'c') metric = new ConditionNumberQualityMetric; else metric = new IdealWeightInverseMeanRatio; LPtoPTemplate function( 1, metric ); VertexMover* solver = 0; if (mSolver == 'j') solver = new ConjugateGradient( &function ); else solver = new FeasibleNewton( &function ); if (PatchSetUser* psu = dynamic_cast<PatchSetUser*>(solver)) psu->use_global_patch(); TerminationCriterion inner; inner.add_absolute_vertex_movement( 1e-4 ); inner.write_mesh_steps( "synchronous", TerminationCriterion::GNUPLOT ); solver->set_inner_termination_criterion( &inner ); InstructionQueue q; QualityAssessor qa( metric, 10 ); q.add_quality_assessor( &qa, err ); q.set_master_quality_improver( solver, err ); q.add_quality_assessor( &qa, err ); MeshDomainAssoc mesh_and_domain = MeshDomainAssoc(&mesh, &domain); q.run_instructions( &mesh_and_domain, err ); delete solver; delete metric; if (MSQ_CHKERR(err)) { std::cerr << err << std::endl; return 3; } mesh.write_vtk( outputFile, err ); if (MSQ_CHKERR(err)) { std::cerr << err << std::endl; return 2; } return 0; }
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 MeshOpt::trustRegion(hier::Patch<NDIM>& patch) { MsqError err; MeshImpl* mesh = createLocalMesh(patch); PlanarDomain domain(PlanarDomain::XY); IdealWeightInverseMeanRatio inverse_mean_ratio(err); LPtoPTemplate obj_func(&inverse_mean_ratio,2,err); TrustRegion t_region(&obj_func); t_region.use_global_patch(); TerminationCriterion tc_inner; tc_inner.add_absolute_gradient_L2_norm(1e-6); tc_inner.add_iteration_limit(1); t_region.set_inner_termination_criterion(&tc_inner); QualityAssessor m_ratio_qa(&inverse_mean_ratio); m_ratio_qa.disable_printing_results(); InstructionQueue queue; queue.add_quality_assessor(&m_ratio_qa,err); queue.set_master_quality_improver(&t_region,err); queue.add_quality_assessor(&m_ratio_qa,err); MeshDomainAssoc mesh_and_domain = MeshDomainAssoc(mesh,&domain); queue.run_instructions(&mesh_and_domain,err); tbox::pout<< "Shape optimization completed." << std::endl; // std::string file_name = "2__patch_3.vtk"; // mesh->write_vtk(file_name.c_str(), err); transformMeshtoPatch(mesh,patch,err); d_flag =2; return; }
int main( int argc, char* argv[] ) { const char* input_file = DEFAULT_INPUT_FILE; const char* output_file_base = 0; bool expect_output_base = false; for (int i = 1; i < argc; ++i) { if (expect_output_base) { output_file_base = argv[i]; expect_output_base = false; } else if (!strcmp(argv[i],"-o")) expect_output_base = true; else if (input_file != DEFAULT_INPUT_FILE) usage(argv[0]); else input_file = argv[i]; } if (expect_output_base) usage(argv[0]); MsqPrintError err(std::cerr); SlaveBoundaryVertices slaver(1); TShapeNB1 tmetric; IdealShapeTarget target; TQualityMetric metric( &target, &tmetric ); PMeanPTemplate of( 1.0, &metric ); SteepestDescent improver( &of ); TerminationCriterion inner; inner.add_absolute_vertex_movement( 1e-3 ); improver.set_inner_termination_criterion( &inner ); QualityAssessor assess( &metric ); InstructionQueue q; q.set_master_quality_improver( &improver, err ); q.add_quality_assessor( &assess, err ); TriLagrangeShape trishape; QuadLagrangeShape quadshape; q.set_mapping_function( &trishape ); q.set_mapping_function( &quadshape ); const int NUM_MODES = 4; Settings::HigherOrderSlaveMode modes[NUM_MODES] = { Settings::SLAVE_NONE, Settings::SLAVE_ALL, Settings::SLAVE_CALCULATED, Settings::SLAVE_FLAG }; std::string names[NUM_MODES] = { "NONE", "ALL", "CALCULATED", "FLAG" }; MeshImpl meshes[NUM_MODES]; std::vector<MeshDomainAssoc> meshes_and_domains; bool have_slaved_flag = true; std::vector<bool> flag(1); for (int i = 0; i < NUM_MODES; ++i) { std::cout << std::endl << "-----------------------------------------------" << std::endl << " Mode: " << names[i] << std::endl << "-----------------------------------------------" << std::endl; meshes[i].read_vtk( input_file, err ); if (err) return 1; if (modes[i] == Settings::SLAVE_CALCULATED) { q.add_vertex_slaver( &slaver, err ); } else if (modes[i] == Settings::SLAVE_FLAG) { std::vector<Mesh::VertexHandle> verts; meshes[i].get_all_vertices( verts, err ); if (err) return 1; meshes[i].vertices_get_slaved_flag( arrptr(verts), flag, 1, err ); if (err) { have_slaved_flag = false; std::cout << "Skipped because input file does not contain slaved attribute" << std::endl; err.clear(); continue; } } if (have_slaved_flag && modes[i] == Settings::SLAVE_FLAG) { if (!check_no_slaved_corners( meshes[i], err ) || err) return 1; if (!check_global_patch_slaved( meshes[i], err ) || err) return 1; } PlanarDomain plane; plane.fit_vertices( &meshes[i], err ); if (err) return 1; q.set_slaved_ho_node_mode( modes[i] ); meshes_and_domains.push_back(MeshDomainAssoc(&meshes[i], &plane)); q.run_instructions( &meshes_and_domains[i], err ); if (err) return 1; if (modes[i] == Settings::SLAVE_CALCULATED) { q.remove_vertex_slaver( &slaver, err ); } if (output_file_base) { tag_patch_slaved( meshes[i], modes[i], err ); std::string name(output_file_base); name += "-"; name += names[i]; name += ".vtk"; meshes[i].write_vtk( name.c_str(), err ); if (err) return 1; } } int exit_code = 0; if (input_file == DEFAULT_INPUT_FILE) { for (int i = 0; i < NUM_MODES; ++i) { std::cout << std::endl << "-----------------------------------------------" << std::endl << " Mode: " << names[i] << std::endl << "-----------------------------------------------" << std::endl; exit_code += check_slaved_coords( meshes[i], modes[i], names[i], have_slaved_flag, err ); if (err) return 1; } // flags should correspond to same slaved nodes as calculated, // so resulting meshes should be identical. if (have_slaved_flag) { int flag_idx = std::find( modes, modes+NUM_MODES, Settings::SLAVE_FLAG ) - modes; int calc_idx = std::find( modes, modes+NUM_MODES, Settings::SLAVE_CALCULATED ) - modes; exit_code += compare_node_coords( meshes[flag_idx], meshes[calc_idx], err ); if (err) return 1; } } return exit_code; }
void TerminationCriterionTest::test_abs_vtx_movement_culling() { /* define a quad mesh like the following 16--17--18--19--20--21--22--23 | | | | | | | | Y 8---9--10--11--12--13--14--15 ^ | | | | | | | | | 0---1---2---3---4---5---6---7 +-->X */ const int nvtx = 24; int fixed[nvtx]; double coords[3*nvtx]; for (int i = 0; i < nvtx; ++i) { coords[3*i ] = i/8; coords[3*i+1] = i%8; coords[3*i+2] = 0; fixed[i] = i < 9 || i > 14; } const int nquad = 14; unsigned long conn[4*nquad]; for (int i= 0; i < nquad; ++i) { int row = i / 7; int idx = i % 7; int n0 = 8*row + idx; conn[4*i ] = n0; conn[4*i+1] = n0 + 1; conn[4*i+2] = n0 + 9; conn[4*i+3] = n0 + 8; } const double tol = 0.05; PlanarDomain zplane(PlanarDomain::XY, 0.0); ArrayMesh mesh( 3, nvtx, coords, fixed, nquad, QUADRILATERAL, conn ); // fill vertex byte with garbage to make sure that quality improver // is initializing correctly. MsqError err; std::vector<unsigned char> junk(nvtx, 255); std::vector<Mesh::VertexHandle> vertices; mesh.get_all_vertices( vertices, err ); ASSERT_NO_ERROR(err); CPPUNIT_ASSERT_EQUAL( junk.size(), vertices.size() ); mesh.vertices_set_byte( &vertices[0], &junk[0], vertices.size(), err ); ASSERT_NO_ERROR(err); // Define optimizer TCTFauxOptimizer smoother( 2*tol ); TerminationCriterion outer, inner; outer.add_absolute_vertex_movement( tol ); inner.cull_on_absolute_vertex_movement( tol ); inner.add_iteration_limit( 1 ); smoother.set_inner_termination_criterion( &inner ); smoother.set_outer_termination_criterion( &outer ); // No run the "optimizer" InstructionQueue q; q.set_master_quality_improver( &smoother, err ); MeshDomainAssoc mesh_and_domain = MeshDomainAssoc(&mesh, &zplane); q.run_instructions( &mesh_and_domain, err ); ASSERT_NO_ERROR(err); CPPUNIT_ASSERT( smoother.should_have_terminated() ); CPPUNIT_ASSERT( smoother.num_passes() > 1 ); }
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; }
bool smooth_mixed_mesh( const char* filename ) { Mesquite::MsqPrintError err(cout); // print a little output so we know when we died std::cout << "**************************************************************************" << std::endl << "* Smoothing: " << filename << std::endl << "**************************************************************************" << std::endl; // The instruction queue to set up InstructionQueue Q; // Use numeric approx of derivitives until analytic solutions // are working for pyramids IdealWeightInverseMeanRatio mr_metric(err); //sRI_DFT dft_metric; UntangleBetaQualityMetric un_metric(0); CPPUNIT_ASSERT(!err); // Create Mesh object Mesquite::MeshImpl mesh; mesh.read_vtk(filename, err); CPPUNIT_ASSERT(!err); // Set up a preconditioner LInfTemplate pre_obj_func( &un_metric ); ConjugateGradient precond( &pre_obj_func, err ); CPPUNIT_ASSERT(!err); precond.use_element_on_vertex_patch(); TerminationCriterion pre_term, pre_outer; //pre_term.add_relative_quality_improvement( 0.1 ); pre_term .add_iteration_limit( 3 ); pre_outer.add_iteration_limit( 1 ); CPPUNIT_ASSERT(!err); precond.set_inner_termination_criterion( &pre_term ); precond.set_outer_termination_criterion( &pre_outer ); //precond.use_element_on_vertex_patch(); // Set up objective function LPtoPTemplate obj_func(&mr_metric, 1, err); CPPUNIT_ASSERT(!err); // Create solver FeasibleNewton solver( &obj_func, true ); CPPUNIT_ASSERT(!err); solver.use_global_patch(); CPPUNIT_ASSERT(!err); // Set stoping criteria for solver TerminationCriterion tc_inner; tc_inner.add_relative_quality_improvement( 0.25 ); solver.set_inner_termination_criterion(&tc_inner); TerminationCriterion tc_outer; tc_outer.add_iteration_limit( 1 ); CPPUNIT_ASSERT(!err); solver.set_outer_termination_criterion(&tc_outer); // Create a QualityAssessor Mesquite::QualityAssessor qa; qa.add_quality_assessment( &mr_metric ); qa.add_quality_assessment( &un_metric ); Q.add_quality_assessor( &qa, err ); CPPUNIT_ASSERT(!err); // Add untangler to queue Q.add_preconditioner( &precond, err ); CPPUNIT_ASSERT(!err); Q.add_quality_assessor( &qa, err ); CPPUNIT_ASSERT(!err); // Add solver to queue Q.set_master_quality_improver(&solver, err); CPPUNIT_ASSERT(!err); Q.add_quality_assessor( &qa, err ); CPPUNIT_ASSERT(!err); // And smooth... Q.run_instructions(&mesh, err); CPPUNIT_ASSERT(!err); return false; }
bool smooth_mesh( Mesh* mesh, Mesh* ref_mesh, Mesh::VertexHandle free_vertex_at_origin, Vector3D initial_free_vertex_position, QualityMetric* metric ) { Mesquite::MsqPrintError err(cout); const Vector3D origin( 0, 0, 0 ); // print a little output so we know when we died std::cout << "**************************************************************************" << std::endl << "* Smoothing..." << std::endl << "* Metric: " << metric->get_name() << std::endl << "* Apex position: " << initial_free_vertex_position << std::endl //<< //"**************************************************************************" << std::endl; // Set free vertex to specified position mesh->vertex_set_coordinates( free_vertex_at_origin, initial_free_vertex_position, err ); CPPUNIT_ASSERT(!err); // Create an InstructionQueue InstructionQueue Q; // Set up objective function LPtoPTemplate obj_func(metric, 1, err); CPPUNIT_ASSERT(!err); // Create solver FeasibleNewton solver( &obj_func, true ); CPPUNIT_ASSERT(!err); solver.use_global_patch(); CPPUNIT_ASSERT(!err); // Set stoping criteria for solver TerminationCriterion tc_inner; tc_inner.add_absolute_vertex_movement( 1e-6 ); solver.set_inner_termination_criterion(&tc_inner); TerminationCriterion tc_outer; tc_outer.add_iteration_limit( 1 ); solver.set_outer_termination_criterion(&tc_outer); // Add solver to queue Q.set_master_quality_improver(&solver, err); CPPUNIT_ASSERT(!err); // And smooth... Q.run_instructions(mesh, err); CPPUNIT_ASSERT(!err); // Verify that vertex was moved back to origin MsqVertex vtx; mesh->vertices_get_coordinates( &free_vertex_at_origin, &vtx, 1, err ); CPPUNIT_ASSERT( !err ); Vector3D position = vtx; // print a little output so we know when we died std::cout //<< //"**************************************************************************" << std::endl << "* Done Smoothing:" << std::endl << "* Metric: " << metric->get_name() << std::endl << "* Apex position: " << position << std::endl << "**************************************************************************" << std::endl; CPPUNIT_ASSERT( position.within_tolerance_box( Vector3D(0,0,0), TOL ) ); return false; }
void run_test( Grouping grouping, int of_power, Weight w, const string filename ) { MsqError err; IdentityTarget target; TSquared target_metric; AffineMapMetric qual_metric( &target, &target_metric ); ElementPMeanP elem_metric( of_power, &qual_metric ); QualityMetric* qm_ptr = (grouping == ELEMENT) ? (QualityMetric*)&elem_metric : (QualityMetric*)&qual_metric; PMeanPTemplate OF( of_power, qm_ptr ); ConjugateGradient solver( &OF ); TerminationCriterion tc; TerminationCriterion itc; tc.add_absolute_vertex_movement( 1e-4 ); itc.add_iteration_limit( 2 ); #ifdef USE_GLOBAL_PATCH solver.use_global_patch(); solver.set_inner_termination_criterion( &tc ); #else solver.use_element_on_vertex_patch(); solver.set_inner_termination_criterion( &itc ); solver.set_outer_termination_criterion( &tc ); #endif MeshImpl mesh, expected_mesh; mesh.read_vtk( SRCDIR "/initial.vtk", err ); CHKERR(err) // expected_mesh.read_vtk( (filename + ".vtk").c_str(), err ); CHKERR(err) PlanarDomain plane( PlanarDomain::XY ); MeshDomainAssoc mesh_and_domain = MeshDomainAssoc(&mesh, &plane); MetricWeight mw( &qual_metric ); InverseMetricWeight imw( &qual_metric ); WeightReader reader; if (w == METRIC) { TargetWriter writer( 0, &mw ); InstructionQueue tq; tq.add_target_calculator( &writer, err ); tq.run_instructions( &mesh_and_domain, err ); CHKERR(err); qual_metric.set_weight_calculator( &reader ); } else if (w == INV_METRIC) { TargetWriter writer( 0, &imw ); InstructionQueue tq; tq.add_target_calculator( &writer, err ); tq.run_instructions( &mesh_and_domain, err ); CHKERR(err); qual_metric.set_weight_calculator( &reader ); } InstructionQueue q; q.set_master_quality_improver( &solver, err ); q.run_instructions( &mesh_and_domain, err ); CHKERR(err) /* vector<Mesh::VertexHandle> vemain.cpprts; vector<MsqVertex> mesh_coords, expected_coords; mesh.get_all_vertices( verts, err ); CHKERR(err) mesh_coords.resize(verts.size()); mesh.vertices_get_coordinates( arrptr(verts), arrptr(mesh_coords), verts.size(), err ); CHKERR(err) expected_mesh.get_all_vertices( verts, err ); CHKERR(err) expected_coords.resize(verts.size()); expected_mesh.vertices_get_coordinates( arrptr(verts), arrptr(expected_coords), verts.size(), err ); CHKERR(err) if (expected_coords.size() != mesh_coords.size()) { cerr << "Invlid expected mesh. Vertex count doesn't match" << endl; exit(1); } unsigned error_count = 0; for (size_t i = 0; i < mesh_coords.size(); ++i) if ((expected_coords[i] - mesh_coords[i]).length_squared() > epsilon*epsilon) ++error_count; if (!error_count) cout << filename << " : SUCCESS" << endl; else cout << filename << " : FAILURE (" << error_count << " vertices differ by more than " << epsilon << ")" << endl; */ if (write_results) mesh.write_vtk( (filename + ".results.vtk").c_str(), err ); CHKERR(err) }
int main( int argc, char* argv[] ) { MeshParams input_params, reference_params; bool fixed_boundary_vertices, feas_newt_solver; TerminationCriterion::TimeStepFileType write_timestep_files; std::string output_file_name; int num_iterations; parse_options( argv, argc, input_params, reference_params, output_file_name, fixed_boundary_vertices, write_timestep_files, feas_newt_solver, num_iterations ); MsqError err; MeshImpl mesh, refmesh; XYRectangle domain( input_params.w, input_params.h ); create_input_mesh( input_params, fixed_boundary_vertices, mesh, err ); CHECKERR create_input_mesh( reference_params, fixed_boundary_vertices, refmesh, err ); CHECKERR domain.setup( &mesh, err ); CHECKERR ReferenceMesh rmesh( &refmesh ); RefMeshTargetCalculator tc( &rmesh ); TShapeB1 tm; TQualityMetric qm( &tc, &tm ); PMeanPTemplate of( 1.0, &qm ); ConjugateGradient cg( &of ); cg.use_element_on_vertex_patch(); FeasibleNewton fn( &of ); fn.use_element_on_vertex_patch(); VertexMover* solver = feas_newt_solver ? (VertexMover*)&fn : (VertexMover*)&cg; TerminationCriterion inner, outer; inner.add_iteration_limit( INNER_ITERATES ); outer.add_iteration_limit( num_iterations ); if (write_timestep_files != TerminationCriterion::NOTYPE) outer.write_mesh_steps( base_name( output_file_name ).c_str(), write_timestep_files ); solver->set_inner_termination_criterion( &inner ); solver->set_outer_termination_criterion( &outer ); QualityAssessor qa( &qm ); InstructionQueue q; q.add_quality_assessor( &qa, err ); q.set_master_quality_improver( solver, err ); q.add_quality_assessor( &qa, err ); MeshDomainAssoc mesh_and_domain = MeshDomainAssoc(&mesh, &domain); q.run_instructions( &mesh_and_domain, err ); CHECKERR mesh.write_vtk( output_file_name.c_str(), err ); CHECKERR // check for inverted elements int inv, unk; qa.get_inverted_element_count( inv, unk, err ); if (inv) { std::cerr << inv << " inverted elements in final mesh" << std::endl; return INVERTED_ELEMENT; } else if (unk) { std::cerr << unk << " degenerate elements in final mesh" << std::endl; return DEGENERATE_ELEMENT; } // find the free vertex std::vector<Mesh::VertexHandle> vertices; mesh.get_all_vertices( vertices, err ); if (vertices.empty()) { std::cerr << "Mesh contains no vertices" << std::endl; return USAGE_ERROR; } std::vector<unsigned short> dof( vertices.size(), 0 ); domain.domain_DoF( arrptr(vertices), arrptr(dof), vertices.size(), err ); CHECKERR int idx = std::find(dof.begin(), dof.end(), 2) - dof.begin(); const Mesh::VertexHandle free_vertex = vertices[idx]; MsqVertex coords; mesh.vertices_get_coordinates( &free_vertex, &coords,1, err ); CHECKERR // calculate optimal position for vertex const double xf = reference_params.x / reference_params.w; const double yf = reference_params.y / reference_params.h; Vector3D expect( xf * input_params.w, yf * input_params.h, 0 ); // Test that we aren't further from the expected location // than when we started. const Vector3D init( input_params.x, input_params.y, 0 ); if ((coords - expect).length() > (init - expect).length()) { std::cerr << "Vertex moved away from expected optimal position: " << "(" << coords[0] << ", " << coords[1] << std::endl; return WRONG_DIRECTION; } // check if vertex moved MIN_FRACT of the way from the original position // to the desired one in the allowed iterations const double MIN_FRACT = 0.2; // 20% of the way in 10 iterations const double fract = (coords - init).length() / (expect - init).length(); if (fract < MIN_FRACT) { std::cerr << "Vertex far from optimimal location" << std::endl << " Expected: (" << expect[0] << ", " << expect[1] << ", " << expect[2] << ")" << std::endl << " Actual: (" << coords[0] << ", " << coords[1] << ", " << coords[2] << ")" << std::endl; return FAR_FROM_TARGET; } // check if vertex is at destired location const double EPS = 5e-2; // allow a little leway if (fabs(coords[0] - expect[0]) > EPS * input_params.w || fabs(coords[1] - expect[1]) > EPS * input_params.h || fabs(expect[2] ) > EPS ) { std::cerr << "Vertex not at optimimal location" << std::endl << " Expected: (" << expect[0] << ", " << expect[1] << ", " << expect[2] << ")" << std::endl << " Actual: (" << coords[0] << ", " << coords[1] << ", " << coords[2] << ")" << std::endl; return NOT_AT_TARGET; } return 0; }
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* initial_mesh_file = 0; const char* final_mesh_file = 0; for (int i = 1; i < argc; ++i) { if (!strcmp(argv[i],"-f")) { ++i; if (i == argc) usage(argv[0]); final_mesh_file = argv[i]; } else if (!strcmp(argv[i],"-i")) { ++i; if (i == argc) usage(argv[0]); initial_mesh_file = argv[i]; } else usage( argv[i] ); } // create mesh const int intervals = 3; const double perturb = 0.3; const int nvtx = (intervals+1) * (intervals+1); double coords[nvtx*3]; double exp_coords[nvtx*3]; int fixed[nvtx]; for (int i = 0; i < nvtx; ++i) { double* c = coords + 3*i; double* e = exp_coords + 3*i; int row = i / (intervals+1); int col = i % (intervals+1); double xdelta, ydelta; if (row > 0 && row < intervals && col > 0 && col < intervals) { fixed[i] = 0; xdelta = row % 2 ? -perturb : 0; ydelta = col % 2 ? perturb : -perturb; } else { fixed[i] = 1; xdelta = ydelta = 0.0; } c[0] = col + xdelta; c[1] = row + ydelta; c[2] = 0.0; e[0] = col; e[1] = row; e[2] = 0.0; } const int nquad = intervals * intervals; unsigned long conn[nquad * 4]; for (int i = 0; i < nquad; ++i) { unsigned long* c = conn + 4*i; int row = i / intervals; int col = i % intervals; int n0 = (intervals+1)*row + col; c[0] = n0; c[1] = n0+1; c[2] = n0+intervals+2; c[3] = n0+intervals+1; } MsqPrintError err(std::cerr); ArrayMesh mesh( 3, nvtx, coords, fixed, nquad, QUADRILATERAL, conn ); PlanarDomain zplane( PlanarDomain::XY ); if (initial_mesh_file) { MeshWriter::write_vtk( &mesh, initial_mesh_file, err ); if (err) { fprintf(stderr,"%s: failed to write file\n", initial_mesh_file ); return 1; } } // do optimization const double eps = 0.01; IdealShapeTarget w; TShapeB1 mu; TQualityMetric metric( &w, &mu ); PMeanPTemplate func( 1.0, &metric ); SteepestDescent solver( &func ); solver.use_element_on_vertex_patch(); solver.do_jacobi_optimization(); TerminationCriterion inner, outer; inner.add_absolute_vertex_movement( 0.5*eps ); outer.add_absolute_vertex_movement( 0.5*eps ); QualityAssessor qa( &metric ); InstructionQueue q; q.add_quality_assessor( &qa, err ); q.set_master_quality_improver( &solver, err ); q.add_quality_assessor( &qa, err ); MeshDomainAssoc mesh_and_domain = MeshDomainAssoc(&mesh, &zplane); q.run_instructions( &mesh_and_domain, err ); if (err) return 2; if (final_mesh_file) { MeshWriter::write_vtk( &mesh, final_mesh_file, err ); if (err) { fprintf(stderr,"%s: failed to write file\n", final_mesh_file ); return 1; } } // check final vertex positions int invalid = 0; for (int i = 0; i < nvtx; ++i) { if (dist( coords + 3*i, exp_coords + 3*i ) > eps) { ++invalid; printf("Vertex %d at (%f,%f,%f), expected at (%f,%f,%f)\n", i, coords[3*i], coords[3*i+1], coords[3*i+2], exp_coords[3*i], exp_coords[3*i+1], exp_coords[3*i+2] ); } } return invalid ? 2 : 0; }
int main( int argc, char* argv[] ) { const double default_fraction = 0.05; const double zero = 0.0; int one = 1; CLArgs::ToggleArg allow_invalid( false ); CLArgs::DoubleRangeArg rand_percent( default_fraction, &zero, 0 ); CLArgs::IntRangeArg unoptimize( 0, &one, 0 ); CLArgs args( "vtkrandom", "Randomize mesh vertex locations.", "Read VTK file, randomize locations of containded vertices, and re-write file." ); args.toggle_flag( INVALID_FLAG, "Allow inverted elements in output", &allow_invalid ); args.double_flag( PERCENT_FLAG, "fract", "Randomize fraction", &rand_percent ); args.int_flag( UNOPTIMIZE_FLAG, "N", "Use UnOptimizer with N passes rather than Randomize", &unoptimize ); add_domain_args( args ); 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]; MsqError err; MeshImpl mesh; mesh.read_vtk( input_file.c_str(), err ); if (err) { std::cerr << "ERROR READING FILE: " << input_file << std::endl << err << std::endl; return 2; } MeshDomain* domain = process_domain_args( &mesh ); TerminationCriterion tc; QualityAssessor qa( false ); InstructionQueue q; Randomize op( rand_percent.value() ); IdealWeightInverseMeanRatio metric; PMeanPTemplate of( 1, &metric ); UnOptimizer op2( &of ); if (unoptimize.seen()) { tc.add_iteration_limit( unoptimize.value() ); op2.set_outer_termination_criterion( &tc ); q.add_preconditioner( &op, err ); q.set_master_quality_improver( &op2, err ); } else { q.set_master_quality_improver( &op, err ); } q.add_quality_assessor( &qa, err ); q.run_instructions( &mesh, domain, err ); if (err) { std::cerr << err << std::endl; return 3; } int inverted, junk; if (qa.get_inverted_element_count( inverted, junk, err ) && inverted ) { if (allow_invalid.value()) std::cerr << "Warning: output mesh contains " << inverted << " inverted elements" << std::endl; else { std::cerr << "Error: output mesh contains " << inverted << " inverted elements" << std::endl; return 4; } } mesh.write_vtk( output_file.c_str(), err ); if (err) { std::cerr << "ERROR WRITING FILE: " << output_file << std::endl << err << std::endl; return 2; } return 0; }