Sierra Toolkit  Version of the Day
UnitTestBulkData_new.cpp
1 /*------------------------------------------------------------------------*/
2 /* Copyright 2010, 2011 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 <stdexcept>
11 
12 #include <stk_util/unit_test_support/stk_utest_macros.hpp>
13 
14 #include <stk_mesh/fixtures/BoxFixture.hpp>
15 #include <stk_mesh/fixtures/HexFixture.hpp>
16 #include <stk_mesh/fixtures/QuadFixture.hpp>
17 
18 #include <stk_mesh/fem/FEMMetaData.hpp>
19 
20 #include <stk_mesh/base/EntityComm.hpp>
21 #include <stk_mesh/base/FieldData.hpp>
22 
24 
25 // UnitTestBulkData_new is the beginnings of a refactoring of the bulk
26 // data unit test. It relies on a customized BoxFixture to rapidly
27 // create a mesh for testing.
28 
29 namespace {
30 
31 void new_insert_transitive_closure( std::set<stk_classic::mesh::EntityProc,stk_classic::mesh::EntityLess> & ,
32  const stk_classic::mesh::EntityProc & entry );
33 void new_comm_sync_send_recv(
35  std::set< stk_classic::mesh::EntityProc , stk_classic::mesh::EntityLess > & new_send ,
36  std::set< stk_classic::mesh::Entity * , stk_classic::mesh::EntityLess > & new_recv );
37 
38 void new_comm_recv_to_send(
40  const std::set< stk_classic::mesh::Entity * , stk_classic::mesh::EntityLess > & new_recv ,
41  std::set< stk_classic::mesh::EntityProc , stk_classic::mesh::EntityLess > & new_send );
42 
48 class TestBoxFixture : public stk_classic::mesh::fixtures::BoxFixture
49 {
50  public:
51  TestBoxFixture(stk_classic::ParallelMachine pm = MPI_COMM_WORLD,
52  unsigned block_size = 1000) :
53  BoxFixture(pm, block_size),
54  m_test_part ( m_fem_meta.declare_part ( "Test Part" ) ),
55  m_cell_part ( m_fem_meta.declare_part ( "Cell list" , 3 /*max rank*/ ) ),
56  m_part_A_0 ( m_fem_meta.declare_part ( "Part A 0", 0 ) ),
57  m_part_A_1 ( m_fem_meta.declare_part ( "Part A 1", 1 ) ),
58  m_part_A_2 ( m_fem_meta.declare_part ( "Part A 2", 2 ) ),
59  m_part_A_3 ( m_fem_meta.declare_part ( "Part A 3", 3 ) ),
60  m_part_A_superset ( m_fem_meta.declare_part ( "Part A superset" ) ),
61  m_part_B_0 ( m_fem_meta.declare_part ( "Part B 0", 0 ) ),
62  m_part_B_1 ( m_fem_meta.declare_part ( "Part B 1", 1 ) ),
63  m_part_B_2 ( m_fem_meta.declare_part ( "Part B 2", 2 ) ),
64  m_part_B_3 ( m_fem_meta.declare_part ( "Part B 3", 3 ) ),
65  m_part_B_superset ( m_fem_meta.declare_part ( "Part B superset" ) )
66  {
67  m_fem_meta.declare_part_subset ( m_part_A_superset , m_part_A_0 );
68  m_fem_meta.declare_part_subset ( m_part_A_superset , m_part_A_1 );
69  m_fem_meta.declare_part_subset ( m_part_A_superset , m_part_A_2 );
70  m_fem_meta.declare_part_subset ( m_part_A_superset , m_part_A_3 );
71 
72  m_fem_meta.declare_part_subset ( m_part_B_superset , m_part_B_0 );
73  m_fem_meta.declare_part_subset ( m_part_B_superset , m_part_B_1 );
74  m_fem_meta.declare_part_subset ( m_part_B_superset , m_part_B_2 );
75  m_fem_meta.declare_part_subset ( m_part_B_superset , m_part_B_3 );
76 
77  // None of the tests currently need to make any addtional changes
78  // to MetaData; if this changes, the line below will have to be
79  // removed.
80  m_fem_meta.commit();
81  }
82 
83  Part & get_test_part () { return m_test_part; }
84  Part & get_cell_part () { return m_cell_part; }
85 
86  Part & get_part_a_0 () { return m_part_A_0; }
87  Part & get_part_a_1 () { return m_part_A_1; }
88  Part & get_part_a_2 () { return m_part_A_2; }
89  Part & get_part_a_3 () { return m_part_A_3; }
90 
91  Part & get_part_a_superset () { return m_part_A_superset; }
92 
93  Part & get_part_b_0 () { return m_part_B_0; }
94  Part & get_part_b_1 () { return m_part_B_1; }
95  Part & get_part_b_2 () { return m_part_B_2; }
96  Part & get_part_b_3 () { return m_part_B_3; }
97 
98  Part & get_part_b_superset () { return m_part_B_superset; }
99 
100  private:
101  Part & m_test_part; // A simple part
102  Part & m_cell_part; // A part to put cells in
103 
104  Part & m_part_A_0;
105  Part & m_part_A_1;
106  Part & m_part_A_2;
107  Part & m_part_A_3;
108 
109  Part & m_part_A_superset;
110 
111  Part & m_part_B_0;
112  Part & m_part_B_1;
113  Part & m_part_B_2;
114  Part & m_part_B_3;
115 
116  Part & m_part_B_superset;
117 };
118 
119 }
120 
121 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyAssertOwnerDeletedEntity )
122 {
123  TestBoxFixture fixture;
124 
125  stk_classic::mesh::BulkData &bulk = fixture.bulk_data();
126  stk_classic::mesh::Part &new_part = fixture.get_test_part ();
128  add_part.push_back ( &new_part );
129 
130  const int root_box[3][2] = { { 0 , 4 } , { 0 , 5 } , { 0 , 6 } };
131  int local_box[3][2] = { { 0 , 0 } , { 0 , 0 } , { 0 , 0 } };
132 
133  bulk.modification_begin();
134  fixture.generate_boxes( root_box, local_box );
135  STKUNIT_ASSERT(bulk.modification_end());
136 
137  // Find a cell owned by this process
138  stk_classic::mesh::Entity *cell_to_delete = NULL;
139  stk_classic::mesh::Entity *cell_to_delete_copy = NULL;
140  std::vector<stk_classic::mesh::Bucket *>::const_iterator cur_bucket = bulk.buckets(3).begin();
141  while ( cur_bucket != bulk.buckets(3).end() )
142  {
143  stk_classic::mesh::Bucket::iterator cur_entity = (*cur_bucket)->begin();
144  while ( cur_entity != (*cur_bucket)->end() )
145  {
146  if ( cur_entity->owner_rank() == fixture.comm_rank() )
147  {
148  cell_to_delete = &*cur_entity;
149  break;
150  }
151  ++cur_entity;
152  }
153  ++cur_bucket;
154  }
155 
156  STKUNIT_ASSERT ( cell_to_delete != NULL );
157  cell_to_delete_copy = cell_to_delete;
158  bulk.modification_begin();
159  bulk.destroy_entity ( cell_to_delete );
160  // Destroying an already destroyed entity returns false
161  STKUNIT_ASSERT( false == bulk.destroy_entity( cell_to_delete_copy ) );
162  bulk.modification_end();
163 }
164 
165 
166 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyDetectsBadKey )
167 {
168  TestBoxFixture fixture;
169 
170  stk_classic::mesh::BulkData &bulk = fixture.bulk_data();
171  stk_classic::mesh::Part &new_part = fixture.get_test_part ();
172  stk_classic::mesh::PartVector add_part, empty_vector;
173  add_part.push_back ( &new_part );
174 
175  stk_classic::mesh::EntityKey bad_key1 ( 45 , 1 ); // Bad entity rank
176  stk_classic::mesh::EntityKey bad_key2 ( 1 , 0 ); // Bad id
177 
178  STKUNIT_ASSERT_THROW ( bulk.declare_entity(bad_key1.rank(),
179  bad_key1.id(),
180  empty_vector),
181  std::logic_error );
182  STKUNIT_ASSERT_THROW ( bulk.declare_entity(bad_key2.rank(),
183  bad_key2.id(),
184  empty_vector),
185  std::logic_error );
186 }
187 
188 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyDetectsNonOwnerChange )
189 {
190  // Set up a mesh where there are shared nodes. Take one of the nodes, and
191  // have the non-owning processes try to make a change to that node; this
192  // should cause an exception.
193 
194  stk_classic::ParallelMachine pm = MPI_COMM_WORLD;
195  unsigned p_size = stk_classic::parallel_machine_size(pm);
196  unsigned p_rank = stk_classic::parallel_machine_rank(pm);
197 
198  stk_classic::mesh::fixtures::QuadFixture fixture(pm, 1 /*nx*/, p_size /*ny*/);
199  fixture.m_fem_meta.commit();
200  fixture.generate_mesh();
201  stk_classic::mesh::BulkData & bulk = fixture.m_bulk_data;
202 
203  stk_classic::mesh::PartVector empty_vector;
204 
205  stk_classic::mesh::Entity* shared_node = fixture.node(1 /*x*/, 1 /*y*/);
206  // Assert that this node is shared
207  if ( p_size > 1 && shared_node && (p_rank == 0 || p_rank == 1) ) {
208  STKUNIT_ASSERT_GE(shared_node->sharing().size(), 1u);
209  }
210 
211  bulk.modification_begin();
212 
213  // Non-owners of shared_node will attempt to make a change to it; this should
214  // cause an exception
215  if (shared_node && p_rank != shared_node->owner_rank()) {
216  STKUNIT_ASSERT_THROW(bulk.change_entity_parts(*shared_node,
217  empty_vector, //add parts
218  empty_vector), //rem parts
219  std::logic_error);
220  }
221 
222  bulk.modification_end();
223 }
224 
225 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyGetEntityGuards )
226 {
227  TestBoxFixture fixture;
228 
229  stk_classic::mesh::BulkData &bulk = fixture.bulk_data();
230  STKUNIT_ASSERT_THROW ( bulk.get_entity ( 1 , 0 ) , std::logic_error );
231 }
232 
233 
234 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyExplicitAddInducedPart )
235 {
236  TestBoxFixture fixture;
237  stk_classic::mesh::BulkData &bulk = fixture.bulk_data ();
238  stk_classic::mesh::PartVector empty_vector;
239  stk_classic::mesh::PartVector cell_part_vector;
240 
241  bulk.modification_begin();
242 
243  stk_classic::mesh::Entity &new_cell = bulk.declare_entity ( 3 , fixture.comm_rank()+1 , empty_vector );
244  stk_classic::mesh::Entity &new_node = bulk.declare_entity ( 0 , fixture.comm_rank()+1 , empty_vector );
245 
246  bulk.declare_relation ( new_cell , new_node , 1 );
247 
248  cell_part_vector.push_back ( &fixture.get_cell_part () );
249  bulk.change_entity_parts ( new_cell , cell_part_vector );
250 #ifdef SIERRA_MIGRATION
251  bulk.change_entity_parts ( new_node , cell_part_vector );
252 #else
253  STKUNIT_ASSERT_THROW ( bulk.change_entity_parts ( new_node , cell_part_vector ) , std::runtime_error );
254 #endif
255 }
256 
257 /************************
258  * This unit test is not possible currently because of the lack of
259  * separation between internal part modification routines and public
260  * part modification routines.
261 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyCannotRemoveFromSpecialParts )
262 {
263  stk_classic::mesh::fixtures::BoxFixture fixture;
264  stk_classic::mesh::BulkData &bulk = fixture.bulk_data();
265  stk_classic::mesh::PartVector test_parts;
266  stk_classic::mesh::PartVector out_parts;
267  stk_classic::mesh::PartVector empty_vector;
268 
269  stk_classic::mesh::Entity &new_cell = bulk.declare_entity ( 3 , fixture.comm_rank()+1 , empty_vector );
270  test_parts.push_back ( &fixture.fem_meta().universal_part() );
271  STKUNIT_ASSERT_THROW ( bulk.change_entity_parts ( new_cell , empty_vector , test_parts ) , std::runtime_error );
272  test_parts.clear();
273  test_parts.push_back ( &fixture.fem_meta().locally_owned_part() );
274  STKUNIT_ASSERT_THROW ( bulk.change_entity_parts ( new_cell , empty_vector , test_parts ) , std::runtime_error );
275  test_parts.clear();
276  test_parts.push_back ( &fixture.fem_meta().globally_shared_part() );
277  STKUNIT_ASSERT_THROW ( bulk.change_entity_parts ( new_cell , empty_vector , test_parts ) , std::runtime_error );
278 }
279  */
280 
281 
282 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyDefaultPartAddition )
283 {
284  TestBoxFixture fixture;
285  stk_classic::mesh::BulkData &bulk = fixture.bulk_data ();
286 
287  bulk.modification_begin();
288  stk_classic::mesh::Entity &new_cell = fixture.get_new_entity ( 3 , 1 );
289  bulk.modification_end();
290 
291  STKUNIT_ASSERT ( new_cell.bucket().member ( fixture.fem_meta().universal_part() ) );
292  STKUNIT_ASSERT ( new_cell.bucket().member ( fixture.fem_meta().locally_owned_part() ) );
293 }
294 
295 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyChangePartsSerial )
296 {
297  TestBoxFixture fixture;
298  stk_classic::mesh::BulkData &bulk = fixture.bulk_data ();
299  stk_classic::mesh::PartVector create_parts , remove_parts , add_parts, empty_parts;
300 
301  create_parts.push_back ( &fixture.get_test_part() );
302  create_parts.push_back ( &fixture.get_part_a_3() );
303  remove_parts.push_back ( &fixture.get_part_a_3() );
304  add_parts.push_back ( &fixture.get_part_b_superset() );
305  add_parts.push_back ( &fixture.get_cell_part() );
306 
307  bulk.modification_begin();
308  stk_classic::mesh::Entity &new_cell = fixture.get_new_entity ( 3 , 1 );
309  bulk.change_entity_parts ( new_cell , create_parts , empty_parts );
310  bulk.modification_end();
311  STKUNIT_ASSERT ( new_cell.bucket().member ( fixture.get_test_part() ) );
312  STKUNIT_ASSERT ( new_cell.bucket().member ( fixture.get_part_a_3() ) );
313  STKUNIT_ASSERT ( new_cell.bucket().member ( fixture.get_part_a_superset() ) );
314  STKUNIT_ASSERT ( !new_cell.bucket().member ( fixture.get_part_b_superset() ) );
315  STKUNIT_ASSERT ( !new_cell.bucket().member ( fixture.get_cell_part() ) );
316 
317  bulk.modification_begin();
318  bulk.change_entity_parts ( new_cell , add_parts , remove_parts );
319  bulk.modification_end();
320  STKUNIT_ASSERT ( new_cell.bucket().member ( fixture.get_test_part() ) );
321  STKUNIT_ASSERT ( !new_cell.bucket().member ( fixture.get_part_a_3() ) );
322  STKUNIT_ASSERT ( new_cell.bucket().member ( fixture.get_part_a_superset() ) );
323  STKUNIT_ASSERT ( new_cell.bucket().member ( fixture.get_part_b_superset() ) );
324  STKUNIT_ASSERT ( new_cell.bucket().member ( fixture.get_cell_part() ) );
325 
326  bulk.modification_begin();
327  bulk.change_entity_parts ( new_cell , empty_parts , add_parts );
328  bulk.modification_end();
329  STKUNIT_ASSERT ( new_cell.bucket().member ( fixture.get_test_part() ) );
330  STKUNIT_ASSERT ( !new_cell.bucket().member ( fixture.get_part_a_3() ) );
331  STKUNIT_ASSERT ( new_cell.bucket().member ( fixture.get_part_a_superset() ) );
332  STKUNIT_ASSERT ( !new_cell.bucket().member ( fixture.get_part_b_superset() ) );
333  STKUNIT_ASSERT ( !new_cell.bucket().member ( fixture.get_cell_part() ) );
334 
335  //Verify still a member of default parts
336  STKUNIT_ASSERT ( new_cell.bucket().member ( fixture.fem_meta().universal_part() ) );
337  STKUNIT_ASSERT ( new_cell.bucket().member ( fixture.fem_meta().locally_owned_part() ) );
338 }
339 
340 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyParallelAddParts )
341 {
342  TestBoxFixture fixture;
343  stk_classic::mesh::BulkData &bulk = fixture.bulk_data ();
345 
346  const int root_box[3][2] = { { 0 , 4 } , { 0 , 5 } , { 0 , 6 } };
347  int local_box[3][2] = { { 0 , 0 } , { 0 , 0 } , { 0 , 0 } };
348 
349  add_part.push_back ( &fixture.get_part_a_0() );
350 
351  bulk.modification_begin();
352  fixture.generate_boxes( root_box, local_box );
353  STKUNIT_ASSERT(bulk.modification_end());
354 
355  bulk.modification_begin();
356 
357  for ( std::vector<stk_classic::mesh::Entity*>::const_iterator
358  cur_entity = bulk.entity_comm().begin();
359  cur_entity != bulk.entity_comm().end() ; ++cur_entity ) {
360  stk_classic::mesh::Entity & entity = **cur_entity ;
361  if ( entity.entity_rank() == 0 ) {
362  if ( entity.owner_rank() == fixture.comm_rank() ) {
363  bulk.change_entity_parts ( entity, add_part, stk_classic::mesh::PartVector() );
364  }
365  }
366  }
367 
368  bulk.modification_end();
369 
370  for ( std::vector<stk_classic::mesh::Entity*>::const_iterator
371  cur_entity = bulk.entity_comm().begin();
372  cur_entity != bulk.entity_comm().end() ; ++cur_entity ) {
373  stk_classic::mesh::Entity & entity = **cur_entity ;
374  if ( entity.entity_rank() == 0 ) {
375  STKUNIT_ASSERT ( entity.bucket().member ( fixture.get_part_a_0 () ) );
376  }
377  }
378 }
379 
380 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyInducedMembership )
381 {
382  TestBoxFixture fixture;
383  stk_classic::mesh::BulkData &bulk = fixture.bulk_data ();
384  stk_classic::mesh::PartVector create_node_parts , create_cell_parts , empty_parts;
385 
386  create_node_parts.push_back ( &fixture.get_part_a_0() );
387  create_cell_parts.push_back ( &fixture.get_cell_part() );
388 
389  bulk.modification_begin();
390 
391  stk_classic::mesh::Entity &node = fixture.get_new_entity ( 0 , 1 );
392  stk_classic::mesh::Entity &cell = fixture.get_new_entity ( 3 , 1 );
393 
394  bulk.modification_begin();
395 
396  bulk.change_entity_parts ( node , create_node_parts , stk_classic::mesh::PartVector () );
397  bulk.change_entity_parts ( cell , create_cell_parts , stk_classic::mesh::PartVector () );
398  // Add node to cell part
399  stk_classic::mesh::RelationIdentifier cell_node_rel_id = 0;
400  bulk.declare_relation ( cell , node , cell_node_rel_id );
401  bulk.modification_end();
402 
403  STKUNIT_ASSERT ( node.bucket().member ( fixture.get_cell_part() ) );
404 
405  bulk.modification_begin();
406  bulk.destroy_relation ( cell , node, cell_node_rel_id );
407  bulk.modification_end();
408 
409  STKUNIT_ASSERT ( !node.bucket().member ( fixture.get_cell_part() ) );
410 }
411 
412 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyCanRemoveFromSetWithDifferentRankSubset )
413 {
414  TestBoxFixture fixture;
415  stk_classic::mesh::BulkData &bulk = fixture.bulk_data ();
416  stk_classic::mesh::PartVector add_parts , remove_parts, empty_parts;
417 
418  add_parts.push_back ( &fixture.get_part_b_3() );
419  add_parts.push_back ( &fixture.get_part_a_superset() );
420 
421  remove_parts.push_back ( &fixture.get_part_a_superset() );
422 
423  bulk.modification_begin();
424 
425  stk_classic::mesh::Entity &e = bulk.declare_entity ( 3 , fixture.comm_rank()+1 , add_parts );
426  bulk.modification_end();
427 
428  bulk.modification_begin();
429  bulk.change_entity_parts ( e , empty_parts , remove_parts );
430  bulk.modification_end();
431 
432  STKUNIT_ASSERT ( e.bucket().member ( fixture.get_part_b_3() ) );
433  STKUNIT_ASSERT ( !e.bucket().member ( fixture.get_part_a_superset() ) );
434 }
435 
436 
437 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyCommonGhostingName )
438 {
439 
440  TestBoxFixture fixture;
441  stk_classic::mesh::BulkData &bulk = fixture.bulk_data ();
442 
443  bulk.modification_begin();
444 
445  if ( fixture.comm_size() == 1 ) return;
446 
447  if ( fixture.comm_rank() == 0 )
448  {
449  STKUNIT_ASSERT_THROW ( bulk.create_ghosting ( "Name 1" ) , std::runtime_error );
450  }
451  else
452  {
453  STKUNIT_ASSERT_THROW ( bulk.create_ghosting ( "Name 2" ) , std::runtime_error );
454  }
455 }
456 
457 
458 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyTrivialDestroyAllGhostings )
459 {
460  TestBoxFixture fixture;
461 
462  if ( fixture.comm_size() == 1 ) return;
463 
464  stk_classic::mesh::BulkData &bulk = fixture.bulk_data();
465 
466  const int root_box[3][2] = { { 0 , 4 } , { 0 , 5 } , { 0 , 6 } };
467  int local_box[3][2] = { { 0 , 0 } , { 0 , 0 } , { 0 , 0 } };
468 
469  bulk.modification_begin();
470  fixture.generate_boxes( root_box, local_box );
471  STKUNIT_ASSERT(bulk.modification_end());
472 
473  bulk.modification_begin();
474 
475  stk_classic::mesh::Ghosting &ghosting = bulk.create_ghosting ( "Ghost 1" );
476 
477  // Find a cell owned by this process
478  std::vector<stk_classic::mesh::Bucket *>::const_iterator cur_bucket = bulk.buckets(3).begin();
479  unsigned send_rank = 0;
480 
481  std::vector<stk_classic::mesh::EntityProc> to_send;
482  std::vector<stk_classic::mesh::Entity *> empty_vector;
483  while ( cur_bucket != bulk.buckets(3).end() )
484  {
485  stk_classic::mesh::Bucket::iterator cur_entity = (*cur_bucket)->begin();
486  while ( cur_entity != (*cur_bucket)->end() )
487  {
488  if ( cur_entity->owner_rank() == fixture.comm_rank() )
489  {
490  if ( send_rank == fixture.comm_size() ) send_rank = 0;
491  if ( send_rank != fixture.comm_rank() )
492  to_send.push_back ( std::make_pair ( &*cur_entity , send_rank ) );
493  send_rank++;
494  }
495  ++cur_entity;
496  }
497  ++cur_bucket;
498  }
499  bulk.change_ghosting ( ghosting , to_send , empty_vector );
500  bulk.modification_end();
501 
502 
503  {
504  std::vector<stk_classic::mesh::EntityProc> send_list ;
505  std::vector<stk_classic::mesh::Entity*> recv_list ;
506  ghosting.send_list( send_list );
507  ghosting.receive_list( recv_list );
508 
509  STKUNIT_ASSERT ( ! send_list.empty() );
510  STKUNIT_ASSERT ( ! recv_list.empty() );
511  }
512 
513  // Usage of operator << in Ghosting.cpp
514  std::ostringstream oss;
515  oss << ghosting;
516 
517  bulk.modification_begin();
518  bulk.destroy_all_ghosting ();
519  bulk.modification_end();
520 
521  {
522  std::vector<stk_classic::mesh::EntityProc> send_list ;
523  std::vector<stk_classic::mesh::Entity*> recv_list ;
524  ghosting.send_list( send_list );
525  ghosting.receive_list( recv_list );
526 
527  STKUNIT_ASSERT ( send_list.empty() );
528  STKUNIT_ASSERT ( recv_list.empty() );
529  }
530 }
531 
532 
533 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyChangeGhostingGuards )
534 {
535  TestBoxFixture fixture1, fixture2;
536  stk_classic::mesh::BulkData & bulk1 = fixture1.bulk_data ();
537  stk_classic::mesh::BulkData & bulk2 = fixture2.bulk_data ();
538 
539  const int root_box[3][2] = { { 0 , 4 } , { 0 , 5 } , { 0 , 6 } };
540  int local_box1[3][2] = { { 0 , 0 } , { 0 , 0 } , { 0 , 0 } };
541  int local_box2[3][2] = { { 0 , 0 } , { 0 , 0 } , { 0 , 0 } };
542 
543  bulk1.modification_begin();
544  fixture1.generate_boxes( root_box, local_box1 );
545  STKUNIT_ASSERT(bulk1.modification_end());
546 
547  bulk2.modification_begin();
548  fixture2.generate_boxes( root_box, local_box2 );
549  STKUNIT_ASSERT(bulk2.modification_end());
550 
551  bulk1.modification_begin();
552  bulk2.modification_begin();
553 
554  std::vector<stk_classic::mesh::EntityProc> to_send;
555  std::vector<stk_classic::mesh::Entity *> empty_vector;
556  std::vector<stk_classic::mesh::Bucket *>::const_iterator cur_bucket = bulk1.buckets(3).begin();
557  unsigned send_rank = 0;
558  while ( cur_bucket != bulk1.buckets(3).end() )
559  {
560  stk_classic::mesh::Bucket::iterator cur_entity = (*cur_bucket)->begin();
561  while ( cur_entity != (*cur_bucket)->end() )
562  {
563  if ( cur_entity->owner_rank() == fixture1.comm_rank() )
564  {
565  if ( send_rank == fixture1.comm_size() ) send_rank = 0;
566  if ( send_rank != fixture1.comm_rank() )
567  to_send.push_back ( std::make_pair ( &*cur_entity , send_rank ) );
568  ++send_rank;
569  }
570  ++cur_entity;
571  }
572  ++cur_bucket;
573  }
574 
575  stk_classic::mesh::Ghosting &ghosting = bulk1.create_ghosting ( "Ghost 1" );
576  STKUNIT_ASSERT_THROW ( bulk2.change_ghosting ( ghosting , to_send , empty_vector ) , std::runtime_error );
577  STKUNIT_ASSERT_THROW ( bulk1.change_ghosting ( bulk1.shared_aura() , to_send , empty_vector ) , std::runtime_error );
578 
579  ghosting.receive_list(empty_vector);
580  ghosting.send_list(to_send);
581 
582  bulk1.modification_end();
583  bulk2.modification_end();
584 }
585 
586 
587 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyOtherGhostingGuards )
588 {
589  TestBoxFixture fixture;
590  stk_classic::mesh::BulkData &bulk = fixture.bulk_data ();
591 
592  const int root_box[3][2] = { { 0 , 4 } , { 0 , 5 } , { 0 , 6 } };
593  int local_box[3][2] = { { 0 , 0 } , { 0 , 0 } , { 0 , 0 } };
594 
595  bulk.modification_begin();
596  fixture.generate_boxes( root_box, local_box );
597  STKUNIT_ASSERT(bulk.modification_end());
598 
599  bulk.modification_begin();
600 
601  std::vector<stk_classic::mesh::EntityProc> to_send_unowned;
602  std::vector<stk_classic::mesh::EntityProc> empty_send;
603  std::vector<stk_classic::mesh::Entity *> to_remove_not_ghosted;
604  std::vector<stk_classic::mesh::Entity *> empty_remove;
605  std::vector<stk_classic::mesh::Bucket *>::const_iterator cur_bucket = bulk.buckets(3).begin();
606  unsigned send_rank = 0;
607  while ( cur_bucket != bulk.buckets(3).end() )
608  {
609  stk_classic::mesh::Bucket::iterator cur_entity = (*cur_bucket)->begin();
610  while ( cur_entity != (*cur_bucket)->end() )
611  {
612  if ( cur_entity->owner_rank() != fixture.comm_rank() )
613  {
614  if ( send_rank == fixture.comm_size() ) send_rank = 0;
615  if ( send_rank != fixture.comm_rank() )
616  to_send_unowned.push_back ( std::make_pair ( &*cur_entity , send_rank ) );
617  ++send_rank;
618  }
619  else
620  {
621  to_remove_not_ghosted.push_back ( &*cur_entity );
622  }
623  ++cur_entity;
624  }
625  ++cur_bucket;
626  }
627 
628  stk_classic::mesh::Ghosting &ghosting = bulk.create_ghosting ( "Ghost 1" );
629  if ( to_send_unowned.size() > 0 )
630  {
631  STKUNIT_ASSERT_THROW ( bulk.change_ghosting ( ghosting , to_send_unowned , empty_remove ) , std::runtime_error );
632  }
633  else
634  {
635  bulk.change_ghosting ( ghosting , to_send_unowned , empty_remove );
636  }
637 
638  if ( to_remove_not_ghosted.size() > 0 )
639  {
640  STKUNIT_ASSERT_THROW ( bulk.change_ghosting ( ghosting , empty_send , to_remove_not_ghosted ) , std::runtime_error );
641  }
642  else
643  {
644  bulk.change_ghosting ( ghosting , empty_send , to_remove_not_ghosted );
645  }
646  bulk.modification_end();
647 }
648 
649 
650 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyPartsOnCreate )
651 {
652  TestBoxFixture fixture;
653  stk_classic::mesh::BulkData & bulk = fixture.bulk_data ();
654  stk_classic::mesh::Part & part_a = fixture.get_part_a_0 ();
655  stk_classic::mesh::Part & part_b = fixture.get_part_b_0 ();
656 
657  stk_classic::mesh::PartVector create_vector;
658  create_vector.push_back ( &part_a );
659 
660  bulk.modification_begin();
661 
662  stk_classic::mesh::Entity &node = bulk.declare_entity ( 0 , fixture.comm_rank()+1 ,create_vector );
663  bulk.modification_end();
664 
665  STKUNIT_ASSERT ( node.bucket().member ( part_a ) );
666 
667  bulk.modification_begin();
668  create_vector.push_back ( &part_b );
669  stk_classic::mesh::Entity &node2 = bulk.declare_entity ( 0 , fixture.comm_size() + fixture.comm_rank() + 1 , create_vector );
670  bulk.modification_end();
671 
672  STKUNIT_ASSERT ( node2.bucket().member ( part_a ) );
673  STKUNIT_ASSERT ( node2.bucket().member ( part_b ) );
674 }
675 
676 //----------------------------------------------------------------------
677 
678 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , verifyBoxGhosting )
679 {
680  const unsigned p_size = stk_classic::parallel_machine_size( MPI_COMM_WORLD );
681  if ( 8 < p_size ) { return ; }
682 
683  stk_classic::mesh::fixtures::HexFixture fixture( MPI_COMM_WORLD, 2, 2, 2 );
684  fixture.m_fem_meta.commit();
685  fixture.generate_mesh();
686 
687  for ( size_t iz = 0 ; iz < 3 ; ++iz ) {
688  for ( size_t iy = 0 ; iy < 3 ; ++iy ) {
689  for ( size_t ix = 0 ; ix < 3 ; ++ix ) {
690  stk_classic::mesh::Entity * const node = fixture.node(ix,iy,iz);
691  STKUNIT_ASSERT( NULL != node );
692 
693  STKUNIT_ASSERT( fixture.node_id(ix,iy,iz) == node->identifier() );
694  stk_classic::mesh::fixtures::HexFixture::Scalar * const node_coord =
695  stk_classic::mesh::field_data( fixture.m_coord_field , *node );
696  STKUNIT_ASSERT( node_coord != NULL );
697  }
698  }
699  }
700 
701  for ( size_t iz = 0 ; iz < 2 ; ++iz ) {
702  for ( size_t iy = 0 ; iy < 2 ; ++iy ) {
703  for ( size_t ix = 0 ; ix < 2 ; ++ix ) {
704  stk_classic::mesh::Entity * const elem = fixture.elem(ix,iy,iz);
705  STKUNIT_ASSERT( NULL != elem );
706 
707  stk_classic::mesh::PairIterRelation elem_nodes = elem->relations();
708  STKUNIT_ASSERT_EQUAL( 8u , elem_nodes.size() );
709  stk_classic::mesh::fixtures::HexFixture::Scalar ** const elem_node_coord =
710  stk_classic::mesh::field_data( fixture.m_coord_gather_field , *elem );
711  for ( size_t j = 0 ; j < elem_nodes.size() ; ++j ) {
712  STKUNIT_ASSERT_EQUAL( j , elem_nodes[j].identifier() );
713  stk_classic::mesh::fixtures::HexFixture::Scalar * const node_coord =
714  stk_classic::mesh::field_data( fixture.m_coord_field , *elem_nodes[j].entity() );
715  STKUNIT_ASSERT( node_coord == elem_node_coord[ elem_nodes[j].identifier() ] );
716  }
717  if ( 8u == elem_nodes.size() ) {
718  STKUNIT_ASSERT( elem_nodes[0].entity() == fixture.node(ix,iy,iz));
719  STKUNIT_ASSERT( elem_nodes[1].entity() == fixture.node(ix+1,iy,iz));
720  STKUNIT_ASSERT( elem_nodes[2].entity() == fixture.node(ix+1,iy,iz+1));
721  STKUNIT_ASSERT( elem_nodes[3].entity() == fixture.node(ix,iy,iz+1));
722  STKUNIT_ASSERT( elem_nodes[4].entity() == fixture.node(ix,iy+1,iz));
723  STKUNIT_ASSERT( elem_nodes[5].entity() == fixture.node(ix+1,iy+1,iz));
724  STKUNIT_ASSERT( elem_nodes[6].entity() == fixture.node(ix+1,iy+1,iz+1));
725  STKUNIT_ASSERT( elem_nodes[7].entity() == fixture.node(ix,iy+1,iz+1));
726  }
727 
728  }
729  }
730  }
731 }
732 
733 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , testEntityComm )
734 {
735  //Test on unpack_field_values in EntityComm.cpp
736  //code based on ../base/BulkDataGhosting.cpp
737  //Create a simple mesh. Add nodes one element and some parts.
738 
739  const int spatial_dimension = 3;
740 
742  fem_meta.FEM_initialize(spatial_dimension, stk_classic::mesh::fem::entity_rank_names ( spatial_dimension ));
743 
744  stk_classic::mesh::fem::CellTopology tet_top(shards::getCellTopologyData<shards::Tetrahedron<4> >());
745  stk_classic::mesh::Part & part_a = fem_meta.declare_part( "block_a", tet_top );
746  stk_classic::mesh::Part & part_b = fem_meta.declare_part( "block_b", tet_top );
747 
748  stk_classic::mesh::fem::CellTopology node_top(shards::getCellTopologyData<shards::Node>());
749  stk_classic::mesh::Part & part_a_0 = fem_meta.declare_part( "block_a_0", node_top );
750 
752 
753  ScalarFieldType & volume =
754  fem_meta.declare_field < ScalarFieldType > ( "volume" , 4 );
755  ScalarFieldType & temperature =
756  fem_meta.declare_field < ScalarFieldType > ( "temperature" , 4 );
757  stk_classic::mesh::Part & universal = fem_meta.universal_part ();
758  put_field ( volume , 3 , universal );
759  put_field ( temperature , 3 , universal );
760 
761  fem_meta.commit();
762 
763  stk_classic::mesh::PartVector create_vector;
764  stk_classic::mesh::PartVector empty_vector;
765  create_vector.push_back ( &part_a );
766  create_vector.push_back ( &part_b );
767 
769  stk_classic::mesh::BulkData bulk ( meta , MPI_COMM_WORLD , 100 );
770 
771  bulk.modification_begin();
772 
773  stk_classic::mesh::Ghosting &ghosts = bulk.create_ghosting ( "Ghost 1" );
774 
775  unsigned size2 = stk_classic::parallel_machine_size( MPI_COMM_WORLD );
776  unsigned rank_count2 = stk_classic::parallel_machine_rank( MPI_COMM_WORLD );
777  int new_id2 = size2 + rank_count2;
778 
779  stk_classic::mesh::Entity &elem2 = bulk.declare_entity ( 3 , new_id2+1 ,create_vector );
780  STKUNIT_ASSERT_EQUAL( elem2.bucket().member ( part_a ), true );
781 
782  unsigned size = stk_classic::parallel_machine_size( MPI_COMM_WORLD );
783  unsigned rank_count = stk_classic::parallel_machine_rank( MPI_COMM_WORLD );
784 
785  int id_base = 0;
786  for ( id_base = 0 ; id_base < 99 ; ++id_base )
787  {
788  int new_id = size * id_base + rank_count;
789  stk_classic::mesh::Entity &new_node = bulk.declare_entity( 0 , new_id+1 , empty_vector );
790  STKUNIT_ASSERT_EQUAL( new_node.bucket().member ( part_a_0 ), false );
791  }
792 
793  //Create a bucket of nodes for sending
794 
795  std::vector<stk_classic::mesh::EntityProc> add_send;
796 
797  const std::vector<stk_classic::mesh::Bucket*> & buckets = bulk.buckets( 0 );
798 
799  std::vector<stk_classic::mesh::Bucket*>::const_iterator cur_bucket;
800 
801  cur_bucket = buckets.begin();
802 
803  unsigned send_rank = 0;
804  while ( cur_bucket != buckets.end() )
805  {
806  stk_classic::mesh::Bucket::iterator cur_entity = (*cur_bucket)->begin();
807  while ( cur_entity != (*cur_bucket)->end() )
808  {
809  if ( cur_entity->owner_rank() == rank_count )
810  {
811  if ( send_rank == size ) send_rank = 0;
812  if ( send_rank != rank_count )
813  add_send.push_back ( std::make_pair ( &*cur_entity , send_rank ) );
814  ++send_rank;
815  }
816  ++cur_entity;
817  }
818  ++cur_bucket;
819  }
820 
821  std::set< stk_classic::mesh::EntityProc , stk_classic::mesh::EntityLess > new_send ;
822  std::set< stk_classic::mesh::Entity * , stk_classic::mesh::EntityLess > new_recv ;
823 
824  // Keep the closure of the remaining received ghosts.
825  // Working from highest-to-lowest key (rank entity type)
826  // results in insertion of the transitive closure.
827  // Insertion will not invalidate the associative container's iterator.
828 
829  for ( std::set< stk_classic::mesh::Entity * , stk_classic::mesh::EntityLess >::iterator
830  i = new_recv.end() ; i != new_recv.begin() ; ) {
831  --i ;
832 
833  const unsigned erank = (*i)->entity_rank();
834 
836  irel = (*i)->relations(); ! irel.empty() ; ++irel ) {
837  if ( irel->entity_rank() < erank &&
838  in_receive_ghost( ghosts , * irel->entity() ) ) {
839  new_recv.insert( irel->entity() );
840  }
841  }
842  }
843 
844  // Initialize the new_send from the new_recv
845  new_comm_recv_to_send( bulk , new_recv , new_send );
846 
847  //------------------------------------
848  // Add the specified entities and their closure to the send ghosting
849 
850  for ( std::vector< stk_classic::mesh::EntityProc >::const_iterator
851  i = add_send.begin() ; i != add_send.end() ; ++i ) {
852  new_insert_transitive_closure( new_send , *i );
853  }
854 
855  // Synchronize the send and receive list.
856  // If the send list contains a not-owned entity
857  // inform the owner and receiver to ad that entity
858  // to their ghost send and receive lists.
859 
860  new_comm_sync_send_recv( bulk , new_send , new_recv );
861 
862  //------------------------------------
863  // Push newly ghosted entities to the receivers and update the comm list.
864  // Unpacking must proceed in entity-rank order so that higher ranking
865  // entities that have relations to lower ranking entities will have
866  // the lower ranking entities unpacked first. The higher and lower
867  // ranking entities may be owned by different processes,
868  // as such unpacking must be performed in rank order.
869 
870  //Start of CommAll section:
871  {
872  stk_classic::CommAll comm( MPI_COMM_WORLD );
873 
874  for ( std::set< stk_classic::mesh::EntityProc , stk_classic::mesh::EntityLess >::iterator
875  j = new_send.begin(); j != new_send.end() ; ++j ) {
876  stk_classic::mesh::Entity & entity = * j->first ;
877  if ( ! in_ghost( ghosts , entity , j->second ) ) {
878  // Not already being sent , must send it.
879  stk_classic::CommBuffer & buf = comm.send_buffer( j->second );
880  buf.pack<unsigned>( entity.entity_rank() );
881  stk_classic::mesh::pack_entity_info( buf , entity );
882  stk_classic::mesh::pack_field_values( buf , entity );
883  }
884  }
885 
886  comm.allocate_buffers( size / 4 );
887 
888  for ( std::set< stk_classic::mesh::EntityProc , stk_classic::mesh::EntityLess >::iterator
889  j = new_send.begin(); j != new_send.end() ; ++j ) {
890  stk_classic::mesh::Entity & entity = * j->first ;
891  if ( ! in_ghost( ghosts , entity , j->second ) ) {
892  // Not already being sent , must send it.
893  stk_classic::CommBuffer & buf = comm.send_buffer( j->second );
894  buf.pack<unsigned>( entity.entity_rank() );
895  stk_classic::mesh::pack_entity_info( buf , entity );
896  stk_classic::mesh::pack_field_values( buf , entity );
897 
898  }
899  }
900 
901  comm.communicate();
902 
903  std::ostringstream error_msg ;
904 
905  for ( unsigned rank = 0 ; rank < rank_count ; ++rank ) {
906 
907  for ( unsigned p = 0 ; p < size ; ++p ) {
908 
909  stk_classic::CommBuffer & buf = comm.recv_buffer(p);
910 
911  while ( buf.remaining() ) {
912 
913  // Only unpack if of the current entity rank.
914  // If not the current entity rank, break the iteration
915  // until a subsequent entity rank iteration.
916  {
917  unsigned this_rank = ~0u ;
918  buf.peek<unsigned>( this_rank );
919  if ( this_rank != rank ) break ;
920 
921  buf.unpack<unsigned>( this_rank );
922  }
923 
924  // FIXME for Carol; the code below did not work with -np 4
925  //STKUNIT_ASSERT_EQUAL( stk_classic::mesh::unpack_field_values( buf , elem2 , error_msg ), false);
926  //std::cout << "Error message for unpack_field_values = " << error_msg.str() << std::endl ;
927 
928  }
929  }
930 
931  }
932  }//end of CommAll section
933 
934  bulk.modification_end ();
935 }
936 
937 STKUNIT_UNIT_TEST ( UnitTestBulkData_new , testUninitializedMetaData )
938 {
939  stk_classic::ParallelMachine pm = MPI_COMM_WORLD;
940 
941  stk_classic::mesh::MetaData meta; // Construct, but do not initialize
942  stk_classic::mesh::BulkData bulk(meta, pm);
943 
944  meta.set_entity_rank_names(stk_classic::mesh::fem::entity_rank_names(2 /*spatial-dim*/));
945 
946  meta.commit();
947 
948  bulk.modification_begin();
949 
950  STKUNIT_ASSERT_THROW( bulk.declare_entity(0, /*rank*/
951  1, /*id*/
953  std::logic_error);
954 }
955 
956 namespace {
957 
958 void new_insert_transitive_closure( std::set<stk_classic::mesh::EntityProc,stk_classic::mesh::EntityLess> & new_send ,
959  const stk_classic::mesh::EntityProc & entry )
960 {
961  // Do not insert if I can determine that this entity is already
962  // owned or shared by the receiving processor.
963 
964  if ( entry.second != entry.first->owner_rank() &&
965  ! in_shared( * entry.first , entry.second ) ) {
966 
967  std::pair< std::set<stk_classic::mesh::EntityProc,stk_classic::mesh::EntityLess>::iterator , bool >
968  result = new_send.insert( entry );
969 
970  if ( result.second ) {
971  // A new insertion, must also insert the closure
972 
973  const unsigned etype = entry.first->entity_rank();
974  stk_classic::mesh::PairIterRelation irel = entry.first->relations();
975 
976  for ( ; ! irel.empty() ; ++irel ) {
977  if ( irel->entity_rank() < etype ) {
978  stk_classic::mesh::EntityProc tmp( irel->entity() , entry.second );
979  new_insert_transitive_closure( new_send , tmp );
980  }
981  }
982  }
983  }
984 }
985 
986 
987 // Synchronize the send list to the receive list.
988 
989 void new_comm_sync_send_recv(
991  std::set< stk_classic::mesh::EntityProc , stk_classic::mesh::EntityLess > & new_send ,
992  std::set< stk_classic::mesh::Entity * , stk_classic::mesh::EntityLess > & new_recv )
993 {
994  const unsigned parallel_rank = mesh.parallel_rank();
995  const unsigned parallel_size = mesh.parallel_size();
996 
997  stk_classic::CommAll all( mesh.parallel() );
998 
999  // Communication sizing:
1000 
1001  for ( std::set< stk_classic::mesh::EntityProc , stk_classic::mesh::EntityLess >::iterator
1002  i = new_send.begin() ; i != new_send.end() ; ++i ) {
1003  const unsigned owner = i->first->owner_rank();
1004  all.send_buffer( i->second ).skip<stk_classic::mesh::EntityKey>(2);
1005  if ( owner != parallel_rank ) {
1006  all.send_buffer( owner ).skip<stk_classic::mesh::EntityKey>(2);
1007  }
1008  }
1009 
1010  all.allocate_buffers( parallel_size / 4 , false /* Not symmetric */ );
1011 
1012  // Communication packing (with message content comments):
1013  for ( std::set< stk_classic::mesh::EntityProc , stk_classic::mesh::EntityLess >::iterator
1014  i = new_send.begin() ; i != new_send.end() ; ) {
1015  const unsigned owner = i->first->owner_rank();
1016 
1017  // Inform receiver of ghosting, the receiver does not own
1018  // and does not share this entity.
1019  // The ghost either already exists or is a to-be-done new ghost.
1020  // This status will be resolved on the final communication pass
1021  // when new ghosts are packed and sent.
1022 
1023  const stk_classic::mesh::EntityKey &entity_key = i->first->key();
1024  const uint64_t &proc = i->second;
1025 
1026  all.send_buffer( i->second ).pack(entity_key).pack(proc);
1027 
1028  if ( owner != parallel_rank ) {
1029  // I am not the owner of this entity.
1030  // Inform the owner of this ghosting need.
1031  all.send_buffer( owner ).pack(entity_key).pack(proc);
1032 
1033  // Erase it from my processor's ghosting responsibility:
1034  // The iterator passed to the erase method will be invalidated.
1035  std::set< stk_classic::mesh::EntityProc , stk_classic::mesh::EntityLess >::iterator jrem = i ; ++i ;
1036  new_send.erase( jrem );
1037  }
1038  else {
1039  ++i ;
1040  }
1041  }
1042 
1043  all.communicate();
1044 
1045  // Communication unpacking:
1046  for ( unsigned p = 0 ; p < parallel_size ; ++p ) {
1047  stk_classic::CommBuffer & buf = all.recv_buffer(p);
1048  while ( buf.remaining() ) {
1049 
1050  stk_classic::mesh::EntityKey entity_key;
1051  uint64_t proc(0);
1052 
1053  buf.unpack(entity_key).unpack(proc);
1054 
1055  stk_classic::mesh::Entity * const e = mesh.get_entity( entity_key );
1056 
1057  if ( parallel_rank != proc ) {
1058  // Receiving a ghosting need for an entity I own.
1059  // Add it to my send list.
1060  STKUNIT_ASSERT( e != NULL );
1061  stk_classic::mesh::EntityProc tmp( e , proc );
1062  new_send.insert( tmp );
1063  }
1064  else if ( e != NULL ) {
1065  // I am the receiver for this ghost.
1066  // If I already have it add it to the receive list,
1067  // otherwise don't worry about it - I will receive
1068  // it in the final new-ghosting communication.
1069  new_recv.insert( e );
1070  }
1071  }
1072  }
1073 }
1074 
1075 void new_comm_recv_to_send(
1077  const std::set< stk_classic::mesh::Entity * , stk_classic::mesh::EntityLess > & new_recv ,
1078  std::set< stk_classic::mesh::EntityProc , stk_classic::mesh::EntityLess > & new_send )
1079 {
1080  const unsigned parallel_size = mesh.parallel_size();
1081 
1082  stk_classic::CommAll all( mesh.parallel() );
1083 
1084  for ( std::set< stk_classic::mesh::Entity * , stk_classic::mesh::EntityLess >::const_iterator
1085  i = new_recv.begin() ; i != new_recv.end() ; ++i ) {
1086  const unsigned owner = (*i)->owner_rank();
1087  all.send_buffer( owner ).skip<stk_classic::mesh::EntityKey>(1);
1088  }
1089 
1090  all.allocate_buffers( parallel_size / 4 , false /* Not symmetric */ );
1091 
1092  for ( std::set< stk_classic::mesh::Entity * , stk_classic::mesh::EntityLess >::const_iterator
1093  i = new_recv.begin() ; i != new_recv.end() ; ++i ) {
1094  const unsigned owner = (*i)->owner_rank();
1095  const stk_classic::mesh::EntityKey key = (*i)->key();
1096  all.send_buffer( owner ).pack<stk_classic::mesh::EntityKey>( & key , 1 );
1097  }
1098 
1099  all.communicate();
1100 
1101  for ( unsigned p = 0 ; p < parallel_size ; ++p ) {
1102  stk_classic::CommBuffer & buf = all.recv_buffer(p);
1103  while ( buf.remaining() ) {
1105  buf.unpack<stk_classic::mesh::EntityKey>( & key , 1 );
1106  stk_classic::mesh::EntityProc tmp( mesh.get_entity( entity_rank(key), entity_id(key) ) , p );
1107  new_send.insert( tmp );
1108  }
1109  }
1110 }
1111 
1112 }
void declare_relation(Entity &e_from, Entity &e_to, const RelationIdentifier local_id)
Declare a relation and its converse between entities in the same mesh.
FEMMetaData is a class that implements a Finite Element Method skin on top of the Sierra Tool Kit Met...
Definition: FEMMetaData.hpp:54
The manager of an integrated collection of parts and fields.
Definition: MetaData.hpp:56
PairIterEntityComm sharing() const
Parallel processes which share this entity.
Definition: Entity.hpp:178
Ghosting & create_ghosting(const std::string &name)
Asymmetric parallel relations for owner-to-ghosted mesh entities.
const std::vector< Entity * > & entity_comm() const
All entities with communication information.
Definition: BulkData.hpp:367
Data for ghosting mesh entities.
Definition: Ghosting.hpp:28
bool destroy_relation(Entity &e_from, Entity &e_to, const RelationIdentifier local_id)
Remove all relations between two entities.
FieldTraits< field_type >::data_type * field_data(const field_type &f, const Bucket::iterator i)
Pointer to the field data array.
Definition: FieldData.hpp:116
Part & universal_part() const
Universal subset for the problem domain. All other parts are a subset of the universal part...
Bucket & bucket() const
The bucket which holds this mesh entity&#39;s field data.
Definition: Entity.hpp:141
const std::vector< Bucket * > & buckets(EntityRank rank) const
Query all buckets of a given entity rank.
Definition: BulkData.hpp:195
void change_ghosting(Ghosting &ghosts, const std::vector< EntityProc > &add_send, const std::vector< Entity *> &remove_receive)
Change the members of a ghosting list on the sending processor.
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.
Ghosting & shared_aura() const
Query the shared-entity aura. Is likely to be stale if ownership or sharing has changed and the &#39;modi...
Definition: BulkData.hpp:375
Entity * get_entity(EntityRank entity_rank, EntityId entity_id) const
Get entity with a given key.
Definition: BulkData.hpp:211
Integer type for the entity keys, which is an encoding of the entity type and entity identifier...
std::pair< Entity *, unsigned > EntityProc
Pairing of an entity with a processor rank.
Definition: Types.hpp:111
int parallel_rank()
function parallel_rank returns the rank of this processor in the current mpi communicator.
Definition: Env.cpp:318
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
void change_entity_parts(Entity &entity, const PartVector &add_parts, const PartVector &remove_parts=PartVector())
Change the parallel-locally-owned entity&#39;s part membership by adding and/or removing parts...
Definition: BulkData.hpp:249
void destroy_all_ghosting()
Empty every single Ghosting. Same result, but more efficient than, calling change_ghosting to remove ...
ParallelMachine parallel() const
The parallel machine.
Definition: BulkData.hpp:79
Part & declare_part(const std::string &name, fem::CellTopology cell_topology)
Declare a part with a given cell topology.
void receive_list(std::vector< Entity * > &) const
Entities ghosted on this processor from the owner.
Definition: Ghosting.cpp:33
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
PairIterRelation relations() const
All Entity relations for which this entity is a member. The relations are ordered from lowest entity-...
Definition: Entity.hpp:161
void set_entity_rank_names(const std::vector< std::string > &entity_rank_names)
entity-rank names
Definition: MetaData.cpp:155
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
EntityId entity_id(const EntityKey &key)
Given an entity key, return the identifier for the entity.
static MetaData & get_meta_data(FEMMetaData &fem_meta)
Getter for MetaData off of a FEMMetaData object.
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
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
MPI_Comm ParallelMachine
Definition: Parallel.hpp:32
void send_list(std::vector< EntityProc > &) const
Locally owned entities ghosted on other processors.
Definition: Ghosting.cpp:17
int parallel_size()
function parallel_size returns the number of processors in the current mpi communicator.
Definition: Env.cpp:314
unsigned parallel_rank() const
Rank of the parallel machine&#39;s local processor.
Definition: BulkData.hpp:85
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
EntityId identifier() const
Identifier for this entity which is globally unique for a given entity type.
Definition: Entity.hpp:133
std::vector< Part *> PartVector
Collections of parts are frequently maintained as a vector of Part pointers.
Definition: Types.hpp:31
EntityRank entity_rank(const EntityKey &key)
Given an entity key, return an entity type (rank).
bool destroy_entity(Entity *&entity)
Request the destruction an entity on the local process.
Definition: BulkData.cpp:698
void commit()
Commit the part and field declarations so that the meta data manager can be used to create mesh bulk ...
Definition: MetaData.cpp:368
bool member(const Part &) const
Bucket is a subset of the given part.
Definition: Bucket.cpp:60
unsigned owner_rank() const
Parallel processor rank of the processor which owns this entity.
Definition: Entity.hpp:175
void FEM_initialize(size_t spatial_dimension, const std::vector< std::string > &in_entity_rank_names=std::vector< std::string >())
Initialize the spatial dimension and an optional list of entity rank names associated with each rank...
Definition: FEMMetaData.cpp:61