![]() |
Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
00001 #ifndef __smoab_SimpleMoab_h
00002 #define __smoab_SimpleMoab_h
00003
00004 #include "moab/Core.hpp"
00005 #include "moab/Interface.hpp"
00006 #include "moab/Range.hpp"
00007 #include "moab/CN.hpp"
00008
00009 #include "MBTagConventions.hpp"
00010
00011 #include
00012
00013 namespace smoab
00014 {
00015 //adjacency intersect / union named enum to match
00016 //the types from moab
00017 enum adjacency_type
00018 {
00019 INTERSECT = moab::Interface::INTERSECT,
00020 UNION = moab::Interface::UNION
00021 };
00022
00023 //make our range equal to moabs range
00024 typedef moab::Range Range;
00025 typedef moab::EntityHandle EntityHandle;
00026 typedef moab::EntityType EntityType;
00027
00028 //bring in range functions
00029 using moab::intersect;
00030 using moab::subtract;
00031 using moab::unite;
00032
00033 class Tag
00034 {
00035 const std::string Name_;
00036
00037 public:
00038 Tag( std::string const& n ) : Name_( n ) {}
00039
00040 virtual ~Tag() {}
00041
00042 const char* name() const
00043 {
00044 return this->Name_.c_str();
00045 }
00046 moab::DataType virtual dataType() const
00047 {
00048 return moab::MB_TYPE_INTEGER;
00049 }
00050 virtual bool isComparable() const
00051 {
00052 return false;
00053 }
00054 virtual int value() const
00055 {
00056 return int();
00057 }
00058 };
00059
00060 //lightweight structs to wrap set names, so we detected
00061 //incorrect names at compile time. In the future I expect material and
00062 //boundary conditions to be comparable
00063 class MaterialTag : public Tag
00064 {
00065 public:
00066 MaterialTag() : Tag( "MATERIAL_SET" ) {}
00067 };
00068 class DirichletTag : public Tag
00069 {
00070 public:
00071 DirichletTag() : Tag( "DIRICHLET_SET" ) {}
00072 };
00073 class NeumannTag : public Tag
00074 {
00075 public:
00076 NeumannTag() : Tag( "NEUMANN_SET" ) {}
00077 };
00078 class GroupTag : public Tag
00079 {
00080 public:
00081 GroupTag() : Tag( "GROUP" ) {}
00082 };
00083
00084 //geom is the only comparable tag, since it can have a dimension.
00085 class GeomTag : public Tag
00086 {
00087 int dim;
00088
00089 public:
00090 GeomTag( int d ) : Tag( "GEOM_DIMENSION" ), dim( d ) {}
00091 GeomTag() : Tag( "GEOM_DIMENSION" ), dim( 0 ) {}
00092
00093 virtual ~GeomTag() {}
00094
00095 bool isComparable() const
00096 {
00097 return dim > 0;
00098 }
00099 int value() const
00100 {
00101 return dim;
00102 }
00103 };
00104
00105 //forward declare this->Moab for Tag
00106 struct Interface;
00107
00108 //forward declare the DataSetConverter so it can be a friend of Interface
00109 class DataSetConverter;
00110
00111 //forward declare the LoadGeometry so it can be a friend of Interface
00112 namespace detail
00113 {
00114 class LoadGeometry;
00115 }
00116 namespace detail
00117 {
00118 class LoadPoly;
00119 }
00120
00121 //light weight wrapper on a moab this->Moab that exposes only the reduced class
00122 //that we need
00123 class Interface
00124 {
00125 public:
00126 Interface( const std::string& file )
00127 {
00128 this->Moab = new moab::Core();
00129 this->Moab->load_file( file.c_str() );
00130 }
00131
00132 ~Interface()
00133 {
00134 if( this->Moab )
00135 {
00136 delete this->Moab;
00137 this->Moab = NULL;
00138 }
00139 }
00140
00141 //----------------------------------------------------------------------------
00142 moab::Tag getMoabTag( const smoab::Tag& simpleTag ) const
00143 {
00144 moab::Tag tag;
00145 this->Moab->tag_get_handle( simpleTag.name(), 1, simpleTag.dataType(), tag );
00146 return tag;
00147 }
00148
00149 //----------------------------------------------------------------------------
00150 template < typename T >
00151 T getDefaultTagVaue( moab::Tag tag ) const
00152 {
00153 T defaultValue;
00154 this->Moab->tag_get_default_value( tag, &defaultValue );
00155 return defaultValue;
00156 }
00157
00158 //----------------------------------------------------------------------------
00159 template < typename T >
00160 T getDefaultTagVaue( smoab::Tag tag ) const
00161 {
00162 return this->getDefaultTagVaue< T >( getMoabTag( tag ) );
00163 }
00164
00165 //----------------------------------------------------------------------------
00166 template < typename T >
00167 T getTagData( moab::Tag tag, const smoab::EntityHandle& entity, T value ) const
00168 {
00169 this->Moab->tag_get_data( tag, &entity, 1, &value );
00170 return value;
00171 }
00172
00173 //----------------------------------------------------------------------------
00174 template < typename T >
00175 T getTagData( smoab::Tag tag, const smoab::EntityHandle& entity, T value = T() ) const
00176 {
00177 return this->getTagData( getMoabTag( tag ), entity, value );
00178 }
00179
00180 //----------------------------------------------------------------------------
00181 //returns the moab name for the given entity handle if it has a sparse Name tag
00182 std::string name( const smoab::EntityHandle& entity ) const
00183 {
00184 moab::Tag nameTag;
00185 moab::ErrorCode rval =
00186 this->Moab->tag_get_handle( NAME_TAG_NAME, NAME_TAG_SIZE, moab::MB_TYPE_OPAQUE, nameTag );
00187 if( rval != moab::MB_SUCCESS )
00188 {
00189 return std::string();
00190 }
00191
00192 char name[NAME_TAG_SIZE];
00193 rval = this->Moab->tag_get_data( nameTag, &entity, 1, &name );
00194 if( rval != moab::MB_SUCCESS )
00195 {
00196 return std::string();
00197 }
00198
00199 return std::string( name );
00200 }
00201
00202 //----------------------------------------------------------------------------
00203 //returns the geometeric dimension of an entity.
00204 int dimension( const smoab::EntityHandle& entity ) const
00205 {
00206 return this->Moab->dimension_from_handle( entity );
00207 }
00208
00209 //----------------------------------------------------------------------------
00210 //returns the geometeric dimension of an entity.
00211 smoab::EntityType entityType( const smoab::EntityHandle& entity ) const
00212 {
00213 return this->Moab->type_from_handle( entity );
00214 }
00215
00216 //----------------------------------------------------------------------------
00217 smoab::EntityHandle getRoot() const
00218 {
00219 return this->Moab->get_root_set();
00220 }
00221
00222 //----------------------------------------------------------------------------
00223 smoab::Range findEntities( const smoab::EntityHandle root, moab::EntityType type ) const
00224 {
00225 smoab::Range result;
00226 // get all the sets of that type in the mesh
00227 this->Moab->get_entities_by_type( root, type, result );
00228 return result;
00229 }
00230
00231 //----------------------------------------------------------------------------
00232 //given a single entity handle find all items in that mesh set that aren't
00233 //them selves entitysets. If recurse is true we also recurse sub entitysets
00234 smoab::Range findAllMeshEntities( smoab::EntityHandle const& entity, bool recurse = false ) const
00235 {
00236 smoab::Range result;
00237 this->Moab->get_entities_by_handle( entity, result, recurse );
00238 return result;
00239 }
00240
00241 //----------------------------------------------------------------------------
00242 //Find all entities with a given tag. We don't use geom as a tag as that
00243 //isn't a fast operation. Yes finding the intersection of geom entities and
00244 //a material / boundary tag will be more work, but it is rarely done currently
00245 //Returns the found group of entities
00246 smoab::Range findEntitiesWithTag( const smoab::Tag& tag,
00247 smoab::EntityHandle root,
00248 moab::EntityType type = moab::MBENTITYSET ) const
00249 {
00250 smoab::Range result;
00251
00252 moab::Tag t = this->getMoabTag( tag );
00253
00254 // get all the entities of that type in the mesh
00255 this->Moab->get_entities_by_type_and_tag( root, type, &t, NULL, 1, result );
00256
00257 if( tag.isComparable() )
00258 {
00259 int value = 0;
00260 //now we have to remove any that doesn't match the tag value
00261 smoab::Range resultMatchingTag;
00262 typedef moab::Range::const_iterator iterator;
00263 for( iterator i = result.begin(); i != result.end(); ++i )
00264 {
00265 value = 0;
00266 moab::EntityHandle handle = *i;
00267 this->Moab->tag_get_data( t, &handle, 1, &value );
00268 if( value == tag.value() )
00269 {
00270 resultMatchingTag.insert( *i );
00271 }
00272 }
00273
00274 return resultMatchingTag;
00275 }
00276 else
00277 {
00278 //we return all the items we found
00279 return result;
00280 }
00281 }
00282
00283 //----------------------------------------------------------------------------
00284 //Find all entities from a given root of a given dimensionality
00285 smoab::Range findEntitiesWithDimension( const smoab::EntityHandle root,
00286 const int dimension,
00287 bool recurse = false ) const
00288 {
00289 typedef smoab::Range::const_iterator iterator;
00290
00291 smoab::Range result;
00292 this->Moab->get_entities_by_dimension( root, dimension, result, recurse );
00293
00294 if( recurse )
00295 {
00296 smoab::Range children;
00297 this->Moab->get_child_meshsets( root, children, 0 );
00298 for( iterator i = children.begin(); i != children.end(); ++i )
00299 {
00300 this->Moab->get_entities_by_dimension( *i, dimension, result );
00301 }
00302 }
00303 return result;
00304 }
00305
00306 //----------------------------------------------------------------------------
00307 smoab::Range findHighestDimensionEntities( const smoab::EntityHandle& entity, bool recurse = false ) const
00308 {
00309 //the goal is to load all entities that are not entity sets of this
00310 //node, while also subsetting by the highest dimension
00311
00312 //lets find the entities of only the highest dimension
00313 int num_ents = 0;
00314 int dim = 3;
00315 while( num_ents <= 0 && dim > 0 )
00316 {
00317 this->Moab->get_number_entities_by_dimension( entity, dim, num_ents, recurse );
00318 --dim;
00319 }
00320 ++dim; //reincrement to correct last decrement
00321 if( num_ents > 0 )
00322 {
00323 //we have found entities of a given dimension
00324 return this->findEntitiesWithDimension( entity, dim, recurse );
00325 }
00326 return smoab::Range();
00327 }
00328
00329 //----------------------------------------------------------------------------
00330 //Find all elements in the database that have children and zero parents.
00331 //this doesn't find
00332 smoab::Range findEntityRootParents( const smoab::EntityHandle& root ) const
00333 {
00334 smoab::Range parents;
00335
00336 typedef moab::Range::const_iterator iterator;
00337 moab::Range sets;
00338
00339 this->Moab->get_entities_by_type( root, moab::MBENTITYSET, sets );
00340 for( iterator i = sets.begin(); i != sets.end(); ++i )
00341 {
00342 int numParents = 0, numChildren = 0;
00343 this->Moab->num_parent_meshsets( *i, &numParents );
00344 if( numParents == 0 )
00345 {
00346 this->Moab->num_child_meshsets( *i, &numChildren );
00347 if( numChildren >= 0 )
00348 {
00349 parents.insert( *i );
00350 }
00351 }
00352 }
00353 return parents;
00354 }
00355
00356 //----------------------------------------------------------------------------
00357 //finds entities that have zero children and zero parents
00358 smoab::Range findDetachedEntities( const moab::EntityHandle& root ) const
00359 {
00360 smoab::Range detached;
00361
00362 typedef moab::Range::const_iterator iterator;
00363 moab::Range sets;
00364
00365 this->Moab->get_entities_by_type( root, moab::MBENTITYSET, sets );
00366 for( iterator i = sets.begin(); i != sets.end(); ++i )
00367 {
00368 int numParents = 0, numChildren = 0;
00369 this->Moab->num_parent_meshsets( *i, &numParents );
00370 if( numParents == 0 )
00371 {
00372 this->Moab->num_child_meshsets( *i, &numChildren );
00373 if( numChildren == 0 )
00374 {
00375 detached.insert( *i );
00376 }
00377 }
00378 }
00379 return detached;
00380 }
00381
00382 //----------------------------------------------------------------------------
00383 //find all children of the entity passed in that has multiple parents
00384 smoab::Range findEntitiesWithMultipleParents( const smoab::EntityHandle& root ) const
00385 {
00386 smoab::Range multipleParents;
00387 typedef moab::Range::const_iterator iterator;
00388
00389 //for all the elements in the range, find all items with multiple parents
00390 moab::Range children;
00391 this->Moab->get_child_meshsets( root, children, 0 );
00392 for( iterator i = children.begin(); i != children.end(); ++i )
00393 {
00394 int numParents = 0;
00395 this->Moab->num_parent_meshsets( *i, &numParents );
00396 if( numParents > 1 )
00397 {
00398 multipleParents.insert( *i );
00399 }
00400 }
00401 return multipleParents;
00402 }
00403
00404 //----------------------------------------------------------------------------
00405 //find all entities that are adjacent to a single entity
00406 smoab::Range findAdjacencies( const smoab::EntityHandle& entity, int dimension ) const
00407 {
00408 const int adjType = static_cast< int >( smoab::INTERSECT );
00409 smoab::Range result;
00410 const bool create_if_missing = false;
00411 this->Moab->get_adjacencies( &entity, 1, dimension, create_if_missing, result, adjType );
00412 return result;
00413 }
00414
00415 //----------------------------------------------------------------------------
00416 smoab::Range findAdjacencies( const smoab::Range& range,
00417 int dimension,
00418 const smoab::adjacency_type type = smoab::UNION ) const
00419 {
00420 //the smoab and moab adjacent intersection enums are in the same order
00421 const int adjType = static_cast< int >( type );
00422 smoab::Range result;
00423 const bool create_if_missing = false;
00424 this->Moab->get_adjacencies( range, dimension, create_if_missing, result, adjType );
00425
00426 return result;
00427 }
00428
00429 //----------------------------------------------------------------------------
00430 //create adjacencies, only works when the dimension requested is lower than
00431 //dimension of the range of entities
00432 smoab::Range createAdjacencies( const smoab::Range& range,
00433 int dimension,
00434 const smoab::adjacency_type type = smoab::UNION ) const
00435 {
00436 //the smoab and moab adjacent intersection enums are in the same order
00437 const int adjType = static_cast< int >( type );
00438 smoab::Range result;
00439 const bool create_if_missing = true;
00440 this->Moab->get_adjacencies( range, dimension, create_if_missing, result, adjType );
00441
00442 return result;
00443 }
00444
00445 //----------------------------------------------------------------------------
00446 int numChildMeshSets( const smoab::EntityHandle& root ) const
00447 {
00448 int numChildren;
00449 this->Moab->num_child_meshsets( root, &numChildren );
00450 return numChildren;
00451 }
00452
00453 //----------------------------------------------------------------------------
00454 smoab::Range getChildSets( const smoab::EntityHandle& root ) const
00455 {
00456 smoab::Range children;
00457 this->Moab->get_child_meshsets( root, children, 0 );
00458 return children;
00459 }
00460
00461 //----------------------------------------------------------------------------
00462 //remove a collection of entities from the database
00463 void remove( smoab::Range const& toDelete ) const
00464 {
00465 this->Moab->delete_entities( toDelete );
00466 }
00467
00468 //----------------------------------------------------------------------------
00469 //a entityHandle with value zero means no side element was found
00470 smoab::EntityHandle sideElement( smoab::EntityHandle const& cell, int dim, int side ) const
00471 {
00472 smoab::EntityHandle result( 0 );
00473 this->Moab->side_element( cell, dim, side, result );
00474 return result;
00475 }
00476
00477 //----------------------------------------------------------------------------
00478 //returns all the existing side elements of a cell, elements that
00479 //are zero mean that side element doesn't exist
00480 std::vector< smoab::EntityHandle > sideElements( smoab::EntityHandle const& cell, int dim ) const
00481 {
00482 const EntityType volumeCellType = this->Moab->type_from_handle( cell );
00483 const int numSides = static_cast< int >( moab::CN::NumSubEntities( volumeCellType, dim ) );
00484
00485 std::vector< smoab::EntityHandle > result( numSides );
00486 for( int side = 0; side < numSides; ++side )
00487 {
00488 smoab::EntityHandle* sideElem = &result[side]; //get memory of vector
00489 this->Moab->side_element( cell, dim, side, *sideElem );
00490 }
00491 return result;
00492 }
00493
00494 //----------------------------------------------------------------------------
00495 //prints all elements in a range objects
00496 void printRange( const smoab::Range& range ) const
00497 {
00498 typedef Range::const_iterator iterator;
00499 for( iterator i = range.begin(); i != range.end(); ++i )
00500 {
00501 std::cout << "entity id: " << *i << std::endl;
00502 this->Moab->list_entity( *i );
00503 }
00504 }
00505 friend class smoab::DataSetConverter;
00506 friend class smoab::detail::LoadGeometry;
00507 friend class smoab::detail::LoadPoly;
00508
00509 private:
00510 moab::Interface* Moab;
00511 };
00512
00513 //----------------------------------------------------------------------------
00514 void RangeToVector( const smoab::Range& range, std::vector< smoab::EntityHandle >& vector )
00515 {
00516 vector.reserve( range.size() );
00517 std::copy( range.begin(), range.end(), std::back_inserter( vector ) );
00518 }
00519
00520 } // namespace smoab
00521
00522 #endif