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 #include <stk_mesh/base/EntityComm.hpp>
00024 
00025 #include <stk_mesh/baseImpl/EntityRepository.hpp>
00026 #include <stk_mesh/baseImpl/BucketRepository.hpp>
00027 
00028 #include <algorithm>
00029 #include <map>
00030 
00031 //----------------------------------------------------------------------
00032 
00033 namespace stk {
00034 namespace mesh {
00035 
00040 //----------------------------------------------------------------------
00049 class BulkData {
00050 public:
00051 
00052   void optimize_buckets_at_modification_end(bool b) { m_optimize_buckets = b; }
00053 
00054   inline static BulkData & get( const Bucket & bucket);
00055   inline static BulkData & get( const Entity & entity);
00056   inline static BulkData & get( const Ghosting & ghost);
00057 
00058   enum BulkDataSyncState { MODIFIABLE = 1 , SYNCHRONIZED = 2 };
00059 
00060   ~BulkData();
00061 
00069   BulkData( MetaData & mesh_meta_data ,
00070       ParallelMachine parallel ,
00071       unsigned bucket_max_size = 1000 ,
00072       bool use_memory_pool = true );
00073 
00074   //------------------------------------
00076   const MetaData & mesh_meta_data() const { return m_mesh_meta_data ; }
00077 
00079   ParallelMachine parallel() const { return m_parallel_machine ; }
00080 
00082   unsigned parallel_size()   const { return m_parallel_size ; }
00083 
00085   unsigned parallel_rank()   const { return m_parallel_rank ; }
00086 
00087   //------------------------------------
00092   BulkDataSyncState synchronized_state() const { return m_sync_state ; }
00093 
00098   size_t synchronized_count() const { return m_sync_count ; }
00099 
00111   bool modification_begin();
00112 
00130   bool modification_end();
00131 
00132   bool final_modification_end()
00133   {
00134     optimize_buckets_at_modification_end(true);
00135     const bool mod_flag =  modification_end();
00136 
00137     //call modification_begin and end one last time to free deleted entities
00138     modification_begin();
00139     modification_end();
00140 
00141     m_mesh_finalized = true;
00142 
00143     return mod_flag;
00144   }
00145 
00161   void change_entity_owner( const std::vector<EntityProc> & arg_change);
00162 
00174   void update_field_data_states() const { m_bucket_repository.update_field_data_states(); }
00175 
00182   void copy_entity_fields( const Entity & src, Entity & dest) {
00183     //TODO fix const correctness for src
00184     Entity & non_const_src = const_cast<Entity &>(src);
00185     m_bucket_repository.copy_fields(
00186         dest.bucket(),
00187         dest.bucket_ordinal(),
00188         non_const_src.bucket(),
00189         non_const_src.bucket_ordinal()
00190         );
00191   }
00192 
00193   //------------------------------------
00195   const std::vector<Bucket*> & buckets( EntityRank rank ) const
00196   { return m_bucket_repository.buckets(rank); }
00197 
00198 #ifndef SWIG //SRK
00199   AllBucketsRange get_bucket_range() const
00200   {
00201     return m_bucket_repository.get_bucket_range();
00202   }
00203 
00204   AllBucketsRange get_bucket_range( EntityRank rank ) const
00205   {
00206     return m_bucket_repository.get_bucket_range(rank);
00207   }
00208 #endif
00209 
00211   Entity * get_entity( EntityRank entity_rank , EntityId entity_id ) const {
00212     require_good_rank_and_id(entity_rank, entity_id);
00213     return m_entity_repo.get_entity( EntityKey(entity_rank, entity_id));
00214   }
00215 
00217   Entity * get_entity( const EntityKey key ) const  {
00218     return m_entity_repo.get_entity(key);
00219   }
00220 
00221   //------------------------------------
00235   Entity & declare_entity( EntityRank ent_rank ,
00236       EntityId ent_id , const PartVector& parts);
00237 
00238   void change_entity_id( EntityId id, Entity & entity);
00239 
00249   void change_entity_parts( Entity & entity,
00250       const PartVector & add_parts ,
00251       const PartVector & remove_parts = PartVector() )
00252   {
00253     change_entity_parts(entity,
00254                         add_parts.begin(), add_parts.end(),
00255                         remove_parts.begin(), remove_parts.end());
00256   }
00257 
00258 //Optional parameter 'always_propagate_internal_changes' is always true except when this function
00259 //is being called from the sierra-framework. The fmwk redundantly does its own propagation of the
00260 //internal part changes (mostly induced-part stuff), so it's a performance optimization to avoid
00261 //the propagation that stk-mesh does.
00262   template<typename AddIterator, typename RemoveIterator>
00263   void change_entity_parts( Entity & entity,
00264                             AddIterator begin_add_parts, AddIterator end_add_parts,
00265                             RemoveIterator begin_remove_parts, RemoveIterator end_remove_parts,
00266                             bool always_propagate_internal_changes=true );
00267 
00301   bool destroy_entity( Entity * & entity );
00302 
00303   //------------------------------------
00304 
00314   void generate_new_entities(const std::vector<size_t>& requests,
00315       std::vector<Entity *>& requested_entities);
00316 
00317   //------------------------------------
00337   void declare_relation( Entity & e_from ,
00338       Entity & e_to ,
00339       const RelationIdentifier local_id );
00340 
00344   void declare_relation( Entity & entity, const std::vector<Relation> & rel);
00345 
00360   bool destroy_relation( Entity & e_from ,
00361                          Entity & e_to,
00362                          const RelationIdentifier local_id );
00363 
00364   //------------------------------------
00365   //------------------------------------
00367   const std::vector<Entity*> & entity_comm() const
00368     { return m_entity_comm ; }
00369 
00370   //------------------------------------
00375   Ghosting & shared_aura() const { return * m_ghosting[1] ; }
00376 
00382   Ghosting & create_ghosting( const std::string & name );
00383 
00401   void change_ghosting( Ghosting & ghosts,
00402                         const std::vector<EntityProc> & add_send ,
00403                         const std::vector<Entity*> & remove_receive );
00404 
00409   void destroy_all_ghosting();
00410 
00412   const std::vector<Ghosting*> & ghostings() const { return m_ghosting ; }
00413 
00418   PairIterEntityComm entity_comm(const EntityKey & key) const { return m_entity_comm_map.comm(key); }
00419   PairIterEntityComm entity_comm_sharing(const EntityKey & key) const { return m_entity_comm_map.sharing(key); }
00420   PairIterEntityComm entity_comm(const EntityKey & key, const Ghosting & sub ) const { return m_entity_comm_map.comm(key,sub); }
00421   bool entity_comm_insert( const EntityKey & key, const EntityCommInfo & val) { return m_entity_comm_map.insert(key,val); }
00422   bool entity_comm_erase(  const EntityKey & key, const EntityCommInfo & val) { return m_entity_comm_map.erase(key,val); }
00423   bool entity_comm_erase(  const EntityKey & key, const Ghosting & ghost) { return m_entity_comm_map.erase(key,ghost); }
00424   void entity_comm_clear_ghosting(const EntityKey & key ) { m_entity_comm_map.comm_clear_ghosting(key); }
00425   void entity_comm_clear(const EntityKey & key) { m_entity_comm_map.comm_clear(key); }
00426   void entity_comm_swap(const EntityKey & key1, const EntityKey & key2) { m_entity_comm_map.comm_swap(key1, key2); }
00427 
00428 private:
00429 
00431   MetaData & meta_data() const { return m_mesh_meta_data ; }
00432 
00433 #ifndef DOXYGEN_COMPILE
00434 
00435   BulkData();
00436   BulkData( const BulkData & );
00437   BulkData & operator = ( const BulkData & );
00438 
00440   parallel::DistributedIndex          m_entities_index ;
00441   impl::EntityRepository              m_entity_repo ;
00442   impl::BucketRepository              m_bucket_repository ;
00443   std::vector<Entity*>                m_entity_comm ;
00444   std::vector<Ghosting*>              m_ghosting ; 
00446   // Other information:
00447   MetaData &         m_mesh_meta_data ;
00448   ParallelMachine    m_parallel_machine ;
00449   unsigned           m_parallel_size ;
00450   unsigned           m_parallel_rank ;
00451   size_t             m_sync_count ;
00452   BulkDataSyncState  m_sync_state ;
00453   bool               m_meta_data_verified ;
00454   bool               m_optimize_buckets;
00455   bool               m_mesh_finalized;
00456   EntityComm         m_entity_comm_map;
00457 
00462   unsigned determine_new_owner( Entity & ) const ;
00463 
00464   /*  Entity modification consequences:
00465    *  1) Change entity relation => update via part relation => change parts
00466    *  2) Change parts => update forward relations via part relation
00467    *                  => update via field relation
00468    */
00469   void internal_change_entity_parts( Entity & ,
00470                                      const PartVector & add_parts ,
00471                                      const PartVector & remove_parts );
00472 
00473 //Optional parameter 'always_propagate_internal_changes' is always true except when this function
00474 //is being called from the sierra-framework. The fmwk redundantly does its own propagation of the
00475 //internal part changes (mostly induced-part stuff), so it's a performance optimization to avoid
00476 //the propagation that stk-mesh does.
00477   void internal_change_entity_parts( Entity & ,
00478                                      const OrdinalVector & add_parts ,
00479                                      const OrdinalVector & remove_parts,
00480                                      bool always_propagate_internal_changes=true);
00481 
00482   void internal_propagate_part_changes( Entity & entity, const PartVector & removed );
00483   void internal_propagate_part_changes( Entity & entity, const OrdinalVector & removed );
00484 
00485   void internal_change_ghosting( Ghosting & ghosts,
00486                                  const std::vector<EntityProc> & add_send ,
00487                                  const std::vector<Entity*> & remove_receive );
00488 
00489   bool internal_modification_end( bool regenerate_aura );
00490     void internal_resolve_shared_modify_delete();
00491     void internal_resolve_shared_modify_delete_second_pass();
00492     void internal_resolve_ghosted_modify_delete();
00493     void internal_resolve_parallel_create();
00494     void internal_resolve_shared_membership();
00495 
00496   void internal_update_distributed_index( std::vector<Entity*> & shared_new );
00497 
00503   void internal_regenerate_shared_aura();
00504 
00505   void internal_basic_part_check(const Part* part,
00506                                  const unsigned entity_rank,
00507                                  const unsigned undef_rank,
00508                                  bool& intersection_ok,
00509                                  bool& rel_target_ok,
00510                                  bool& rank_ok) const;
00511 
00512   // Returns false if there is a problem. It is expected that
00513   // verify_change_parts will be called if quick_verify_change_part detects
00514   // a problem, therefore we leave the generation of an exception to
00515   // verify_change_parts. We want this function to be as fast as
00516   // possible.
00517   bool internal_quick_verify_change_part(const Part* part,
00518                                          const unsigned entity_rank,
00519                                          const unsigned undef_rank) const;
00520 
00521   void internal_verify_change_parts( const MetaData   & meta ,
00522                                      const Entity     & entity ,
00523                                      const PartVector & parts ) const;
00524 
00525   void internal_verify_change_parts( const MetaData   & meta ,
00526                                      const Entity     & entity ,
00527                                      const OrdinalVector & parts ) const;
00528 
00529   //------------------------------------
00530 
00536   void require_ok_to_modify() const ;
00537 
00538   void require_entity_owner( const Entity & entity, unsigned owner) const ;
00539 
00540   void require_metadata_committed() const;
00541 
00542   void require_good_rank_and_id(EntityRank ent_rank, EntityId ent_id) const;
00543 
00544   void require_valid_relation( const char action[] ,
00545                                const BulkData & mesh ,
00546                                const Entity   & e_from ,
00547                                const Entity   & e_to );
00548 
00551   //------------------------------------
00552 
00553   // FIXME: Remove this friend once unit-testing has been refactored
00554   friend class UnitTestModificationEndWrapper;
00555   friend class ::stk::mesh::MetaData;
00556 #endif /* DOXYGEN_COMPILE */
00557 };
00558 
00559 BulkData & BulkData::get( const Bucket & bucket) {
00560   return bucket.bulk_data();
00561 }
00562 
00563 BulkData & BulkData::get( const Entity & entity) {
00564   return BulkData::get(entity.bucket());
00565 }
00566 
00567 BulkData & BulkData::get( const Ghosting & ghost) {
00568   return ghost.bulk_data();
00569 }
00570 
00577 // TODO - Does this need to be in the public API? It's only used internally.
00578 // In what context would a client ever call this?
00579 void set_field_relations( Entity & e_from ,
00580                           Entity & e_to ,
00581                           const unsigned ident );
00582 
00583 inline
00584 void BulkData::internal_basic_part_check(const Part* part,
00585                                          const unsigned entity_rank,
00586                                          const unsigned undef_rank,
00587                                          bool& intersection_ok,
00588                                          bool& rel_target_ok,
00589                                          bool& rank_ok) const
00590 {
00591   // const unsigned part_rank = part->primary_entity_rank();
00592 
00593   intersection_ok = part->intersection_of().empty();
00594   rel_target_ok   = ( part->relations().empty() ||
00595                       part != part->relations().begin()->m_target );
00596   // Do we allow arbitrary part changes to entities regardless of part rank? For the sake of the migration, we will for now.
00597 #ifdef SIERRA_MIGRATION
00598   rank_ok = true;
00599 #else
00600   const unsigned part_rank = part->primary_entity_rank();
00601   rank_ok         = ( entity_rank == part_rank ||
00602                       undef_rank  == part_rank );
00603 #endif
00604 }
00605 
00606 inline bool BulkData::internal_quick_verify_change_part(const Part* part,
00607                                                         const unsigned entity_rank,
00608                                                         const unsigned undef_rank) const
00609 {
00610   bool intersection_ok, rel_target_ok, rank_ok;
00611   internal_basic_part_check(part, entity_rank, undef_rank, intersection_ok, rel_target_ok, rank_ok);
00612   return intersection_ok && rel_target_ok && rank_ok;
00613 }
00614 
00615 //Optional parameter 'always_propagate_internal_changes' is always true except when this function
00616 //is being called from the sierra-framework. The fmwk redundantly does its own propagation of the
00617 //internal part changes (mostly induced-part stuff), so it's a performance optimization to avoid
00618 //the propagation that stk-mesh does.
00619 template<typename AddIterator, typename RemoveIterator>
00620 void BulkData::change_entity_parts( Entity & entity,
00621                                     AddIterator begin_add_parts, AddIterator end_add_parts,
00622                                     RemoveIterator begin_remove_parts, RemoveIterator end_remove_parts,
00623                                     bool always_propagate_internal_changes)
00624 {
00625   TraceIfWatching("stk::mesh::BulkData::change_entity_parts", LOG_ENTITY, entity.key());
00626   DiagIfWatching(LOG_ENTITY, entity.key(), "entity state: " << entity);
00627   //DiagIfWatching(LOG_ENTITY, entity.key(), "add_parts: " << add_parts);
00628   //DiagIfWatching(LOG_ENTITY, entity.key(), "remove_parts: " << remove_parts);
00629 
00630   require_ok_to_modify();
00631 
00632   require_entity_owner( entity , m_parallel_rank );
00633 
00634   const EntityRank entity_rank = entity.entity_rank();
00635   const EntityRank undef_rank  = InvalidEntityRank;
00636 
00637   // Transitive addition and removal:
00638   // 1) Include supersets of add_parts
00639   // 2) Do not include a remove_part if it appears in the add_parts
00640   // 3) Include subsets of remove_parts
00641 
00642   // most parts will at least have universal and topology part as supersets
00643   const unsigned expected_min_num_supersets = 2;
00644 
00645   OrdinalVector a_parts;
00646   a_parts.reserve( std::distance(begin_add_parts, end_add_parts) * (expected_min_num_supersets + 1) );
00647   for(AddIterator add_iter=begin_add_parts; add_iter!=end_add_parts; ++add_iter) {
00648     a_parts.push_back((*add_iter)->mesh_meta_data_ordinal());
00649   }
00650   bool quick_verify_check = true;
00651 
00652   for ( AddIterator ia = begin_add_parts; ia != end_add_parts ; ++ia ) {
00653     quick_verify_check = quick_verify_check &&
00654       internal_quick_verify_change_part(*ia, entity_rank, undef_rank);
00655     const PartVector& supersets = (*ia)->supersets();
00656     for(PartVector::const_iterator s_iter=supersets.begin(), s_end=supersets.end();
00657         s_iter!=s_end; ++s_iter) {
00658       a_parts.push_back((*s_iter)->mesh_meta_data_ordinal());
00659     }
00660   }
00661 
00662   order(a_parts);
00663 
00664   OrdinalVector::const_iterator a_parts_begin = a_parts.begin(),
00665                                 a_parts_end   = a_parts.end();
00666   OrdinalVector r_parts ;
00667 
00668   for ( RemoveIterator ir = begin_remove_parts; ir != end_remove_parts ; ++ir ) {
00669 
00670     // The following guards should be in the public interface to
00671     // changing parts.  However, internal mechanisms such as changing
00672     // ownership calls this function to add or remove an entity from
00673     // the three special parts.  Without refactoring, these guards
00674     // cannot be put in place.
00675     /*
00676     ThrowErrorMsgIf( m_mesh_meta_data.universal_part() == **ir,
00677                      "Cannot remove entity from universal part" );
00678     ThrowErrorMsgIf( m_mesh_meta_data.locally_owned_part() == **ir,
00679                      "Cannot remove entity from locally owned part" );
00680     ThrowErrorMsgIf( m_mesh_meta_data.globally_shared_part() == **ir,
00681                      "Cannot remove entity from globally shared part" );
00682     */
00683 
00684     quick_verify_check = quick_verify_check &&
00685       internal_quick_verify_change_part(*ir, entity_rank, undef_rank);
00686 
00687     if ( ! contains_ordinal( a_parts_begin, a_parts_end , (*ir)->mesh_meta_data_ordinal() ) ) {
00688       r_parts.push_back( (*ir)->mesh_meta_data_ordinal() );
00689       for ( PartVector::const_iterator  cur_part = (*ir)->subsets().begin() ;
00690             cur_part != (*ir)->subsets().end() ;
00691             ++cur_part )
00692         if ( entity.bucket().member ( **cur_part ) )
00693           r_parts.push_back ( (*cur_part)->mesh_meta_data_ordinal() );
00694     }
00695   }
00696 
00697   order(r_parts);
00698 
00699   // If it looks like we have a problem, run the full check and we should
00700   // expect to see an exception thrown; otherwise, only do the full check in
00701   // debug mode because it incurs significant overhead.
00702   if ( ! quick_verify_check ) {
00703     internal_verify_change_parts( m_mesh_meta_data , entity , a_parts );
00704     internal_verify_change_parts( m_mesh_meta_data , entity , r_parts );
00705     ThrowRequireMsg(false, "Expected throw from verify methods above.");
00706   }
00707   else {
00708 #ifndef NDEBUG
00709     internal_verify_change_parts( m_mesh_meta_data , entity , a_parts );
00710     internal_verify_change_parts( m_mesh_meta_data , entity , r_parts );
00711 #endif
00712   }
00713 
00714   internal_change_entity_parts( entity , a_parts , r_parts , always_propagate_internal_changes );
00715 
00716   return ;
00717 }
00718 
00719 } // namespace mesh
00720 } // namespace stk
00721 
00722 //----------------------------------------------------------------------
00723 //----------------------------------------------------------------------
00724 
00725 #endif //  stk_mesh_BulkData_hpp
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines