|
Sierra Toolkit
Version of the Day
|
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