Sierra Toolkit Version of the Day
Entity.hpp
00001 /*------------------------------------------------------------------------*/
00002 /*                 Copyright 2010 Sandia Corporation.                     */
00003 /*  Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive   */
00004 /*  license for use of this work by or on behalf of the U.S. Government.  */
00005 /*  Export of this program may require a license from the                 */
00006 /*  United States Government.                                             */
00007 /*------------------------------------------------------------------------*/
00008 
00009 #ifndef stk_mesh_base_Entity_hpp
00010 #define stk_mesh_base_Entity_hpp
00011 
00012 #include <utility>
00013 #include <vector>
00014 #include <iosfwd>
00015 #include <string>
00016 
00017 #include <stk_mesh/base/Types.hpp>
00018 
00019 #include <stk_mesh/baseImpl/EntityImpl.hpp>
00020 
00021 #include <boost/range.hpp>
00022 
00023 #ifdef SIERRA_MIGRATION
00024 #include <stk_mesh/base/Relation.hpp>
00025 
00026 namespace stk {
00027 namespace mesh {
00028 typedef RelationVector::const_iterator   RelationIterator;
00029 typedef boost::iterator_range<RelationIterator> RelationRange;
00030 class Entity;
00031 
00032 //On a *strictly temporary* basis, we need to stick the following
00033 //fmwk stuff on an entity, just to help us through the sierra migration.
00034 //Move along folks, there's nothing to see here.
00035 struct fmwk_attributes {
00036   // Each member has an explanation of why it can't be handled by Entity.
00037 
00038   // Relations of this mesh object that can't be managed by STK such as PARENT/CHILD
00039   RelationVector aux_relations;
00040 
00041   // Not a supported STK_Mesh concept
00042   const void*           shared_attr;
00043 
00044   // Cannot just use the id embedded in the entity-key because of negative global-ids
00045   // for temporaries.
00046   int                   global_id;
00047 
00048   // Can't use STK_Mesh's notion of this entity's owner because STK_Mesh is being used
00049   // in serial mode and therefore every process will thinks it owns everything.
00050   int                   owner;
00051 
00052   // Not a supported STK_Mesh concept
00053   unsigned short        connect_count;
00054 };
00055 
00056 }
00057 }
00058 
00059 namespace sierra {
00060 namespace Fmwk {
00061 
00062 class MeshObjRoster;
00063 class MeshObjSharedAttr;
00064 class MeshBulkData;
00065 
00066 extern const unsigned int INVALID_LOCAL_ID;
00067 extern const stk::mesh::RelationIterator INVALID_RELATION_ITR;
00068 
00069 namespace detail {
00070 bool set_attributes( stk::mesh::Entity & , const int , const MeshObjSharedAttr*, const int);
00071 bool set_attributes( stk::mesh::Entity & , const MeshObjSharedAttr*, const int);
00072 void unset_shared_attr(stk::mesh::Entity& );
00073 }
00074 
00075 namespace roster_only {
00076 void destroy_meshobj(stk::mesh::Entity*);
00077 void set_shared_attr(stk::mesh::Entity&, const MeshObjSharedAttr*);
00078 }
00079 
00080 const MeshObjSharedAttr * get_shared_attr(const stk::mesh::Entity&);
00081 bool insert_relation( stk::mesh::Entity * const, const stk::mesh::Relation::RelationType, stk::mesh::Entity * const, const unsigned, const unsigned, const bool, MeshBulkData &);
00082 bool remove_relation(stk::mesh::Entity &, const stk::mesh::RelationIterator, MeshBulkData &);
00083 bool verify_relations(const stk::mesh::Entity &);
00084 }
00085 }
00086 #endif
00087 
00088 namespace stk {
00089 namespace mesh {
00090 
00091 namespace impl {
00092 
00093 class EntityRepository;
00094 class BucketRepository;
00095 
00096 }
00097 
00102 //----------------------------------------------------------------------
00103 
00104 //----------------------------------------------------------------------
00120 class Entity {
00121 public:
00122   ~Entity() {}
00123 
00125   EntityModificationLog log_query() const { return m_entityImpl.log_query(); }
00126 
00128   EntityRank entity_rank() const { return m_entityImpl.entity_rank(); }
00129 
00133   EntityId identifier() const { return m_entityImpl.identifier(); }
00134 
00138   const EntityKey & key() const { return m_entityImpl.key(); }
00139 
00141   Bucket & bucket() const { return m_entityImpl.bucket(); }
00142   Bucket * bucket_ptr() const { return m_entityImpl.bucket_ptr(); }
00143 
00145   unsigned bucket_ordinal() const { return m_entityImpl.bucket_ordinal(); }
00146 
00154   size_t synchronized_count() const { return m_entityImpl.synchronized_count(); }
00155 
00156   //------------------------------------
00161   PairIterRelation relations() const { return m_entityImpl.relations(); }
00162 
00166   PairIterRelation relations( EntityRank type ) const { return m_entityImpl.relations(type); }
00167   PairIterRelation node_relations() const { return m_entityImpl.node_relations(); }
00168 
00169 #ifdef SIERRA_MIGRATION
00170   RelationIterator node_relation(unsigned ordinal) const { return m_entityImpl.node_relation(ordinal); }
00171 #endif
00172 
00173   //------------------------------------
00175   unsigned owner_rank() const { return m_entityImpl.owner_rank(); }
00176 
00178   PairIterEntityComm sharing() const { return m_entityImpl.sharing(); }
00179 
00181   PairIterEntityComm comm() const { return m_entityImpl.comm(); }
00182 
00184   PairIterEntityComm comm( const Ghosting & sub ) const { return m_entityImpl.comm( sub ); }
00185 
00186 //  RelationVector& rel_vec() { return m_entityImpl.rel_vec(); }
00187   void compress_relation_capacity();
00188 
00189 private:
00190 
00191   void set_key(const EntityKey& arg_key) { m_entityImpl.set_key(arg_key); }
00192 
00193   impl::EntityImpl m_entityImpl;
00194 
00195   explicit Entity( const EntityKey & arg_key );
00196 
00197   Entity();
00198   Entity & operator = ( const Entity & ); 
00199 
00200 #ifndef DOXYGEN_COMPILE
00201   friend class impl::EntityRepository ;
00202   friend class impl::EntityImpl ;
00203 #endif /* DOXYGEN_COMPILE */
00204 
00205 
00206 
00207 // Issue: We began the migration of Fmwk MeshObj with an implementation that
00208 // had a stk entity pointer underneath the MeshObj that could be used to manage
00209 // the state that stk entities can manage while leaving the rest to MeshObj.
00210 // This proved to be a performance killer since many operations required an
00211 // extra dereference (the entity pointer) compared to before, causing lots of
00212 // additional cache misses even for simple operations.
00213 //
00214 // The solution is similar to what we did with Relation; we will use the preprocessor
00215 // to add in the Fmwk pieces of the class API when the class is being compiled
00216 // with Sierra.
00217 #ifdef SIERRA_MIGRATION
00218  public:
00219   friend class sierra::Fmwk::MeshObjRoster;
00220   // These are free functions to facilitate the stk migration:
00221   friend const sierra::Fmwk::MeshObjSharedAttr * sierra::Fmwk::get_shared_attr(const Entity &);
00222   friend bool sierra::Fmwk::detail::set_attributes( Entity &, const int, const sierra::Fmwk::MeshObjSharedAttr *, const int);
00223   friend bool sierra::Fmwk::detail::set_attributes( Entity &, const sierra::Fmwk::MeshObjSharedAttr *, const int);
00224   friend void sierra::Fmwk::detail::unset_shared_attr(Entity &);
00225   friend bool sierra::Fmwk::insert_relation( Entity * const, const stk::mesh::Relation::RelationType, Entity * const, const unsigned, const unsigned, const bool, sierra::Fmwk::MeshBulkData &);
00226   friend bool sierra::Fmwk::remove_relation(Entity &, const stk::mesh::RelationIterator, sierra::Fmwk::MeshBulkData &);
00227   friend bool sierra::Fmwk::verify_relations(const Entity &);
00228   friend void sierra::Fmwk::roster_only::destroy_meshobj(stk::mesh::Entity*);
00229   friend void sierra::Fmwk::roster_only::set_shared_attr(stk::mesh::Entity&, const sierra::Fmwk::MeshObjSharedAttr*);
00230 
00231   typedef unsigned DerivedType; 
00232 
00236   enum ObjectTypeEnum {
00237     NODE = 0, EDGE = 1, FACE = 2, ELEMENT = 3, CONSTRAINT = 4, NUM_TYPES = 5, BASE_CLASS = 0x00ff
00238   };
00239   static std::string TypeToString (ObjectTypeEnum type);
00240 
00241 
00242 
00243   template <class SharedAttr>
00244   void init_fmwk(
00245     const int         id,
00246     const SharedAttr* attr,
00247     const int         owner,
00248     const int         parallel_rank,
00249     const int         parallel_size)
00250   {
00251     ThrowAssertMsg(aux_relations().capacity() == 0, "Leftover memory found in relation vector");
00252 
00253     m_fmwk_attrs->global_id     = id;
00254     m_fmwk_attrs->shared_attr   = attr;
00255     m_fmwk_attrs->owner         = owner;
00256     m_fmwk_attrs->connect_count = 0;
00257     m_local_id                  = sierra::Fmwk::INVALID_LOCAL_ID;
00258 
00259     if (attr->locally_owned() && owner_processor_rank() == -1) {
00260       m_fmwk_attrs->owner = parallel_rank;
00261       ThrowAssert(owner_processor_rank() < parallel_size);
00262     }
00263 
00264     internal_verify_initialization_invariant();
00265   }
00266 
00270   int global_id() const {
00271     return m_fmwk_attrs->global_id;
00272   }
00273 
00287   inline unsigned local_id() const { return m_local_id; }
00288   void set_local_id(unsigned int l_id) { m_local_id = l_id; }
00289 
00290   int owner_processor_rank() const { return m_fmwk_attrs->owner; }
00291   void set_owner_processor_rank(int owner) { m_fmwk_attrs->owner = owner; }
00292 
00299   unsigned size_connection() const {
00300     return m_fmwk_attrs->connect_count;
00301   }
00302 
00306   unsigned inc_connection() {
00307     ++m_fmwk_attrs->connect_count;
00308     ThrowAssert(m_fmwk_attrs->connect_count /* Did not roll over */);
00309     return m_fmwk_attrs->connect_count;
00310   }
00311 
00315   unsigned dec_connection() {
00316     ThrowAssert(m_fmwk_attrs->connect_count /* Will not roll-under */);
00317     --m_fmwk_attrs->connect_count;
00318     return m_fmwk_attrs->connect_count;
00319   }
00320 
00321   RelationIterator aux_relation_begin() const { return m_fmwk_attrs->aux_relations.begin(); }
00322   RelationIterator aux_relation_end() const { return m_fmwk_attrs->aux_relations.end(); }
00323 
00324   RelationVector& aux_relations() { return m_fmwk_attrs->aux_relations; }
00325 
00330   RelationIterator internal_begin_relation(const Relation::RelationType relation_type) const {
00331     if (internal_is_handled_generically(relation_type)) {
00332       return relations().first;
00333     }
00334     else {
00335       return aux_relation_begin();
00336     }
00337   }
00338 
00343   RelationIterator internal_end_relation(const Relation::RelationType relation_type) const {
00344     if (internal_is_handled_generically(relation_type)) {
00345       return relations().second;
00346     }
00347     else {
00348       return aux_relation_end();
00349     }
00350   }
00351 
00352   void set_shared_attr(const void* attr) { m_fmwk_attrs->shared_attr = attr; }
00353   const void* get_shared_attr() const { return m_fmwk_attrs->shared_attr; }
00354 
00355   // TODO: Refactor clients so that this method is no longer needed
00356   void set_relation_orientation(RelationIterator rel, unsigned orientation);
00357 
00358  private:
00359 
00367   void reserve_relation(const unsigned num);
00368 
00377   bool update_relation(const RelationIterator ir, const bool back_rel_flag) const;
00378 
00379   RelationIterator find_relation(const Relation& relation) const;
00380 
00381   void erase_and_clear_if_empty(RelationIterator rel_itr);
00382 
00383   void internal_verify_meshobj_invariant() const;
00384 
00385   void internal_swap_in_real_entity(const int globalId);
00386 
00387   void internal_verify_initialization_invariant() {
00388     // If this MeshObj has a proper ID (fully initialized), then the id should match
00389     // the id in the entity-key; otherwise they should not match.
00390     ThrowAssert( !(m_fmwk_attrs->global_id < 0 && key().id() == static_cast<uint64_t>(m_fmwk_attrs->global_id)) &&
00391                  !(m_fmwk_attrs->global_id > 0 && key().id() != static_cast<uint64_t>(m_fmwk_attrs->global_id)) );
00392 
00393   }
00394 
00395   unsigned stk_entity_rank() const { return key().rank(); }
00396 
00397   bool internal_is_handled_generically(const Relation::RelationType relation_type) const
00398   {
00399     return relation_type == Relation::USES || relation_type == Relation::USED_BY;
00400   }
00401 
00402   //
00403   // Members needed to support Fmwk_MeshObj API
00404   //
00405 
00406   fmwk_attributes* m_fmwk_attrs;
00407 
00408   // Not a supported STK_Mesh concept, but fmwk requires it. We have it
00409   // here instead of in m_fmwk_attrs for performance reasons (saves a
00410   // memory hop when accessing local_id).
00411   unsigned m_local_id;
00412 #endif
00413 };
00414 
00415 #ifdef SIERRA_MIGRATION
00416 
00417 inline
00418 Relation::RelationType
00419 back_relation_type(const Relation::RelationType relType)
00420 {
00421   /* %TRACE[NONE]% */  /* %TRACE% */
00422   switch(relType) {
00423   case Relation::USES:
00424     return Relation::USED_BY;
00425   case Relation::USED_BY:
00426     return Relation::USES;
00427   case Relation::CHILD:
00428     return Relation::PARENT;
00429   case Relation::PARENT:
00430     return Relation::CHILD;
00431   default:
00432     return relType;
00433   }
00434 }
00435 
00436 // Made publicly available so that MeshObj.C can use it
00437 template <class Iterator>
00438 bool
00439 verify_relation_ordering(Iterator begin, Iterator end)
00440 {
00441   for (Iterator itr = begin; itr != end; ) {
00442     Iterator prev = itr;
00443     ++itr;
00444     if (itr != end) {
00445 
00446       if (itr->entity_rank() < prev->entity_rank()) {
00447         return false ;
00448       }
00449 
00450       if (itr->entity_rank() == prev->entity_rank()) {
00451 
00452         if (itr->getRelationType() < prev->getRelationType()) {
00453           return false ;
00454         }
00455 
00456         if (itr->getRelationType() == prev->getRelationType()) {
00457 
00458           if (itr->getOrdinal() < prev->getOrdinal()) {
00459             return false ;
00460           }
00461         }
00462       }
00463     }
00464   }
00465   return true ;
00466 }
00467 
00468 template <class Range>
00469 bool
00470 verify_relation_ordering(Range range)
00471 {
00472   return verify_relation_ordering(boost::const_begin(range), boost::const_end(range));
00473 }
00474 
00475 #endif
00476 
00478 class EntityLess {
00479 public:
00480   ~EntityLess() {}
00481   EntityLess() {}
00482   EntityLess( const EntityLess & ) {}
00483   EntityLess & operator = ( const EntityLess & ) { return *this ; }
00484 
00486   bool operator()(const Entity& lhs, const Entity& rhs) const
00487   { return lhs.key() < rhs.key(); }
00488 
00489   bool operator()(const Entity& lhs, const EntityKey & rhs) const
00490   { return lhs.key() < rhs ; }
00491 
00493   bool operator()(const Entity* lhs, const Entity* rhs) const
00494   {
00495     const EntityKey lhs_key = lhs ? lhs->key() : EntityKey() ;
00496     const EntityKey rhs_key = rhs ? rhs->key() : EntityKey() ;
00497     return lhs_key < rhs_key ;
00498   }
00499 
00500   bool operator()(const Entity* lhs, const Entity& rhs) const
00501   {
00502     const EntityKey lhs_key = lhs ? lhs->key() : EntityKey();
00503     return lhs_key < rhs.key() ;
00504   }
00505 
00506   bool operator()(const Entity& lhs, const Entity* rhs) const
00507   {
00508     const EntityKey rhs_key = rhs ? rhs->key() : EntityKey();
00509     return lhs.key() < rhs_key ;
00510   }
00511 
00512   bool operator()(const Entity* lhs, const EntityKey & rhs) const
00513   {
00514     const EntityKey lhs_key = lhs ? lhs->key() : EntityKey() ;
00515     return lhs_key < rhs ;
00516   }
00517 
00518   bool operator()( const EntityProc & lhs, const EntityProc & rhs) const
00519   {
00520     const EntityKey lhs_key = lhs.first ? lhs.first->key() : EntityKey() ;
00521     const EntityKey rhs_key = rhs.first ? rhs.first->key() : EntityKey() ;
00522     return lhs_key != rhs_key ? lhs_key < rhs_key : lhs.second < rhs.second ;
00523   }
00524 
00525   bool operator()( const EntityProc & lhs, const Entity & rhs) const
00526   {
00527     const EntityKey lhs_key = lhs.first ? lhs.first->key() : EntityKey() ;
00528     return lhs_key < rhs.key();
00529   }
00530 
00531   bool operator()( const EntityProc & lhs, const Entity * rhs) const
00532   {
00533     const EntityKey lhs_key = lhs.first ? lhs.first->key() : EntityKey() ;
00534     const EntityKey rhs_key = rhs       ? rhs->key() : EntityKey() ;
00535     return lhs_key < rhs_key ;
00536   }
00537 
00538   bool operator()( const EntityProc & lhs, const EntityKey & rhs) const
00539   {
00540     const EntityKey lhs_key = lhs.first ? lhs.first->key() : EntityKey() ;
00541     return lhs_key < rhs ;
00542   }
00543 
00544 }; //class EntityLess
00545 
00546 class EntityEqual
00547 {
00548 public:
00549   bool operator()(const stk::mesh::Entity* lhs, const stk::mesh::Entity* rhs) const
00550   {
00551     const stk::mesh::EntityKey lhs_key = lhs ? lhs->key() : stk::mesh::EntityKey();
00552     const stk::mesh::EntityKey rhs_key = rhs ? rhs->key() : stk::mesh::EntityKey();
00553     return lhs_key == rhs_key;
00554   }
00555 
00556   bool operator()(const stk::mesh::Entity& lhs, const stk::mesh::Entity& rhs) const
00557   {
00558     const stk::mesh::EntityKey lhs_key = lhs.key();
00559     const stk::mesh::EntityKey rhs_key = rhs.key();
00560     return lhs_key == rhs_key;
00561   }
00562 };
00563 
00564 std::string print_entity_key(const Entity& entity);
00565 
00566 std::string print_entity_key(const Entity* entity);
00567 
00568 inline
00569 Entity::Entity()
00570   : m_entityImpl()
00571 #ifdef SIERRA_MIGRATION
00572    , m_fmwk_attrs(NULL)
00573 #endif
00574 {}
00575 
00576 inline
00577 Entity::Entity( const EntityKey & arg_key )
00578   : m_entityImpl( arg_key )
00579 #ifdef SIERRA_MIGRATION
00580    , m_fmwk_attrs(NULL)
00581 #endif
00582 {}
00583 
00586 } // namespace mesh
00587 } // namespace stk
00588 
00589 #endif /* stk_mesh_base_Entity_hpp */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines