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 
stk_classic::mesh::Entity::sharing
PairIterEntityComm sharing() const
Parallel processes which share this entity.
Definition: Entity.hpp:178
stk_classic::mesh::fixtures::RingFixture
Definition: RingFixture.hpp:37
stk_classic::parallel_machine_size
unsigned parallel_machine_size(ParallelMachine parallel_machine)
Member function parallel_machine_size ...
Definition: Parallel.cpp:18
stk_classic::mesh::BulkData::destroy_entity
bool destroy_entity(Entity *&entity)
Request the destruction an entity on the local process.
Definition: BulkData.cpp:698
stk_classic::mesh::Part
An application-defined subset of a problem domain.
Definition: Part.hpp:49
stk_classic::ParallelMachine
MPI_Comm ParallelMachine
Definition: Parallel.hpp:32
stk_classic::mesh::BulkData::get_entity
Entity * get_entity(EntityRank entity_rank, EntityId entity_id) const
Get entity with a given key.
Definition: BulkData.hpp:211
stk_classic::mesh::BulkData::modification_end
bool modification_end()
Parallel synchronization of modifications and transition to the guaranteed parallel consistent state.
Definition: BulkDataEndSync.cpp:729
stk_classic::mesh::Bucket::capacity
size_t capacity() const
Capacity of this bucket.
Definition: Bucket.hpp:122
stk_classic::mesh::BulkData::entity_comm
const std::vector< Entity * > & entity_comm() const
All entities with communication information.
Definition: BulkData.hpp:367
stk_classic::mesh::BulkData::modification_begin
bool modification_begin()
Begin a modification phase during which the mesh bulk data could become parallel inconsistent....
Definition: BulkData.cpp:172
stk_classic::mesh::Entity::relations
PairIterRelation relations() const
All Entity relations for which this entity is a member. The relations are ordered from lowest entity-...
Definition: Entity.hpp:161
stk_classic::mesh::MetaData
The manager of an integrated collection of parts and fields.
Definition: MetaData.hpp:56
stk_classic::mesh::PartVector
std::vector< Part * > PartVector
Collections of parts are frequently maintained as a vector of Part pointers.
Definition: Types.hpp:31
stk_classic::mesh::Selector
This is a class for selecting buckets based on a set of meshparts and set logic.
Definition: Selector.hpp:112
stk_classic::mesh::Entity::bucket
Bucket & bucket() const
The bucket which holds this mesh entity's field data.
Definition: Entity.hpp:141
stk_classic::mesh::Entity::owner_rank
unsigned owner_rank() const
Parallel processor rank of the processor which owns this entity.
Definition: Entity.hpp:175
stk_classic::parallel_machine_rank
unsigned parallel_machine_rank(ParallelMachine parallel_machine)
Member function parallel_machine_rank ...
Definition: Parallel.cpp:29
stk_classic::mesh::Entity
A fundamental unit within the discretization of a problem domain, including but not limited to nodes,...
Definition: Entity.hpp:120
stk_classic::mesh::BulkData
Manager for an integrated collection of entities, entity relations, and buckets of field data.
Definition: BulkData.hpp:49