Sierra Toolkit  Version of the Day
UnitTestBulkData_Destroy.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 <stk_util/unit_test_support/stk_utest_macros.hpp>
10 
11 #include <stk_util/parallel/Parallel.hpp>
12 
13 #include <stk_mesh/base/BulkData.hpp>
14 #include <stk_mesh/base/GetEntities.hpp>
15 #include <stk_mesh/base/Comm.hpp>
16 
17 #include <stk_mesh/fixtures/RingFixture.hpp>
18 
19 #include <unit_tests/UnitTestModificationEndWrapper.hpp>
20 
27 using stk_classic::mesh::EntityId;
29 
30 //----------------------------------------------------------------------
31 // Testing for mesh entities without relations
32 
33 STKUNIT_UNIT_TEST(UnitTestingOfBulkData, testDestroy_nodes)
34 {
35  stk_classic::ParallelMachine pm = MPI_COMM_WORLD;
36  MPI_Barrier( pm );
37 
38  enum { nPerProc = 10 };
39  const unsigned p_rank = stk_classic::parallel_machine_rank( pm );
40  const unsigned p_size = stk_classic::parallel_machine_size( pm );
41  const unsigned id_total = nPerProc * p_size ;
42  const unsigned id_begin = nPerProc * p_rank ;
43  const unsigned id_end = nPerProc * ( p_rank + 1 );
44 
45  const int spatial_dimension = 3;
46  MetaData meta( stk_classic::mesh::fem::entity_rank_names(spatial_dimension) );
47 
48  const PartVector no_parts ;
49 
50  meta.commit();
51 
52  BulkData bulk( meta , pm , 100 );
53 
54  // Ids for all entities (all entities have type 0):
55 
56  std::vector<EntityId> ids( id_total );
57 
58  for ( unsigned i = 0 ; i < id_total ; ++i ) {
59  ids[i] = i + 1;
60  }
61 
62  // Declare just those entities in my range of ids:
63 
64  STKUNIT_ASSERT( bulk.modification_begin() );
65  for ( unsigned i = id_begin ; i < id_end ; ++i ) {
66  bulk.declare_entity( 0 , ids[i] , no_parts );
67  }
68  STKUNIT_ASSERT( bulk.modification_end() );
69 
70  // Verify that I only have entities in my range:
71 
72  for ( unsigned i = 0 ; i < id_total ; ++i ) {
73  Entity * e = bulk.get_entity( 0 , ids[ i ] );
74  if ( id_begin <= i && i < id_end ) {
75  STKUNIT_ASSERT( NULL != e );
76  STKUNIT_ASSERT( p_rank == e->owner_rank() );
77  }
78  else {
79  STKUNIT_ASSERT( NULL == e );
80  }
81  }
82 
83  // Delete one entity at a time.
84 
85  for ( unsigned i = id_begin ; i < id_end ; ++i ) {
86  Entity * e = bulk.get_entity( 0 , ids[ i ] );
87 
88  STKUNIT_ASSERT( NULL != e );
89 
90  bulk.modification_begin();
91  STKUNIT_ASSERT( bulk.destroy_entity( e ) );
92  bulk.modification_end();
93 
94  // Due to change logging the previously deleted entity
95  // should be gone, but the currently deleted entity
96  // should exist in the 'nil' set.
97 
98  if ( id_begin < i ) {
99  STKUNIT_ASSERT( NULL == bulk.get_entity( 0 , ids[ i - 1 ] ) );
100  }
101 
102  e = bulk.get_entity( 0 , ids[ i ] );
103  STKUNIT_ASSERT( NULL != e );
104  STKUNIT_ASSERT( 0 == e->bucket().capacity() );
105  }
106 }
107 
108 //----------------------------------------------------------------------
109 
110 void assert_is_destroyed( const Entity * const entity )
111 {
112  STKUNIT_ASSERT( entity == NULL || entity->bucket().capacity() == 0 );
113 }
114 
115 STKUNIT_UNIT_TEST(UnitTestingOfBulkData, testDestory_ring)
116 {
117  stk_classic::ParallelMachine pm = MPI_COMM_WORLD;
118  MPI_Barrier( pm );
119 
120  enum { nPerProc = 10 };
121  const unsigned p_rank = stk_classic::parallel_machine_rank( pm );
122  const unsigned p_size = stk_classic::parallel_machine_size( pm );
123  // const unsigned nLocalNode = nPerProc + ( 1 < p_size ? 1 : 0 );
124  const unsigned nLocalEdge = nPerProc ;
125 
126  const int spatial_dimension = 3;
127  MetaData meta( stk_classic::mesh::fem::entity_rank_names(spatial_dimension) );
128 
129  meta.commit();
130 
131  Selector select_owned( meta.locally_owned_part() );
132  Selector select_used = meta.locally_owned_part() | meta.globally_shared_part();
133  Selector select_all( meta.universal_part() );
134 
135  PartVector no_parts ;
136 
137  std::vector<unsigned> local_count ;
138 
139  //------------------------------
140  { // No ghosting
141  const bool aura_flag = false ;
142 
143  RingFixture mesh( pm , nPerProc , false /* No edge parts */ );
144  mesh.m_meta_data.commit();
145  BulkData& bulk = mesh.m_bulk_data;
146 
147  bulk.modification_begin();
148  mesh.generate_mesh( );
149  STKUNIT_ASSERT(stk_classic::unit_test::modification_end_wrapper(bulk,
150  false /*no aura*/));
151 
152  bulk.modification_begin();
153  mesh.fixup_node_ownership();
154  STKUNIT_ASSERT(stk_classic::unit_test::modification_end_wrapper(bulk,
155  false /*no aura*/));
156 
157  // This process' first element in the loop
158  // if a parallel mesh has a shared node
159  Entity * edge = bulk.get_entity( 1 , mesh.m_edge_ids[ nLocalEdge * p_rank ] );
160  Entity * node0 = edge->relations()[0].entity();
161  Entity * node1 = edge->relations()[1].entity();
162 
163  const size_t node0_edges = node0->relations().size();
164  const size_t node1_edges = node1->relations().size();
165 
166  STKUNIT_ASSERT( 1 <= node0_edges && node0_edges <= 2 );
167  STKUNIT_ASSERT( 1 <= node1_edges && node1_edges <= 2 );
168 
169  STKUNIT_ASSERT( node0->relations()[0].entity() == edge ||
170  node0->relations()[1].entity() == edge );
171 
172  STKUNIT_ASSERT( node1->relations()[0].entity() == edge ||
173  node1->relations()[1].entity() == edge );
174 
175  bulk.modification_begin();
176 
177  // Destroy the element:
178  bool result = bulk.destroy_entity( edge );
179  STKUNIT_ASSERT( true == result );
180  STKUNIT_ASSERT( NULL == edge );
181 
182  // Destroy orphanned node:
183  if ( node0->relations().size() == 0 ) {
184  STKUNIT_ASSERT( bulk.destroy_entity( node0 ) );
185  STKUNIT_ASSERT( NULL == node0 );
186  }
187  if ( node1->relations().size() == 0 ) {
188  STKUNIT_ASSERT( bulk.destroy_entity( node1 ) );
189  STKUNIT_ASSERT( NULL == node1 );
190  }
191  STKUNIT_ASSERT( stk_classic::unit_test::modification_end_wrapper(bulk, aura_flag) );
192 
193  if ( NULL != node0 ) {
194  STKUNIT_ASSERT_EQUAL( node0_edges - 1 , node0->relations().size() );
195  }
196  if ( NULL != node1 ) {
197  STKUNIT_ASSERT_EQUAL( node1_edges - 1 , node1->relations().size() );
198  }
199  }
200  //------------------------------
201  if ( 1 < p_size ) { // With ghosting
202  RingFixture mesh( pm , nPerProc , false /* No edge parts */ );
203  mesh.m_meta_data.commit();
204  BulkData& bulk = mesh.m_bulk_data;
205 
206  bulk.modification_begin();
207  mesh.generate_mesh( );
208  STKUNIT_ASSERT( bulk.modification_end() );
209 
210  bulk.modification_begin();
211  mesh.fixup_node_ownership();
212  STKUNIT_ASSERT( bulk.modification_end() );
213 
214  const unsigned nNotOwned = nPerProc * p_rank ;
215 
216  // The not-owned shared entity:
217  Entity * node = bulk.get_entity( 0 , mesh.m_node_ids[ nNotOwned ] );
218 
219  STKUNIT_ASSERT( node != NULL );
220  STKUNIT_ASSERT_NE( p_rank , node->owner_rank() );
221  STKUNIT_ASSERT_EQUAL( size_t(1) , node->sharing().size() );
222  STKUNIT_ASSERT_EQUAL( size_t(2) , node->relations().size() );
223 
224  EntityId node_edge_ids[2] ;
225  node_edge_ids[0] = node->relations()[0].entity()->identifier();
226  node_edge_ids[1] = node->relations()[1].entity()->identifier();
227 
228  bulk.modification_begin();
229 
230  // This process' first node in the loop is shared, destroy it
231  // First have to destroy attached edges.
232  // One will be owned and the other ghosted
233 
234  while ( node->relations().size() ) {
235  Entity * e = node->relations().back().entity();
236  STKUNIT_ASSERT( bulk.destroy_entity( e ) );
237  }
238  STKUNIT_ASSERT( bulk.destroy_entity( node ) );
239 
240  STKUNIT_ASSERT( bulk.modification_end() );
241 
242  assert_is_destroyed( bulk.get_entity(0, mesh.m_node_ids[nNotOwned] ) );
243  assert_is_destroyed( bulk.get_entity(1, node_edge_ids[0] ) );
244  assert_is_destroyed( bulk.get_entity(1, node_edge_ids[1] ) );
245 
246  // assert that no entities are shared or ghosted
247  STKUNIT_ASSERT( bulk.entity_comm().empty() );
248  }
249  //------------------------------
250  if ( 1 < p_size ) { // With ghosting
251  RingFixture mesh( pm , nPerProc , false /* No edge parts */ );
252  mesh.m_meta_data.commit();
253  BulkData& bulk = mesh.m_bulk_data;
254 
255  bulk.modification_begin();
256  mesh.generate_mesh( );
257  STKUNIT_ASSERT( bulk.modification_end() );
258 
259  bulk.modification_begin();
260  mesh.fixup_node_ownership();
261  STKUNIT_ASSERT( bulk.modification_end() );
262 
263  // The owned shared entity:
264  const unsigned nOwned = ( nPerProc * ( p_rank + 1 ) ) % mesh.m_node_ids.size();
265  const unsigned nNotOwned = nPerProc * p_rank ;
266 
267  Entity * node_owned = bulk.get_entity( 0 , mesh.m_node_ids[ nOwned ] );
268  Entity * node_not_owned = bulk.get_entity( 0 , mesh.m_node_ids[ nNotOwned ] );
269 
270  STKUNIT_ASSERT( node_owned != NULL );
271  STKUNIT_ASSERT( node_not_owned != NULL );
272  STKUNIT_ASSERT_NE( p_rank , node_not_owned->owner_rank() );
273  STKUNIT_ASSERT_EQUAL( p_rank , node_owned->owner_rank() );
274  STKUNIT_ASSERT_EQUAL( size_t(1) , node_owned->sharing().size() );
275  STKUNIT_ASSERT_EQUAL( size_t(1) , node_not_owned->sharing().size() );
276  STKUNIT_ASSERT_EQUAL( size_t(2) , node_owned->relations().size() );
277 
278  EntityId node_edge_ids[2] ;
279  node_edge_ids[0] = node_owned->relations()[0].entity()->identifier();
280  node_edge_ids[1] = node_owned->relations()[1].entity()->identifier();
281 
282  bulk.modification_begin();
283 
284  // This process' first node in the loop is shared, destroy it
285  // First have to destroy attached edges.
286  // One will be owned and the other ghosted
287 
288  while ( node_owned->relations().size() ) {
289  Entity * e = node_owned->relations().back().entity();
290  STKUNIT_ASSERT( bulk.destroy_entity( e ) );
291  }
292  STKUNIT_ASSERT( bulk.destroy_entity( node_owned ) );
293 
294  STKUNIT_ASSERT( bulk.modification_end() );
295 
296  // Ownership of the other process' owned, shared, and destroyed node
297  // has been transferred to this process.
298 
299  STKUNIT_ASSERT_EQUAL( p_rank , node_not_owned->owner_rank() );
300  assert_is_destroyed( bulk.get_entity(0, mesh.m_node_ids[ nOwned ] ) );
301  assert_is_destroyed( bulk.get_entity(1, node_edge_ids[0] ) );
302  assert_is_destroyed( bulk.get_entity(1, node_edge_ids[1] ) );
303 
304  // assert that no entities are shared or ghosted
305  STKUNIT_ASSERT( bulk.entity_comm().empty() );
306  }
307 }
308 
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
const std::vector< Entity * > & entity_comm() const
All entities with communication information.
Definition: BulkData.hpp:367
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
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
PairIterRelation relations() const
All Entity relations for which this entity is a member. The relations are ordered from lowest entity-...
Definition: Entity.hpp:161
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
MPI_Comm ParallelMachine
Definition: Parallel.hpp:32
size_t capacity() const
Capacity of this bucket.
Definition: Bucket.hpp:122
std::vector< Part *> PartVector
Collections of parts are frequently maintained as a vector of Part pointers.
Definition: Types.hpp:31
bool destroy_entity(Entity *&entity)
Request the destruction an entity on the local process.
Definition: BulkData.cpp:698
unsigned owner_rank() const
Parallel processor rank of the processor which owns this entity.
Definition: Entity.hpp:175