MeshKit  1.0
MesquiteOpt.cpp
Go to the documentation of this file.
00001 #include "meshkit/MesquiteOpt.hpp"
00002 #include "meshkit/ModelEnt.hpp"
00003 #include "meshkit/iMesh.hpp"
00004 #include "moab/Skinner.hpp"
00005 #include "MsqIMesh.hpp"
00006 #include "QualityAssessor.hpp"
00007 #include "MsqError.hpp"
00008 #ifdef MSQIGEOM
00009 # include "MsqIGeom.hpp"
00010 #endif
00011 #include "FreeSmoothDomain.hpp"
00012 
00013 #include "mesquite_version.h"
00014 #if MSQ_VERSION_MAJOR > 2 || (MSQ_VERSION_MAJOR == 2 && MSQ_VERSION_MINOR > 1)
00015 #include "ShapeImprover.hpp"
00016 typedef Mesquite::ShapeImprover DefaultAlgorithm;
00017 #else
00018 #include "ShapeImprovementWrapper.hpp"
00019 typedef Mesquite::ShapeImprovementWrapper DefaultAlgorithm;
00020 #endif
00021 
00022     
00023 #define MSQERRCHK(err)                                 \
00024   do {                                                 \
00025     if ((err)) {                                       \
00026       throw Error(MK_FAILURE,"%s:%d: Mesquite error: %s",     \
00027           __FILE__, __LINE__, (err).error_message() ); \
00028     }                                                  \
00029   } while(false)
00030 
00031 
00032 using namespace Mesquite;
00033 
00034 namespace MeshKit { 
00035 
00036 MesquiteOpt::MesquiteOpt( MKCore* core, const MEntVector &me_vec )
00037   : MeshOp(core, me_vec),
00038     msqAlgo(0),
00039     fixedBoundary(true),
00040     haveFixedTag(false),
00041     createdByteTag(false),
00042     verboseOutput(false)
00043 {}
00044 
00045 const moab::EntityType* MesquiteOpt::output_types() 
00046 {
00047   const static moab::EntityType end = moab::MBMAXTYPE;
00048   return &end;
00049 }
00050 
00051 bool MesquiteOpt::can_mesh( iBase_EntityType dim )
00052 {
00053   return dim >= 2;
00054 }
00055 
00056 bool MesquiteOpt::can_mesh( ModelEnt* ent )
00057 {
00058   return can_mesh( (iBase_EntityType)ent->dimension() );
00059 }
00060 
00061 iBase_TagHandle MesquiteOpt::get_fixed_tag()
00062 {
00063   if (!haveFixedTag)
00064     set_fixed_tag( "fixed" );
00065   return fixedTag;
00066 }
00067 
00068 void MesquiteOpt::set_fixed_tag( iBase_TagHandle tag )
00069 {
00070   int size;
00071   iMesh::TagValueType type;
00072   mk_core()->imesh_instance()->getTagSizeValues( tag, size );
00073   mk_core()->imesh_instance()->getTagType( tag, type );
00074   if (size != 1 || type != iBase_INTEGER) 
00075     throw Error(MK_WRONG_DIMENSION,"Tag as invalid type or size");
00076   haveFixedTag = true;
00077   fixedTag = tag;
00078 }
00079 
00080 void MesquiteOpt::set_fixed_tag( const char* name )
00081 {
00082   iBase_TagHandle tag;
00083   iBase_ErrorType err = mk_core()->imesh_instance()->getTagHandle( name, tag );
00084   if (iBase_SUCCESS == err) {
00085     set_fixed_tag(tag);
00086   }
00087   else {
00088       // create though moab so we can make it a dense tag
00089     moab::Tag t;
00090     moab::ErrorCode rval;
00091     int zero = 0;
00092     rval = mk_core()->moab_instance()->tag_get_handle( name,
00093                                                    1,
00094                                                    moab::MB_TYPE_INTEGER,
00095                                                    t,
00096                                                    moab::MB_TAG_DENSE|moab::MB_TAG_CREAT,
00097                                                    &zero );
00098     MBERRCHK(rval,mk_core()->moab_instance());
00099     
00100     err = mk_core()->imesh_instance()->getTagHandle( name, tag );
00101     IBERRCHK(err,"Tag created via Moab not accessable via iMesh");
00102     set_fixed_tag( tag );
00103   }
00104 }
00105 
00106 void MesquiteOpt::create_byte_tag()
00107 {
00108   if (!createdByteTag) {
00109         // Create though moab so we can make it a dense tag
00110         // Don't check error code.  We don't care if it already exists
00111         // and futher, we really aren't responsiblefor creating it anyway.
00112         // We do it here only so we can make it a dense tag.
00113     moab::Tag t;
00114     unsigned char zero = 0;
00115     mk_core()->moab_instance()->tag_get_handle( Mesquite::VERTEX_BYTE_TAG_NAME,
00116                                             1,
00117                                             moab::MB_TYPE_INTEGER,
00118                                             t,
00119                                             moab::MB_TAG_DENSE|moab::MB_TAG_CREAT,
00120                                             &zero );
00121     createdByteTag = true;
00122   }
00123 }
00124 
00125 void MesquiteOpt::smooth_with_fixed_boundary()
00126 { 
00127   fixedBoundary = true;
00128 }
00129 
00130 void MesquiteOpt::smooth_with_free_boundary()
00131 {
00132 #ifndef MSQIGEOM
00133   throw Error(MK_NOT_IMPLEMENTED,"Cannot do free smooth w/out Mesquite iRel support");
00134 #else
00135   fixedBoundary = false;
00136 #endif
00137 }
00138 
00139 void MesquiteOpt::setup_this()
00140 {
00141   get_fixed_tag();
00142   create_byte_tag();
00143 }
00144 
00145 void MesquiteOpt::set_fixed_tag( ModelEnt* ent, int value )
00146 {
00147   std::vector<int> fixed_vals;
00148   iBase_TagHandle fixed = get_fixed_tag();
00149   iMesh* mesh = mk_core()->imesh_instance();
00150   std::vector<iBase_EntityHandle> ents, verts;
00151   iMesh::Error err;
00152 
00153   ents.clear();
00154   err = mesh->getEntities( (iBase_EntitySetHandle)ent->mesh_handle(), 
00155                            (iMesh::EntityType)ent->dimension(),
00156                            iMesh_ALL_TOPOLOGIES,
00157                            ents );
00158   IBERRCHK(err,"Error getting ModelEnt mesh entities via iMesh");
00159 
00160   if (ent->dimension() > 0) {
00161     verts.clear();
00162     fixed_vals.resize(ents.size()+1);
00163     err = mesh->getEntArrAdj( &ents[0], ents.size(), iBase_VERTEX, verts, &fixed_vals[0] );
00164     IBERRCHK(err,"Error mesh vertices from mesh entities via iMesh");
00165   }
00166   else {
00167     verts.swap(ents);
00168   }
00169   
00170   fixed_vals.clear();
00171   fixed_vals.resize( verts.size(), value );
00172   err = mesh->setIntArrData( &verts[0], verts.size(), fixed, &fixed_vals[0] );
00173   IBERRCHK(err,"Clearing fixed tag on mesh vertices");
00174 }
00175 
00176 void MesquiteOpt::set_fixed_tag_on_skin( ModelEnt* ent, int value )
00177 {
00178   if (ent->dimension() > 0) {
00179       // if geometric entity, skin is defined by bounding geometry
00180     if (ent->geom_handle()) {
00181       MEntVector children;
00182       ent->get_adjacencies( ent->dimension() - 1, children );
00183       for (MEntVector::iterator i = children.begin(); i != children.end(); ++i)
00184         set_fixed_tag( *i, value );
00185     }
00186       // otherwise find the actual skin
00187     else {
00188       moab::Interface* mb = mk_core()->moab_instance();
00189       moab::EntityHandle set = static_cast<moab::EntityHandle>( ent->mesh_handle() );
00190       moab::ErrorCode rval;
00191       moab::Range elems;
00192       rval = mb->get_entities_by_dimension( set, ent->dimension(), elems );
00193       MBERRCHK(rval, mk_core()->moab_instance());
00194       
00195       moab::Range verts;
00196       moab::Skinner tool(mb);
00197       moab::ErrorCode err = tool.find_skin( 0, elems, 0, verts );
00198       MBERRCHK(err, mk_core()->moab_instance());
00199      
00200       moab::Tag t = reinterpret_cast<moab::Tag>( get_fixed_tag() );
00201       err = mb->tag_clear_data( t, verts, &value );
00202       MBERRCHK(err, mk_core()->moab_instance());
00203     }
00204   }
00205 }
00206 
00207 bool MesquiteOpt::all_model_ents_have_geom() const
00208 {
00209   MEntSelection::const_iterator i;
00210   for (i = mentSelection.begin(); i != mentSelection.end(); ++i) {
00211     ModelEnt* ent = i->first;
00212     if (!ent->geom_handle())
00213       return false;
00214   }
00215   return true;
00216 }
00217 
00218 void MesquiteOpt::get_adjacent_entity_set( MEntSet& from_this,
00219                                            MEntVector& ents,
00220                                            iBase_EntitySetHandle& result,
00221                                            iBase_EntityType& dimension,
00222                                            bool& created_result_set )
00223 {
00224   if (from_this.empty())
00225     throw Error(MK_BAD_INPUT,"Input set is empty");
00226   
00227   iMesh* imesh = mk_core()->imesh_instance();
00228   bool first = true;
00229   iBase_ErrorType err;
00230   created_result_set = false;
00231   MEntVector front, adj, adj2;
00232   front.push_back(*from_this.begin());
00233   from_this.erase(from_this.begin());
00234   while (!front.empty()) {
00235     ModelEnt* ent = front.back();
00236     front.pop_back();
00237     ents.push_back(ent);
00238     
00239     try {
00240       if (first) {
00241         dimension = (iBase_EntityType)ent->dimension();
00242         result = (iBase_EntitySetHandle)ent->mesh_handle();
00243         first = false;
00244       }
00245       else {
00246         if (ent->dimension() != dimension)
00247           dimension = iBase_ALL_TYPES;
00248 
00249         if (!created_result_set) {
00250           err = imesh->unite( result, (iBase_EntitySetHandle)ent->mesh_handle(), result );
00251           IBERRCHK(err,"WTF?");
00252           created_result_set = true;
00253         }
00254         else {
00255           iBase_EntitySetHandle tmp;
00256           err = imesh->unite( result, (iBase_EntitySetHandle)ent->mesh_handle(), tmp );
00257           IBERRCHK(err,"WTF?");
00258           imesh->destroyEntSet( result );
00259           result = tmp;
00260         }
00261       }
00262     }
00263     catch (...) {
00264       if (created_result_set)
00265         imesh->destroyEntSet( result );
00266       throw;
00267     }
00268     
00269     if (ent->dimension() == 3) {
00270       adj.clear();
00271       ent->get_adjacencies( 2, adj );
00272       for (MEntVector::iterator i = adj.begin(); i != adj.end(); ++i) {
00273         MEntSet::iterator j = from_this.find(*i);
00274         if (j != from_this.end()) {
00275           front.push_back( *j );
00276           from_this.erase( j );
00277         }
00278         adj2.clear();
00279         (*i)->get_adjacencies( 3, adj2 );
00280         for (MEntVector::iterator k = adj2.begin(); k != adj2.end(); ++k) {
00281           j = from_this.find(*k);
00282           if (j != from_this.end()) {
00283             front.push_back( *j );
00284             from_this.erase( j );
00285           }
00286         }
00287       }
00288     }
00289     
00290     adj.clear();
00291     ent->get_adjacencies( 1, adj );
00292     for (MEntVector::iterator i = adj.begin(); i != adj.end(); ++i) {
00293       for (int dim = 2; dim <= 3; ++dim) {
00294         adj2.clear();
00295         (*i)->get_adjacencies( dim, adj2 );
00296         for (MEntVector::iterator k = adj2.begin(); k != adj2.end(); ++k) {
00297           MEntSet::iterator j = from_this.find(*k);
00298           if (j != from_this.end()) {
00299             front.push_back( *j );
00300             from_this.erase( j );
00301           }
00302         }
00303       }
00304     }
00305   }
00306 }
00307 
00308 
00309 void MesquiteOpt::execute_this()
00310 {
00311   MEntSelection::iterator i;
00312   MsqError err;
00313   iMesh* imesh = mk_core()->imesh_instance();
00314   iGeom* igeom = mk_core()->igeom_instance();
00315 
00316   IQInterface* smoother;
00317   DefaultAlgorithm defaultAlgo;
00318   if (msqAlgo == 0) {
00319     smoother = &defaultAlgo;
00320     if (!verboseOutput)
00321       defaultAlgo.quality_assessor().disable_printing_results();
00322   }
00323   else
00324     smoother = msqAlgo;
00325     
00326   create_byte_tag();
00327 
00328   MsqIMesh msqmesh( imesh->instance(), iBase_ALL_TYPES, err, &fixedTag );
00329   MSQERRCHK(err);
00330 
00331   if (fixedBoundary) {
00332     for (int dim = 2; dim <= 3; ++dim) {
00333       for (i = mentSelection.begin(); i != mentSelection.end(); ++i) {
00334         ModelEnt* ent = i->first;
00335         if (ent->dimension() != dim)
00336           continue;
00337         
00338         set_fixed_tag( ent, 0 );
00339         set_fixed_tag_on_skin( ent, 1 );
00340         MsqIMesh msqmesh( imesh->instance(), 
00341                           (iBase_EntitySetHandle)ent->mesh_handle(),
00342                           (iBase_EntityType)dim,
00343                           err, &fixedTag );
00344         MSQERRCHK(err);
00345         
00346         if (ent->dimension() == 2 && ent->geom_handle()) {
00347 #ifndef MSQIGEOM
00348           throw Error(MK_BAD_GEOMETRIC_EVALUATION,
00349               "Mesquite not configured with iGeom support.  "
00350               "Cannot optimize surface meshes.");
00351 #else
00352           MsqIGeom msqgeom( igeom->instance(), ent->geom_handle() );
00353           smoother->run_instructions( &msqmesh, &msqgeom, err );
00354 #endif
00355         }
00356         else {
00357           smoother->run_instructions( &msqmesh, err );
00358         }
00359         MSQERRCHK(err);
00360       }
00361     }
00362   }
00363   else {
00364     // shouuld be checked by FreeSmoothDomain
00365     //if (!all_model_ents_have_geom())
00366     //  throw Error(MK_BAD_GEOMETRIC_EVALUATION,
00367     //        "Cannot do free smooth of entity that doesn't have bounding geometry.");
00368 
00369     MEntSet remaining;
00370     for (i = mentSelection.begin(); i != mentSelection.end(); ++i) {
00371       ModelEnt* ent = i->first;
00372       MEntSet::iterator hint = remaining.begin();
00373       if (ent->dimension() == 2 || ent->dimension() == 3) 
00374         hint = remaining.insert( hint, ent );
00375     }
00376     
00377     MEntVector ents;
00378     while (!remaining.empty()) {
00379       iBase_EntitySetHandle set;
00380       bool free_set = false;
00381       iBase_EntityType dim;
00382       ents.clear();
00383       get_adjacent_entity_set( remaining, ents, set, dim, free_set );
00384       
00385       try {
00386         FreeSmoothDomain msqgeom( mk_core(), ents );
00387         MsqIMesh msqmesh( imesh->instance(), set, dim, err, &fixedTag );
00388         MSQERRCHK(err);
00389         smoother->run_instructions( &msqmesh, &msqgeom, err );
00390         MSQERRCHK(err);
00391       }
00392       catch (...) {
00393         if (free_set)
00394           imesh->destroyEntSet( set );
00395         throw;
00396       }
00397     }
00398   }
00399 }
00400 
00401 } // namespace MeshKit
00402   
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines