|
Sierra Toolkit
Version of the Day
|
00001 /*------------------------------------------------------------------------*/ 00002 /* Copyright 2010 Sandia Corporation. */ 00003 /* Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive */ 00004 /* license for use of this work by or on behalf of the U.S. Government. */ 00005 /* Export of this program may require a license from the */ 00006 /* United States Government. */ 00007 /*------------------------------------------------------------------------*/ 00008 00009 #include <stk_util/unit_test_support/stk_utest_macros.hpp> 00010 00011 #include <stk_util/parallel/Parallel.hpp> 00012 00013 #include <stk_mesh/base/BulkData.hpp> 00014 #include <stk_mesh/base/GetEntities.hpp> 00015 #include <stk_mesh/base/Comm.hpp> 00016 00017 #include <stk_mesh/fixtures/RingFixture.hpp> 00018 00019 #include <unit_tests/UnitTestModificationEndWrapper.hpp> 00020 00021 using stk_classic::mesh::Part; 00022 using stk_classic::mesh::MetaData; 00023 using stk_classic::mesh::BulkData; 00024 using stk_classic::mesh::Entity; 00025 using stk_classic::mesh::Selector; 00026 using stk_classic::mesh::PartVector; 00027 using stk_classic::mesh::EntityId; 00028 using stk_classic::mesh::fixtures::RingFixture; 00029 00030 //---------------------------------------------------------------------- 00031 // Testing for mesh entities without relations 00032 00033 STKUNIT_UNIT_TEST(UnitTestingOfBulkData, testDestroy_nodes) 00034 { 00035 stk_classic::ParallelMachine pm = MPI_COMM_WORLD; 00036 MPI_Barrier( pm ); 00037 00038 enum { nPerProc = 10 }; 00039 const unsigned p_rank = stk_classic::parallel_machine_rank( pm ); 00040 const unsigned p_size = stk_classic::parallel_machine_size( pm ); 00041 const unsigned id_total = nPerProc * p_size ; 00042 const unsigned id_begin = nPerProc * p_rank ; 00043 const unsigned id_end = nPerProc * ( p_rank + 1 ); 00044 00045 const int spatial_dimension = 3; 00046 MetaData meta( stk_classic::mesh::fem::entity_rank_names(spatial_dimension) ); 00047 00048 const PartVector no_parts ; 00049 00050 meta.commit(); 00051 00052 BulkData bulk( meta , pm , 100 ); 00053 00054 // Ids for all entities (all entities have type 0): 00055 00056 std::vector<EntityId> ids( id_total ); 00057 00058 for ( unsigned i = 0 ; i < id_total ; ++i ) { 00059 ids[i] = i + 1; 00060 } 00061 00062 // Declare just those entities in my range of ids: 00063 00064 STKUNIT_ASSERT( bulk.modification_begin() ); 00065 for ( unsigned i = id_begin ; i < id_end ; ++i ) { 00066 bulk.declare_entity( 0 , ids[i] , no_parts ); 00067 } 00068 STKUNIT_ASSERT( bulk.modification_end() ); 00069 00070 // Verify that I only have entities in my range: 00071 00072 for ( unsigned i = 0 ; i < id_total ; ++i ) { 00073 Entity * e = bulk.get_entity( 0 , ids[ i ] ); 00074 if ( id_begin <= i && i < id_end ) { 00075 STKUNIT_ASSERT( NULL != e ); 00076 STKUNIT_ASSERT( p_rank == e->owner_rank() ); 00077 } 00078 else { 00079 STKUNIT_ASSERT( NULL == e ); 00080 } 00081 } 00082 00083 // Delete one entity at a time. 00084 00085 for ( unsigned i = id_begin ; i < id_end ; ++i ) { 00086 Entity * e = bulk.get_entity( 0 , ids[ i ] ); 00087 00088 STKUNIT_ASSERT( NULL != e ); 00089 00090 bulk.modification_begin(); 00091 STKUNIT_ASSERT( bulk.destroy_entity( e ) ); 00092 bulk.modification_end(); 00093 00094 // Due to change logging the previously deleted entity 00095 // should be gone, but the currently deleted entity 00096 // should exist in the 'nil' set. 00097 00098 if ( id_begin < i ) { 00099 STKUNIT_ASSERT( NULL == bulk.get_entity( 0 , ids[ i - 1 ] ) ); 00100 } 00101 00102 e = bulk.get_entity( 0 , ids[ i ] ); 00103 STKUNIT_ASSERT( NULL != e ); 00104 STKUNIT_ASSERT( 0 == e->bucket().capacity() ); 00105 } 00106 } 00107 00108 //---------------------------------------------------------------------- 00109 00110 void assert_is_destroyed( const Entity * const entity ) 00111 { 00112 STKUNIT_ASSERT( entity == NULL || entity->bucket().capacity() == 0 ); 00113 } 00114 00115 STKUNIT_UNIT_TEST(UnitTestingOfBulkData, testDestory_ring) 00116 { 00117 stk_classic::ParallelMachine pm = MPI_COMM_WORLD; 00118 MPI_Barrier( pm ); 00119 00120 enum { nPerProc = 10 }; 00121 const unsigned p_rank = stk_classic::parallel_machine_rank( pm ); 00122 const unsigned p_size = stk_classic::parallel_machine_size( pm ); 00123 // const unsigned nLocalNode = nPerProc + ( 1 < p_size ? 1 : 0 ); 00124 const unsigned nLocalEdge = nPerProc ; 00125 00126 const int spatial_dimension = 3; 00127 MetaData meta( stk_classic::mesh::fem::entity_rank_names(spatial_dimension) ); 00128 00129 meta.commit(); 00130 00131 Selector select_owned( meta.locally_owned_part() ); 00132 Selector select_used = meta.locally_owned_part() | meta.globally_shared_part(); 00133 Selector select_all( meta.universal_part() ); 00134 00135 PartVector no_parts ; 00136 00137 std::vector<unsigned> local_count ; 00138 00139 //------------------------------ 00140 { // No ghosting 00141 const bool aura_flag = false ; 00142 00143 RingFixture mesh( pm , nPerProc , false /* No edge parts */ ); 00144 mesh.m_meta_data.commit(); 00145 BulkData& bulk = mesh.m_bulk_data; 00146 00147 bulk.modification_begin(); 00148 mesh.generate_mesh( ); 00149 STKUNIT_ASSERT(stk_classic::unit_test::modification_end_wrapper(bulk, 00150 false /*no aura*/)); 00151 00152 bulk.modification_begin(); 00153 mesh.fixup_node_ownership(); 00154 STKUNIT_ASSERT(stk_classic::unit_test::modification_end_wrapper(bulk, 00155 false /*no aura*/)); 00156 00157 // This process' first element in the loop 00158 // if a parallel mesh has a shared node 00159 Entity * edge = bulk.get_entity( 1 , mesh.m_edge_ids[ nLocalEdge * p_rank ] ); 00160 Entity * node0 = edge->relations()[0].entity(); 00161 Entity * node1 = edge->relations()[1].entity(); 00162 00163 const size_t node0_edges = node0->relations().size(); 00164 const size_t node1_edges = node1->relations().size(); 00165 00166 STKUNIT_ASSERT( 1 <= node0_edges && node0_edges <= 2 ); 00167 STKUNIT_ASSERT( 1 <= node1_edges && node1_edges <= 2 ); 00168 00169 STKUNIT_ASSERT( node0->relations()[0].entity() == edge || 00170 node0->relations()[1].entity() == edge ); 00171 00172 STKUNIT_ASSERT( node1->relations()[0].entity() == edge || 00173 node1->relations()[1].entity() == edge ); 00174 00175 bulk.modification_begin(); 00176 00177 // Destroy the element: 00178 bool result = bulk.destroy_entity( edge ); 00179 STKUNIT_ASSERT( true == result ); 00180 STKUNIT_ASSERT( NULL == edge ); 00181 00182 // Destroy orphanned node: 00183 if ( node0->relations().size() == 0 ) { 00184 STKUNIT_ASSERT( bulk.destroy_entity( node0 ) ); 00185 STKUNIT_ASSERT( NULL == node0 ); 00186 } 00187 if ( node1->relations().size() == 0 ) { 00188 STKUNIT_ASSERT( bulk.destroy_entity( node1 ) ); 00189 STKUNIT_ASSERT( NULL == node1 ); 00190 } 00191 STKUNIT_ASSERT( stk_classic::unit_test::modification_end_wrapper(bulk, aura_flag) ); 00192 00193 if ( NULL != node0 ) { 00194 STKUNIT_ASSERT_EQUAL( node0_edges - 1 , node0->relations().size() ); 00195 } 00196 if ( NULL != node1 ) { 00197 STKUNIT_ASSERT_EQUAL( node1_edges - 1 , node1->relations().size() ); 00198 } 00199 } 00200 //------------------------------ 00201 if ( 1 < p_size ) { // With ghosting 00202 RingFixture mesh( pm , nPerProc , false /* No edge parts */ ); 00203 mesh.m_meta_data.commit(); 00204 BulkData& bulk = mesh.m_bulk_data; 00205 00206 bulk.modification_begin(); 00207 mesh.generate_mesh( ); 00208 STKUNIT_ASSERT( bulk.modification_end() ); 00209 00210 bulk.modification_begin(); 00211 mesh.fixup_node_ownership(); 00212 STKUNIT_ASSERT( bulk.modification_end() ); 00213 00214 const unsigned nNotOwned = nPerProc * p_rank ; 00215 00216 // The not-owned shared entity: 00217 Entity * node = bulk.get_entity( 0 , mesh.m_node_ids[ nNotOwned ] ); 00218 00219 STKUNIT_ASSERT( node != NULL ); 00220 STKUNIT_ASSERT_NE( p_rank , node->owner_rank() ); 00221 STKUNIT_ASSERT_EQUAL( size_t(1) , node->sharing().size() ); 00222 STKUNIT_ASSERT_EQUAL( size_t(2) , node->relations().size() ); 00223 00224 EntityId node_edge_ids[2] ; 00225 node_edge_ids[0] = node->relations()[0].entity()->identifier(); 00226 node_edge_ids[1] = node->relations()[1].entity()->identifier(); 00227 00228 bulk.modification_begin(); 00229 00230 // This process' first node in the loop is shared, destroy it 00231 // First have to destroy attached edges. 00232 // One will be owned and the other ghosted 00233 00234 while ( node->relations().size() ) { 00235 Entity * e = node->relations().back().entity(); 00236 STKUNIT_ASSERT( bulk.destroy_entity( e ) ); 00237 } 00238 STKUNIT_ASSERT( bulk.destroy_entity( node ) ); 00239 00240 STKUNIT_ASSERT( bulk.modification_end() ); 00241 00242 assert_is_destroyed( bulk.get_entity(0, mesh.m_node_ids[nNotOwned] ) ); 00243 assert_is_destroyed( bulk.get_entity(1, node_edge_ids[0] ) ); 00244 assert_is_destroyed( bulk.get_entity(1, node_edge_ids[1] ) ); 00245 00246 // assert that no entities are shared or ghosted 00247 STKUNIT_ASSERT( bulk.entity_comm().empty() ); 00248 } 00249 //------------------------------ 00250 if ( 1 < p_size ) { // With ghosting 00251 RingFixture mesh( pm , nPerProc , false /* No edge parts */ ); 00252 mesh.m_meta_data.commit(); 00253 BulkData& bulk = mesh.m_bulk_data; 00254 00255 bulk.modification_begin(); 00256 mesh.generate_mesh( ); 00257 STKUNIT_ASSERT( bulk.modification_end() ); 00258 00259 bulk.modification_begin(); 00260 mesh.fixup_node_ownership(); 00261 STKUNIT_ASSERT( bulk.modification_end() ); 00262 00263 // The owned shared entity: 00264 const unsigned nOwned = ( nPerProc * ( p_rank + 1 ) ) % mesh.m_node_ids.size(); 00265 const unsigned nNotOwned = nPerProc * p_rank ; 00266 00267 Entity * node_owned = bulk.get_entity( 0 , mesh.m_node_ids[ nOwned ] ); 00268 Entity * node_not_owned = bulk.get_entity( 0 , mesh.m_node_ids[ nNotOwned ] ); 00269 00270 STKUNIT_ASSERT( node_owned != NULL ); 00271 STKUNIT_ASSERT( node_not_owned != NULL ); 00272 STKUNIT_ASSERT_NE( p_rank , node_not_owned->owner_rank() ); 00273 STKUNIT_ASSERT_EQUAL( p_rank , node_owned->owner_rank() ); 00274 STKUNIT_ASSERT_EQUAL( size_t(1) , node_owned->sharing().size() ); 00275 STKUNIT_ASSERT_EQUAL( size_t(1) , node_not_owned->sharing().size() ); 00276 STKUNIT_ASSERT_EQUAL( size_t(2) , node_owned->relations().size() ); 00277 00278 EntityId node_edge_ids[2] ; 00279 node_edge_ids[0] = node_owned->relations()[0].entity()->identifier(); 00280 node_edge_ids[1] = node_owned->relations()[1].entity()->identifier(); 00281 00282 bulk.modification_begin(); 00283 00284 // This process' first node in the loop is shared, destroy it 00285 // First have to destroy attached edges. 00286 // One will be owned and the other ghosted 00287 00288 while ( node_owned->relations().size() ) { 00289 Entity * e = node_owned->relations().back().entity(); 00290 STKUNIT_ASSERT( bulk.destroy_entity( e ) ); 00291 } 00292 STKUNIT_ASSERT( bulk.destroy_entity( node_owned ) ); 00293 00294 STKUNIT_ASSERT( bulk.modification_end() ); 00295 00296 // Ownership of the other process' owned, shared, and destroyed node 00297 // has been transferred to this process. 00298 00299 STKUNIT_ASSERT_EQUAL( p_rank , node_not_owned->owner_rank() ); 00300 assert_is_destroyed( bulk.get_entity(0, mesh.m_node_ids[ nOwned ] ) ); 00301 assert_is_destroyed( bulk.get_entity(1, node_edge_ids[0] ) ); 00302 assert_is_destroyed( bulk.get_entity(1, node_edge_ids[1] ) ); 00303 00304 // assert that no entities are shared or ghosted 00305 STKUNIT_ASSERT( bulk.entity_comm().empty() ); 00306 } 00307 } 00308