Sierra Toolkit  Version of the Day
BulkData.hpp
1 /*------------------------------------------------------------------------*/
2 /* Copyright 2010 Sandia Corporation. */
3 /* Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive */
4 /* license for use of this work by or on behalf of the U.S. Government. */
5 /* Export of this program may require a license from the */
6 /* United States Government. */
7 /*------------------------------------------------------------------------*/
8 
9 #ifndef stk_mesh_BulkData_hpp
10 #define stk_mesh_BulkData_hpp
11 
12 //----------------------------------------------------------------------
13 
14 #include <stk_util/parallel/Parallel.hpp>
15 #include <stk_util/parallel/DistributedIndex.hpp>
16 
17 #include <stk_mesh/base/Types.hpp>
18 #include <stk_mesh/base/Field.hpp>
19 #include <stk_mesh/base/MetaData.hpp>
20 #include <stk_mesh/base/Ghosting.hpp>
21 #include <stk_mesh/base/Selector.hpp>
22 #include <stk_mesh/base/Trace.hpp>
23 #include <stk_mesh/base/EntityComm.hpp>
24 
25 #include <stk_mesh/baseImpl/EntityRepository.hpp>
26 #include <stk_mesh/baseImpl/BucketRepository.hpp>
27 
28 #include <algorithm>
29 #include <map>
30 
31 //----------------------------------------------------------------------
32 
33 namespace stk_classic {
34 namespace mesh {
35 
40 //----------------------------------------------------------------------
49 class BulkData {
50 public:
51 
52  void optimize_buckets_at_modification_end(bool b) { m_optimize_buckets = b; }
53 
54  inline static BulkData & get( const Bucket & bucket);
55  inline static BulkData & get( const Entity & entity);
56  inline static BulkData & get( const Ghosting & ghost);
57 
58  enum BulkDataSyncState { MODIFIABLE = 1 , SYNCHRONIZED = 2 };
59 
60  ~BulkData();
61 
71  unsigned bucket_max_size = 1000 ,
72  bool use_memory_pool = true );
73 
74  //------------------------------------
76  const MetaData & mesh_meta_data() const { return m_mesh_meta_data ; }
77 
79  ParallelMachine parallel() const { return m_parallel_machine ; }
80 
82  unsigned parallel_size() const { return m_parallel_size ; }
83 
85  unsigned parallel_rank() const { return m_parallel_rank ; }
86 
87  //------------------------------------
92  BulkDataSyncState synchronized_state() const { return m_sync_state ; }
93 
98  size_t synchronized_count() const { return m_sync_count ; }
99 
111  bool modification_begin();
112 
130  bool modification_end();
131 
132  bool final_modification_end()
133  {
134  optimize_buckets_at_modification_end(true);
135  const bool mod_flag = modification_end();
136 
137  //call modification_begin and end one last time to free deleted entities
140 
141  m_mesh_finalized = true;
142 
143  return mod_flag;
144  }
145 
161  void change_entity_owner( const std::vector<EntityProc> & arg_change);
162 
174  void update_field_data_states() const { m_bucket_repository.update_field_data_states(); }
175 
182  void copy_entity_fields( const Entity & src, Entity & dest) {
183  //TODO fix const correctness for src
184  Entity & non_const_src = const_cast<Entity &>(src);
185  m_bucket_repository.copy_fields(
186  dest.bucket(),
187  dest.bucket_ordinal(),
188  non_const_src.bucket(),
189  non_const_src.bucket_ordinal()
190  );
191  }
192 
193  //------------------------------------
195  const std::vector<Bucket*> & buckets( EntityRank rank ) const
196  { return m_bucket_repository.buckets(rank); }
197 
198 #ifndef SWIG //SRK
199  AllBucketsRange get_bucket_range() const
200  {
201  return m_bucket_repository.get_bucket_range();
202  }
203 
204  AllBucketsRange get_bucket_range( EntityRank rank ) const
205  {
206  return m_bucket_repository.get_bucket_range(rank);
207  }
208 #endif
209 
211  Entity * get_entity( EntityRank entity_rank , EntityId entity_id ) const {
212  require_good_rank_and_id(entity_rank, entity_id);
213  return m_entity_repo.get_entity( EntityKey(entity_rank, entity_id));
214  }
215 
217  Entity * get_entity( const EntityKey key ) const {
218  return m_entity_repo.get_entity(key);
219  }
220 
221  //------------------------------------
235  Entity & declare_entity( EntityRank ent_rank ,
236  EntityId ent_id , const PartVector& parts);
237 
238  void change_entity_id( EntityId id, Entity & entity);
239 
249  void change_entity_parts( Entity & entity,
250  const PartVector & add_parts ,
251  const PartVector & remove_parts = PartVector() )
252  {
253  change_entity_parts(entity,
254  add_parts.begin(), add_parts.end(),
255  remove_parts.begin(), remove_parts.end());
256  }
257 
258 //Optional parameter 'always_propagate_internal_changes' is always true except when this function
259 //is being called from the sierra-framework. The fmwk redundantly does its own propagation of the
260 //internal part changes (mostly induced-part stuff), so it's a performance optimization to avoid
261 //the propagation that stk-mesh does.
262  template<typename AddIterator, typename RemoveIterator>
263  void change_entity_parts( Entity & entity,
264  AddIterator begin_add_parts, AddIterator end_add_parts,
265  RemoveIterator begin_remove_parts, RemoveIterator end_remove_parts,
266  bool always_propagate_internal_changes=true );
267 
301  bool destroy_entity( Entity * & entity );
302 
303  //------------------------------------
304 
314  void generate_new_entities(const std::vector<size_t>& requests,
315  std::vector<Entity *>& requested_entities);
316 
317  //------------------------------------
337  void declare_relation( Entity & e_from ,
338  Entity & e_to ,
339  const RelationIdentifier local_id );
340 
344  void declare_relation( Entity & entity, const std::vector<Relation> & rel);
345 
360  bool destroy_relation( Entity & e_from ,
361  Entity & e_to,
362  const RelationIdentifier local_id );
363 
364  //------------------------------------
365  //------------------------------------
367  const std::vector<Entity*> & entity_comm() const
368  { return m_entity_comm ; }
369 
370  //------------------------------------
375  Ghosting & shared_aura() const { return * m_ghosting[1] ; }
376 
382  Ghosting & create_ghosting( const std::string & name );
383 
401  void change_ghosting( Ghosting & ghosts,
402  const std::vector<EntityProc> & add_send ,
403  const std::vector<Entity*> & remove_receive );
404 
409  void destroy_all_ghosting();
410 
412  const std::vector<Ghosting*> & ghostings() const { return m_ghosting ; }
413 
418  PairIterEntityComm entity_comm(const EntityKey & key) const { return m_entity_comm_map.comm(key); }
419  PairIterEntityComm entity_comm_sharing(const EntityKey & key) const { return m_entity_comm_map.sharing(key); }
420  PairIterEntityComm entity_comm(const EntityKey & key, const Ghosting & sub ) const { return m_entity_comm_map.comm(key,sub); }
421  bool entity_comm_insert( const EntityKey & key, const EntityCommInfo & val) { return m_entity_comm_map.insert(key,val); }
422  bool entity_comm_erase( const EntityKey & key, const EntityCommInfo & val) { return m_entity_comm_map.erase(key,val); }
423  bool entity_comm_erase( const EntityKey & key, const Ghosting & ghost) { return m_entity_comm_map.erase(key,ghost); }
424  void entity_comm_clear_ghosting(const EntityKey & key ) { m_entity_comm_map.comm_clear_ghosting(key); }
425  void entity_comm_clear(const EntityKey & key) { m_entity_comm_map.comm_clear(key); }
426  void entity_comm_swap(const EntityKey & key1, const EntityKey & key2) { m_entity_comm_map.comm_swap(key1, key2); }
427 
428 private:
429 
431  MetaData & meta_data() const { return m_mesh_meta_data ; }
432 
433 #ifndef DOXYGEN_COMPILE
434 
435  BulkData();
436  BulkData( const BulkData & );
437  BulkData & operator = ( const BulkData & );
438 
440  parallel::DistributedIndex m_entities_index ;
441  impl::EntityRepository m_entity_repo ;
442  impl::BucketRepository m_bucket_repository ;
443  std::vector<Entity*> m_entity_comm ;
444  std::vector<Ghosting*> m_ghosting ;
446  // Other information:
447  MetaData & m_mesh_meta_data ;
448  ParallelMachine m_parallel_machine ;
449  unsigned m_parallel_size ;
450  unsigned m_parallel_rank ;
451  size_t m_sync_count ;
452  BulkDataSyncState m_sync_state ;
453  bool m_meta_data_verified ;
454  bool m_optimize_buckets;
455  bool m_mesh_finalized;
456  EntityComm m_entity_comm_map;
457 
462  unsigned determine_new_owner( Entity & ) const ;
463 
464  /* Entity modification consequences:
465  * 1) Change entity relation => update via part relation => change parts
466  * 2) Change parts => update forward relations via part relation
467  * => update via field relation
468  */
469  void internal_change_entity_parts( Entity & ,
470  const PartVector & add_parts ,
471  const PartVector & remove_parts );
472 
473 //Optional parameter 'always_propagate_internal_changes' is always true except when this function
474 //is being called from the sierra-framework. The fmwk redundantly does its own propagation of the
475 //internal part changes (mostly induced-part stuff), so it's a performance optimization to avoid
476 //the propagation that stk-mesh does.
477  void internal_change_entity_parts( Entity & ,
478  const OrdinalVector & add_parts ,
479  const OrdinalVector & remove_parts,
480  bool always_propagate_internal_changes=true);
481 
482  void internal_propagate_part_changes( Entity & entity, const PartVector & removed );
483  void internal_propagate_part_changes( Entity & entity, const OrdinalVector & removed );
484 
485  void internal_change_ghosting( Ghosting & ghosts,
486  const std::vector<EntityProc> & add_send ,
487  const std::vector<Entity*> & remove_receive );
488 
489  bool internal_modification_end( bool regenerate_aura );
490  void internal_resolve_shared_modify_delete();
491  void internal_resolve_shared_modify_delete_second_pass();
492  void internal_resolve_ghosted_modify_delete();
493  void internal_resolve_parallel_create();
494  void internal_resolve_shared_membership();
495 
496  void internal_update_distributed_index( std::vector<Entity*> & shared_new );
497 
503  void internal_regenerate_shared_aura();
504 
505  void internal_basic_part_check(const Part* part,
506  const unsigned entity_rank,
507  const unsigned undef_rank,
508  bool& intersection_ok,
509  bool& rel_target_ok,
510  bool& rank_ok) const;
511 
512  // Returns false if there is a problem. It is expected that
513  // verify_change_parts will be called if quick_verify_change_part detects
514  // a problem, therefore we leave the generation of an exception to
515  // verify_change_parts. We want this function to be as fast as
516  // possible.
517  bool internal_quick_verify_change_part(const Part* part,
518  const unsigned entity_rank,
519  const unsigned undef_rank) const;
520 
521  void internal_verify_change_parts( const MetaData & meta ,
522  const Entity & entity ,
523  const PartVector & parts ) const;
524 
525  void internal_verify_change_parts( const MetaData & meta ,
526  const Entity & entity ,
527  const OrdinalVector & parts ) const;
528 
529  //------------------------------------
530 
536  void require_ok_to_modify() const ;
537 
538  void require_entity_owner( const Entity & entity, unsigned owner) const ;
539 
540  void require_metadata_committed() const;
541 
542  void require_good_rank_and_id(EntityRank ent_rank, EntityId ent_id) const;
543 
544  void require_valid_relation( const char action[] ,
545  const BulkData & mesh ,
546  const Entity & e_from ,
547  const Entity & e_to );
548 
551  //------------------------------------
552 
553  // FIXME: Remove this friend once unit-testing has been refactored
554  friend class UnitTestModificationEndWrapper;
555  friend class ::stk_classic::mesh::MetaData;
556 #endif /* DOXYGEN_COMPILE */
557 };
558 
559 BulkData & BulkData::get( const Bucket & bucket) {
560  return bucket.bulk_data();
561 }
562 
563 BulkData & BulkData::get( const Entity & entity) {
564  return BulkData::get(entity.bucket());
565 }
566 
567 BulkData & BulkData::get( const Ghosting & ghost) {
568  return ghost.bulk_data();
569 }
570 
577 // TODO - Does this need to be in the public API? It's only used internally.
578 // In what context would a client ever call this?
579 void set_field_relations( Entity & e_from ,
580  Entity & e_to ,
581  const unsigned ident );
582 
583 inline
584 void BulkData::internal_basic_part_check(const Part* part,
585  const unsigned entity_rank,
586  const unsigned undef_rank,
587  bool& intersection_ok,
588  bool& rel_target_ok,
589  bool& rank_ok) const
590 {
591  // const unsigned part_rank = part->primary_entity_rank();
592 
593  intersection_ok = part->intersection_of().empty();
594  rel_target_ok = ( part->relations().empty() ||
595  part != part->relations().begin()->m_target );
596  // Do we allow arbitrary part changes to entities regardless of part rank? For the sake of the migration, we will for now.
597 #ifdef SIERRA_MIGRATION
598  rank_ok = true;
599 #else
600  const unsigned part_rank = part->primary_entity_rank();
601  rank_ok = ( entity_rank == part_rank ||
602  undef_rank == part_rank );
603 #endif
604 }
605 
606 inline bool BulkData::internal_quick_verify_change_part(const Part* part,
607  const unsigned entity_rank,
608  const unsigned undef_rank) const
609 {
610  bool intersection_ok, rel_target_ok, rank_ok;
611  internal_basic_part_check(part, entity_rank, undef_rank, intersection_ok, rel_target_ok, rank_ok);
612  return intersection_ok && rel_target_ok && rank_ok;
613 }
614 
615 //Optional parameter 'always_propagate_internal_changes' is always true except when this function
616 //is being called from the sierra-framework. The fmwk redundantly does its own propagation of the
617 //internal part changes (mostly induced-part stuff), so it's a performance optimization to avoid
618 //the propagation that stk-mesh does.
619 template<typename AddIterator, typename RemoveIterator>
620 void BulkData::change_entity_parts( Entity & entity,
621  AddIterator begin_add_parts, AddIterator end_add_parts,
622  RemoveIterator begin_remove_parts, RemoveIterator end_remove_parts,
623  bool always_propagate_internal_changes)
624 {
625  TraceIfWatching("stk_classic::mesh::BulkData::change_entity_parts", LOG_ENTITY, entity.key());
626  DiagIfWatching(LOG_ENTITY, entity.key(), "entity state: " << entity);
627  //DiagIfWatching(LOG_ENTITY, entity.key(), "add_parts: " << add_parts);
628  //DiagIfWatching(LOG_ENTITY, entity.key(), "remove_parts: " << remove_parts);
629 
630  require_ok_to_modify();
631 
632  require_entity_owner( entity , m_parallel_rank );
633 
634  const EntityRank entity_rank = entity.entity_rank();
635  const EntityRank undef_rank = InvalidEntityRank;
636 
637  // Transitive addition and removal:
638  // 1) Include supersets of add_parts
639  // 2) Do not include a remove_part if it appears in the add_parts
640  // 3) Include subsets of remove_parts
641 
642  // most parts will at least have universal and topology part as supersets
643  const unsigned expected_min_num_supersets = 2;
644 
645  OrdinalVector a_parts;
646  a_parts.reserve( std::distance(begin_add_parts, end_add_parts) * (expected_min_num_supersets + 1) );
647  for(AddIterator add_iter=begin_add_parts; add_iter!=end_add_parts; ++add_iter) {
648  a_parts.push_back((*add_iter)->mesh_meta_data_ordinal());
649  }
650  bool quick_verify_check = true;
651 
652  for ( AddIterator ia = begin_add_parts; ia != end_add_parts ; ++ia ) {
653  quick_verify_check = quick_verify_check &&
654  internal_quick_verify_change_part(*ia, entity_rank, undef_rank);
655  const PartVector& supersets = (*ia)->supersets();
656  for(PartVector::const_iterator s_iter=supersets.begin(), s_end=supersets.end();
657  s_iter!=s_end; ++s_iter) {
658  a_parts.push_back((*s_iter)->mesh_meta_data_ordinal());
659  }
660  }
661 
662  order(a_parts);
663 
664  OrdinalVector::const_iterator a_parts_begin = a_parts.begin(),
665  a_parts_end = a_parts.end();
666  OrdinalVector r_parts ;
667 
668  for ( RemoveIterator ir = begin_remove_parts; ir != end_remove_parts ; ++ir ) {
669 
670  // The following guards should be in the public interface to
671  // changing parts. However, internal mechanisms such as changing
672  // ownership calls this function to add or remove an entity from
673  // the three special parts. Without refactoring, these guards
674  // cannot be put in place.
675  /*
676  ThrowErrorMsgIf( m_mesh_meta_data.universal_part() == **ir,
677  "Cannot remove entity from universal part" );
678  ThrowErrorMsgIf( m_mesh_meta_data.locally_owned_part() == **ir,
679  "Cannot remove entity from locally owned part" );
680  ThrowErrorMsgIf( m_mesh_meta_data.globally_shared_part() == **ir,
681  "Cannot remove entity from globally shared part" );
682  */
683 
684  quick_verify_check = quick_verify_check &&
685  internal_quick_verify_change_part(*ir, entity_rank, undef_rank);
686 
687  if ( ! contains_ordinal( a_parts_begin, a_parts_end , (*ir)->mesh_meta_data_ordinal() ) ) {
688  r_parts.push_back( (*ir)->mesh_meta_data_ordinal() );
689  for ( PartVector::const_iterator cur_part = (*ir)->subsets().begin() ;
690  cur_part != (*ir)->subsets().end() ;
691  ++cur_part )
692  if ( entity.bucket().member ( **cur_part ) )
693  r_parts.push_back ( (*cur_part)->mesh_meta_data_ordinal() );
694  }
695  }
696 
697  order(r_parts);
698 
699  // If it looks like we have a problem, run the full check and we should
700  // expect to see an exception thrown; otherwise, only do the full check in
701  // debug mode because it incurs significant overhead.
702  if ( ! quick_verify_check ) {
703  internal_verify_change_parts( m_mesh_meta_data , entity , a_parts );
704  internal_verify_change_parts( m_mesh_meta_data , entity , r_parts );
705  ThrowRequireMsg(false, "Expected throw from verify methods above.");
706  }
707  else {
708 #ifndef NDEBUG
709  internal_verify_change_parts( m_mesh_meta_data , entity , a_parts );
710  internal_verify_change_parts( m_mesh_meta_data , entity , r_parts );
711 #endif
712  }
713 
714  internal_change_entity_parts( entity , a_parts , r_parts , always_propagate_internal_changes );
715 
716  return ;
717 }
718 
719 } // namespace mesh
720 } // namespace stk_classic
721 
722 //----------------------------------------------------------------------
723 //----------------------------------------------------------------------
724 
725 #endif // stk_mesh_BulkData_hpp
void declare_relation(Entity &e_from, Entity &e_to, const RelationIdentifier local_id)
Declare a relation and its converse between entities in the same mesh.
unsigned bucket_ordinal() const
The ordinal for this entity within its bucket.
Definition: Entity.hpp:145
PairIterEntityComm entity_comm(const EntityKey &key) const
Entity Comm functions that are now moved to BulkData These functions are only here for backwards comp...
Definition: BulkData.hpp:418
The manager of an integrated collection of parts and fields.
Definition: MetaData.hpp:56
Ghosting & create_ghosting(const std::string &name)
Asymmetric parallel relations for owner-to-ghosted mesh entities.
const std::vector< Entity * > & entity_comm() const
All entities with communication information.
Definition: BulkData.hpp:367
Data for ghosting mesh entities.
Definition: Ghosting.hpp:28
bool destroy_relation(Entity &e_from, Entity &e_to, const RelationIdentifier local_id)
Remove all relations between two entities.
Bucket & bucket() const
The bucket which holds this mesh entity&#39;s field data.
Definition: Entity.hpp:141
void order(PartVector &v)
Order a collection of parts: invoke sort and then unique.
Definition: Part.cpp:76
BulkData(MetaData &mesh_meta_data, ParallelMachine parallel, unsigned bucket_max_size=1000, bool use_memory_pool=true)
Construct mesh bulk data manager conformal to the given meta data manager and will distribute bulk da...
Definition: BulkData.cpp:90
const std::vector< Bucket * > & buckets(EntityRank rank) const
Query all buckets of a given entity rank.
Definition: BulkData.hpp:195
void change_ghosting(Ghosting &ghosts, const std::vector< EntityProc > &add_send, const std::vector< Entity *> &remove_receive)
Change the members of a ghosting list on the sending processor.
Ghosting & shared_aura() const
Query the shared-entity aura. Is likely to be stale if ownership or sharing has changed and the &#39;modi...
Definition: BulkData.hpp:375
Entity * get_entity(EntityRank entity_rank, EntityId entity_id) const
Get entity with a given key.
Definition: BulkData.hpp:211
Integer type for the entity keys, which is an encoding of the entity type and entity identifier...
void copy_entity_fields(const Entity &src, Entity &dest)
Copy field data from src entity to Dest entity.
Definition: BulkData.hpp:182
BulkDataSyncState synchronized_state() const
Bulk data has two states: guaranteed to be parallel synchronized or modification in progress and may ...
Definition: BulkData.hpp:92
void change_entity_parts(Entity &entity, const PartVector &add_parts, const PartVector &remove_parts=PartVector())
Change the parallel-locally-owned entity&#39;s part membership by adding and/or removing parts...
Definition: BulkData.hpp:249
void destroy_all_ghosting()
Empty every single Ghosting. Same result, but more efficient than, calling change_ghosting to remove ...
ParallelMachine parallel() const
The parallel machine.
Definition: BulkData.hpp:79
Entity * get_entity(const EntityKey key) const
Get entity with a given key.
Definition: BulkData.hpp:217
bool modification_end()
Parallel synchronization of modifications and transition to the guaranteed parallel consistent state...
unsigned parallel_size() const
Size of the parallel machine.
Definition: BulkData.hpp:82
bool modification_begin()
Begin a modification phase during which the mesh bulk data could become parallel inconsistent. This is a parallel synchronous call. The first time this method is called the mesh meta data is verified to be committed and parallel consistent. An exception is thrown if this verification fails.
Definition: BulkData.cpp:172
size_t synchronized_count() const
Count of the number of times that the bulk data has been parallel synchronized. This count gets updat...
Definition: BulkData.hpp:98
Manager for an integrated collection of entities, entity relations, and buckets of field data...
Definition: BulkData.hpp:49
EntityId entity_id(const EntityKey &key)
Given an entity key, return the identifier for the entity.
const MetaData & mesh_meta_data() const
The meta data manager for this bulk data manager.
Definition: BulkData.hpp:76
A fundamental unit within the discretization of a problem domain, including but not limited to nodes...
Definition: Entity.hpp:120
Sierra Toolkit.
MPI_Comm ParallelMachine
Definition: Parallel.hpp:32
void change_entity_owner(const std::vector< EntityProc > &arg_change)
Give away ownership of entities to other parallel processes.
const std::vector< Ghosting * > & ghostings() const
Query all ghostings.
Definition: BulkData.hpp:412
unsigned parallel_rank() const
Rank of the parallel machine&#39;s local processor.
Definition: BulkData.hpp:85
Entity & declare_entity(EntityRank ent_rank, EntityId ent_id, const PartVector &parts)
Create or retrieve a locally owned entity of a given rank and id.
Definition: BulkData.cpp:215
std::vector< Part *> PartVector
Collections of parts are frequently maintained as a vector of Part pointers.
Definition: Types.hpp:31
PairIter< std::vector< EntityCommInfo >::const_iterator > PairIterEntityComm
Span of ( communication-subset-ordinal , process-rank ) pairs for the communication of an entity...
Definition: Types.hpp:128
void generate_new_entities(const std::vector< size_t > &requests, std::vector< Entity *> &requested_entities)
Generate a set of entites with globally unique id&#39;s.
Definition: BulkData.cpp:773
A container for the field data of a homogeneous collection of entities.
Definition: Bucket.hpp:94
EntityRank entity_rank(const EntityKey &key)
Given an entity key, return an entity type (rank).
bool destroy_entity(Entity *&entity)
Request the destruction an entity on the local process.
Definition: BulkData.cpp:698
void update_field_data_states() const
Rotate the field data of multistate fields.
Definition: BulkData.hpp:174