Sierra Toolkit  Version of the Day
UnitTestPart.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 <sstream>
10 #include <stdexcept>
11 
12 #include <stk_util/unit_test_support/stk_utest_macros.hpp>
13 
14 #include <stk_util/parallel/Parallel.hpp>
15 
16 #include <stk_mesh/fem/FEMMetaData.hpp>
17 #include <stk_mesh/fem/FEMHelpers.hpp>
18 
19 #include <stk_mesh/base/MetaData.hpp>
20 #include <stk_mesh/base/Part.hpp>
21 #include <stk_mesh/baseImpl/PartRepository.hpp>
22 #include <stk_mesh/base/FieldRelation.hpp>
23 #include <stk_mesh/base/PartRelation.hpp>
24 
29 using stk_classic::mesh::impl::PartRepository;
30 
31 namespace {
32 
33 STKUNIT_UNIT_TEST(UnitTestPart, testUnit)
34 {
35  const int spatial_dimension = 3;
36  MetaData m(stk_classic::mesh::fem::entity_rank_names(spatial_dimension));
37  PartRepository partRepo(&m);
38  PartRepository partRepo2(&m);
39  PartRepository partRepo3(&m);
40  PartRepository partRepo4(&m);
41  Part & universal = *partRepo.universal_part();
42  PartVector intersection;
43  PartVector intersection2;
44  PartVector intersection4;
45  PartVector intersection5;
46  m.commit();
47 
48  STKUNIT_ASSERT( universal.supersets().empty() );
49  STKUNIT_ASSERT( 1u == partRepo.get_all_parts().size() );
50 
51  //--------------------------------------------------------------------
52  // Test multiple part creation
53 
54  enum { NPARTS = 100 };
55 
56  Part * parts[NPARTS];
57 
58  parts[0] = & universal ;
59 
60  for ( int i = 1 ; i < NPARTS-1 ; ++i ) {
61  std::ostringstream name ;
62  name << "Part_" << i ;
63  parts[i] = partRepo.declare_part( name.str() , 0 );
64  }
65  parts[99] = partRepo.declare_part( "Part_99" , 1 );
66 
67  STKUNIT_ASSERT( universal.supersets().empty() );
68  STKUNIT_ASSERT( NPARTS == partRepo.get_all_parts().size() );
69  STKUNIT_ASSERT_EQUAL( partRepo.get_all_parts()[0] , & universal );
70 
71  for ( unsigned i = 1 ; i < NPARTS ; ++i ) {
72  STKUNIT_ASSERT( parts[i]->subsets().empty() );
73  STKUNIT_ASSERT( parts[i]->intersection_of().empty() );
74  STKUNIT_ASSERT( parts[i]->mesh_meta_data_ordinal() == i );
75  STKUNIT_ASSERT( 1u == parts[i]->supersets().size() );
76  STKUNIT_ASSERT( & universal == parts[i]->supersets()[0] );
77  STKUNIT_ASSERT_EQUAL( parts[i] , universal.subsets()[i-1] );
78  STKUNIT_ASSERT_EQUAL( parts[i] , find( universal.subsets() , parts[i]->name() ) );
79  }
80 
81  //--------------------------------------------------------------------
82  // Test multiple parts and transitive subset declarations:
83 
84  partRepo.declare_subset( * parts[3], * parts[4] );
85  partRepo.declare_subset( * parts[4], * parts[5] );
86 
87  partRepo.declare_subset( * parts[1], * parts[2] );
88  // 1 and 2 pick up 4 and 5 via transitive relationship:
89  partRepo.declare_subset( * parts[2], * parts[3] );
90 
91  STKUNIT_ASSERT( 4u == parts[1]->subsets().size() );
92  STKUNIT_ASSERT( 3u == parts[2]->subsets().size() );
93  STKUNIT_ASSERT( 2u == parts[3]->subsets().size() );
94  STKUNIT_ASSERT( 1u == parts[4]->subsets().size() );
95  STKUNIT_ASSERT( 0u == parts[5]->subsets().size() );
96 
97  STKUNIT_ASSERT( contain( parts[1]->subsets() , * parts[2] ) );
98  STKUNIT_ASSERT( contain( parts[1]->subsets() , * parts[3] ) );
99  STKUNIT_ASSERT( contain( parts[1]->subsets() , * parts[4] ) );
100  STKUNIT_ASSERT( contain( parts[1]->subsets() , * parts[5] ) );
101 
102  STKUNIT_ASSERT( contain( parts[5]->supersets() , * parts[1] ) );
103  STKUNIT_ASSERT( contain( parts[5]->supersets() , * parts[2] ) );
104  STKUNIT_ASSERT( contain( parts[5]->supersets() , * parts[3] ) );
105  STKUNIT_ASSERT( contain( parts[5]->supersets() , * parts[4] ) );
106 
107  //--------------------------------------------------------------------
108  // Test declaration of an intersection part
109 
110  intersection.push_back( parts[1] );
111  intersection.push_back( parts[2] );
112  intersection.push_back( parts[3] );
113  intersection.push_back( parts[4] ); // Smallest subset of 1..4
114 
115  // Test filtering of trivial intersection
116 
117  STKUNIT_ASSERT( parts[4] == partRepo.declare_part( intersection ) );
118 
119  // Test non-trivial intersection:
120 
121  intersection.push_back( parts[6] );
122  intersection.push_back( parts[7] );
123 
124  Part & pint_4_6_7 = * partRepo.declare_part( intersection );
125 
126  STKUNIT_ASSERT( 3u == pint_4_6_7.intersection_of().size() );
127  STKUNIT_ASSERT( contain( pint_4_6_7.intersection_of() , * parts[4] ) );
128  STKUNIT_ASSERT( contain( pint_4_6_7.intersection_of() , * parts[6] ) );
129  STKUNIT_ASSERT( contain( pint_4_6_7.intersection_of() , * parts[7] ) );
130 
131  STKUNIT_ASSERT( 7u == pint_4_6_7.supersets().size() );
132 
133  // Test redeclaration of intersection, should give the same part back:
134 
135  STKUNIT_ASSERT( pint_4_6_7 == * partRepo.declare_part( intersection ) );
136 
137  partRepo.declare_subset( pint_4_6_7, * parts[8] );
138 
139  //--------------------------------------------------------------------
140  // Test intersection-induced subset relationship
141 
142  partRepo.declare_subset( * parts[7], * parts[10] );
143  STKUNIT_ASSERT( ! contain( pint_4_6_7.subsets() , * parts[10] ) );
144 
145  partRepo.declare_subset( * parts[6], * parts[10] );
146  STKUNIT_ASSERT( ! contain( pint_4_6_7.subsets() , * parts[10] ) );
147 
148  partRepo.declare_subset( * parts[3], * parts[10] );
149  STKUNIT_ASSERT( ! contain( pint_4_6_7.subsets() , * parts[10] ) );
150 
151  partRepo.declare_subset( * parts[4], * parts[10] );
152  STKUNIT_ASSERT( contain( pint_4_6_7.subsets() , * parts[10] ) );
153 
154  // Test intersection-induced subset relationship triggered from a subset
155 
156  partRepo.declare_subset( * parts[7], * parts[11] );
157  STKUNIT_ASSERT( ! contain( pint_4_6_7.subsets() , * parts[11] ) );
158 
159  partRepo.declare_subset( * parts[6], * parts[11] );
160  STKUNIT_ASSERT( ! contain( pint_4_6_7.subsets() , * parts[11] ) );
161 
162  partRepo.declare_subset( * parts[3], * parts[11] );
163  STKUNIT_ASSERT( ! contain( pint_4_6_7.subsets() , * parts[11] ) );
164 
165  partRepo.declare_subset( * parts[5], * parts[11] );
166  STKUNIT_ASSERT( contain( pint_4_6_7.subsets() , * parts[11] ) );
167 
168  std::cout << std::endl << "Part: test intersection generated" << std::endl ;
169  print( std::cout , " " , pint_4_6_7 );
170  print( std::cout , " " , * parts[10] );
171  print( std::cout , " " , * parts[11] );
172 
173  std::cout << std::endl ;
174 
175  //Test to cover assert_same_universe in PartRepository - Part is not in the same universe
176  {
177  std::vector< std::string > dummy_names(1);
178  dummy_names[0].assign("dummy");
179 
180  stk_classic::mesh::MetaData meta2( dummy_names );
181 
182  stk_classic::mesh::Part &part_not_in_same_universe = meta2.declare_part ( "part_not_in_same_universe");
183  meta2.commit();
184 
185  intersection4.push_back( &part_not_in_same_universe );
186 
187  PartVector::const_iterator i = intersection4.begin() ;
188  Part * const p = *i ;
189  STKUNIT_ASSERT_THROW(
190  partRepo3.declare_subset(*parts[5], *p),
191  std::runtime_error
192  );
193  }
194 
195  //Test to cover assert_not_superset in PartRepository - parts[11] is not a superset of parts[7]
196  {
197  STKUNIT_ASSERT_THROW(
198  partRepo.declare_subset(*parts[11], *parts[7] ),
199  std::runtime_error
200  );
201  }
202 
203  //Test to cover assert_not_superset in PartRepository - parts[99] is not the same rank of parts[11]
204  {
205  STKUNIT_ASSERT_THROW(
206  partRepo.declare_subset(*parts[11], *parts[99] ),
207  std::runtime_error
208  );
209  }
210 
211  //Test to cover declare_part(arg_name, arg_rank) - Part_99 of rank 1 already exists..
212  {
213  STKUNIT_ASSERT_THROW(
214  partRepo.declare_part("Part_99", 0 ),
215  std::runtime_error
216  );
217  }
218 
219  //Test to cover declare_part(const PartVector & part_intersect) in PartRepository - failed from malicious abuse
220  {
221  int ok = 0 ;
222  try {
223  //create part with intersection
224 
225  // Test declaration of an intersection part
226 
227  enum { NPARTS = 100 };
228 
229  Part * parts2[ NPARTS ] ;
230 
231  parts2[0] = & universal ;
232 
233  for ( int i = 1 ; i < NPARTS-1 ; ++i ) {
234  std::ostringstream name ;
235  name << "Part_" << i ;
236  parts2[i] = partRepo4.declare_part( name.str() , 0 );
237  }
238 
239  partRepo4.declare_subset( * parts2[3], * parts2[4] );
240  partRepo4.declare_subset( * parts2[4], * parts2[5] );
241 
242  partRepo4.declare_subset( * parts2[1], * parts2[2] );
243  // 1 and 2 pick up 4 and 5 via transitive relationship:
244  partRepo4.declare_subset( * parts2[2], * parts2[3] );
245 
246  intersection5.push_back( parts2[1] );
247  intersection5.push_back( parts2[2] );
248  intersection5.push_back( parts2[3] );
249  intersection5.push_back( parts2[4] ); // Smallest subset of 1..4
250  intersection5.push_back( parts2[6] );
251  intersection5.push_back( parts2[7] );
252 
253  Part & partB = * partRepo2.declare_part("{Part_4^Part_6^Part_7}", 0);
254 
255  std::cout << "UnitTestPart name of partB is " << partB.name() << std::endl ;
256 
257  Part & pintersect_4_6_7 = * partRepo2.declare_part( intersection5 );
258 
259  std::cout << "UnitTestPart name of intersection part, pintersect_4_6_7 is " << pintersect_4_6_7.name() << std::endl ;
260  }
261  catch( const std::exception & x ) {
262  ok = 1 ;
263  std::cout << "UnitTestPart CORRECTLY caught error for : "
264  << x.what()
265  << std::endl ;
266  }
267 
268  if ( ! ok ) {
269  throw std::runtime_error("UnitTestPart FAILED to catch error for declare_part in PartRepository");
270  }
271  }
272 }
273 
274 STKUNIT_UNIT_TEST(UnitTestPart, testPartNotaSubset)
275 {
276  //Test to cover assert_contain in PartRepository - Part is not a subset
277  const int spatial_dimension = 3;
278  MetaData m(stk_classic::mesh::fem::entity_rank_names(spatial_dimension));
279  PartVector intersection;
280  PartRepository partRepo(&m);
281 
282  stk_classic::mesh::Part &part_not_a_subset = m.declare_part ( "part_not_a_subset");
283  m.commit();
284 
285  intersection.push_back( &part_not_a_subset );
286 
287  STKUNIT_ASSERT_THROW(
288  partRepo.declare_part(intersection),
289  std::runtime_error
290  );
291 }
292 
293 //----------------------------------------------------------------------
294 
295 STKUNIT_UNIT_TEST(UnitTestPart, testPartVector)
296 {
297  const int spatial_dimension = 3;
298  MetaData m(stk_classic::mesh::fem::entity_rank_names(spatial_dimension));
299  PartRepository partRepo(&m);
300 
301  Part * const pa = partRepo.declare_part( std::string("a") , 0 );
302  Part * const pb = partRepo.declare_part( std::string("b") , 0 );
303  Part * const pc = partRepo.declare_part( std::string("c") , 0 );
304  Part * const pd = partRepo.declare_part( std::string("d") , 0 );
305  Part * const pe = partRepo.declare_part( std::string("e") , 0 );
306  Part * const pf = partRepo.declare_part( std::string("f") , 0 );
307 
308  STKUNIT_ASSERT( ! intersect( *pa , *pb ) );
309  STKUNIT_ASSERT( ! intersect( *pb , *pc ) );
310  STKUNIT_ASSERT( ! intersect( *pc , *pd ) );
311  STKUNIT_ASSERT( ! intersect( *pd , *pe ) );
312  STKUNIT_ASSERT( ! intersect( *pe , *pf ) );
313  STKUNIT_ASSERT( ! intersect( *pf , *pa ) );
314 
315  PartVector vabc , vbcd , vdef , vresult ;
316 
317  vabc.push_back( pa );
318  vabc.push_back( pb );
319  vabc.push_back( pc );
320 
321  vbcd.push_back( pb );
322  vbcd.push_back( pc );
323  vbcd.push_back( pd );
324 
325  vdef.push_back( pd );
326  vdef.push_back( pe );
327  vdef.push_back( pf );
328 
329  order( vabc );
330  order( vbcd );
331  order( vdef );
332 
333  vresult.clear();
334  STKUNIT_ASSERT_EQUAL( size_t(2) , intersect( vabc , vbcd ) );
335  size_t intersect_size = intersect( vabc , vbcd , vresult );
336  STKUNIT_ASSERT_EQUAL( size_t(2) , intersect_size );
337  STKUNIT_ASSERT_EQUAL( pb , vresult[0] );
338  STKUNIT_ASSERT_EQUAL( pc , vresult[1] );
339 
340  vresult.clear();
341  STKUNIT_ASSERT_EQUAL( size_t(1) , intersect( vdef , vbcd ) );
342  intersect_size = intersect( vdef , vbcd , vresult );
343  STKUNIT_ASSERT_EQUAL( size_t(1) , intersect_size );
344  STKUNIT_ASSERT_EQUAL( pd , vresult[0] );
345 
346  vresult.clear();
347  STKUNIT_ASSERT_EQUAL( size_t(0) , intersect( vdef , vabc ) );
348  intersect_size = intersect( vdef , vabc , vresult );
349  STKUNIT_ASSERT_EQUAL( size_t(0) , intersect_size );
350  STKUNIT_ASSERT_EQUAL( size_t(0) , vresult.size() );
351 
352  Part * const pabc = partRepo.declare_part( std::string("abc") , 0 );
353  Part * const pbcd = partRepo.declare_part( std::string("bcd") , 0 );
354  Part * const pdef = partRepo.declare_part( std::string("def") , 0 );
355 
356  partRepo.declare_subset( * pabc, *pa );
357  partRepo.declare_subset( * pabc, *pb );
358  partRepo.declare_subset( * pabc, *pc );
359 
360  partRepo.declare_subset( * pbcd, *pb );
361  partRepo.declare_subset( * pbcd, *pc );
362  partRepo.declare_subset( * pbcd, *pd );
363 
364  partRepo.declare_subset( * pdef, *pd );
365  partRepo.declare_subset( * pdef, *pe );
366  partRepo.declare_subset( * pdef, *pf );
367 
368  STKUNIT_ASSERT( intersect( *pabc , *pa ) );
369  STKUNIT_ASSERT( intersect( *pabc , *pb ) );
370  STKUNIT_ASSERT( intersect( *pabc , *pc ) );
371  STKUNIT_ASSERT( intersect( *pa , *pabc ) );
372  STKUNIT_ASSERT( intersect( *pb , *pabc ) );
373  STKUNIT_ASSERT( intersect( *pc , *pabc ) );
374 
375  STKUNIT_ASSERT( intersect( *pabc , *pbcd ) );
376  STKUNIT_ASSERT( ! intersect( *pabc , *pdef ) );
377 }
378 
379 // Unit test the PartRelation copy constructor:
380 STKUNIT_UNIT_TEST(UnitTestPart, testPartRelation)
381 {
382  PartRelation rA;
383  PartRelation rB( rA);
384 
385  rA = rB;
386 }
387 
388 } // empty namespace
std::ostream & print(std::ostream &os, const std::string &indent, const Bucket &bucket)
Print the parts and entities of this bucket.
Definition: Bucket.cpp:259
The manager of an integrated collection of parts and fields.
Definition: MetaData.hpp:56
void order(PartVector &v)
Order a collection of parts: invoke sort and then unique.
Definition: Part.cpp:76
size_t intersect(const PartVector &v, const PartVector &p)
Query cardinality of intersection of two PartVectors.
Definition: Part.cpp:141
An application-defined subset of a problem domain.
Definition: Part.hpp:49
bool contain(const PartVector &v, const Part &part)
Query containment within properly ordered PartVector.
Definition: Part.cpp:108
const PartVector & intersection_of() const
Parts for which this part is defined as the intersection.
Definition: Part.hpp:81
const std::string & name() const
Application-defined text name of this part.
Definition: Part.hpp:67
const PartVector & supersets() const
Parts that are supersets of this part.
Definition: Part.hpp:75
const PartVector & subsets() const
Parts that are subsets of this part.
Definition: Part.hpp:78
A defined entity-relationship between parts. An internal class that should never need to be directly...
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