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_ghosted_modify_delete();
00446     void internal_resolve_parallel_create();
00447     void internal_resolve_shared_membership();
00448 
00449   void internal_update_distributed_index( std::vector<Entity*> & shared_new );
00450 
00456   void internal_regenerate_shared_aura();
00457 
00458   // Returns false if there is a problem. It is expected that
00459   // verify_change_parts will be called if quick_verify_change_part detects
00460   // a problem, therefore we leave the generation of an exception to
00461   // verify_change_parts. We want this function to be as fast as
00462   // possible.
00463   inline bool internal_quick_verify_change_part(const Entity& entity,
00464                                                 const Part* part,
00465                                                 const unsigned entity_rank,
00466                                                 const unsigned undef_rank) const;
00467 
00468   void internal_verify_change_parts( const MetaData   & meta ,
00469                                      const Entity     & entity ,
00470                                      const PartVector & parts ) const;
00471 
00472   //------------------------------------
00473 
00479   void require_ok_to_modify() const ;
00480 
00481   void require_entity_owner( const Entity & entity, unsigned owner) const ;
00482 
00483   void require_metadata_committed() const;
00484 
00485   void require_good_rank_and_id(EntityRank ent_rank, EntityId ent_id) const;
00486 
00487   void require_valid_relation( const char action[] ,
00488                                const BulkData & mesh ,
00489                                const Entity   & e_from ,
00490                                const Entity   & e_to );
00491 
00494   //------------------------------------
00495 
00496   // FIXME: Remove this friend once unit-testing has been refactored
00497   friend class UnitTestModificationEndWrapper;
00498   friend class ::stk::mesh::MetaData;
00499 #endif /* DOXYGEN_COMPILE */
00500 };
00501 
00502 BulkData & BulkData::get( const Bucket & bucket) {
00503   return bucket.bulk_data();
00504 }
00505 
00506 BulkData & BulkData::get( const Entity & entity) {
00507   return BulkData::get(entity.bucket());
00508 }
00509 
00510 BulkData & BulkData::get( const Ghosting & ghost) {
00511   return ghost.bulk_data();
00512 }
00513 
00520 // TODO - Does this need to be in the public API? It's only used internally.
00521 // In what context would a client ever call this?
00522 void set_field_relations( Entity & e_from ,
00523                           Entity & e_to ,
00524                           const unsigned ident );
00525 
00526 inline bool BulkData::internal_quick_verify_change_part(const Entity& entity,
00527                                                         const Part* part,
00528                                                         const unsigned entity_rank,
00529                                                         const unsigned undef_rank) const
00530 {
00531   const unsigned part_rank = part->primary_entity_rank();
00532 
00533   // The code below is coupled with the code in verify_change_parts. If we
00534   // change what it means for a part to be valid, code will need to be
00535   // changed in both places unfortunately.
00536   const bool intersection_ok = part->intersection_of().empty();
00537   const bool rel_target_ok   = ( part->relations().empty() ||
00538                                  part != part->relations().begin()->m_target );
00539   const bool rank_ok         = ( entity_rank == part_rank ||
00540                                  undef_rank  == part_rank );
00541 
00542   return intersection_ok && rel_target_ok && rank_ok;
00543 }
00544 
00545 template<typename AddIterator, typename RemoveIterator>
00546 void BulkData::change_entity_parts( Entity & entity,
00547                                     AddIterator begin_add_parts, AddIterator end_add_parts,
00548                                     RemoveIterator begin_remove_parts, RemoveIterator end_remove_parts )
00549 {
00550   TraceIfWatching("stk::mesh::BulkData::change_entity_parts", LOG_ENTITY, entity.key());
00551   DiagIfWatching(LOG_ENTITY, entity.key(), "entity state: " << entity);
00552   //DiagIfWatching(LOG_ENTITY, entity.key(), "add_parts: " << add_parts);
00553   //DiagIfWatching(LOG_ENTITY, entity.key(), "remove_parts: " << remove_parts);
00554 
00555   require_ok_to_modify();
00556 
00557   require_entity_owner( entity , m_parallel_rank );
00558 
00559   const EntityRank entity_rank = entity.entity_rank();
00560   const EntityRank undef_rank  = InvalidEntityRank;
00561 
00562   // Transitive addition and removal:
00563   // 1) Include supersets of add_parts
00564   // 2) Do not include a remove_part if it appears in the add_parts
00565   // 3) Include subsets of remove_parts
00566 
00567   // most parts will at least have universal and topology part as supersets
00568   const unsigned expected_min_num_supersets = 2;
00569 
00570   PartVector a_parts;
00571   a_parts.reserve( std::distance(begin_add_parts, end_add_parts) * (expected_min_num_supersets + 1) );
00572   a_parts.insert( a_parts.begin(), begin_add_parts, end_add_parts );
00573   bool quick_verify_check = true;
00574 
00575   for ( AddIterator ia = begin_add_parts; ia != end_add_parts ; ++ia ) {
00576     quick_verify_check = quick_verify_check &&
00577       internal_quick_verify_change_part(entity, *ia, entity_rank, undef_rank);
00578     a_parts.insert( a_parts.end(), (*ia)->supersets().begin(),
00579                                    (*ia)->supersets().end() );
00580   }
00581 
00582   order( a_parts );
00583 
00584   PartVector r_parts ;
00585 
00586   for ( RemoveIterator ir = begin_remove_parts; ir != end_remove_parts ; ++ir ) {
00587 
00588     // The following guards should be in the public interface to
00589     // changing parts.  However, internal mechanisms such as changing
00590     // ownership calls this function to add or remove an entity from
00591     // the three special parts.  Without refactoring, these guards
00592     // cannot be put in place.
00593     /*
00594     ThrowErrorMsgIf( m_mesh_meta_data.universal_part() == **ir,
00595                      "Cannot remove entity from universal part" );
00596     ThrowErrorMsgIf( m_mesh_meta_data.locally_owned_part() == **ir,
00597                      "Cannot remove entity from locally owned part" );
00598     ThrowErrorMsgIf( m_mesh_meta_data.globally_shared_part() == **ir,
00599                      "Cannot remove entity from globally shared part" );
00600     */
00601 
00602     quick_verify_check = quick_verify_check &&
00603       internal_quick_verify_change_part(entity, *ir, entity_rank, undef_rank);
00604 
00605     if ( ! contain( a_parts , **ir ) ) {
00606       r_parts.push_back( *ir );
00607       for ( PartVector::const_iterator  cur_part = (*ir)->subsets().begin() ;
00608             cur_part != (*ir)->subsets().end() ;
00609             ++cur_part )
00610         if ( entity.bucket().member ( **cur_part ) )
00611           r_parts.push_back ( *cur_part );
00612     }
00613   }
00614 
00615   order( r_parts );
00616 
00617   // If it looks like we have a problem, run the full check and we should
00618   // expect to see an exception thrown; otherwise, only do the full check in
00619   // debug mode because it incurs significant overhead.
00620   if ( ! quick_verify_check ) {
00621     internal_verify_change_parts( m_mesh_meta_data , entity , a_parts );
00622     internal_verify_change_parts( m_mesh_meta_data , entity , r_parts );
00623     ThrowRequireMsg(false, "Expected throw from verify methods above.");
00624   }
00625   else {
00626 #ifndef NDEBUG
00627     internal_verify_change_parts( m_mesh_meta_data , entity , a_parts );
00628     internal_verify_change_parts( m_mesh_meta_data , entity , r_parts );
00629 #endif
00630   }
00631 
00632   internal_change_entity_parts( entity , a_parts , r_parts );
00633 
00634   return ;
00635 }
00636 
00637 } // namespace mesh
00638 } // namespace stk
00639 
00640 //----------------------------------------------------------------------
00641 //----------------------------------------------------------------------
00642 
00643 #endif //  stk_mesh_BulkData_hpp
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends