MOAB: Mesh Oriented datABase
(version 5.4.1)
|
00001 #include "Randomize.hpp" 00002 #include "InstructionQueue.hpp" 00003 #include "QualityAssessor.hpp" 00004 #include "MeshImpl.hpp" 00005 00006 #include "PatchData.hpp" 00007 #include "MsqVertex.hpp" 00008 #include "IdealWeightInverseMeanRatio.hpp" 00009 #include "PMeanPTemplate.hpp" 00010 #include "TerminationCriterion.hpp" 00011 #include <cassert> 00012 00013 #include "domain.hpp" 00014 00015 #include <iostream> 00016 #include <iomanip> 00017 #include <memory> 00018 #include <cstdio> 00019 #include <cstring> 00020 #include <cctype> 00021 #include <cstdlib> 00022 00023 using namespace MBMesquite; 00024 00025 const char INVALID_FLAG = 'i'; 00026 const char PERCENT_FLAG = 'p'; 00027 const char UNOPTIMIZE_FLAG = 'u'; 00028 00029 class UnOptimizer : public VertexMover 00030 { 00031 public: 00032 UnOptimizer( ObjectiveFunction* of ) : objectiveFunction( of ) {} 00033 00034 virtual ~UnOptimizer() {} 00035 00036 virtual std::string get_name() const; 00037 00038 virtual PatchSet* get_patch_set(); 00039 00040 protected: 00041 virtual void initialize( PatchData& pd, MsqError& err ); 00042 00043 virtual void optimize_vertex_positions( PatchData& pd, MsqError& err ); 00044 00045 virtual void initialize_mesh_iteration( PatchData& pd, MsqError& err ); 00046 00047 virtual void terminate_mesh_iteration( PatchData& pd, MsqError& err ); 00048 00049 virtual void cleanup(); 00050 00051 private: 00052 std::vector< size_t > adjVtxList; 00053 VertexPatches patchSet; 00054 ObjectiveFunction* objectiveFunction; 00055 }; 00056 00057 std::string UnOptimizer::get_name() const 00058 { 00059 return "UnOptimize"; 00060 } 00061 PatchSet* UnOptimizer::get_patch_set() 00062 { 00063 return &patchSet; 00064 } 00065 void UnOptimizer::initialize( PatchData&, MsqError& ) {} 00066 void UnOptimizer::initialize_mesh_iteration( PatchData&, MsqError& ) {} 00067 void UnOptimizer::terminate_mesh_iteration( PatchData&, MsqError& ) {} 00068 void UnOptimizer::cleanup() {} 00069 00070 void UnOptimizer::optimize_vertex_positions( PatchData& pd, MsqError& err ) 00071 { 00072 assert( pd.num_free_vertices() == 1 && pd.vertex_by_index( 0 ).is_free_vertex() ); 00073 std::vector< Vector3D > grad( 1 ); 00074 double val, junk, coeff; 00075 bool state; 00076 00077 state = objectiveFunction->evaluate_with_gradient( ObjectiveFunction::CALCULATE, pd, val, grad, err );MSQ_ERRRTN( err ); 00078 if( !state ) 00079 { 00080 MSQ_SETERR( err )( MsqError::INVALID_MESH ); 00081 return; 00082 } 00083 grad[0] /= grad[0].length(); 00084 00085 PatchDataVerticesMemento* memento = pd.create_vertices_memento( err );MSQ_ERRRTN( err ); 00086 std::unique_ptr< PatchDataVerticesMemento > deleter( memento ); 00087 pd.get_minmax_edge_length( junk, coeff ); 00088 00089 for( int i = 0; i < 100; ++i ) 00090 { 00091 pd.set_free_vertices_constrained( memento, arrptr( grad ), 1, coeff, err );MSQ_ERRRTN( err ); 00092 state = objectiveFunction->evaluate( ObjectiveFunction::CALCULATE, pd, val, true, err );MSQ_ERRRTN( err ); 00093 if( state ) break; 00094 coeff *= 0.5; 00095 } 00096 if( !state ) 00097 { 00098 pd.set_to_vertices_memento( memento, err ); 00099 } 00100 } 00101 00102 int main( int argc, char* argv[] ) 00103 { 00104 const double default_fraction = 0.05; 00105 const double zero = 0.0; 00106 int one = 1; 00107 CLArgs::ToggleArg allow_invalid( false ); 00108 CLArgs::DoubleRangeArg rand_percent( default_fraction, &zero, 0 ); 00109 CLArgs::IntRangeArg unoptimize( 0, &one, 0 ); 00110 00111 CLArgs args( "vtkrandom", "Randomize mesh vertex locations.", 00112 "Read VTK file, randomize locations of containded vertices, and re-write file." ); 00113 args.toggle_flag( INVALID_FLAG, "Allow inverted elements in output", &allow_invalid ); 00114 args.double_flag( PERCENT_FLAG, "fract", "Randomize fraction", &rand_percent ); 00115 args.int_flag( UNOPTIMIZE_FLAG, "N", "Use UnOptimizer with N passes rather than Randomize", &unoptimize ); 00116 add_domain_args( args ); 00117 args.add_required_arg( "input_file" ); 00118 args.add_required_arg( "output_file" ); 00119 00120 std::vector< std::string > files; 00121 if( !args.parse_options( argc, argv, files, std::cerr ) ) 00122 { 00123 args.print_usage( std::cerr ); 00124 exit( 1 ); 00125 } 00126 std::string input_file = files[0]; 00127 std::string output_file = files[1]; 00128 00129 MsqError err; 00130 MeshImpl mesh; 00131 mesh.read_vtk( input_file.c_str(), err ); 00132 if( err ) 00133 { 00134 std::cerr << "ERROR READING FILE: " << input_file << std::endl << err << std::endl; 00135 return 2; 00136 } 00137 MeshDomain* domain = process_domain_args( &mesh ); 00138 00139 TerminationCriterion tc; 00140 QualityAssessor qa( false ); 00141 InstructionQueue q; 00142 Randomize op( rand_percent.value() ); 00143 IdealWeightInverseMeanRatio metric; 00144 PMeanPTemplate of( 1, &metric ); 00145 UnOptimizer op2( &of ); 00146 if( unoptimize.seen() ) 00147 { 00148 tc.add_iteration_limit( unoptimize.value() ); 00149 op2.set_outer_termination_criterion( &tc ); 00150 q.add_preconditioner( &op, err ); 00151 q.set_master_quality_improver( &op2, err ); 00152 } 00153 else 00154 { 00155 q.set_master_quality_improver( &op, err ); 00156 } 00157 q.add_quality_assessor( &qa, err ); 00158 MeshDomainAssoc mesh_and_domain = MeshDomainAssoc( &mesh, domain ); 00159 q.run_instructions( &mesh_and_domain, err ); 00160 if( err ) 00161 { 00162 std::cerr << err << std::endl; 00163 return 3; 00164 } 00165 00166 int inverted, junk; 00167 if( qa.get_inverted_element_count( inverted, junk, err ) && inverted ) 00168 { 00169 if( allow_invalid.value() ) 00170 std::cerr << "Warning: output mesh contains " << inverted << " inverted elements" << std::endl; 00171 else 00172 { 00173 std::cerr << "Error: output mesh contains " << inverted << " inverted elements" << std::endl; 00174 return 4; 00175 } 00176 } 00177 00178 mesh.write_vtk( output_file.c_str(), err ); 00179 if( err ) 00180 { 00181 std::cerr << "ERROR WRITING FILE: " << output_file << std::endl << err << std::endl; 00182 return 2; 00183 } 00184 00185 return 0; 00186 }