MeshKit
1.0
|
00001 #include "meshkit/Mesh.hpp" 00002 #include <iostream> 00003 00004 #ifdef HAVE_MESQUITE 00005 #include "Mesquite_all_headers.hpp" 00006 using namespace MESQUITE_NS; 00007 #endif 00008 00010 00011 int Jaal::MeshOptimization::shape_optimize(Jaal::Mesh *mesh, int algo, int niter) 00012 { 00013 algorithm = algo; 00014 numIter = niter; 00015 00016 #ifdef HAVE_MESQUITE 00017 int topo = mesh->isHomogeneous(); 00018 00019 if( topo == 3 ) { 00020 execute(mesh); 00021 return 0; 00022 } 00023 00024 if( topo == 4 ) { 00025 if( mesh->count_concave_faces() ) { 00026 cout << " Optimizing triangle mesh of the quadrilateral mesh: " << endl; 00027 vector<Vertex*> steiner; 00028 Mesh *trimesh = Jaal::quad_to_tri4( mesh, steiner); 00029 execute(trimesh); 00030 trimesh->deleteFaces(); 00031 for( size_t i = 0; i < steiner.size(); i++) 00032 delete steiner[i]; 00033 delete trimesh; 00034 } else { 00035 cout << " Optimizing Quadrilateral mesh directly: " << endl; 00036 execute(mesh); 00037 } 00038 00039 return 0; 00040 } 00041 #endif 00042 return 1; 00043 } 00044 00045 #ifdef HAVE_MESQUITE 00046 00047 Mesquite::ArrayMesh* Jaal::MeshOptimization::jaal_to_mesquite( Jaal::Mesh *mesh ) 00048 { 00049 MsqError err; 00050 00051 unsigned long int numnodes = mesh->getSize(0); 00052 unsigned long int numfaces = mesh->getSize(2); 00053 00054 // 00056 // Mesquite works only when the faces are convex, and our mesh may contain some 00057 // truly bad elements. Therefore, we will skip those faces and mark them fix. 00058 // Hopefully, later by some other operations ( smoothing, decimation, refinement 00059 // etc.) those bad elements may get removed. 00060 00061 // By ignoring some of the faces, the mesh may get disconnected. ( I need to test 00062 // such cases ). 00063 // 00064 // The mesh must be doublets free. ( I found out this after some pains ). 00066 00067 mesh->search_boundary(); 00068 00069 size_t index = 0; 00070 for (size_t i = 0; i < numnodes; i++) { 00071 Vertex *vertex = mesh->getNodeAt(i); 00072 if( vertex->isActive() ) vertex->setID( index++ ); 00073 } 00074 size_t noptnodes = index; 00075 00076 vfixed.resize(noptnodes); 00077 for (size_t i = 0; i < numnodes; i++) { 00078 Vertex *vertex = mesh->getNodeAt(i); 00079 if( vertex->isActive() ) { 00080 int lid = vertex->getID(); 00081 if (vertex->isBoundary()) 00082 vfixed[lid] = 1; 00083 else 00084 vfixed[lid] = 0; 00085 } 00086 } 00087 00088 size_t noptfaces = 0; 00089 for( size_t i = 0; i < numfaces; i++) { 00090 Face *f = mesh->getFaceAt(i); 00091 if( f->isActive() ) noptfaces++; 00092 } 00093 00094 mesh->getCoordsArray( vCoords, l2g ); 00095 mesh->getNodesArray( vNodes, etopo ); 00096 00097 Mesquite::ArrayMesh *optmesh = NULL; 00098 00099 int topo = mesh->isHomogeneous(); 00100 00101 assert( noptnodes == vCoords.size()/3 ); 00102 assert( noptnodes == vfixed.size()); 00103 00104 if (topo == 4) 00105 optmesh = new Mesquite::ArrayMesh(3, noptnodes, &vCoords[0], &vfixed[0], 00106 noptfaces, Mesquite::QUADRILATERAL, &vNodes[0]); 00107 if (topo == 3) { 00108 optmesh = new Mesquite::ArrayMesh(3, noptnodes, &vCoords[0], &vfixed[0], 00109 noptfaces, Mesquite::TRIANGLE, &vNodes[0]); 00110 } 00111 00112 return optmesh; 00113 } 00114 00115 #endif 00116 00118 00119 int Jaal::MeshOptimization::execute(Jaal::Mesh *mesh) 00120 { 00121 #ifdef HAVE_MESQUITE 00122 MsqError err; 00123 00124 Mesquite::ArrayMesh *optmesh = NULL; 00125 optmesh = Jaal::MeshOptimization::jaal_to_mesquite( mesh); 00126 if( optmesh == NULL ) return 1; 00127 00128 Vector3D normal(0, 0, 1); 00129 Vector3D point (0, 0, 0); 00130 PlanarDomain mesh_plane(normal, point); 00131 00132 // creates a mean ratio quality metric ... 00133 IdealWeightInverseMeanRatio mesh_quality; 00134 00135 // IdealWeightMeanRatio mesh_quality; 00136 // ConditionNumberQualityMetric mesh_quality; 00137 // EdgeLengthQualityMetric mesh_quality; 00138 00139 // sets the objective function template 00140 LPtoPTemplate obj_func(&mesh_quality, 2, err); 00141 00142 // creates the optimization procedures 00143 00144 TerminationCriterion tc_outer; 00145 00146 TerminationCriterion tc_inner; 00147 tc_inner.add_absolute_gradient_L2_norm(1e-4); 00148 tc_inner.write_iterations("opt.dat", err); 00149 00150 SteepestDescent *sp = NULL; 00151 QuasiNewton *qn = NULL; 00152 TrustRegion *tr = NULL; 00153 FeasibleNewton *fn = NULL; 00154 ConjugateGradient *cg = NULL; 00155 SmartLaplacianSmoother *lp = NULL; 00156 00157 improver = NULL; 00158 00159 switch (algorithm) { 00160 case STEEPEST_DESCENT: 00161 sp = new SteepestDescent( &obj_func); // Fastest but poor convergence in the tail. 00162 sp->use_global_patch(); 00163 improver = sp; 00164 tc_inner.add_iteration_limit(numIter); 00165 improver->set_inner_termination_criterion(&tc_inner); 00166 break; 00167 case QUASI_NEWTON: 00168 qn = new QuasiNewton( &obj_func); // Fastest but poor convergence in the tail. 00169 qn->use_global_patch(); 00170 // qn->use_element_on_vertex_patch(); 00171 improver = qn; 00172 tc_inner.add_iteration_limit(numIter); 00173 improver->set_inner_termination_criterion(&tc_inner); 00174 break; 00175 case TRUST_REGION: 00176 tr = new TrustRegion( &obj_func); // Fastest but poor convergence in the tail. 00177 tr->use_global_patch(); 00178 improver = tr; 00179 tc_inner.add_iteration_limit(numIter); 00180 improver->set_inner_termination_criterion(&tc_inner); 00181 break; 00182 case FEASIBLE_NEWTON: 00183 fn = new FeasibleNewton( &obj_func); // Fastest but poor convergence in the tail. 00184 fn->use_global_patch(); 00185 improver = fn; 00186 tc_inner.add_iteration_limit(numIter); 00187 improver->set_inner_termination_criterion(&tc_inner); 00188 break; 00189 case CONJUGATE_GRADIENT: 00190 cg = new ConjugateGradient(&obj_func); 00191 cg->use_global_patch(); 00192 improver = cg; 00193 tc_inner.add_iteration_limit(numIter); 00194 improver->set_inner_termination_criterion(&tc_inner); 00195 break; 00196 case LAPLACIAN: 00197 lp = new SmartLaplacianSmoother( &obj_func); // Fastest but poor convergence in the tail. 00198 improver = lp; 00199 tc_outer.add_iteration_limit(numIter); 00200 improver->set_outer_termination_criterion(&tc_outer); 00201 break; 00202 default: 00203 cout << "Warning: Invalid optimization algorithm selected: "<< endl; 00204 } 00205 00206 if( improver ) { 00207 00208 // creates a quality assessor 00209 QualityAssessor qa(&mesh_quality); 00210 00211 // creates an instruction queue 00212 InstructionQueue queue; 00213 queue.add_quality_assessor(&qa, err); 00214 queue.set_master_quality_improver(improver, err); 00215 queue.add_quality_assessor(&qa, err); 00216 00217 // do optimization of the mesh_set 00218 queue.run_instructions(optmesh, &mesh_plane, err); 00219 00220 cout << "# of iterations " << tc_inner.get_iteration_count() << endl; 00221 00222 if (err) { 00223 std::cout << err << std::endl; 00224 return 2; 00225 } 00226 00227 mesh->setCoordsArray(vCoords, l2g); 00228 delete improver; 00229 } 00230 00231 delete optmesh; 00232 00233 return 0; 00234 #endif 00235 00236 return 1; 00237 } 00238