Sierra Toolkit  Version of the Day
BulkModification.cpp
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 #include <set>
10 #include <stdexcept>
11 #include <sstream>
12 
13 #include <stk_util/parallel/ParallelComm.hpp>
14 
15 #include <stk_mesh/base/BulkModification.hpp>
16 
17 #include <stk_mesh/base/BulkData.hpp>
18 #include <stk_mesh/base/Entity.hpp>
19 #include <stk_mesh/base/EntityComm.hpp>
20 
21 
22 namespace stk_classic {
23 namespace mesh {
24 
25 typedef std::set<Entity *, EntityLess> EntitySet;
26 typedef std::set<EntityProc , EntityLess> EntityProcSet;
27 
28 namespace {
29 
30 void construct_transitive_closure( EntitySet & closure , Entity & entry )
31 {
32 
33  std::pair< EntitySet::const_iterator , bool >
34  result = closure.insert( & entry );
35 
36  // A new insertion, must also insert the closure
37  if ( result.second ) {
38 
39  const unsigned erank = entry.entity_rank();
40  PairIterRelation irel = entry.relations();
41 
42  for ( ; irel.first != irel.second ; ++irel.first ) {
43  // insert entities with relations of lower rank into the closure
44  if ( irel.first->entity_rank() < erank ) {
45  Entity * tmp = irel.first->entity();
46  construct_transitive_closure( closure , *tmp );
47  }
48  }
49  }
50 }
51 
52 void find_local_closure ( EntitySet & closure, const EntityVector & entities)
53 {
54  for (EntityVector::const_iterator i = entities.begin();
55  i != entities.end(); ++i)
56  {
57  construct_transitive_closure(closure, **i);
58  }
59 }
60 
61 void construct_communication_set( const BulkData & bulk, const EntitySet & closure, EntityProcSet & communication_set)
62 {
63  if (bulk.parallel_size() < 2) return;
64 
65  for ( EntitySet::const_iterator
66  i = closure.begin(); i != closure.end(); ++i) {
67 
68  Entity & entity = **i;
69 
70  const bool owned = bulk.parallel_rank() == entity.owner_rank();
71 
72  // Add sharing processes and ghost-send processes to communication_set
73 
74  for ( PairIterEntityComm ec = entity.comm(); ! ec.empty() ; ++ec ) {
75  if ( owned || ec->ghost_id == 0 ) {
76  EntityProc tmp( & entity , ec->proc );
77  communication_set.insert( tmp );
78  }
79  }
80  }
81 }
82 
83 size_t count_non_used_entities( const BulkData & bulk, const EntityVector & entities)
84 {
85  const unsigned proc_local = bulk.parallel_rank();
86  size_t non_used_entities = 0;
87 
88  for ( EntityVector::const_iterator
89  i = entities.begin(); i != entities.end(); ++i ) {
90  if ( ! in_owned_closure( **i , proc_local ) ) {
91  ++non_used_entities;
92  }
93  }
94 
95  return non_used_entities;
96 }
97 
98 }
99 
100 
101 
102 void find_closure( const BulkData & bulk,
103  const std::vector< Entity *> & entities,
104  std::vector< Entity *> & entities_closure)
105 {
106 
107  entities_closure.clear();
108 
109 
110  EntityProcSet send_list;
111  EntitySet temp_entities_closure;
112 
113  const bool bulk_not_synchronized = bulk.synchronized_state() != BulkData::SYNCHRONIZED;
114  const size_t non_used_entities = bulk_not_synchronized ? 0 : count_non_used_entities(bulk, entities);
115 
116  const bool local_bad_input = bulk_not_synchronized || (0 < non_used_entities);
117 
118  //Can skip if error on input
119  if ( !local_bad_input) {
120 
121  find_local_closure(temp_entities_closure, entities);
122 
123  construct_communication_set(bulk, temp_entities_closure, send_list);
124  }
125 
126 
127  CommAll all( bulk.parallel() );
128 
129  //pack send_list for sizing
130  for ( EntityProcSet::const_iterator
131  ep = send_list.begin() ; ep != send_list.end() ; ++ep ) {
132  all.send_buffer( ep->second).pack<EntityKey>(ep->first->key());
133  }
134 
135 
136  const bool global_bad_input = all.allocate_buffers( bulk.parallel_size() / 4 , false, local_bad_input );
137 
138  if (global_bad_input) {
139 
140  std::ostringstream msg;
141  //parallel consisent throw
142  if (bulk_not_synchronized) {
143  msg << "stk_classic::mesh::find_closure( const BulkData & bulk, ... ) bulk is not synchronized";
144  }
145  else if ( 0 < non_used_entities) {
146  msg << "stk_classic::mesh::find_closure( const BulkData & bulk, std::vector<Entity *> entities, ... ) \n"
147  << "entities contains " << non_used_entities << " non locally used entities \n";
148  }
149 
150  throw std::runtime_error(msg.str());
151  }
152 
153 
154  //pack send_list
155  for ( EntityProcSet::const_iterator
156  ep = send_list.begin() ; ep != send_list.end() ; ++ep ) {
157  all.send_buffer( ep->second).pack<EntityKey>(ep->first->key());
158  }
159 
160 
161  all.communicate();
162 
163  //unpack the send_list into the temp entities closure set
164  for ( unsigned p = 0 ; p < bulk.parallel_size() ; ++p ) {
165  CommBuffer & buf = all.recv_buffer( p );
166  EntityKey k ;
167  while ( buf.remaining() ) {
168  buf.unpack<EntityKey>( k );
169  Entity * e = bulk.get_entity(k);
170  temp_entities_closure.insert(e);
171  }
172  }
173 
174  //copy the set into the entities_closure vector
175  entities_closure.assign(temp_entities_closure.begin(), temp_entities_closure.end());
176 }
177 
178 } // namespace mesh
179 } // namespace stk_classic
180 
PairIterEntityComm comm() const
Complete communicaiton list for this entity.
Definition: Entity.hpp:181
std::pair< Entity *, unsigned > EntityProc
Pairing of an entity with a processor rank.
Definition: Types.hpp:111
Sierra Toolkit.
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
unsigned owner_rank() const
Parallel processor rank of the processor which owns this entity.
Definition: Entity.hpp:175