Sierra Toolkit  Version of the Day
PartRepository.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 <stdexcept>
10 #include <sstream>
11 
12 #include <stk_util/environment/ReportHandler.hpp>
13 
14 #include <stk_mesh/base/Part.hpp>
15 #include <stk_mesh/base/Types.hpp>
16 #include <stk_mesh/base/Trace.hpp>
17 
18 #include <stk_mesh/baseImpl/PartRepository.hpp>
19 
20 #include <stdlib.h>
21 
22 #include <iostream>
23 
24 namespace stk_classic {
25 namespace mesh {
26 namespace impl {
27 
28 namespace {
29 
30 inline
31 std::string universal_part_name()
32 {
33  static const std::string name = convert_to_internal_name("UNIVERSAL");
34  return name;
35 }
36 
37 void assert_same_universe( const Part & superset ,
38  const Part & subset,
39  const char * method )
40 {
41  const PartVector & a = superset.supersets();
42  const PartVector & b = subset.supersets();
43 
44  ThrowErrorMsgIf( a.empty() || b.empty() || a[0] != b[0],
45  method << "(...) FAILED Requirement that " <<
46  "Part[" << superset.name() << "] and " <<
47  "Part[" << subset.name() << "] are in the same " <<
48  universal_part_name() );
49 }
50 
51 void assert_same( const Part & part1 ,
52  const Part & part2,
53  const char * method )
54 {
55  ThrowErrorMsgIf( & part1 != & part2,
56  method << "(...) FAILED Requirement that " <<
57  "Part[" << part1.name() << "] and " <<
58  "Part[" << part2.name() << "] are the same" );
59 }
60 
61 void assert_not_same( const Part & part1 ,
62  const Part & part2 ,
63  const char * method )
64 {
65  ThrowErrorMsgIf( & part1 == & part2,
66  method << "(...) FAILED Requirement that " <<
67  "Part[" << part1.name() << "] and " <<
68  "Part[" << part2.name() << "] are not the same" );
69 }
70 
71 void assert_superset( Part & superset ,
72  Part & subset ,
73  const char * method )
74 {
75  ThrowErrorMsgIf( ! contain( subset.supersets() , superset ),
76  method << "(...) FAILED Requirement that " <<
77  "Part[" << superset.name() << "] " <<
78  "is a superset of " <<
79  "Part[" << subset.name() << "]" );
80 }
81 
82 void assert_not_superset( const Part & superset ,
83  const Part & subset ,
84  const char * method )
85 {
86  ThrowErrorMsgIf( contain( subset.supersets() , superset ),
87  method << "(...) FAILED Requirement that " <<
88  "Part[" << superset.name() << "] " <<
89  "is not a superset of " <<
90  "Part[" << subset.name() << "]" );
91 }
92 
93 void assert_rank_ordering( const Part & superset ,
94  const Part & subset ,
95  const char * method )
96 {
97  ThrowErrorMsgIf( superset.primary_entity_rank() < subset.primary_entity_rank(),
98  method << "(...) FAILED Requirement that " <<
99  "Part[ " << superset.name() <<
100  " , rank(" << superset.primary_entity_rank() <<
101  ") ] has greater rank than " <<
102  "Part[ " << subset.name() <<
103  " , rank(" << subset.primary_entity_rank() << ") ]");
104 }
105 
106 } // namespace
107 
108 
109 Part * PartRepository::universal_part() const
110 {
111  return m_universal_part;
112 }
113 
114 const PartVector & PartRepository::get_all_parts() const
115 {
116  return m_all_parts;
117 }
118 
119 Part * PartRepository::declare_part( const std::string & arg_name , EntityRank arg_rank )
120 {
121  Trace_("stk_classic::mesh::impl::PartRepository::declare_part");
122 
123  const PartVector & all_parts = get_all_parts();
124  Part * p = find( all_parts, arg_name );
125 
126  if ( p == NULL ) {
127  p = declare_part_impl( arg_name, arg_rank );
128  }
129  else {
130  p->m_partImpl.set_primary_entity_rank(arg_rank);
131  }
132 
133  return p;
134 }
135 
136 Part * PartRepository::declare_part( const PartVector & part_intersect )
137 {
138  static const char method[] = "stk_classic::mesh::impl::PartRepository::declare_part" ;
139  Trace_(method);
140 
141  PartVector pset_clean ;
142 
143  for ( PartVector::const_iterator
144  i = part_intersect.begin() ; i != part_intersect.end() ; ++i ) {
145  Part * const p = *i ;
146  assert_superset( *m_universal_part, *p , method );
147 
148  // If 'p' is a superset of another member
149  // then it is redundant in this intersection.
150  // Only keep non-redundant intersections.
151 
152  PartVector::const_iterator j = part_intersect.begin();
153  for ( ; j != part_intersect.end() &&
154  ! contain( (*j)->supersets() , *p ) ; ++j );
155  if ( j == part_intersect.end() ) {
156  pset_clean.push_back( p );
157  }
158  }
159 
160  // Sort and unique the intersection
161  order( pset_clean );
162 
163  Part * p = NULL ;
164  if ( 1 == pset_clean.size() ) {
165  // Only one remaining part, it is the subset.
166  p = pset_clean[0] ;
167  }
168  else {
169  const char separator[] = "^" ;
170  // Generate a name and rank reflecting the intersection.
171  // Rank is the minimum rank of the intersection members.
172 
173  std::string p_name ;
174  EntityRank p_rank = InvalidEntityRank;
175 
176  p_name.assign("{");
177  for ( PartVector::iterator
178  i = pset_clean.begin() ; i != pset_clean.end() ; ++i ) {
179  if ( i != pset_clean.begin() ) { p_name.append( separator ); }
180  p_name.append( (*i)->name() );
181  if ( (*i)->primary_entity_rank() < p_rank ) {
182  p_rank = (*i)->primary_entity_rank();
183  }
184  }
185  p_name.append("}");
186 
187  const PartVector & all_parts = get_all_parts();
188  p = find( all_parts, p_name );
189  if ( p == NULL ) {
190  // Create the part:
191 
192  p = declare_part_impl( p_name , p_rank );
193 
194  // Define the part to be an intersection of the given parts:
195 
196  p->m_partImpl.set_intersection_of( pset_clean );
197 
198  for ( PartVector::iterator
199  i = pset_clean.begin() ; i != pset_clean.end() ; ++i ) {
200  declare_subset( **i, *p );
201  }
202  }
203  else {
204  // This error is "inconceivable" and is
205  // only possible by heroic malicious abuse.
206  ThrowInvalidArgMsgIf( pset_clean != p->intersection_of(),
207  p_name << " FAILED FROM MALICIOUS ABUSE" );
208  }
209  }
210 
211  return p ;
212 }
213 
214 
215 Part * PartRepository::declare_part_impl( const std::string & name, EntityRank rank)
216 {
217  size_t ordinal = get_all_parts().size();
218  Part * part = new Part(m_meta_data,name,rank,ordinal);
219  declare_subset_impl(*m_universal_part, *part);
220  m_all_parts.push_back(part);
221  return part;
222 }
223 
224 
225 void PartRepository::declare_subset_impl( Part & superset_part, Part & subset_part )
226 {
227  superset_part.m_partImpl.add_part_to_subset( subset_part );
228  subset_part.m_partImpl.add_part_to_superset( superset_part );
229 }
230 
231 
232 void PartRepository::declare_subset( Part & superset, Part & subset )
233 {
234  static const char method[] = "stk_classic::mesh::impl::PartRepository::declare_subset" ;
235  Trace_(method);
236 
237  if ( ! contain( subset.supersets() , superset ) ) {
238 
239  assert_not_same( superset , subset , method );
240  assert_not_superset( superset , subset , method );
241  assert_same_universe( superset , subset , method );
242  assert_rank_ordering( superset , subset , method );
243 
244  // Insert this symmetric relationship first
245  // so that it does not get revisited.
246 
247  declare_subset_impl( superset, subset );
248 
249  // Transitive:
250 
251  const PartVector & subset_subsets = subset.subsets();
252  for ( PartVector::const_iterator
253  i = subset_subsets.begin() ; i != subset_subsets.end() ; ++i ) {
254  declare_subset( superset, **i );
255  }
256 
257  const PartVector & superset_supersets = superset.supersets();
258  for ( PartVector::const_iterator
259  i = superset_supersets.begin() ; i != superset_supersets.end() ; ++i ) {
260  declare_subset( **i, subset );
261  }
262 
263  // Induced intersection-part membership:
264 
265  const PartVector & superset_subsets = superset.subsets();
266  for ( PartVector::const_iterator
267  i = superset_subsets.begin() ;
268  i != superset_subsets.end() ; ++i ) {
269 
270  Part & pint = **i ;
271 
272  if ( ! pint.intersection_of().empty() && ( & pint != & subset ) ) {
273 
274  // If 'subset' is a subset of every member of 'pint.intersection_of()'
275  // then it is by definition a subset of 'pint.
276  if ( contain( subset.supersets() , pint.intersection_of() ) ) {
277  declare_subset( pint, subset );
278  }
279  }
280  }
281  }
282 }
283 
284 
285 void PartRepository::declare_part_relation( Part & root_part, PartRelation relation, Part & target_part )
286 {
287  static const char method[] = "stk_classic::mesh::impl::PartRepository::declare_part_relation" ;
288  Trace_(method);
289 
290  assert_not_same( root_part , target_part , method );
291  assert_same_universe( root_part , target_part , method );
292  assert_same( root_part , *relation.m_root , method );
293  assert_same( target_part , *relation.m_target , method );
294 
295  root_part.m_partImpl.add_relation( relation );
296  target_part.m_partImpl.add_relation( relation );
297 }
298 
299 
300 PartRepository::PartRepository(MetaData * meta)
301  : m_meta_data(meta),
302  m_universal_part(NULL),
303  m_all_parts()
304 {
305  m_universal_part = new Part( m_meta_data, universal_part_name(), ~0u, 0 );
306  m_all_parts.push_back(m_universal_part);
307 }
308 
309 PartRepository::~PartRepository()
310 {
311  try {
312  for ( PartVector::const_iterator i = m_all_parts.begin() ;
313  i != m_all_parts.end() ; ++i) {
314  Part * part = *i ;
315  try { delete part ; } catch(...) {}
316  }
317  } catch(...){}
318 }
319 
320 } // namespace impl
321 } // namespace mesh
322 } // namespace stk_classic
323 
void order(PartVector &v)
Order a collection of parts: invoke sort and then unique.
Definition: Part.cpp:76
bool contain(const PartVector &v, const Part &part)
Query containment within properly ordered PartVector.
Definition: Part.cpp:108
Part & declare_part(FEMMetaData &meta_data, const std::string &name)
Declare a part with a given cell topology. This is just a convenient function that wraps FEMMetaData&#39;...
Definition: FEMHelpers.hpp:93
Sierra Toolkit.
std::vector< Part *> PartVector
Collections of parts are frequently maintained as a vector of Part pointers.
Definition: Types.hpp:31
Part * find(const PartVector &parts, const std::string &name)
Find a part by name in a collection of parts.
Definition: Part.cpp:22