Sierra Toolkit Version of the Day
BulkData.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_BulkData_hpp
00010 #define stk_mesh_BulkData_hpp
00011 
00012 //----------------------------------------------------------------------
00013 
00014 #include <stk_util/parallel/Parallel.hpp>
00015 #include <stk_util/parallel/DistributedIndex.hpp>
00016 
00017 #include <stk_mesh/base/Types.hpp>
00018 #include <stk_mesh/base/Field.hpp>
00019 #include <stk_mesh/base/MetaData.hpp>
00020 #include <stk_mesh/base/Ghosting.hpp>
00021 #include <stk_mesh/base/Selector.hpp>
00022 #include <stk_mesh/base/Trace.hpp>
00023 
00024 #include <stk_mesh/baseImpl/EntityRepository.hpp>
00025 #include <stk_mesh/baseImpl/BucketRepository.hpp>
00026 
00027 #include <algorithm>
00028 #include <map>
00029 
00030 //----------------------------------------------------------------------
00031 
00032 namespace stk {
00033 namespace mesh {
00034 
00039 //----------------------------------------------------------------------
00048 class BulkData {
00049 public:
00050 
00051   inline static BulkData & get( const Bucket & bucket);
00052   inline static BulkData & get( const Entity & entity);
00053   inline static BulkData & get( const Ghosting & ghost);
00054 
00055   enum BulkDataSyncState { MODIFIABLE = 1 , SYNCHRONIZED = 2 };
00056 
00057   ~BulkData();
00058 
00066   BulkData( MetaData & mesh_meta_data ,
00067       ParallelMachine parallel ,
00068       unsigned bucket_max_size = 1000 );
00069 
00070   //------------------------------------
00072   const MetaData & mesh_meta_data() const { return m_mesh_meta_data ; }
00073 
00075   ParallelMachine parallel() const { return m_parallel_machine ; }
00076 
00078   unsigned parallel_size()   const { return m_parallel_size ; }
00079 
00081   unsigned parallel_rank()   const { return m_parallel_rank ; }
00082 
00083   //------------------------------------
00087   unsigned bucket_capacity() const { return m_bucket_repository.bucket_capacity(); }
00088 
00089   //------------------------------------
00094   BulkDataSyncState synchronized_state() const { return m_sync_state ; }
00095 
00100   size_t synchronized_count() const { return m_sync_count ; }
00101 
00113   bool modification_begin();
00114 
00132   bool modification_end();
00133 
00149   void change_entity_owner( const std::vector<EntityProc> & arg_change);
00150 
00162   void update_field_data_states() const { m_bucket_repository.update_field_data_states(); }
00163 
00170   void copy_entity_fields( const Entity & src, Entity & dest) {
00171     //TODO fix const correctness for src
00172     Entity & non_const_src = const_cast<Entity &>(src);
00173     m_bucket_repository.copy_fields(
00174         dest.bucket(),
00175         dest.bucket_ordinal(),
00176         non_const_src.bucket(),
00177         non_const_src.bucket_ordinal()
00178         );
00179   }
00180 
00181   //------------------------------------
00183   const std::vector<Bucket*> & buckets( EntityRank rank ) const
00184   { return m_bucket_repository.buckets(rank); }
00185 
00186 #ifndef SWIG //SRK
00187   AllBucketsRange get_bucket_range() const
00188   {
00189     return m_bucket_repository.get_bucket_range();
00190   }
00191 
00192   AllBucketsRange get_bucket_range( EntityRank rank ) const
00193   {
00194     return m_bucket_repository.get_bucket_range(rank);
00195   }
00196 #endif
00197 
00199   Entity * get_entity( EntityRank entity_rank , EntityId entity_id ) const {
00200     require_good_rank_and_id(entity_rank, entity_id);
00201     return m_entity_repo.get_entity( EntityKey(entity_rank, entity_id));
00202   }
00203 
00205   Entity * get_entity( const EntityKey key ) const  {
00206     return m_entity_repo.get_entity(key);
00207   }
00208 
00209   //------------------------------------
00223   Entity & declare_entity( EntityRank ent_rank ,
00224       EntityId ent_id , const PartVector& parts);
00225 
00235   void change_entity_parts( Entity & entity,
00236       const PartVector & add_parts ,
00237       const PartVector & remove_parts = PartVector() )
00238   {
00239     change_entity_parts(entity,
00240                         add_parts.begin(), add_parts.end(),
00241                         remove_parts.begin(), remove_parts.end());
00242   }
00243 
00244   template<typename AddIterator, typename RemoveIterator>
00245   void change_entity_parts( Entity & entity,
00246                             AddIterator begin_add_parts, AddIterator end_add_parts,
00247                             RemoveIterator begin_remove_parts, RemoveIterator end_remove_parts );
00248 
00282   bool destroy_entity( Entity * & entity );
00283 
00284   //------------------------------------
00285 
00295   void generate_new_entities(const std::vector<size_t>& requests,
00296       std::vector<Entity *>& requested_entities);
00297 
00298   //------------------------------------
00318   void declare_relation( Entity & e_from ,
00319       Entity & e_to ,
00320       const RelationIdentifier local_id );
00321 
00325   void declare_relation( Entity & entity, const std::vector<Relation> & rel);
00326 
00341   bool destroy_relation( Entity & e_from ,
00342                          Entity & e_to,
00343                          const RelationIdentifier local_id );
00344 
00345   //------------------------------------
00346   //------------------------------------
00348   const std::vector<Entity*> & entity_comm() const
00349     { return m_entity_comm ; }
00350 
00351   //------------------------------------
00356   Ghosting & shared_aura() const { return * m_ghosting[1] ; }
00357 
00363   Ghosting & create_ghosting( const std::string & name );
00364 
00382   void change_ghosting( Ghosting & ghosts,
00383                         const std::vector<EntityProc> & add_send ,
00384                         const std::vector<Entity*> & remove_receive );
00385 
00390   void destroy_all_ghosting();
00391 
00393   const std::vector<Ghosting*> & ghostings() const { return m_ghosting ; }
00394 
00395 private:
00396 
00398   MetaData & meta_data() const { return m_mesh_meta_data ; }
00399 
00400 #ifndef DOXYGEN_COMPILE
00401 
00402   BulkData();
00403   BulkData( const BulkData & );
00404   BulkData & operator = ( const BulkData & );
00405 
00407   parallel::DistributedIndex          m_entities_index ;
00408   impl::EntityRepository              m_entity_repo ;
00409   impl::BucketRepository              m_bucket_repository ;
00410   std::vector<Entity*>                m_entity_comm ;
00411   std::vector<Ghosting*>              m_ghosting ; 
00413   // Other information:
00414   MetaData &   m_mesh_meta_data ;
00415   ParallelMachine    m_parallel_machine ;
00416   unsigned           m_parallel_size ;
00417   unsigned           m_parallel_rank ;
00418   size_t             m_sync_count ;
00419   BulkDataSyncState  m_sync_state ;
00420   bool               m_meta_data_verified ;
00421 
00426   unsigned determine_new_owner( Entity & ) const ;
00427 
00428   /*  Entity modification consequences:
00429    *  1) Change entity relation => update via part relation => change parts
00430    *  2) Change parts => update forward relations via part relation
00431    *                  => update via field relation
00432    */
00433   void internal_change_entity_parts( Entity & ,
00434                                      const PartVector & add_parts ,
00435                                      const PartVector & remove_parts );
00436 
00437   void internal_propagate_part_changes( Entity & entity, const PartVector & removed );
00438 
00439   void internal_change_ghosting( Ghosting & ghosts,
00440                                  const std::vector<EntityProc> & add_send ,
00441                                  const std::vector<Entity*> & remove_receive );
00442 
00443   bool internal_modification_end( bool regenerate_aura );
00444     void internal_resolve_shared_modify_delete();
00445     void internal_resolve_shared_modify_delete_second_pass();
00446     void internal_resolve_ghosted_modify_delete();
00447     void internal_resolve_parallel_create();
00448     void internal_resolve_shared_membership();
00449 
00450   void internal_update_distributed_index( std::vector<Entity*> & shared_new );
00451 
00457   void internal_regenerate_shared_aura();
00458 
00459   // Returns false if there is a problem. It is expected that
00460   // verify_change_parts will be called if quick_verify_change_part detects
00461   // a problem, therefore we leave the generation of an exception to
00462   // verify_change_parts. We want this function to be as fast as
00463   // possible.
00464   inline bool internal_quick_verify_change_part(const Entity& entity,
00465                                                 const Part* part,
00466                                                 const unsigned entity_rank,
00467                                                 const unsigned undef_rank) const;
00468 
00469   void internal_verify_change_parts( const MetaData   & meta ,
00470                                      const Entity     & entity ,
00471                                      const PartVector & parts ) const;
00472 
00473   //------------------------------------
00474 
00480   void require_ok_to_modify() const ;
00481 
00482   void require_entity_owner( const Entity & entity, unsigned owner) const ;
00483 
00484   void require_metadata_committed() const;
00485 
00486   void require_good_rank_and_id(EntityRank ent_rank, EntityId ent_id) const;
00487 
00488   void require_valid_relation( const char action[] ,
00489                                const BulkData & mesh ,
00490                                const Entity   & e_from ,
00491                                const Entity   & e_to );
00492 
00495   //------------------------------------
00496 
00497   // FIXME: Remove this friend once unit-testing has been refactored
00498   friend class UnitTestModificationEndWrapper;
00499   friend class ::stk::mesh::MetaData;
00500 #endif /* DOXYGEN_COMPILE */
00501 };
00502 
00503 BulkData & BulkData::get( const Bucket & bucket) {
00504   return bucket.bulk_data();
00505 }
00506 
00507 BulkData & BulkData::get( const Entity & entity) {
00508   return BulkData::get(entity.bucket());
00509 }
00510 
00511 BulkData & BulkData::get( const Ghosting & ghost) {
00512   return ghost.bulk_data();
00513 }
00514 
00521 // TODO - Does this need to be in the public API? It's only used internally.
00522 // In what context would a client ever call this?
00523 void set_field_relations( Entity & e_from ,
00524                           Entity & e_to ,
00525                           const unsigned ident );
00526 
00527 inline bool BulkData::internal_quick_verify_change_part(const Entity& entity,
00528                                                         const Part* part,
00529                                                         const unsigned entity_rank,
00530                                                         const unsigned undef_rank) const
00531 {
00532   const unsigned part_rank = part->primary_entity_rank();
00533 
00534   // The code below is coupled with the code in verify_change_parts. If we
00535   // change what it means for a part to be valid, code will need to be
00536   // changed in both places unfortunately.
00537   const bool intersection_ok = part->intersection_of().empty();
00538   const bool rel_target_ok   = ( part->relations().empty() ||
00539                                  part != part->relations().begin()->m_target );
00540   const bool rank_ok         = ( entity_rank == part_rank ||
00541                                  undef_rank  == part_rank );
00542 
00543   return intersection_ok && rel_target_ok && rank_ok;
00544 }
00545 
00546 template<typename AddIterator, typename RemoveIterator>
00547 void BulkData::change_entity_parts( Entity & entity,
00548                                     AddIterator begin_add_parts, AddIterator end_add_parts,
00549                                     RemoveIterator begin_remove_parts, RemoveIterator end_remove_parts )
00550 {
00551   TraceIfWatching("stk::mesh::BulkData::change_entity_parts", LOG_ENTITY, entity.key());
00552   DiagIfWatching(LOG_ENTITY, entity.key(), "entity state: " << entity);
00553   //DiagIfWatching(LOG_ENTITY, entity.key(), "add_parts: " << add_parts);
00554   //DiagIfWatching(LOG_ENTITY, entity.key(), "remove_parts: " << remove_parts);
00555 
00556   require_ok_to_modify();
00557 
00558   require_entity_owner( entity , m_parallel_rank );
00559 
00560   const EntityRank entity_rank = entity.entity_rank();
00561   const EntityRank undef_rank  = InvalidEntityRank;
00562 
00563   // Transitive addition and removal:
00564   // 1) Include supersets of add_parts
00565   // 2) Do not include a remove_part if it appears in the add_parts
00566   // 3) Include subsets of remove_parts
00567 
00568   // most parts will at least have universal and topology part as supersets
00569   const unsigned expected_min_num_supersets = 2;
00570 
00571   PartVector a_parts;
00572   a_parts.reserve( std::distance(begin_add_parts, end_add_parts) * (expected_min_num_supersets + 1) );
00573   a_parts.insert( a_parts.begin(), begin_add_parts, end_add_parts );
00574   bool quick_verify_check = true;
00575 
00576   for ( AddIterator ia = begin_add_parts; ia != end_add_parts ; ++ia ) {
00577     quick_verify_check = quick_verify_check &&
00578       internal_quick_verify_change_part(entity, *ia, entity_rank, undef_rank);
00579     a_parts.insert( a_parts.end(), (*ia)->supersets().begin(),
00580                                    (*ia)->supersets().end() );
00581   }
00582 
00583   order( a_parts );
00584 
00585   PartVector r_parts ;
00586 
00587   for ( RemoveIterator ir = begin_remove_parts; ir != end_remove_parts ; ++ir ) {
00588 
00589     // The following guards should be in the public interface to
00590     // changing parts.  However, internal mechanisms such as changing
00591     // ownership calls this function to add or remove an entity from
00592     // the three special parts.  Without refactoring, these guards
00593     // cannot be put in place.
00594     /*
00595     ThrowErrorMsgIf( m_mesh_meta_data.universal_part() == **ir,
00596                      "Cannot remove entity from universal part" );
00597     ThrowErrorMsgIf( m_mesh_meta_data.locally_owned_part() == **ir,
00598                      "Cannot remove entity from locally owned part" );
00599     ThrowErrorMsgIf( m_mesh_meta_data.globally_shared_part() == **ir,
00600                      "Cannot remove entity from globally shared part" );
00601     */
00602 
00603     quick_verify_check = quick_verify_check &&
00604       internal_quick_verify_change_part(entity, *ir, entity_rank, undef_rank);
00605 
00606     if ( ! contain( a_parts , **ir ) ) {
00607       r_parts.push_back( *ir );
00608       for ( PartVector::const_iterator  cur_part = (*ir)->subsets().begin() ;
00609             cur_part != (*ir)->subsets().end() ;
00610             ++cur_part )
00611         if ( entity.bucket().member ( **cur_part ) )
00612           r_parts.push_back ( *cur_part );
00613     }
00614   }
00615 
00616   order( r_parts );
00617 
00618   // If it looks like we have a problem, run the full check and we should
00619   // expect to see an exception thrown; otherwise, only do the full check in
00620   // debug mode because it incurs significant overhead.
00621   if ( ! quick_verify_check ) {
00622     internal_verify_change_parts( m_mesh_meta_data , entity , a_parts );
00623     internal_verify_change_parts( m_mesh_meta_data , entity , r_parts );
00624     ThrowRequireMsg(false, "Expected throw from verify methods above.");
00625   }
00626   else {
00627 #ifndef NDEBUG
00628     internal_verify_change_parts( m_mesh_meta_data , entity , a_parts );
00629     internal_verify_change_parts( m_mesh_meta_data , entity , r_parts );
00630 #endif
00631   }
00632 
00633   internal_change_entity_parts( entity , a_parts , r_parts );
00634 
00635   return ;
00636 }
00637 
00638 } // namespace mesh
00639 } // namespace stk
00640 
00641 //----------------------------------------------------------------------
00642 //----------------------------------------------------------------------
00643 
00644 #endif //  stk_mesh_BulkData_hpp
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends