Sierra Toolkit  Version of the Day
UnitTestBulkData_ChangeParts.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 <iostream>
10 #include <sstream>
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/base/BulkData.hpp>
17 #include <stk_mesh/base/GetEntities.hpp>
18 #include <stk_mesh/base/Comm.hpp>
19 
20 #include <stk_mesh/fixtures/RingFixture.hpp>
21 
22 #include <unit_tests/UnitTestModificationEndWrapper.hpp>
23 
32 
33 //----------------------------------------------------------------------
34 
35 STKUNIT_UNIT_TEST(UnitTestingOfBulkData, testChangeParts)
36 {
37  // This unit test tests part operations and verifies operations
38  // by looking at bucket supersets. We use contrived entities
39  // (as opposed to a fixture) for simplicity and clarity.
40 
41  stk_classic::ParallelMachine pm = MPI_COMM_WORLD;
42  MPI_Barrier( pm );
43 
44  const unsigned p_size = stk_classic::parallel_machine_size( pm );
45  const unsigned p_rank = stk_classic::parallel_machine_rank( pm );
46 
47  // Single process, no sharing
48 
49  // Meta data with entity ranks [0..9]
50  const unsigned spatial_dimension = 10;
51  std::vector<std::string> entity_names(spatial_dimension+1);
52  for ( size_t i = 0 ; i <= spatial_dimension ; ++i ) {
53  std::ostringstream name ;
54  name << "EntityRank_" << i ;
55  entity_names[i] = name.str();
56  }
57 
58  // Create a mesh with a bunch of parts
59 
60  FEMMetaData meta( spatial_dimension, entity_names );
61  BulkData bulk( FEMMetaData::get_meta_data(meta) , pm , 100 );
62 
63  Part & part_univ = meta.universal_part();
64  Part & part_owns = meta.locally_owned_part();
65  Part & part_shared = meta.globally_shared_part();
66 
67  Part & part_A_0 = meta.declare_part(std::string("A_0"), 0 /*entity_rank*/);
68  Part & part_A_1 = meta.declare_part(std::string("A_1"), 1 /*entity_rank*/);
69  Part & part_A_2 = meta.declare_part(std::string("A_2"), 2 /*entity_rank*/);
70  Part & part_A_3 = meta.declare_part(std::string("A_3"), 3 /*entity_rank*/);
71 
72  Part & part_B_0 = meta.declare_part(std::string("B_0"), 0 /*entity_rank*/);
73  Part & part_B_2 = meta.declare_part(std::string("B_2"), 2 /*entity_rank*/);
74 
75  meta.commit();
76  bulk.modification_begin();
77 
78  PartVector tmp(1), no_parts;
79 
80  // Declare a few entities of various ranks. In order for the sharing
81  // to work, we need to have all the entities we'll be playing with
82  // to be in the owned-closure of a high-level non-shared entity, we'll
83  // call that entity the closure_entity because all the other entities
84  // will be in it's closure.
85 
86  Entity& closure_entity = bulk.declare_entity(4 /*entity rank*/,
87  p_rank+1 /*id*/,
88  no_parts);
89 
90  tmp[0] = & part_A_0 ;
91  Entity& entity_0_1 = bulk.declare_entity(0 /*entity rank*/, 1 /*id*/, tmp);
92  bulk.declare_relation( closure_entity , entity_0_1 , 0 /*local_rel_id*/ );
93 
94  tmp[0] = & part_A_1 ;
95  Entity& entity_1_1 = bulk.declare_entity(1 /*entity rank*/, 1 /*id*/, tmp);
96  bulk.declare_relation( closure_entity , entity_1_1 , 1 /*local_rel_id*/ );
97 
98  tmp[0] = & part_A_2 ;
99  Entity& entity_2_1 = bulk.declare_entity(2 /*entity rank*/, 1 /*id*/, tmp);
100  bulk.declare_relation( closure_entity , entity_2_1 , 2 /*local_rel_id*/ );
101 
102  tmp[0] = & part_A_3 ;
103  Entity& entity_3_1 = bulk.declare_entity(3 /*entity rank*/, 1 /*id*/, tmp);
104  bulk.declare_relation( closure_entity , entity_3_1 , 3 /*local_rel_id*/ );
105 
106  // Ensure that the supersets of the buckets containing the entities we
107  // just created are correct.
108 
109  entity_0_1.bucket().supersets( tmp );
110  STKUNIT_ASSERT_EQUAL( size_t(3) , tmp.size() );
111  STKUNIT_ASSERT( entity_0_1.bucket().member(part_univ) );
112  STKUNIT_ASSERT( entity_0_1.bucket().member(part_owns) );
113  STKUNIT_ASSERT( entity_0_1.bucket().member(part_A_0) );
114 
115  entity_1_1.bucket().supersets( tmp );
116  STKUNIT_ASSERT_EQUAL( size_t(3) , tmp.size() );
117  STKUNIT_ASSERT( entity_1_1.bucket().member(part_univ) );
118  STKUNIT_ASSERT( entity_1_1.bucket().member(part_owns) );
119  STKUNIT_ASSERT( entity_1_1.bucket().member(part_A_1) );
120 
121  entity_2_1.bucket().supersets( tmp );
122  STKUNIT_ASSERT_EQUAL( size_t(3) , tmp.size() );
123  STKUNIT_ASSERT( entity_2_1.bucket().member(part_univ) );
124  STKUNIT_ASSERT( entity_2_1.bucket().member(part_owns) );
125  STKUNIT_ASSERT( entity_2_1.bucket().member(part_A_2) );
126 
127  entity_3_1.bucket().supersets( tmp );
128  STKUNIT_ASSERT_EQUAL( size_t(3) , tmp.size() );
129  STKUNIT_ASSERT( entity_3_1.bucket().member(part_univ) );
130  STKUNIT_ASSERT( entity_3_1.bucket().member(part_owns) );
131  STKUNIT_ASSERT( entity_3_1.bucket().member(part_A_3) );
132 
133  // Add entity_0_1 to the part it was already in
134  {
135  tmp.resize(1);
136  tmp[0] = & part_A_0 ;
137  bulk.change_entity_parts( entity_0_1 , tmp );
138  entity_0_1.bucket().supersets( tmp );
139  STKUNIT_ASSERT_EQUAL( size_t(3) , tmp.size() );
140  STKUNIT_ASSERT( entity_0_1.bucket().member(part_univ) );
141  STKUNIT_ASSERT( entity_0_1.bucket().member(part_owns) );
142  STKUNIT_ASSERT( entity_0_1.bucket().member(part_A_0) );
143  }
144 
145  // Add entity_0_1 to part_B_0
146  {
147  tmp.resize(1);
148  tmp[0] = & part_B_0 ;
149  bulk.change_entity_parts( entity_0_1 , tmp );
150  entity_0_1.bucket().supersets( tmp );
151  STKUNIT_ASSERT_EQUAL( size_t(4) , tmp.size() );
152  STKUNIT_ASSERT( entity_0_1.bucket().member(part_univ) );
153  STKUNIT_ASSERT( entity_0_1.bucket().member(part_owns) );
154  STKUNIT_ASSERT( entity_0_1.bucket().member(part_A_0) );
155  STKUNIT_ASSERT( entity_0_1.bucket().member(part_B_0) );
156  }
157 
158  // Remove entity_0_1 from the part it was just added to above
159  {
160  tmp.resize(1);
161  tmp[0] = & part_B_0 ;
162  bulk.change_entity_parts( entity_0_1 , PartVector() , tmp );
163  entity_0_1.bucket().supersets( tmp );
164  STKUNIT_ASSERT_EQUAL( size_t(3) , tmp.size() );
165  STKUNIT_ASSERT( entity_0_1.bucket().member(part_univ) );
166  STKUNIT_ASSERT( entity_0_1.bucket().member(part_owns) );
167  STKUNIT_ASSERT( entity_0_1.bucket().member(part_A_0) );
168  }
169 
170  // Add relation from entity_1_1 (which is in part_A_1) to
171  // entity_0_1 (which is in part_A_0). After the relation
172  // is added, there is an induced membership of entity_0_1
173  // within part A_1.
174  stk_classic::mesh::RelationIdentifier test_rel_id = 0;
175  {
176  bulk.declare_relation( entity_1_1 , entity_0_1 , test_rel_id );
177  entity_0_1.bucket().supersets( tmp );
178  STKUNIT_ASSERT_EQUAL( size_t(4) , tmp.size() );
179  STKUNIT_ASSERT( entity_0_1.bucket().member(part_univ) );
180  STKUNIT_ASSERT( entity_0_1.bucket().member(part_owns) );
181  STKUNIT_ASSERT( entity_0_1.bucket().member(part_A_0) );
182  STKUNIT_ASSERT( entity_0_1.bucket().member(part_A_1) );
183  }
184 
185  // Remove the relationship added in the step above and
186  // demonstrate that the induced membership of entity_0_1
187  // in part_A_1 is gone
188  {
189  bulk.destroy_relation( entity_1_1 , entity_0_1, test_rel_id );
190  entity_0_1.bucket().supersets( tmp );
191  STKUNIT_ASSERT_EQUAL( size_t(3) , tmp.size() );
192  STKUNIT_ASSERT( entity_0_1.bucket().member(part_univ) );
193  STKUNIT_ASSERT( entity_0_1.bucket().member(part_owns) );
194  STKUNIT_ASSERT( entity_0_1.bucket().member(part_A_0) );
195  }
196 
197  // Add entity_2_1 to part_B_2
198  {
199  tmp.resize(1);
200  tmp[0] = & part_B_2 ;
201  bulk.change_entity_parts( entity_2_1 , tmp );
202  entity_2_1.bucket().supersets( tmp );
203  STKUNIT_ASSERT_EQUAL( size_t(4) , tmp.size() );
204  STKUNIT_ASSERT( entity_2_1.bucket().member(part_univ) );
205  STKUNIT_ASSERT( entity_2_1.bucket().member(part_owns) );
206  STKUNIT_ASSERT( entity_2_1.bucket().member(part_A_2) );
207  STKUNIT_ASSERT( entity_2_1.bucket().member(part_B_2) );
208  }
209 
210  // Add relation from entity_2_1 (which is in part_A_2 and B_2) to
211  // entity_0_1 (which is in part_A_0). After the relation
212  // is added, there is an induced membership of entity_0_1
213  // within entity_2_1's parts (A_2 and B_2) (and of course entity_0_1
214  // is still in the parts it was already in).
215  {
216  bulk.declare_relation( entity_2_1 , entity_0_1 , test_rel_id );
217  entity_0_1.bucket().supersets( tmp );
218  STKUNIT_ASSERT_EQUAL( size_t(5) , tmp.size() );
219  STKUNIT_ASSERT( entity_0_1.bucket().member(part_univ) );
220  STKUNIT_ASSERT( entity_0_1.bucket().member(part_owns) );
221  STKUNIT_ASSERT( entity_0_1.bucket().member(part_A_0) );
222  STKUNIT_ASSERT( entity_0_1.bucket().member(part_A_2) );
223  STKUNIT_ASSERT( entity_0_1.bucket().member(part_B_2) );
224  }
225 
226  // Remove the relationship added in the step above and
227  // demonstrate that the induced membership of entity_0_1
228  // in parts A_2 and B_2 is gone.
229  {
230  bulk.destroy_relation( entity_2_1 , entity_0_1, test_rel_id );
231  entity_0_1.bucket().supersets( tmp );
232  STKUNIT_ASSERT_EQUAL( size_t(3) , tmp.size() );
233  STKUNIT_ASSERT( entity_0_1.bucket().member(part_univ) );
234  STKUNIT_ASSERT( entity_0_1.bucket().member(part_owns) );
235  STKUNIT_ASSERT( entity_0_1.bucket().member(part_A_0) );
236  }
237 
238  bulk.modification_end();
239 
240  //------------------------------
241  // Now the parallel fun. Existing entities should be shared
242  // by all processes since they have the same identifiers.
243  // They should also have the same parts.
244 
245  bool parallel = p_size > 1;
246 
247  // For parallel runs, the entities should be in the same parts
248  // as they were before the modification end and they should
249  // be in the shared part as well.
250 
251  entity_0_1.bucket().supersets( tmp );
252  if ( entity_0_1.owner_rank() == p_rank ) {
253  STKUNIT_ASSERT_EQUAL( size_t(parallel ? 4 : 3) , tmp.size() );
254  STKUNIT_ASSERT( entity_0_1.bucket().member(part_univ) );
255  STKUNIT_ASSERT( entity_0_1.bucket().member(part_owns) );
256  if ( parallel )
257  STKUNIT_ASSERT( entity_0_1.bucket().member(part_shared) );
258  STKUNIT_ASSERT( entity_0_1.bucket().member(part_A_0) );
259  }
260  else {
261  STKUNIT_ASSERT( parallel );
262  STKUNIT_ASSERT_EQUAL( size_t(3) , tmp.size() );
263  STKUNIT_ASSERT( entity_0_1.bucket().member(part_univ) );
264  STKUNIT_ASSERT( entity_0_1.bucket().member(part_shared) );
265  STKUNIT_ASSERT( entity_0_1.bucket().member(part_A_0) );
266  }
267 
268  entity_2_1.bucket().supersets( tmp );
269  if ( entity_2_1.owner_rank() == p_rank ) {
270  STKUNIT_ASSERT_EQUAL( size_t(parallel ? 5 : 4) , tmp.size() );
271  STKUNIT_ASSERT( entity_2_1.bucket().member(part_univ) );
272  STKUNIT_ASSERT( entity_2_1.bucket().member(part_owns) );
273  if ( parallel )
274  STKUNIT_ASSERT( entity_2_1.bucket().member(part_shared) );
275  STKUNIT_ASSERT( entity_2_1.bucket().member(part_A_2) );
276  STKUNIT_ASSERT( entity_2_1.bucket().member(part_B_2) );
277  }
278  else {
279  STKUNIT_ASSERT_EQUAL( size_t(4) , tmp.size() );
280  STKUNIT_ASSERT( entity_2_1.bucket().member(part_univ) );
281  STKUNIT_ASSERT( entity_2_1.bucket().member(part_shared) );
282  STKUNIT_ASSERT( entity_2_1.bucket().member(part_A_2) );
283  STKUNIT_ASSERT( entity_2_1.bucket().member(part_B_2) );
284  }
285 
286  if ( parallel ) {
287  // If parallel, check that the entities are shared across all procs.
288  STKUNIT_ASSERT_EQUAL( size_t(p_size - 1) , entity_0_1.sharing().size() );
289  STKUNIT_ASSERT_EQUAL( size_t(p_size - 1) , entity_1_1.sharing().size() );
290  STKUNIT_ASSERT_EQUAL( size_t(p_size - 1) , entity_2_1.sharing().size() );
291  STKUNIT_ASSERT_EQUAL( size_t(p_size - 1) , entity_3_1.sharing().size() );
292  }
293 
294  bulk.modification_begin();
295 
296  // Add entity_0_1 to a new part on the owning process
297 
298  int ok_to_modify = entity_0_1.owner_rank() == p_rank ;
299 
300  try {
301  tmp.resize(1);
302  tmp[0] = & part_B_0 ;
303  bulk.change_entity_parts( entity_0_1 , tmp );
304  STKUNIT_ASSERT( ok_to_modify );
305  }
306  catch( const std::exception & x ) {
307  STKUNIT_ASSERT( ! ok_to_modify );
308  }
309 
310  // Check that entity_0_1 is in the new part on the owning
311  // process, but not on other processes.
312 
313  entity_0_1.bucket().supersets( tmp );
314  if ( entity_0_1.owner_rank() == p_rank ) {
315  STKUNIT_ASSERT_EQUAL( size_t(parallel ? 5 : 4) , tmp.size() );
316  STKUNIT_ASSERT( entity_0_1.bucket().member(part_univ) );
317  STKUNIT_ASSERT( entity_0_1.bucket().member(part_owns) );
318  if ( parallel )
319  STKUNIT_ASSERT( entity_0_1.bucket().member(part_shared) );
320  STKUNIT_ASSERT( entity_0_1.bucket().member(part_A_0) );
321  STKUNIT_ASSERT( entity_0_1.bucket().member(part_B_0) );
322  }
323  else {
324  STKUNIT_ASSERT_EQUAL( size_t(3) , tmp.size() );
325  STKUNIT_ASSERT( entity_0_1.bucket().member(part_univ) );
326  STKUNIT_ASSERT( entity_0_1.bucket().member(part_shared) );
327  STKUNIT_ASSERT( entity_0_1.bucket().member(part_A_0) );
328  }
329 
330  bulk.modification_end();
331 
332  // Now that modification_end has been called, entity_0_1 should
333  // be in the new part (B_0) on all processes.
334 
335  entity_0_1.bucket().supersets( tmp );
336  if ( entity_0_1.owner_rank() == p_rank ) {
337  STKUNIT_ASSERT_EQUAL( size_t(parallel ? 5 : 4) , tmp.size() );
338  STKUNIT_ASSERT( entity_0_1.bucket().member(part_univ) );
339  STKUNIT_ASSERT( entity_0_1.bucket().member(part_owns) );
340  if ( parallel )
341  STKUNIT_ASSERT( entity_0_1.bucket().member(part_shared) );
342  STKUNIT_ASSERT( entity_0_1.bucket().member(part_A_0) );
343  STKUNIT_ASSERT( entity_0_1.bucket().member(part_B_0) );
344  }
345  else {
346  STKUNIT_ASSERT_EQUAL( size_t(4) , tmp.size() );
347  STKUNIT_ASSERT( entity_0_1.bucket().member(part_univ) );
348  STKUNIT_ASSERT( entity_0_1.bucket().member(part_shared) );
349  STKUNIT_ASSERT( entity_0_1.bucket().member(part_A_0) );
350  STKUNIT_ASSERT( entity_0_1.bucket().member(part_B_0) );
351  }
352 }
353 
354 //----------------------------------------------------------------------
355 //----------------------------------------------------------------------
356 
357 STKUNIT_UNIT_TEST(UnitTestingOfBulkData, testChangeParts_ringmesh)
358 {
359  // This unit test tests part operations and verifies operations
360  // by looking at bucket supersets. We use RingMesh for a slightly
361  // more realistic test than the test above but it's a bit harder
362  // to read.
363 
364  stk_classic::ParallelMachine pm = MPI_COMM_WORLD;
365  MPI_Barrier( pm );
366 
367  const unsigned nPerProc = 10;
368  const unsigned p_rank = stk_classic::parallel_machine_rank( pm );
369  const unsigned p_size = stk_classic::parallel_machine_size( pm );
370  const unsigned nLocalNode = nPerProc + ( 1 < p_size ? 1 : 0 );
371  const unsigned nLocalEdge = nPerProc ;
372 
373  // Create the ring mesh
374 
375  RingFixture ring_mesh( pm , nPerProc , true /* generate parts */ );
376  ring_mesh.m_meta_data.commit();
377  BulkData& bulk = ring_mesh.m_bulk_data;
378 
379  bulk.modification_begin();
380  ring_mesh.generate_mesh( );
381  STKUNIT_ASSERT(stk_classic::unit_test::modification_end_wrapper(bulk,
382  false /* no aura */));
383 
384  bulk.modification_begin();
385  ring_mesh.fixup_node_ownership();
386  STKUNIT_ASSERT(stk_classic::unit_test::modification_end_wrapper(bulk,
387  false /* no aura */));
388 
389  Part & part_owns = ring_mesh.m_meta_data.locally_owned_part();
390  Part & part_univ = ring_mesh.m_meta_data.universal_part();
391 
392  // Check that local edges are in the expected parts. Note that the
393  // RingMesh puts each edge in its own part.
394  for ( unsigned i = 0 ; i < nLocalEdge ; ++i ) {
395  const unsigned n = i + nPerProc * p_rank ;
396  Entity * const edge = bulk.get_entity( 1 /*entity rank*/,
397  ring_mesh.m_edge_ids[n] );
398  STKUNIT_ASSERT( edge != NULL );
399  STKUNIT_ASSERT( edge->bucket().member( part_univ ) );
400  STKUNIT_ASSERT( edge->bucket().member( part_owns ) );
401  STKUNIT_ASSERT( edge->bucket().member( * ring_mesh.m_edge_parts[ n % ring_mesh.m_edge_parts.size() ] ) );
402  }
403 
404  // Check that local nodes are in the expected parts. Note that the relations
405  // that nodes have to edges should cause induced membership of the node
406  // in the parts of both edges it touches.
407  for ( unsigned i = 0 ; i < nLocalNode ; ++i ) {
408  const unsigned n = ( i + nPerProc * p_rank ) % ring_mesh.m_node_ids.size();
409  const unsigned e0 = n ;
410  const unsigned e1 = ( n + ring_mesh.m_edge_ids.size() - 1 ) % ring_mesh.m_edge_ids.size();
411  const unsigned ns = ring_mesh.m_edge_parts.size();
412  const unsigned n0 = e0 % ns ;
413  const unsigned n1 = e1 % ns ;
414  Part * const epart_0 = ring_mesh.m_edge_parts[ n0 < n1 ? n0 : n1 ];
415  Part * const epart_1 = ring_mesh.m_edge_parts[ n0 < n1 ? n1 : n0 ];
416 
417  Entity * const node = bulk.get_entity( 0 , ring_mesh.m_node_ids[n] );
418  STKUNIT_ASSERT( node != NULL );
419  if ( node->owner_rank() == p_rank ) {
420  STKUNIT_ASSERT( node->bucket().member( part_univ ) );
421  STKUNIT_ASSERT( node->bucket().member( part_owns ) );
422  STKUNIT_ASSERT( node->bucket().member( *epart_0 ) );
423  STKUNIT_ASSERT( node->bucket().member( *epart_1 ) );
424  }
425  else {
426  STKUNIT_ASSERT( node->bucket().member( part_univ ) );
427  STKUNIT_ASSERT( ! node->bucket().member( part_owns ) );
428  STKUNIT_ASSERT( node->bucket().member( * epart_0 ) );
429  STKUNIT_ASSERT( node->bucket().member( * epart_1 ) );
430  }
431  }
432 
433  bulk.modification_begin();
434 
435  // On rank 0, change all locally owned edges to the extra-part then check
436  // for correct part membership
437  if ( 0 == p_rank ) {
438  for ( unsigned i = 0 ; i < nLocalEdge ; ++i ) {
439  const unsigned n = i + nPerProc * p_rank ;
440 
441  PartVector add(1); add[0] = & ring_mesh.m_edge_part_extra ;
442  PartVector rem(1); rem[0] = ring_mesh.m_edge_parts[ n % ring_mesh.m_edge_parts.size() ];
443 
444  Entity * const edge = bulk.get_entity( 1 , ring_mesh.m_edge_ids[n] );
445  bulk.change_entity_parts( *edge , add , rem );
446  STKUNIT_ASSERT( edge->bucket().member( part_univ ) );
447  STKUNIT_ASSERT( edge->bucket().member( part_owns ) );
448  STKUNIT_ASSERT( edge->bucket().member(ring_mesh.m_edge_part_extra ) );
449  }
450  }
451 
452  bulk.modification_end();
453 
454  // Modification end has been called, check that the part changes made
455  // in the previous step are reflected across the other procs.
456  for ( unsigned i = 0 ; i < nLocalNode ; ++i ) {
457  const unsigned n = ( i + nPerProc * p_rank ) % ring_mesh.m_node_ids.size();
458  const unsigned e0 = n ;
459  const unsigned e1 = ( n + ring_mesh.m_edge_ids.size() - 1 ) % ring_mesh.m_edge_ids.size();
460  const unsigned ns = ring_mesh.m_edge_parts.size();
461  const unsigned n0 = e0 % ns ;
462  const unsigned n1 = e1 % ns ;
463  Part * ep_0 = e0 < nLocalEdge ? & ring_mesh.m_edge_part_extra : ring_mesh.m_edge_parts[n0] ;
464  Part * ep_1 = e1 < nLocalEdge ? & ring_mesh.m_edge_part_extra : ring_mesh.m_edge_parts[n1] ;
465 
466  Part * epart_0 = ep_0->mesh_meta_data_ordinal() < ep_1->mesh_meta_data_ordinal() ? ep_0 : ep_1 ;
467  Part * epart_1 = ep_0->mesh_meta_data_ordinal() < ep_1->mesh_meta_data_ordinal() ? ep_1 : ep_0 ;
468 
469  Entity * const node = bulk.get_entity( 0 , ring_mesh.m_node_ids[n] );
470  STKUNIT_ASSERT( node != NULL );
471  if ( node->owner_rank() == p_rank ) {
472  STKUNIT_ASSERT( node->bucket().member( part_owns ) );
473  }
474  else {
475  STKUNIT_ASSERT( ! node->bucket().member( part_owns ) );
476  }
477 
478  STKUNIT_ASSERT( node->bucket().member( part_univ ) );
479  STKUNIT_ASSERT( node->bucket().member( *epart_0 ) );
480  STKUNIT_ASSERT( node->bucket().member( *epart_1 ) );
481  }
482 }
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
Bucket & bucket() const
The bucket which holds this mesh entity&#39;s field data.
Definition: Entity.hpp:141
This is a class for selecting buckets based on a set of meshparts and set logic.
Definition: Selector.hpp:112
Entity * get_entity(EntityRank entity_rank, EntityId entity_id) const
Get entity with a given key.
Definition: BulkData.hpp:211
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
bool modification_end()
Parallel synchronization of modifications and transition to the guaranteed parallel consistent state...
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
unsigned mesh_meta_data_ordinal() const
Internally generated ordinal of this part that is unique within the owning meta data manager...
Definition: Part.hpp:72
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
A fundamental unit within the discretization of a problem domain, including but not limited to nodes...
Definition: Entity.hpp:120
void supersets(PartVector &) const
This bucket is a subset of these parts.
Definition: Bucket.cpp:164
MPI_Comm ParallelMachine
Definition: Parallel.hpp:32
std::vector< Part *> PartVector
Collections of parts are frequently maintained as a vector of Part pointers.
Definition: Types.hpp:31
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