Sierra Toolkit  Version of the Day
EntityImpl.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 <algorithm>
10 #include <sstream>
11 #include <stdexcept>
12 
13 #include <stk_mesh/base/Ghosting.hpp>
14 #include <stk_mesh/base/Bucket.hpp>
15 #include <stk_mesh/base/BulkData.hpp>
16 #include <stk_mesh/base/MetaData.hpp>
17 
18 #include <stk_mesh/baseImpl/EntityImpl.hpp>
19 
20 namespace stk_classic {
21 namespace mesh {
22 namespace impl {
23 
24 
25 PairIterRelation EntityImpl::relations( unsigned rank ) const
26 {
27  RelationVector::const_iterator i = m_relation.begin();
28  RelationVector::const_iterator e = m_relation.end();
29 
30  //Nodes
31  if ( rank != 0 ) {
32  const Relation::raw_relation_id_type lo_attr = Relation::raw_relation_id( rank , 0 );
33  i = std::lower_bound( i , e , lo_attr , LessRelation() );
34  }
35 
36  const Relation::raw_relation_id_type hi_attr = Relation::raw_relation_id( rank + 1 , 0 );
37  e = std::lower_bound( i , e , hi_attr , LessRelation() );
38 
39  return PairIterRelation( i , e );
40 }
41 
42 
43 namespace {
44 
45 inline bool is_degenerate_relation ( const Relation &r1 , const Relation &r2 )
46 {
47  return r1.raw_relation_id() == r2.raw_relation_id() && r1.entity() != r2.entity() ;
48 }
49 
50 }
51 
52 void EntityImpl::log_resurrect()
53 {
54  TraceIfWatching("stk_classic::mesh::impl::EntityImpl::log_resurrect", LOG_ENTITY, key());
55 
56  ThrowErrorMsgIf( EntityLogDeleted != m_mod_log,
57  "Trying to resurrect non-deleted entity: " <<
58  print_entity_key( MetaData::get( bucket() ), key() ) );
59 
60  m_mod_log = EntityLogModified;
61  m_bucket = NULL;
62 }
63 
64 void EntityImpl::log_modified_and_propagate()
65 {
66  TraceIfWatching("stk_classic::mesh::impl::EntityImpl::log_modified_and_propagate", LOG_ENTITY, key());
67 
68  // If already in modified state, return
69  if (m_mod_log != EntityLogNoChange) {
70  return;
71  }
72 
73  // mark this entity as modified
74  m_mod_log = EntityLogModified;
75 
76  // recurse on related entities w/ higher rank
77  EntityRank rank_of_original_entity = entity_rank();
78  for ( PairIterRelation irel = relations() ; irel.first != irel.second ; ) {
79  --irel.second;
80  Entity & entity = *(irel.second->entity());
81  if ( rank_of_original_entity >= entity.entity_rank() ) {
82  break; //we're done
83  }
84  else if ( entity.log_query() == EntityLogNoChange ) {
85  entity.m_entityImpl.log_modified_and_propagate();
86  }
87  }
88 
89 }
90 
91 void EntityImpl::compress_relation_capacity()
92 {
93  RelationVector tmp(m_relation);
94  tmp.swap(m_relation);
95 }
96 
97 void EntityImpl::log_created_parallel_copy()
98 {
99  TraceIfWatching("stk_classic::mesh::impl::EntityImpl::log_created_parallel_copy", LOG_ENTITY, key());
100 
101  if ( EntityLogCreated == m_mod_log ) {
102  m_mod_log = EntityLogModified ;
103  }
104 }
105 
106 bool EntityImpl::destroy_relation( Entity& e_to, const RelationIdentifier local_id )
107 {
108  TraceIfWatching("stk_classic::mesh::impl::EntityImpl::destroy_relation", LOG_ENTITY, key());
109 
110  bool destroyed_relations = false;
111  for ( RelationVector::iterator
112  i = m_relation.begin() ; i != m_relation.end() ; ++i ) {
113  if ( i->entity() == & e_to && i->identifier() == local_id ) {
114  i = m_relation.erase( i ); // invalidates iterators, but we're breaking so it's OK
115  destroyed_relations = true;
116  break;
117  }
118  }
119  return destroyed_relations;
120 }
121 
122 bool EntityImpl::declare_relation( Entity & e_to,
123  const RelationIdentifier local_id,
124  unsigned sync_count,
125  bool is_back_relation )
126 {
127  TraceIfWatching("stk_classic::mesh::impl::EntityImpl::declare_relation", LOG_ENTITY, key());
128 
129  const MetaData & meta_data = MetaData::get( bucket() );
130 
131  Relation new_relation( e_to , local_id );
132 #ifdef SIERRA_MIGRATION
133  new_relation.setRelationType( e_to.entity_rank() > entity_rank() ? Relation::USED_BY : Relation::USES );
134  new_relation.setOrientation(0);
135 #endif
136 
137  const RelationVector::iterator rel_end = m_relation.end();
138  RelationVector::iterator rel_begin = m_relation.begin();
139  RelationVector::iterator lower;
140 
141  lower = std::lower_bound( rel_begin , rel_end , new_relation , LessRelation() );
142 
143  // The ordering of the Relations allows for two situations that do
144  // not arise often in meshes. The first situation is 2 relations between
145  // e_from and e_to with the same kind but different local_ids. This
146  // can happen if, for example, a triangle should be used as a quad. In
147  // this case, one node of the triangle must be two different local nodes of
148  // the quad. This situation is a valid state of mesh entities.
149 
150  // The second situation involves malformed stencils. Given e_from, e_to1,
151  // and e_to2, e_to1 and eto2 can share a relation with e_from with the same
152  // kind and local_id. This can arise, for instance, if an edge has three
153  // nodes. The local_id 1 of the edge may point to two different nodes.
154  // This situation is disallowed in the mesh. We now check for it.
155 
156  // "Degenerate" -> case where we have two relations whose attributes
157  // (rel id + rel rank) match but point to different entities. It's
158  // OK for back-relations to be degenerate because there's nothing
159  // wrong with a node having several back-relations (with similar id)
160  // to different elements.
161 
162  // Check for bad degenerate relations (degenerate forward relations)
163  // Cannot be degenerate relation if there are no prior relations
164  if ( !m_relation.empty() && !is_back_relation ) {
165  // Since LessRelation takes the related entity into account, we must check
166  // the result of lower_bound AND the iter before to be sure this isn't a
167  // bad degenerate relation.
168  RelationVector::iterator start, end;
169  start = (lower == rel_begin) ? rel_begin : lower - 1;
170  end = (lower == rel_end) ? rel_end : lower + 1;
171 
172  for (RelationVector::iterator itr = start; itr != end; ++itr) {
173  ThrowErrorMsgIf( is_degenerate_relation ( new_relation , *itr ),
174  "Could not declare relation from " <<
175  print_entity_key( meta_data, key() ) << " to " <<
176  print_entity_key( meta_data, e_to.key() ) << ", with id " <<
177  local_id << ". Relation already exists to " <<
178  print_entity_key( meta_data, itr->entity()->key() ));
179  }
180  }
181 
182  bool not_already_exists = (rel_end == lower) ||
183  ( !is_back_relation && new_relation.raw_relation_id() != lower->raw_relation_id() ) ||
184  ( is_back_relation && new_relation != *lower );
185 
186  // If the relation does not already exist, we add it
187  if (not_already_exists) {
188  lower = m_relation.insert( lower , new_relation );
189 
190  set_sync_count( sync_count );
191 
192  return true;
193  }
194  else {
195  return false;
196  }
197 }
198 
199 void EntityImpl::set_key(EntityKey key)
200 {
201  m_key = key;
202 }
203 
204 void EntityImpl::update_key(EntityKey key)
205 {
206  m_key = key;
207 
208  std::sort(m_relation.begin(), m_relation.end(), LessRelation());
209  log_modified_and_propagate();
210 
211  for ( RelationVector::iterator i = m_relation.begin(), e = m_relation.end();
212  i != e;
213  ++i
214  )
215  {
216  EntityImpl & entity = i->entity()->m_entityImpl;
217  std::sort(entity.m_relation.begin(), entity.m_relation.end(), LessRelation());
218  entity.log_modified_and_propagate();
219  }
220 
221 }
222 
223 PairIterEntityComm EntityImpl::comm() const
224 {
225  return BulkData::get(bucket()).entity_comm(m_key);
226 }
227 
228 PairIterEntityComm EntityImpl::sharing() const
229 {
230  return BulkData::get(bucket()).entity_comm_sharing(m_key);
231 }
232 
233 PairIterEntityComm EntityImpl::comm( const Ghosting & sub ) const
234 {
235  return BulkData::get(bucket()).entity_comm(m_key,sub);
236 }
237 
238 bool EntityImpl::insert( const EntityCommInfo & val )
239 {
240  return BulkData::get(bucket()).entity_comm_insert(m_key,val);
241 }
242 
243 bool EntityImpl::erase( const EntityCommInfo & val )
244 {
245  return BulkData::get(bucket()).entity_comm_erase(m_key,val);
246 }
247 
248 bool EntityImpl::erase( const Ghosting & ghost )
249 {
250  return BulkData::get(bucket()).entity_comm_erase(m_key,ghost);
251 }
252 
253 void EntityImpl::comm_clear_ghosting()
254 {
255  return BulkData::get(bucket()).entity_comm_clear_ghosting(m_key);
256 }
257 
258 void EntityImpl::comm_clear()
259 {
260  return BulkData::get(bucket()).entity_comm_clear(m_key);
261 }
262 
263 } // namespace impl
264 } // namespace mesh
265 } // namespace stk_classic
266 
String lower(const String &s)
Function lower returns a lower case version of the string.
Definition: StringUtil.hpp:281
raw_relation_id_type raw_relation_id() const
The encoded relation raw_relation_id.
Definition: Relation.hpp:77
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
std::vector< Relation > RelationVector
Span of a sorted relations for a given domain entity.
Definition: Types.hpp:161
EntityRank entity_rank(const EntityKey &key)
Given an entity key, return an entity type (rank).
bool insert(PartVector &v, Part &part)
Insert a part into a properly ordered collection of parts. Returns true if this is a new insertion...
Definition: Part.cpp:85