MeshKit
1.0
|
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