|
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_classic { 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_classic::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_classic::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_classic 00721 00722 //---------------------------------------------------------------------- 00723 //---------------------------------------------------------------------- 00724 00725 #endif // stk_mesh_BulkData_hpp