|
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 00010 #include <sstream> 00011 #include <stdexcept> 00012 #include <iostream> 00013 00014 /*#include <cppunit/TestCase.h> 00015 #include <cppunit/extensions/HelperMacros.h> 00016 #include <cppunit/extensions/TestFactoryRegistry.h> 00017 #include <cppunit/ui/text/TestRunner.h> 00018 */ 00019 #include <stk_util/unit_test_support/stk_utest_macros.hpp> 00020 00021 #include <stk_util/parallel/Parallel.hpp> 00022 #include <stk_mesh/base/BulkData.hpp> 00023 #include <stk_mesh/base/GetEntities.hpp> 00024 #include <stk_mesh/base/Field.hpp> 00025 #include <stk_mesh/base/FieldData.hpp> 00026 #include <stk_mesh/base/Comm.hpp> 00027 #include <stk_mesh/base/EntityComm.hpp> 00028 #include <stk_mesh/fem/EntityRanks.hpp> 00029 00030 #include <unit_tests/UnitTestRelation.hpp> 00031 #include <unit_tests/UnitTestBulkData.hpp> 00032 #include <unit_tests/UnitTestRingMeshFixture.hpp> 00033 00034 #include <Shards_BasicTopologies.hpp> 00035 #include <stk_mesh/fem/TopologyHelpers.hpp> 00036 #include <stk_mesh/fem/TopologicalMetaData.hpp> 00037 00038 /*class UnitTestingOfRelation : public ::CppUnit::TestCase { 00039 private: 00040 CPPUNIT_TEST_SUITE( UnitTestingOfRelation ); 00041 CPPUNIT_TEST( testUnit ); 00042 CPPUNIT_TEST_SUITE_END(); 00043 00044 public: 00045 UnitTestingOfRelation() : CppUnit::TestCase() {} 00046 00047 void setUp() {} 00048 void tearDown() {} 00049 void testUnit(); 00050 }; 00051 00052 CPPUNIT_TEST_SUITE_REGISTRATION( UnitTestingOfRelation ); 00053 00054 void UnitTestingOfRelation::testUnit() 00055 { 00056 MPI_Barrier( MPI_COMM_WORLD ); 00057 stk::mesh::UnitTestRelation::testRelation ( MPI_COMM_WORLD ); 00058 } 00059 */ 00060 00061 STKUNIT_UNIT_TEST(UnitTestingOfRelation, testUnit) 00062 { 00063 MPI_Barrier ( MPI_COMM_WORLD ); 00064 stk::mesh::UnitTestRelation::testRelation ( MPI_COMM_WORLD ); 00065 } 00066 00067 //---------------------------------------------------------------------- 00068 //---------------------------------------------------------------------- 00069 00070 namespace stk { 00071 namespace mesh { 00072 00073 00074 // Unit test the Part functionality in isolation: 00075 00076 void UnitTestRelation::testRelation( ParallelMachine pm ) 00077 { 00078 typedef Field<double> ScalarFieldType; 00079 // static const char method[] = "stk::mesh::UnitTestRelation" ; 00080 00081 // Create a mesh for testing buckets 00082 std::cout << std::endl ; 00083 00084 std::vector<std::string> entity_names(10); 00085 for ( size_t i = 0 ; i < 10 ; ++i ) { 00086 std::ostringstream name ; 00087 name << "EntityRank" << i ; 00088 entity_names[i] = name.str(); 00089 } 00090 00091 MetaData meta( entity_names ); 00092 MetaData meta2 ( entity_names ); 00093 const int spatial_dimension = 3; 00094 TopologicalMetaData top( meta, spatial_dimension ); 00095 TopologicalMetaData top2( meta2, spatial_dimension ); 00096 00097 BulkData bulk( meta , pm , 4 ); 00098 BulkData bulk2( meta2 , pm , 4 ); 00099 00100 ScalarFieldType & temperature = 00101 meta.declare_field < ScalarFieldType > ( "temperature" , 4 ); 00102 ScalarFieldType & volume = 00103 meta.declare_field < ScalarFieldType > ( "volume" , 4 ); 00104 ScalarFieldType & temperature2 = 00105 meta2.declare_field < ScalarFieldType > ( "temperature" , 4 ); 00106 ScalarFieldType & volume2 = 00107 meta2.declare_field < ScalarFieldType > ( "volume" , 4 ); 00108 00109 Part & universal = meta.universal_part (); 00110 Part & universal2 = meta2.universal_part (); 00111 Part & owned = meta.locally_owned_part (); 00112 00113 put_field ( temperature , top.node_rank , universal ); 00114 put_field ( volume , top.element_rank , universal ); 00115 meta.commit(); 00116 put_field ( temperature2 , top2.node_rank , universal2 ); 00117 put_field ( volume2 , top2.element_rank , universal2 ); 00118 meta2.commit(); 00119 00120 00121 bulk.modification_begin(); 00122 bulk2.modification_begin(); 00123 00124 const int root_box[3][2] = { { 0,4 } , { 0,5 } , { 0,6 } }; 00125 int local_box[3][2] = { { 0,0 } , { 0,0 } , { 0,0 } }; 00126 generate_boxes( bulk , false /* no aura */ , root_box , local_box ); 00127 generate_boxes( bulk2 , false /* no aura */ , root_box , local_box ); 00128 00129 00130 Entity &cell = *(bulk.buckets (3)[0]->begin()); 00131 Entity &node = bulk.buckets (0)[0]-> operator [] ( 0 ); 00132 Entity &nodeb = bulk.buckets (0)[0]-> operator [] ( 2 ); 00133 00134 std::vector<Part *> parts; 00135 parts.push_back ( &universal ); 00136 parts.push_back ( &owned ); 00137 bulk.modification_begin(); 00138 stk::mesh::EntityId new_id = bulk.parallel_rank() + 1; 00139 Entity &edge = bulk.declare_entity ( 1 , new_id , parts ); 00140 00141 Entity &cell2 = *(bulk2.buckets (3)[0]->begin()); 00142 Entity &node2 = *(bulk2.buckets (0)[0]->begin()); 00143 00144 00145 STKUNIT_ASSERT_THROW ( Relation r ( Relation::attribute( 2 , 0 ) , cell ) , std::invalid_argument ); 00146 00147 { 00148 int ok = 0 ; 00149 try { 00150 00151 unsigned id = 10000*(~(0u)); 00152 00153 Relation r (Relation::attribute( 0 , id ), cell ); 00154 00155 } 00156 catch( const std::exception & x ) { 00157 ok = 1 ; 00158 std::cout << "UnitRelation CORRECTLY caught error for : " 00159 << x.what() 00160 << std::endl ; 00161 } 00162 00163 if ( ! ok ) { 00164 throw std::runtime_error("UnitTestRelation FAILED to catch error for Relation::attribute"); 00165 } 00166 } 00167 00168 STKUNIT_ASSERT_THROW ( bulk.declare_relation ( node , cell , 0 ) , std::runtime_error ); 00169 STKUNIT_ASSERT_THROW ( bulk.declare_relation ( cell , node2 , 0 ) , std::runtime_error ); 00170 STKUNIT_ASSERT_THROW ( bulk.declare_relation ( cell2 , node , 0 ) , std::runtime_error ); 00171 00172 00173 bulk.declare_relation ( edge , node , 1 ); 00174 STKUNIT_ASSERT_THROW ( bulk.declare_relation ( edge , nodeb , 1 ) , std::runtime_error ); 00175 bulk.declare_relation ( edge , nodeb , 2 ); 00176 00177 std::stringstream s; 00178 s << *edge.relations().first ; 00179 00180 bulk.modification_end(); 00181 00182 //Testing on in_send_ghost and in_shared in EntityComm.cpp 00183 enum { nPerProc = 10 }; 00184 const unsigned p_rank = parallel_machine_rank( pm ); 00185 const unsigned p_size = parallel_machine_size( pm ); 00186 00187 00188 const unsigned nLocalEdge = nPerProc ; 00189 MetaData meta3( TopologicalMetaData::entity_rank_names(spatial_dimension) ); 00190 00191 meta3.commit(); 00192 00193 Selector select_owned( meta3.locally_owned_part() ); 00194 Selector select_used = meta3.locally_owned_part() ; 00195 Selector select_all( meta3.universal_part() ); 00196 00197 PartVector no_parts ; 00198 00199 std::vector<unsigned> local_count ; 00200 00201 //------------------------------ 00202 { // No ghosting 00203 00204 const bool aura_flag = false ; 00205 UnitTestRingMeshFixture mesh2( pm , nPerProc , false /* No edge parts */ ); 00206 mesh2.m_meta_data.commit(); 00207 mesh2.generate_mesh( aura_flag ); 00208 00209 // This process' first element in the loop 00210 // if a parallel mesh has a shared node 00211 00212 Entity * edgenew = mesh2.m_bulk_data.get_entity( 1 , mesh2.m_edge_ids[ nLocalEdge * p_rank ] ); 00213 00214 mesh2.m_bulk_data.modification_begin(); 00215 for ( unsigned p = 0 ; p < p_size ; ++p ) if ( p != p_rank ) { 00216 STKUNIT_ASSERT_EQUAL( in_shared( *edgenew , p ), false ); 00217 STKUNIT_ASSERT_EQUAL( in_send_ghost( *edgenew , p ), false ); 00218 } 00219 00220 Entity * edgenew2 = mesh2.m_bulk_data.get_entity( 1 , mesh2.m_edge_ids[ nLocalEdge * p_rank ] ); 00221 STKUNIT_ASSERT_EQUAL( in_send_ghost( *edgenew2 , p_rank+100 ), false ); 00222 00223 Entity * node3 = mesh2.m_bulk_data.get_entity( 0 , mesh2.m_node_ids[ nLocalEdge * p_rank ] ); 00224 STKUNIT_ASSERT_EQUAL( in_shared( *node3 , p_rank+100 ), false ); 00225 00226 } 00227 00228 00229 {//ghosting 00230 00231 if ( 1 < p_size ) { // With ghosting 00232 const bool aura_flag = true ; 00233 00234 UnitTestRingMeshFixture mesh3( pm , nPerProc , false /* No edge parts */ ); 00235 mesh3.m_meta_data.commit(); 00236 mesh3.generate_mesh( aura_flag ); 00237 const unsigned nNotOwned = nPerProc * p_rank ; 00238 00239 // The not-owned shared entity: 00240 Entity * node3 = mesh3.m_bulk_data.get_entity( 0 , mesh3.m_node_ids[ nNotOwned ] ); 00241 Entity * node4 = mesh3.m_bulk_data.get_entity( 0 , mesh3.m_node_ids[ nNotOwned ] ); 00242 00243 00244 EntityId node_edge_ids[2] ; 00245 node_edge_ids[0] = node3->relations()[0].entity()->identifier(); 00246 node_edge_ids[1] = node3->relations()[1].entity()->identifier(); 00247 00248 mesh3.m_bulk_data.modification_begin(); 00249 00250 for ( unsigned p = 0 ; p < p_size ; ++p ) if ( p != p_rank ) { 00251 //FIXME for Carol the check below did not pass for -np 3 or 4 00252 //STKUNIT_ASSERT_EQUAL( in_shared( *node3 , p ), true ); 00253 STKUNIT_ASSERT_EQUAL( in_send_ghost( *node3 , p ), false ); 00254 } 00255 00256 //not owned and not shared 00257 Entity * node5 = mesh3.m_bulk_data.get_entity( 0 , mesh3.m_node_ids[ nLocalEdge * p_rank ] ); 00258 00259 node_edge_ids[0] = node5->relations()[0].entity()->identifier(); 00260 node_edge_ids[1] = node5->relations()[1].entity()->identifier(); 00261 00262 STKUNIT_ASSERT_EQUAL( in_shared( *node5 , p_rank+100 ), false ); 00263 STKUNIT_ASSERT_EQUAL( in_send_ghost( *node4 , p_rank+100 ), false ); 00264 } 00265 00266 } 00267 00268 } 00269 00270 //---------------------------------------------------------------------- 00271 00272 namespace { 00273 00274 /* Recursively split a box into ( up - ip ) sub-boxes */ 00275 00276 typedef int BOX[3][2] ; 00277 00278 void box_partition( int ip , int up , int axis , 00279 const BOX box , 00280 BOX p_box[] ) 00281 { 00282 const int np = up - ip ; 00283 if ( 1 == np ) { 00284 p_box[ip][0][0] = box[0][0] ; p_box[ip][0][1] = box[0][1] ; 00285 p_box[ip][1][0] = box[1][0] ; p_box[ip][1][1] = box[1][1] ; 00286 p_box[ip][2][0] = box[2][0] ; p_box[ip][2][1] = box[2][1] ; 00287 } 00288 else { 00289 const int n = box[ axis ][1] - box[ axis ][0] ; 00290 const int np_low = np / 2 ; /* Rounded down */ 00291 const int np_upp = np - np_low ; 00292 00293 const int n_upp = (int) (((double) n) * ( ((double)np_upp) / ((double)np))); 00294 const int n_low = n - n_upp ; 00295 const int next_axis = ( axis + 2 ) % 3 ; 00296 00297 if ( np_low ) { /* P = [ip,ip+np_low) */ 00298 BOX dbox ; 00299 dbox[0][0] = box[0][0] ; dbox[0][1] = box[0][1] ; 00300 dbox[1][0] = box[1][0] ; dbox[1][1] = box[1][1] ; 00301 dbox[2][0] = box[2][0] ; dbox[2][1] = box[2][1] ; 00302 00303 dbox[ axis ][1] = dbox[ axis ][0] + n_low ; 00304 00305 box_partition( ip, ip + np_low, next_axis, 00306 (const int (*)[2]) dbox, p_box ); 00307 } 00308 00309 if ( np_upp ) { /* P = [ip+np_low,ip+np_low+np_upp) */ 00310 BOX dbox ; 00311 dbox[0][0] = box[0][0] ; dbox[0][1] = box[0][1] ; 00312 dbox[1][0] = box[1][0] ; dbox[1][1] = box[1][1] ; 00313 dbox[2][0] = box[2][0] ; dbox[2][1] = box[2][1] ; 00314 00315 ip += np_low ; 00316 dbox[ axis ][0] += n_low ; 00317 dbox[ axis ][1] = dbox[ axis ][0] + n_upp ; 00318 00319 box_partition( ip, ip + np_upp, next_axis, 00320 (const int (*)[2]) dbox, p_box ); 00321 } 00322 } 00323 } 00324 00325 } 00326 00327 void UnitTestRelation::generate_boxes( 00328 BulkData & mesh , 00329 const bool generate_aura , 00330 const int root_box[][2] , 00331 int local_box[][2] ) 00332 { 00333 const unsigned p_rank = mesh.parallel_rank(); 00334 const unsigned p_size = mesh.parallel_size(); 00335 const unsigned ngx = root_box[0][1] - root_box[0][0] ; 00336 const unsigned ngy = root_box[1][1] - root_box[1][0] ; 00337 const unsigned ngz = root_box[2][1] - root_box[2][0] ; 00338 /* 00339 const unsigned e_global = ngx * ngy * ngz ; 00340 const unsigned n_global = ( ngx + 1 ) * ( ngy + 1 ) * ( ngz + 1 ); 00341 */ 00342 00343 if ( 0 == p_rank ) { 00344 std::cout << "Global box = " << ngx << " x " << ngy << " x " << ngz 00345 << std::endl ; 00346 } 00347 00348 BOX * const p_box = new BOX[ p_size ]; 00349 00350 box_partition( 0 , p_size , 2 , root_box , & p_box[0] ); 00351 00352 local_box[0][0] = p_box[ p_rank ][0][0] ; 00353 local_box[0][1] = p_box[ p_rank ][0][1] ; 00354 local_box[1][0] = p_box[ p_rank ][1][0] ; 00355 local_box[1][1] = p_box[ p_rank ][1][1] ; 00356 local_box[2][0] = p_box[ p_rank ][2][0] ; 00357 local_box[2][1] = p_box[ p_rank ][2][1] ; 00358 00359 const unsigned nx = local_box[0][1] - local_box[0][0] ; 00360 const unsigned ny = local_box[1][1] - local_box[1][0] ; 00361 const unsigned nz = local_box[2][1] - local_box[2][0] ; 00362 00363 const unsigned e_local = nx * ny * nz ; 00364 const unsigned n_local = ( nx + 1 ) * ( ny + 1 ) * ( nz + 1 ); 00365 00366 // Create elements: 00367 00368 std::vector<unsigned> local_count ; 00369 00370 const PartVector no_parts ; 00371 00372 for ( int k = local_box[2][0] ; k < local_box[2][1] ; ++k ) { 00373 for ( int j = local_box[1][0] ; j < local_box[1][1] ; ++j ) { 00374 for ( int i = local_box[0][0] ; i < local_box[0][1] ; ++i ) { 00375 const EntityId n0 = 1 + (i+0) + (j+0) * (ngx+1) + (k+0) * (ngx+1) * (ngy+1); 00376 const EntityId n1 = 1 + (i+1) + (j+0) * (ngx+1) + (k+0) * (ngx+1) * (ngy+1); 00377 const EntityId n2 = 1 + (i+1) + (j+1) * (ngx+1) + (k+0) * (ngx+1) * (ngy+1); 00378 const EntityId n3 = 1 + (i+0) + (j+1) * (ngx+1) + (k+0) * (ngx+1) * (ngy+1); 00379 const EntityId n4 = 1 + (i+0) + (j+0) * (ngx+1) + (k+1) * (ngx+1) * (ngy+1); 00380 const EntityId n5 = 1 + (i+1) + (j+0) * (ngx+1) + (k+1) * (ngx+1) * (ngy+1); 00381 const EntityId n6 = 1 + (i+1) + (j+1) * (ngx+1) + (k+1) * (ngx+1) * (ngy+1); 00382 const EntityId n7 = 1 + (i+0) + (j+1) * (ngx+1) + (k+1) * (ngx+1) * (ngy+1); 00383 00384 const EntityId elem_id = 1 + i + j * ngx + k * ngx * ngy; 00385 00386 Entity & node0 = mesh.declare_entity( 0 , n0 , no_parts ); 00387 Entity & node1 = mesh.declare_entity( 0 , n1 , no_parts ); 00388 Entity & node2 = mesh.declare_entity( 0 , n2 , no_parts ); 00389 Entity & node3 = mesh.declare_entity( 0 , n3 , no_parts ); 00390 Entity & node4 = mesh.declare_entity( 0 , n4 , no_parts ); 00391 Entity & node5 = mesh.declare_entity( 0 , n5 , no_parts ); 00392 Entity & node6 = mesh.declare_entity( 0 , n6 , no_parts ); 00393 Entity & node7 = mesh.declare_entity( 0 , n7 , no_parts ); 00394 Entity & elem = mesh.declare_entity( 3 , elem_id , no_parts ); 00395 00396 mesh.declare_relation( elem , node0 , 0 ); 00397 mesh.declare_relation( elem , node1 , 1 ); 00398 mesh.declare_relation( elem , node2 , 2 ); 00399 mesh.declare_relation( elem , node3 , 3 ); 00400 mesh.declare_relation( elem , node4 , 4 ); 00401 mesh.declare_relation( elem , node5 , 5 ); 00402 mesh.declare_relation( elem , node6 , 6 ); 00403 mesh.declare_relation( elem , node7 , 7 ); 00404 00405 std::vector<Entity*> nodes(8); 00406 std::vector<Entity*> elems ; 00407 nodes[0] = & node0 ; 00408 nodes[1] = & node1 ; 00409 nodes[2] = & node2 ; 00410 nodes[3] = & node3 ; 00411 nodes[4] = & node4 ; 00412 nodes[5] = & node5 ; 00413 nodes[6] = & node6 ; 00414 nodes[7] = & node7 ; 00415 00416 get_entities_through_relations( nodes , elems ); 00417 STKUNIT_ASSERT_EQUAL( elems.size() , size_t(1) ); 00418 STKUNIT_ASSERT_EQUAL( elems[0] , & elem ); 00419 00420 get_entities_through_relations( nodes , 3 , elems ); 00421 STKUNIT_ASSERT_EQUAL( elems.size() , size_t(1) ); 00422 STKUNIT_ASSERT_EQUAL( elems[0] , & elem ); 00423 00424 } 00425 } 00426 } 00427 00428 Selector select_owned( mesh.mesh_meta_data().locally_owned_part() ); 00429 00430 Selector select_used = mesh.mesh_meta_data().locally_owned_part() | 00431 mesh.mesh_meta_data().globally_shared_part(); 00432 00433 Selector select_all(mesh.mesh_meta_data().universal_part()); 00434 00435 count_entities( select_used , mesh , local_count ); 00436 STKUNIT_ASSERT_EQUAL( e_local , local_count[3] ); 00437 STKUNIT_ASSERT_EQUAL( 0u , local_count[2] ); 00438 STKUNIT_ASSERT_EQUAL( 0u , local_count[1] ); 00439 STKUNIT_ASSERT_EQUAL( n_local , local_count[0] ); 00440 00441 //Set up ghosting 00442 const Ghosting & gg = mesh.create_ghosting( std::string("shared") ); 00443 00444 // Set up sharing: 00445 mesh.modification_end(); 00446 00447 00448 // Verify declarations and sharing 00449 00450 count_entities( select_used , mesh , local_count ); 00451 STKUNIT_ASSERT( local_count[3] == e_local ); 00452 STKUNIT_ASSERT( local_count[2] == 0 ); 00453 STKUNIT_ASSERT( local_count[1] == 0 ); 00454 STKUNIT_ASSERT( local_count[0] == n_local ); 00455 00456 for ( int k = local_box[2][0] ; k <= local_box[2][1] ; ++k ) { 00457 for ( int j = local_box[1][0] ; j <= local_box[1][1] ; ++j ) { 00458 for ( int i = local_box[0][0] ; i <= local_box[0][1] ; ++i ) { 00459 EntityRank node_type = 0; 00460 EntityId node_id = 1 + i + j * (ngx+1) + k * (ngx+1) * (ngy+1); 00461 Entity * const node = mesh.get_entity( node_type , node_id ); 00462 STKUNIT_ASSERT( node != NULL ); 00463 // Shared if on a processor boundary. 00464 const bool shared = 00465 ( k == local_box[2][0] && k != root_box[2][0] ) || 00466 ( k == local_box[2][1] && k != root_box[2][1] ) || 00467 ( j == local_box[1][0] && j != root_box[1][0] ) || 00468 ( j == local_box[1][1] && j != root_box[1][1] ) || 00469 ( i == local_box[0][0] && i != root_box[0][0] ) || 00470 ( i == local_box[0][1] && i != root_box[0][1] ); 00471 STKUNIT_ASSERT_EQUAL( shared , ! node->sharing().empty() ); 00472 } 00473 } 00474 } 00475 00476 00477 for ( unsigned p = 0 ; p < p_size ; ++p ) if ( p != p_rank ) { 00478 for ( int k = p_box[p][2][0] ; k <= p_box[p][2][1] ; ++k ) 00479 if ( local_box[2][0] <= k && k <= local_box[2][1] ) { 00480 00481 for ( int j = p_box[p][1][0] ; j <= p_box[p][1][1] ; ++j ) 00482 if ( local_box[1][0] <= j && j <= local_box[1][1] ) { 00483 00484 for ( int i = p_box[p][0][0] ; i <= p_box[p][0][1] ; ++i ) 00485 if ( local_box[0][0] <= i && i <= local_box[0][1] ) { 00486 00487 EntityRank node_type = 0; 00488 EntityId node_id = 1 + i + j * (ngx+1) + k * (ngx+1) * (ngy+1); 00489 Entity * const node = mesh.get_entity( node_type , node_id ); 00490 STKUNIT_ASSERT( node != NULL ); 00491 // Must be shared with 'p' 00492 STKUNIT_ASSERT( in_shared( *node , p ) ); 00493 STKUNIT_ASSERT_EQUAL( in_send_ghost( *node , p ), false ); 00494 00495 //Test for coverage of comm_procs in EntityComm.cpp 00496 std::vector<unsigned> procs ; 00497 comm_procs( gg, *node , procs ); 00498 00499 } 00500 } 00501 } 00502 } 00503 00504 mesh.modification_begin(); 00505 mesh.destroy_all_ghosting(); 00506 mesh.modification_end(); 00507 00508 delete[] p_box ; 00509 } 00510 00511 //---------------------------------------------------------------------- 00512 00513 } // namespace mesh 00514 } // namespace stk 00515