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