Sierra Toolkit  Version of the Day
UnitTestBucket.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 
10 #include <sstream>
11 #include <stdexcept>
12 
13 #include <stk_util/unit_test_support/stk_utest_macros.hpp>
14 
15 #include <stk_util/parallel/Parallel.hpp>
16 
17 #include <stk_mesh/base/MetaData.hpp>
18 #include <stk_mesh/base/BulkData.hpp>
19 #include <stk_mesh/base/GetEntities.hpp>
20 #include <stk_mesh/base/Field.hpp>
21 #include <stk_mesh/base/FieldData.hpp>
22 #include <stk_mesh/base/Comm.hpp>
23 #include <stk_mesh/base/EntityComm.hpp>
24 #include <stk_mesh/base/Part.hpp>
25 #include <stk_mesh/base/Entity.hpp>
26 #include <stk_mesh/base/GetBuckets.hpp>
27 #include <stk_mesh/base/Bucket.hpp>
28 #include <stk_mesh/base/BulkModification.hpp>
29 #include <stk_mesh/base/Entity.hpp>
30 #include <stk_mesh/base/Bucket.hpp>
31 #include <stk_mesh/base/Ghosting.hpp>
32 
33 #include <stk_mesh/fem/FEMMetaData.hpp>
34 #include <stk_mesh/fem/FEMHelpers.hpp>
35 
36 #include <stk_mesh/baseImpl/BucketImpl.hpp>
37 
38 #include <stk_mesh/fixtures/BoxFixture.hpp>
39 
40 #include <Shards_BasicTopologies.hpp>
41 
47 using stk_classic::mesh::EntityRank;
48 using stk_classic::mesh::EntityId;
52 using stk_classic::mesh::BucketIterator;
57 
59 
60 namespace {
61 
62 const EntityRank NODE_RANK = FEMMetaData::NODE_RANK;
63 
64 STKUNIT_UNIT_TEST(UnitTestingOfBucket, testBucket)
65 {
66  // Unit test the Part functionality in isolation:
67 
68  stk_classic::ParallelMachine pm = MPI_COMM_WORLD;
69  MPI_Barrier( pm );
70 
71  // Create a mesh for testing buckets...
72 
73  // Create dummy names for entity ranks to be given to MetaData
74  std::vector<std::string> entity_names(10);
75  for ( size_t i = 0 ; i < 10 ; ++i ) {
76  std::ostringstream name ;
77  name << "EntityRank" << i ;
78  entity_names[i] = name.str();
79  }
80 
81  // Create MetaData, BulkData
82  unsigned max_bucket_size = 4;
83  stk_classic::mesh::fixtures::BoxFixture fixture(pm, max_bucket_size, entity_names);
84  FEMMetaData& meta = fixture.fem_meta();
85  BulkData& bulk = fixture.bulk_data();
86  const EntityRank element_rank = meta.element_rank();
87  // Create two scalar fields, temperature and volume. Put temperature
88  // on all the nodes and put volume on all the elements.
89  unsigned number_of_states = 4;
90 
91  ScalarFieldType & temperature =
92  meta.declare_field < ScalarFieldType > ( "temperature" , number_of_states );
93  ScalarFieldType & volume =
94 
95  meta.declare_field < ScalarFieldType > ( "volume" , number_of_states );
96  Part & universal = meta.universal_part ();
97  put_field ( temperature , NODE_RANK , universal );
98  put_field ( volume , element_rank , universal );
99  meta.commit();
100 
101  // Generate the mesh
102  int root_box[3][2] = { { 0,4 } , { 0,5 } , { 0,6 } };
103  int local_box[3][2] = { { 0,0 } , { 0,0 } , { 0,0 } };
104  bulk.modification_begin();
105  fixture.generate_boxes( root_box, local_box );
106  STKUNIT_ASSERT(bulk.modification_end());
107 
108  // First, test for streaming IO;
109  {
110  std::string gold1;
111  // Parallel and Serial runs have different part intersections for the first
112  // bucket
113  if ( bulk.parallel_size() == 1 )
114  gold1 = "Bucket( EntityRank0 : {UNIVERSAL} {OWNS} )";
115  else
116  gold1 = "Bucket( EntityRank0 : {UNIVERSAL} )";
117  Bucket *b1 = bulk.buckets(0)[0];
118  std::stringstream out1_str;
119  out1_str << (*b1);
120  bool equal = (gold1 == out1_str.str());
121  STKUNIT_ASSERT_EQUAL ( equal, true );
122  }
123 
124  // Second, update state of bucket until circular cue is filled
125  {
126  /* Need to set some data in state, rotate look for it, rotate 3 more times
127  and look for it again */
128  for ( size_t i = 0 ; i != 10 ; ++i )
129  bulk.update_field_data_states ();
130  }
131 
132  // Third, checking field_data_valid (...)
133  {
134  const std::vector< FieldBase * > &field_bases = meta.get_fields();
135  STKUNIT_ASSERT_THROW(field_data_valid ( *field_bases[0] , *bulk.buckets(3)[0] , 1 , "error" ) , std::runtime_error);
136  STKUNIT_ASSERT_EQUAL(field_data_valid ( *field_bases[0] , *bulk.buckets(0)[0] , 1 , "no_error" ) , true);
137  STKUNIT_ASSERT_THROW(field_data_valid ( *field_bases[0] , *bulk.buckets(3)[0] , 99 , "error" ) , std::runtime_error);
138 
139  // Set up a second mesh
140 
141  MetaData meta2 ( entity_names );
142  BulkData bulk2( meta2 , pm , max_bucket_size );
143 
144  ScalarFieldType & temperature2 =
145  meta2.declare_field < ScalarFieldType > ( "temperature2" , number_of_states );
146  ScalarFieldType & volume2 =
147  meta2.declare_field < ScalarFieldType > ( "volume2" , number_of_states );
148  Part & universal2 = meta2.universal_part ();
149  put_field ( temperature2 , NODE_RANK , universal2 );
150  put_field ( volume2 , element_rank , universal2 );
151  meta2.commit();
152 
153  // Cover line containing messsage for wrong MetaData used
154  const std::vector< FieldBase * > &field_bases2 = meta2.get_fields();
155  STKUNIT_ASSERT_THROW(field_data_valid ( *field_bases2[0] , *bulk.buckets(0)[0] , 1 , "error" ) , std::runtime_error);
156  }
157 
158  // Fourth, check has_superset (...) and membership functions
159  {
160  PartVector tmp(2) ;
161  tmp[0] = & meta.universal_part();
162  tmp[1] = & meta.locally_owned_part();
163  STKUNIT_ASSERT_EQUAL ( has_superset ( *bulk.buckets(0)[0] , tmp ) , bulk.parallel_size() == 1 );
164  STKUNIT_ASSERT ( bulk.buckets(0)[0]->member_any ( tmp ) );
165  STKUNIT_ASSERT_EQUAL ( bulk.buckets(0)[0]->member_all ( tmp ) , bulk.parallel_size() == 1 );
166  STKUNIT_ASSERT ( bulk.buckets(0)[0]->member ( **meta.get_parts().begin() ) );
167  }
168 }
169 
170 STKUNIT_UNIT_TEST(UnitTestingOfBucket, testGetInvolvedParts)
171 {
172  // Tests to cover get_involved_parts for GetBuckets.cpp - C.Brickley - 12 May 2010
173 
174  stk_classic::ParallelMachine pm = MPI_COMM_WORLD;
175  MPI_Barrier( pm );
176 
177  const int spatial_dimension = 3;
178 
179  FEMMetaData meta( spatial_dimension );
180  const EntityRank element_rank = meta.element_rank();
181  const EntityRank edge_rank = meta.edge_rank();
182 
183  PartVector involved_parts(2) ;
184  involved_parts[0] = & meta.universal_part();
185  involved_parts[1] = & meta.locally_owned_part();
186 
187  Part & partLeft_1 = stk_classic::mesh::fem::declare_part<shards::Tetrahedron<4> >( meta, "block_left_1" );
188 
189  Part & partLeft_2 = stk_classic::mesh::fem::declare_part<shards::Tetrahedron<4> >( meta, "block_left_2" );
190 
191  meta.commit();
192 
193  PartVector union_parts;
194  union_parts.push_back(&partLeft_1);
195  union_parts.push_back(&partLeft_2);
196 
197  BulkData bulk( FEMMetaData::get_meta_data(meta) , pm , 100 );
198  PartVector add_part4, no_part;
199  add_part4.push_back ( &partLeft_1 );
200 
201  bulk.modification_begin();
202  int size , rank;
205 
206  for ( int id_base = 0 ; id_base < 99 ; ++id_base )
207  {
208  int new_id = size * id_base + rank + 1;
209  bulk.declare_entity( 3 , new_id , add_part4 );
210  bulk.declare_entity( NODE_RANK , new_id , no_part );
211  }
212 
213  bulk.modification_end();
214 
215  const std::vector<Bucket*> & buckets = bulk.buckets( element_rank );
216 
217  std::vector<Bucket*>::const_iterator k;
218 
219  k = buckets.begin();
220 
221  //test 1 covers aecond section of "if" statement in while loop
222  get_involved_parts( union_parts, **k, involved_parts);
223 
224  //test 2 covers union_parts.size() = 0
225  PartVector union_parts2(0) ;
226  get_involved_parts( union_parts2, **k, involved_parts);
227 
228  //test 3 covers first section of "if" statement in while loop
229  const std::vector<Bucket*> & buckets2 = bulk.buckets( NODE_RANK );
230  std::vector<Bucket*>::const_iterator k2;
231 
232  k2 = buckets2.begin();
233  get_involved_parts( union_parts, **k2, involved_parts);
234 
235  // tests on throw_error and BucketIterator in bucket.cpp/hpp
236 
237  FEMMetaData meta2 (spatial_dimension);
238  BulkData bulk2( FEMMetaData::get_meta_data(meta2) , pm , 4 );
239 
240  unsigned number_of_states = 4;
241 
242  ScalarFieldType & temperature2 =
243  meta2.declare_field < ScalarFieldType >("temperature2" , number_of_states);
244  ScalarFieldType & volume2 =
245 
246  meta2.declare_field < ScalarFieldType >("volume2", number_of_states);
247  Part & universal = meta2.universal_part ();
248  put_field ( temperature2 , NODE_RANK , universal );
249  put_field ( volume2 , element_rank , universal );
250 
251  meta2.commit();
252 
253  bulk2.modification_begin();
254  bulk2.declare_entity( edge_rank, rank+1 , no_part );
255  bulk2.modification_end();
256 }
257 
258 STKUNIT_UNIT_TEST(UnitTestingOfBucket, testBucket2)
259 {
260  // Tests to cover print, has_superset and BucketLess::operator() for Buckets.cpp - C.Brickley - 2nd June 2010
261 
262  stk_classic::ParallelMachine pm = MPI_COMM_WORLD;
263  MPI_Barrier( pm );
264 
265  const int spatial_dimension = 3;
266  FEMMetaData meta( spatial_dimension );
267  const EntityRank element_rank = meta.element_rank();
268 
269  PartVector involved_parts(2) ;
270  involved_parts[0] = & meta.universal_part();
271  involved_parts[1] = & meta.locally_owned_part();
272 
273  Part & partLeft_1 = meta.declare_part("block_left_1", element_rank);
274 
275  Part & partLeft_3 = stk_classic::mesh::fem::declare_part<shards::Tetrahedron<4> >( meta, "block_left_3" );
276 
277  meta.commit();
278 
279  BulkData bulk( FEMMetaData::get_meta_data(meta) , pm , 100 );
280  std::vector<Part *> add_part4;
281  add_part4.push_back ( &partLeft_1 );
282 
283  bulk.modification_begin();
284  int size , rank;
287 
288  for ( int id_base = 0 ; id_base < 99 ; ++id_base )
289  {
290  int new_id = size * id_base + rank;
291  bulk.declare_entity( 3 , new_id+1 , add_part4 );
292  }
293 
294  bulk.modification_end();
295 
296  const std::vector<Bucket*> & buckets2 = bulk.buckets( element_rank );
297 
298  std::vector<Bucket*>::const_iterator k2;
299 
300  k2 = buckets2.begin();
301 
302  Bucket& b2 = **k2;
303 
304  //define a new meta and bulkdata
305  std::vector<std::string> entity_names(10);
306 
307  for ( size_t i = 0 ; i < 10 ; ++i ) {
308  std::ostringstream name ;
309  name << "EntityRank" << i ;
310  entity_names[i] = name.str();
311  }
312 
313  MetaData meta2 ( entity_names );
314  BulkData bulk2( meta2 , pm , 4 );
315 
316  unsigned number_of_states = 4;
317 
318  ScalarFieldType & temperature2 =
319  meta2.declare_field < ScalarFieldType >("temperature2" , number_of_states);
320  ScalarFieldType & volume2 =
321  meta2.declare_field < ScalarFieldType >("volume2", number_of_states);
322  Part & universal = meta2.universal_part ();
323  put_field ( temperature2 , NODE_RANK , universal );
324  put_field ( volume2 , element_rank , universal );
325 
326  typedef Field<double> VectorFieldType;
327  typedef Field<double> ElementNodePointerFieldType;
328 
329  meta2.commit();
330 
331  //Test to cover print function in Bucket.cpp
332  std::ostringstream oss;
333  print(oss, " ", b2);
334 
335  //Test to cover has_superset function in Bucket.cpp
336  STKUNIT_ASSERT_EQUAL ( has_superset ( b2 , partLeft_3 ) , false );
337 
338  //Test on BucketLess::operator() in Bucket.cpp/hpp
339 
340  enum { KEY_TMP_BUFFER_SIZE = 64 };
341 
342  const unsigned max = ~(0u);
343 
344  unsigned key_tmp_buffer[ KEY_TMP_BUFFER_SIZE ];
345 
346  std::vector<unsigned> key_tmp_vector ;
347 
348  const unsigned key_size = 2 + 3 ;
349 
350  unsigned * const key =
351  ( key_size <= KEY_TMP_BUFFER_SIZE )
352  ? key_tmp_buffer
353  : ( key_tmp_vector.resize( key_size ) , & key_tmp_vector[0] );
354 
355 
356  key[ key[0] = 3 + 1 ] = max;
357 
358  {
359  unsigned * const k = key + 1 ;
360  for ( unsigned i = 0 ; i < 3 ; ++i ) { k[i] = 1 ; }
361  }
362 
363  // FIXME: The code below needs to be fixed or removed
364  /*
365  impl::BucketImpl::last_bucket_in_family( *k2 );
366 
367  const unsigned * t = key;
368  const Bucket * u = last_bucket;
369 
370  BucketLess Buck;
371 
372  bool res = Buck( &t[0], &u[0] );
373 
374  STKUNIT_EXPECT_EQUAL( res, false );
375  */
376 }
377 
378 STKUNIT_UNIT_TEST(UnitTestingOfBucket, testEntityComm)
379 {
380  // FIXME: With so much code commented out, this unit-test does
381  // not appear to be testing anything.
382 
383  stk_classic::ParallelMachine pm = MPI_COMM_WORLD;
384  MPI_Barrier( pm );
385 
386  const int spatial_dimension = 3;
387  FEMMetaData meta( spatial_dimension );
388 
389  BulkData bulk ( FEMMetaData::get_meta_data(meta) , pm , 100 );
390  std::vector<Part *> add_part4;
391 
392  Part & partLeft_1 = stk_classic::mesh::fem::declare_part<shards::Tetrahedron<4> >( meta, "block_left_1" );
393  meta.commit();
394 
395  add_part4.push_back ( &partLeft_1 );
396 
397  //int rank = stk_classic::parallel_machine_rank( pm );
398  // int size = stk_classic::parallel_machine_size( pm );
399  PartVector tmp(1);
400 
401  bulk.modification_begin();
402 
403  //int id_base = 0;
404  //int new_id = size * id_base + rank;
405  // for ( id_base = 0 ; id_base < 93 ; ++id_base )
406  // {
407  // int new_id = size * id_base + rank;
408  // bulk.declare_entity( 0 , new_id+1 , add_part4 );
409  // }
410 
411  bulk.modification_end();
412 
413  /* cout << endl << "Bucket test line 3" << endl ;
414  bool result = in_shared(elem);
415  if( result) {
416  STKUNIT_ASSERT_EQUAL( result , true );
417  }
418  cout << endl << "Bucket test line 4" << endl ;
419 
420  result = in_receive_ghost(elem);
421  if( result) {
422  STKUNIT_ASSERT_EQUAL( result , true );
423  }
424 
425  for ( unsigned p = 0 ; p < p_size ; ++p ) if ( p != p_rank ) {
426  cout << endl << "in relation h and p =" << p << endl ;
427 
428  STKUNIT_ASSERT_EQUAL( in_send_ghost( *elem , p ), false );
429  cout << endl << "in relation ii =" << endl
430  }
431 
432  cout << endl << "Bucket test line 5" << endl ;
433  result = in_send_ghost(elem);
434  if( result) {
435  STKUNIT_ASSERT_EQUAL( result , true );
436  }
437 
438  cout << endl << "Bucket test line 6" << endl ;
439 
440  unsigned proc = rank;
441  unsigned procnew = rank+10;
442 
443  result = in_shared(elem, proc);
444  if( result) {
445  STKUNIT_ASSERT_EQUAL( result , true );
446  }
447  cout << endl << "Bucket test line 7" << endl ; */
448 }
449 
450 }
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
Part & locally_owned_part() const
Subset for the problem domain that is owned by the local process. Ghost entities are not members of t...
FEMMetaData is a class that implements a Finite Element Method skin on top of the Sierra Tool Kit Met...
Definition: FEMMetaData.hpp:54
Field base class with an anonymous data type and anonymous multi-dimension.
Definition: FieldBase.hpp:53
bool has_superset(const Bucket &bucket, const unsigned &ordinal)
Is this bucket a subset of the given part by partID.
Definition: Bucket.cpp:127
The manager of an integrated collection of parts and fields.
Definition: MetaData.hpp:56
EntityRank element_rank() const
Returns the element rank which is always equal to spatial dimension.
Part & universal_part() const
Universal subset for the problem domain. All other parts are a subset of the universal part...
This is a class for selecting buckets based on a set of meshparts and set logic.
Definition: Selector.hpp:112
const PartVector & get_parts() const
Query all parts of the mesh ordered by the parts&#39; ordinal.
const std::vector< Bucket * > & buckets(EntityRank rank) const
Query all buckets of a given entity rank.
Definition: BulkData.hpp:195
field_type & put_field(field_type &field, EntityRank entity_rank, const Part &part, const void *init_value=NULL)
Declare a field to exist for a given entity type and Part.
Field with defined data type and multi-dimensions (if any)
Definition: Field.hpp:118
An application-defined subset of a problem domain.
Definition: Part.hpp:49
unsigned parallel_machine_rank(ParallelMachine parallel_machine)
Member function parallel_machine_rank ...
Definition: Parallel.cpp:29
const FieldVector & get_fields() const
Get all defined fields.
bool modification_end()
Parallel synchronization of modifications and transition to the guaranteed parallel consistent state...
unsigned parallel_size() const
Size of the parallel machine.
Definition: BulkData.hpp:82
bool modification_begin()
Begin a modification phase during which the mesh bulk data could become parallel inconsistent. This is a parallel synchronous call. The first time this method is called the mesh meta data is verified to be committed and parallel consistent. An exception is thrown if this verification fails.
Definition: BulkData.cpp:172
bool field_data_valid(const FieldBase &f, const Bucket &k, unsigned ord, const char *required_by)
Check for existence of field data.
Definition: Bucket.cpp:194
unsigned parallel_machine_size(ParallelMachine parallel_machine)
Member function parallel_machine_size ...
Definition: Parallel.cpp:18
Manager for an integrated collection of entities, entity relations, and buckets of field data...
Definition: BulkData.hpp:49
void commit()
Commit the part and field declarations so that the meta data manager can be used to create mesh bulk ...
field_type & declare_field(const std::string &name, unsigned number_of_states=1)
Declare a field of the given field_type, test name, and number of states.
A fundamental unit within the discretization of a problem domain, including but not limited to nodes...
Definition: Entity.hpp:120
EntityRank edge_rank() const
Returns the edge rank which changes depending on spatial dimension.
MPI_Comm ParallelMachine
Definition: Parallel.hpp:32
Entity & declare_entity(EntityRank ent_rank, EntityId ent_id, const PartVector &parts)
Create or retrieve a locally owned entity of a given rank and id.
Definition: BulkData.cpp:215
std::vector< Part *> PartVector
Collections of parts are frequently maintained as a vector of Part pointers.
Definition: Types.hpp:31
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
A container for the field data of a homogeneous collection of entities.
Definition: Bucket.hpp:94
void update_field_data_states() const
Rotate the field data of multistate fields.
Definition: BulkData.hpp:174
bool equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2)