Sierra Toolkit  Version of the Day
Entity.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 <stddef.h>
10 #include <stdexcept>
11 #include <iostream>
12 #include <sstream>
13 #include <algorithm>
14 
15 #include <stk_mesh/base/Entity.hpp>
16 #include <stk_mesh/base/BulkData.hpp>
17 #include <stk_mesh/base/MetaData.hpp>
18 
19 #ifdef SIERRA_MIGRATION
20 namespace {
21 static const std::vector<stk_classic::mesh::Relation> dummy_vector;
22 }
23 
24 namespace sierra {
25 namespace Fmwk {
26 
27 const unsigned int INVALID_LOCAL_ID = std::numeric_limits<unsigned int>::max();
28 const stk_classic::mesh::RelationIterator INVALID_RELATION_ITR = dummy_vector.end(); // Some STL implementation use POD for iterators
29 
30 unsigned get_derived_type(const stk_classic::mesh::Entity&);
31 
32 }
33 }
34 #endif
35 
36 namespace stk_classic {
37 namespace mesh {
38 
39 //----------------------------------------------------------------------
40 
41 std::string print_entity_key(const Entity& entity)
42 {
43  return print_entity_key(MetaData::get(entity),
44  entity.key());
45 }
46 
47 std::string print_entity_key(const Entity* entity)
48 {
49  if (entity == NULL) {
50  return "NULL ENTITY";
51  }
52  else {
53  return print_entity_key(*entity);
54  }
55 }
56 
57 
58 
59 
60 //
61 //----------------------------------------------------------------------
62 
63 #ifdef SIERRA_MIGRATION
64 
65 
66 std::string Entity::TypeToString (Entity::ObjectTypeEnum type) {
67  if(type == NODE ) return "NODE";
68  if(type == EDGE ) return "EDGE";
69  if(type == FACE ) return "FACE";
70  if(type == ELEMENT ) return "ELMENT";
71  if(type == CONSTRAINT) return "CONSTRANT";
72  if(type == BASE_CLASS) return "BASE_CLASS";
73  return "UNKNOWN";
74 
75  }
76 
77 
78 // ---------------------------------------------------------------------
79 
80 void Entity::compress_relation_capacity()
81 {
82  m_entityImpl.compress_relation_capacity();
83 #ifdef SIERRA_MIGRATION
84  if (!m_fmwk_attrs->aux_relations.empty()) {
85  RelationVector tmp(m_fmwk_attrs->aux_relations);
86  tmp.swap(m_fmwk_attrs->aux_relations);
87  }
88 #endif
89 }
90 
91 void Entity::internal_swap_in_real_entity(const int globalId)
92 {
93  ThrowRequire(globalId > 0);
94  m_fmwk_attrs->global_id = globalId;
95 
96  BulkData::get(*this).change_entity_id(globalId, *this);
97 
98  internal_verify_initialization_invariant();
99 
100  // Issue: Fmwk-managed relations (also called auxiliary relations, are not
101  // being resorted here, so we have to use a different < operator
102  // when looking for relations
103 
104 #ifndef NDEBUG
105  internal_verify_meshobj_invariant();
106 #endif
107 }
108 
109 // ---------------------------------------------------------------------
110 
111 void Entity::reserve_relation(const unsigned num)
112 {
113  if (num == 0 && aux_relations().empty()) {
114  RelationVector tmp;
115  aux_relations().swap(tmp); // clear memory of m_relations.
116  }
117  else {
118  aux_relations().reserve(num);
119  }
120 }
121 
122 // ---------------------------------------------------------------------
123 
124 namespace {
125 
126 struct IgnoreIdOrder
127 {
128  bool operator()(const Relation& lhs, const Relation& rhs)
129  {
130  bool result = false;
131 
132  if (lhs.entity_rank() != rhs.entity_rank()) {
133  result = lhs.entity_rank() < rhs.entity_rank();
134  }
135  else if (lhs.getRelationType() != rhs.getRelationType()) {
136  result = lhs.getRelationType() < rhs.getRelationType();
137  }
138  else {
139  result = lhs.identifier() < rhs.identifier();
140  }
141  return result;
142  }
143 };
144 
145 }
146 
147 RelationIterator Entity::find_relation(const Relation& relation) const
148 {
149  // Extremely hacky: It would be better to set up the < operator for relations so that lower_bound
150  // can return the desired iterator, but any sane definition would probably force a change in
151  // relation ordering and that's more than I'm willing to take on now.
152  //
153  // The current semantics for relation-searching is as follows:
154  // Ordered based on derived_type, relation_type, and ordinal in descending precedence
155  // If multiple relations have the same derived_type, relation_type, and ordinal, a linear
156  // scan takes place looking for a matching meshobj. If no such meshobj was found, then
157  // we are left with an iterator pointing to the first relation with a different derived_type,
158  // relation_type, or ordinal. To sum up, the result of the search can either be equivalent to
159  // lower_bound OR upper_bound depending upon the state of the relations... YUCK!
160 
161  const Relation::RelationType relation_type = relation.getRelationType();
162 
163  RelationIterator rel = std::lower_bound(internal_begin_relation(relation_type),
164  internal_end_relation(relation_type),
165  relation,
166  IgnoreIdOrder());
167 
168  // Should only loop if we are looking at back-relations, otherwise, relations with
169  // matching specifications are not legal.
170  while (rel != internal_end_relation(relation_type) &&
171  same_specification(*rel, relation) &&
172  rel->getMeshObj() != relation.getMeshObj())
173  ++rel;
174 
175  return rel;
176 }
177 
178 // ---------------------------------------------------------------------
179 
180 bool Entity::update_relation(
181  const RelationIterator ir ,
182  const bool back_rel_flag) const
183 {
184  const Relation::RelationType relType = ir->getRelationType();
185  ThrowAssert(verify_relation_ordering(internal_begin_relation(relType), internal_end_relation(relType)));
186  ThrowAssertMsg(!internal_is_handled_generically(relType),
187  "update_relation should not be called for STK-managed relations");
188 
189  Entity & meshObj = *ir->getMeshObj() ;
190 
191  const Relation::RelationType backRelType = back_relation_type(relType);
192 
193  ThrowAssert(verify_relation_ordering(meshObj.internal_begin_relation(backRelType), meshObj.internal_end_relation(backRelType)));
194 
195  // Create the corresponding back relation to ir
196  Relation backRel_obj(const_cast<Entity*>(this), backRelType, ir->getOrdinal(), ir->getOrientation());
197  RelationIterator backRel_itr = meshObj.find_relation(backRel_obj);
198 
199  const bool exists = backRel_itr != meshObj.internal_end_relation(backRelType) && *backRel_itr == backRel_obj;
200 
201  if (exists && !back_rel_flag) {
202  // Remove back relation and increment the counter
203 
204  meshObj.erase_and_clear_if_empty(backRel_itr);
205 
206  //ThrowAssert(sierra::Fmwk::get_derived_type(meshObj) != Entity::ELEMENT);
207 
208  meshObj.inc_connection();
209  }
210  else if (!exists && back_rel_flag) {
211  // Insert back relation
212 
213  const unsigned k = backRel_itr - meshObj.internal_begin_relation(backRelType) ;
214 
215  meshObj.reserve_relation(meshObj.aux_relations().size() + 1);
216 
217  meshObj.aux_relations().insert(meshObj.aux_relations().begin() + k, backRel_obj);
218 
219  //ThrowAssert(sierra::Fmwk::get_derived_type(meshObj) != Entity::ELEMENT);
220 
221  meshObj.dec_connection();
222  }
223 
224  ThrowAssert(verify_relation_ordering(meshObj.internal_begin_relation(relType), meshObj.internal_end_relation(relType)));
225 
226  return true;
227 }
228 
229 // ---------------------------------------------------------------------
230 
231 void Entity::erase_and_clear_if_empty(RelationIterator rel_itr)
232 {
233  ThrowRequire(!internal_is_handled_generically(rel_itr->getRelationType()));
234 
235  RelationVector& aux_relations = m_fmwk_attrs->aux_relations;
236  aux_relations.erase(aux_relations.begin() + (rel_itr - aux_relations.begin())); // Need to convert to non-const iterator
237 
238  if (aux_relations.empty()) {
239  reserve_relation(0);
240  }
241 }
242 
243 // ---------------------------------------------------------------------
244 
245 void Entity::internal_verify_meshobj_invariant() const
246 {
247  PairIterRelation stk_relations = relations();
248  for ( ; !stk_relations.empty(); ++stk_relations ) {
249  ThrowRequireMsg(stk_relations->getMeshObj() != NULL, "Problem with: " << *stk_relations);
250  }
251 
252  RelationVector& aux_relations = m_fmwk_attrs->aux_relations;
253  for (RelationVector::const_iterator itr = aux_relations.begin(), end = aux_relations.end(); itr != end; ++itr) {
254  ThrowRequireMsg(itr->getMeshObj() != NULL, "Problem with: " << *itr);
255  }
256 }
257 
258 // ---------------------------------------------------------------------
259 
260 void Entity::set_relation_orientation(RelationIterator rel, unsigned orientation)
261 {
262  const Relation::RelationType backRelType = back_relation_type(rel->getRelationType());
263 
264  Entity & meshObj = *rel->getMeshObj();
265  Relation backRel_obj(const_cast<Entity*>(this), backRelType, rel->getOrdinal(), rel->getOrientation());
266  RelationIterator backRel_itr = meshObj.find_relation(backRel_obj);
267 
268  const bool exists = backRel_itr != meshObj.internal_end_relation(backRelType) && *backRel_itr == backRel_obj;
269  ThrowRequire(exists);
270 
271  // Allow clients to make changes to orientation
272  // Orientations do not affect Relation ordering, so this is safe.
273  const_cast<Relation*>(&*rel)->setOrientation(orientation);
274  const_cast<Relation*>(&*backRel_itr)->setOrientation(orientation);
275 }
276 
277 #endif
278 
279 } // namespace mesh
280 } // namespace stk_classic
281 
Definition: Env.cpp:53
const EntityKey & key() const
The globally unique key ( entity type + identifier ) of this entity.
Definition: Entity.hpp:138
PairIterRelation relations() const
All Entity relations for which this entity is a member. The relations are ordered from lowest entity-...
Definition: Entity.hpp:161
A fundamental unit within the discretization of a problem domain, including but not limited to nodes...
Definition: Entity.hpp:120
Sierra Toolkit.
std::vector< Relation > RelationVector
Span of a sorted relations for a given domain entity.
Definition: Types.hpp:161