MeshKit  1.0
MeshOpt.cpp
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines