|
Sierra Toolkit
Version of the Day
|
00001 /*------------------------------------------------------------------------*/ 00002 /* Copyright 2010, 2011 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 <sstream> 00010 #include <stdexcept> 00011 #include <iostream> 00012 00013 #include <stk_util/unit_test_support/stk_utest_macros.hpp> 00014 00015 #include <stk_util/parallel/Parallel.hpp> 00016 00017 #include <stk_mesh/base/BulkData.hpp> 00018 #include <stk_mesh/base/GetEntities.hpp> 00019 #include <stk_mesh/base/Field.hpp> 00020 #include <stk_mesh/base/FieldData.hpp> 00021 #include <stk_mesh/base/Comm.hpp> 00022 #include <stk_mesh/base/EntityComm.hpp> 00023 #include <stk_mesh/base/Ghosting.hpp> 00024 00025 #include <stk_mesh/fem/FEMMetaData.hpp> 00026 00027 #include <stk_mesh/fixtures/BoxFixture.hpp> 00028 #include <stk_mesh/fixtures/RingFixture.hpp> 00029 00030 #include <unit_tests/UnitTestModificationEndWrapper.hpp> 00031 00032 #include <Shards_BasicTopologies.hpp> 00033 00034 using stk_classic::mesh::Entity; 00035 using stk_classic::mesh::EntityRank; 00036 using stk_classic::mesh::EntityVector; 00037 using stk_classic::mesh::Part; 00038 using stk_classic::mesh::Relation; 00039 using stk_classic::mesh::Selector; 00040 using stk_classic::mesh::EntityId; 00041 using stk_classic::mesh::fem::FEMMetaData; 00042 using stk_classic::mesh::BulkData; 00043 using stk_classic::mesh::Ghosting; 00044 using stk_classic::mesh::fixtures::BoxFixture; 00045 using stk_classic::mesh::fixtures::RingFixture; 00046 00047 namespace { 00048 00049 const EntityRank NODE_RANK = FEMMetaData::NODE_RANK; 00050 00051 STKUNIT_UNIT_TEST(UnitTestingOfRelation, testRelation) 00052 { 00053 (void)test_info_; 00054 // Unit test the Part functionality in isolation: 00055 00056 stk_classic::ParallelMachine pm = MPI_COMM_WORLD; 00057 MPI_Barrier ( MPI_COMM_WORLD ); 00058 00059 typedef stk_classic::mesh::Field<double> ScalarFieldType; 00060 // static const char method[] = "stk_classic::mesh::UnitTestRelation" ; 00061 00062 std::vector<std::string> entity_names(10); 00063 for ( size_t i = 0 ; i < 10 ; ++i ) { 00064 std::ostringstream name ; 00065 name << "EntityRank" << i ; 00066 entity_names[i] = name.str(); 00067 } 00068 00069 unsigned max_bucket_size = 4; 00070 00071 BoxFixture fixture1(pm , max_bucket_size, entity_names), 00072 fixture2(pm , max_bucket_size, entity_names); 00073 00074 FEMMetaData& meta = fixture1.fem_meta(); 00075 FEMMetaData& meta2 = fixture2.fem_meta(); 00076 const int spatial_dimension = 3; 00077 const EntityRank element_rank = meta.element_rank(); 00078 00079 BulkData& bulk = fixture1.bulk_data(); 00080 BulkData& bulk2 = fixture2.bulk_data(); 00081 00082 ScalarFieldType & temperature = 00083 meta.declare_field < ScalarFieldType > ( "temperature" , 4 ); 00084 ScalarFieldType & volume = 00085 meta.declare_field < ScalarFieldType > ( "volume" , 4 ); 00086 ScalarFieldType & temperature2 = 00087 meta2.declare_field < ScalarFieldType > ( "temperature" , 4 ); 00088 ScalarFieldType & volume2 = 00089 meta2.declare_field < ScalarFieldType > ( "volume" , 4 ); 00090 00091 Part & universal = meta.universal_part (); 00092 Part & universal2 = meta2.universal_part (); 00093 Part & owned = meta.locally_owned_part (); 00094 00095 stk_classic::mesh::put_field ( temperature , NODE_RANK , universal ); 00096 stk_classic::mesh::put_field ( volume , element_rank , universal ); 00097 meta.commit(); 00098 stk_classic::mesh::put_field ( temperature2 , NODE_RANK , universal2 ); 00099 stk_classic::mesh::put_field ( volume2 , element_rank , universal2 ); 00100 00101 meta2.commit(); 00102 00103 bulk.modification_begin(); 00104 bulk2.modification_begin(); 00105 00106 const int root_box[3][2] = { { 0,4 } , { 0,5 } , { 0,6 } }; 00107 int local_box1[3][2] = { { 0,0 } , { 0,0 } , { 0,0 } }; 00108 int local_box2[3][2] = { { 0,0 } , { 0,0 } , { 0,0 } }; 00109 00110 { 00111 bulk.modification_begin(); 00112 fixture1.generate_boxes(root_box, local_box1); 00113 00114 const Ghosting & gg = bulk.create_ghosting( std::string("shared") ); 00115 00116 // Test for coverage of comm_procs in EntityComm.cpp 00117 EntityVector nodes; 00118 stk_classic::mesh::get_entities(bulk, NODE_RANK, nodes); 00119 std::vector<unsigned> procs ; 00120 STKUNIT_ASSERT(!nodes.empty()); 00121 stk_classic::mesh::comm_procs( gg, *nodes.front() , procs ); 00122 00123 STKUNIT_ASSERT(bulk.modification_end()); 00124 00125 bulk.modification_begin(); 00126 bulk.destroy_all_ghosting(); 00127 STKUNIT_ASSERT(bulk.modification_end()); 00128 } 00129 00130 { 00131 bulk2.modification_begin(); 00132 fixture2.generate_boxes(root_box, local_box2); 00133 00134 bulk2.create_ghosting( std::string("shared") ); 00135 00136 STKUNIT_ASSERT(bulk2.modification_end()); 00137 00138 bulk2.modification_begin(); 00139 bulk2.destroy_all_ghosting(); 00140 STKUNIT_ASSERT(bulk2.modification_end()); 00141 } 00142 00143 Entity &cell = *(bulk.buckets (3)[0]->begin()); 00144 Entity &node = bulk.buckets (0)[0]-> operator [] ( 0 ); 00145 Entity &nodeb = bulk.buckets (0)[0]-> operator [] ( 2 ); 00146 00147 std::vector<Part *> parts; 00148 parts.push_back ( &universal ); 00149 parts.push_back ( &owned ); 00150 bulk.modification_begin(); 00151 stk_classic::mesh::EntityId new_id = bulk.parallel_rank() + 1; 00152 Entity &edge = bulk.declare_entity ( 1 , new_id , parts ); 00153 00154 Entity &cell2 = *(bulk2.buckets (3)[0]->begin()); 00155 Entity &node2 = *(bulk2.buckets (0)[0]->begin()); 00156 00157 STKUNIT_ASSERT_THROW ( bulk.declare_relation ( node , cell , 0 ) , std::runtime_error ); 00158 STKUNIT_ASSERT_THROW ( bulk.declare_relation ( cell , node2 , 0 ) , std::runtime_error ); 00159 STKUNIT_ASSERT_THROW ( bulk.declare_relation ( cell2 , node , 0 ) , std::runtime_error ); 00160 00161 bulk.declare_relation ( edge , node , 1 ); 00162 STKUNIT_ASSERT_THROW ( bulk.declare_relation ( edge , nodeb , 1 ) , std::runtime_error ); 00163 bulk.declare_relation ( edge , nodeb , 2 ); 00164 00165 std::stringstream s; 00166 s << *edge.relations().first ; 00167 00168 bulk.modification_end(); 00169 00170 //Testing on in_send_ghost and in_shared in EntityComm.cpp 00171 enum { nPerProc = 10 }; 00172 const unsigned p_rank = stk_classic::parallel_machine_rank( pm ); 00173 const unsigned p_size = stk_classic::parallel_machine_size( pm ); 00174 00175 const unsigned nLocalEdge = nPerProc ; 00176 FEMMetaData meta3( spatial_dimension ); 00177 00178 meta3.commit(); 00179 00180 Selector select_owned( meta3.locally_owned_part() ); 00181 Selector select_used = meta3.locally_owned_part() ; 00182 Selector select_all( meta3.universal_part() ); 00183 00184 stk_classic::mesh::PartVector no_parts ; 00185 00186 std::vector<unsigned> local_count ; 00187 00188 //------------------------------ 00189 { // No ghosting 00190 bool aura_flag = false; 00191 RingFixture mesh2( pm , nPerProc , false /* No edge parts */ ); 00192 mesh2.m_meta_data.commit(); 00193 00194 mesh2.m_bulk_data.modification_begin(); 00195 mesh2.generate_mesh( ); 00196 STKUNIT_ASSERT(stk_classic::unit_test::modification_end_wrapper(mesh2.m_bulk_data, 00197 aura_flag)); 00198 mesh2.m_bulk_data.modification_begin(); 00199 mesh2.fixup_node_ownership( ); 00200 STKUNIT_ASSERT(stk_classic::unit_test::modification_end_wrapper(mesh2.m_bulk_data, 00201 aura_flag)); 00202 00203 // This process' first element in the loop 00204 // if a parallel mesh has a shared node 00205 00206 Entity * edgenew = mesh2.m_bulk_data.get_entity( 1 , mesh2.m_edge_ids[ nLocalEdge * p_rank ] ); 00207 00208 mesh2.m_bulk_data.modification_begin(); 00209 for ( unsigned p = 0 ; p < p_size ; ++p ) if ( p != p_rank ) { 00210 STKUNIT_ASSERT_EQUAL( in_shared( *edgenew , p ), false ); 00211 STKUNIT_ASSERT_EQUAL( in_send_ghost( *edgenew , p ), false ); 00212 } 00213 00214 Entity * edgenew2 = mesh2.m_bulk_data.get_entity( 1 , mesh2.m_edge_ids[ nLocalEdge * p_rank ] ); 00215 STKUNIT_ASSERT_EQUAL( in_send_ghost( *edgenew2 , p_rank+100 ), false ); 00216 00217 Entity * node3 = mesh2.m_bulk_data.get_entity( 0 , mesh2.m_node_ids[ nLocalEdge * p_rank ] ); 00218 STKUNIT_ASSERT_EQUAL( in_shared( *node3 , p_rank+100 ), false ); 00219 } 00220 00221 { //ghosting 00222 00223 if ( 1 < p_size ) { // With ghosting 00224 RingFixture mesh3( pm , nPerProc , false /* No edge parts */ ); 00225 mesh3.m_meta_data.commit(); 00226 00227 mesh3.m_bulk_data.modification_begin(); 00228 mesh3.generate_mesh(); 00229 STKUNIT_ASSERT(mesh3.m_bulk_data.modification_end()); 00230 00231 mesh3.m_bulk_data.modification_begin(); 00232 mesh3.fixup_node_ownership(); 00233 STKUNIT_ASSERT(mesh3.m_bulk_data.modification_end()); 00234 00235 const unsigned nNotOwned = nPerProc * p_rank ; 00236 00237 // The not-owned shared entity: 00238 Entity * node3 = mesh3.m_bulk_data.get_entity( 0 , mesh3.m_node_ids[ nNotOwned ] ); 00239 Entity * node4 = mesh3.m_bulk_data.get_entity( 0 , mesh3.m_node_ids[ nNotOwned ] ); 00240 00241 //EntityId node_edge_ids[2] ; 00242 //node_edge_ids[0] = node3->relations()[0].entity()->identifier(); 00243 //node_edge_ids[1] = node3->relations()[1].entity()->identifier(); 00244 00245 mesh3.m_bulk_data.modification_begin(); 00246 00247 for ( unsigned p = 0 ; p < p_size ; ++p ) if ( p != p_rank ) { 00248 //FIXME for Carol the check below did not pass for -np 3 or 4 00249 //STKUNIT_ASSERT_EQUAL( in_shared( *node3 , p ), true ); 00250 STKUNIT_ASSERT_EQUAL( in_send_ghost( *node3 , p ), false ); 00251 } 00252 00253 //not owned and not shared 00254 Entity * node5 = mesh3.m_bulk_data.get_entity( 0 , mesh3.m_node_ids[ nLocalEdge * p_rank ] ); 00255 00256 //node_edge_ids[0] = node5->relations()[0].entity()->identifier(); 00257 //node_edge_ids[1] = node5->relations()[1].entity()->identifier(); 00258 00259 STKUNIT_ASSERT_EQUAL( in_shared( *node5 , p_rank+100 ), false ); 00260 STKUNIT_ASSERT_EQUAL( in_send_ghost( *node4 , p_rank+100 ), false ); 00261 } 00262 00263 } 00264 00265 } 00266 00267 STKUNIT_UNIT_TEST(UnitTestingOfRelation, testDegenerateRelation) 00268 { 00269 (void)test_info_; 00270 // Test that, if you set up degenerate relations, only of the relations 00271 // is deleted when you destroy one of the degenerate relations. 00272 // BulkData::destroy_relation has been changed to take a relation-id so 00273 // that it can work this way. 00274 // 00275 // To test this, we set up an element that has several relations 00276 // to the same node and then delete them one by one. 00277 00278 stk_classic::ParallelMachine pm = MPI_COMM_WORLD; 00279 MPI_Barrier( MPI_COMM_WORLD ); 00280 00281 // Set up meta and bulk data 00282 const unsigned spatial_dim = 2; 00283 FEMMetaData meta_data(spatial_dim); 00284 meta_data.commit(); 00285 BulkData mesh(FEMMetaData::get_meta_data(meta_data), pm); 00286 unsigned p_rank = mesh.parallel_rank(); 00287 00288 // Begin modification cycle so we can create the entities and relations 00289 mesh.modification_begin(); 00290 00291 // We're just going to add everything to the universal part 00292 stk_classic::mesh::PartVector empty_parts; 00293 00294 // Create element 00295 const EntityRank entity_rank = meta_data.element_rank(); 00296 Entity & elem = mesh.declare_entity(entity_rank, p_rank+1 /*elem_id*/, empty_parts); 00297 00298 // Create node 00299 Entity & node = mesh.declare_entity(NODE_RANK, p_rank+1 /*node_id*/, empty_parts); 00300 00301 // Add degenerate relations 00302 const unsigned nodes_per_elem = 4; 00303 for (unsigned i = 0; i < nodes_per_elem; ++i) { 00304 mesh.declare_relation( elem, node, i ); 00305 } 00306 00307 // Elem should have nodes-per-elem relations 00308 STKUNIT_ASSERT_EQUAL( nodes_per_elem, elem.relations().size() ); 00309 00310 // Destroy relation one-by-one, always checking that appropriate number 00311 // of relations remain. 00312 for (unsigned i = 0; i < nodes_per_elem; ++i) { 00313 mesh.destroy_relation( elem, node, i ); 00314 STKUNIT_ASSERT_EQUAL( nodes_per_elem - (i+1), elem.relations().size() ); 00315 } 00316 00317 mesh.modification_end(); 00318 } 00319 00320 STKUNIT_UNIT_TEST(UnitTestingOfRelation, testRelationAttribute) 00321 { 00322 (void)test_info_; 00323 // Test relation attribute 00324 00325 stk_classic::ParallelMachine pm = MPI_COMM_WORLD; 00326 00327 // Set up meta and bulk data 00328 const unsigned spatial_dim = 2; 00329 FEMMetaData meta_data(spatial_dim); 00330 meta_data.commit(); 00331 BulkData mesh(FEMMetaData::get_meta_data(meta_data), pm); 00332 unsigned p_rank = mesh.parallel_rank(); 00333 00334 // Begin modification cycle so we can create the entities and relations 00335 mesh.modification_begin(); 00336 00337 // We're just going to add everything to the universal part 00338 stk_classic::mesh::PartVector empty_parts; 00339 00340 // Create element 00341 const EntityRank entity_rank = meta_data.element_rank(); 00342 Entity & elem = mesh.declare_entity(entity_rank, p_rank+1 /*elem_id*/, empty_parts); 00343 00344 // Create node 00345 Entity & node = mesh.declare_entity(NODE_RANK, p_rank+1 /*node_id*/, empty_parts); 00346 00347 mesh.declare_relation( elem, node, 0 ); 00348 00349 const Relation & my_relation = *(elem.relations(NODE_RANK).begin()); 00350 my_relation.set_attribute(6u); 00351 00352 STKUNIT_ASSERT_EQUAL( my_relation.attribute(), 6u); 00353 00354 mesh.modification_end(); 00355 } 00356 00357 STKUNIT_UNIT_TEST(UnitTestingOfRelation, testDoubleDeclareOfRelation) 00358 { 00359 (void)test_info_; 00360 // It should be legal to declare the same relation between shared 00361 // entities on two procs. 00362 // 00363 // 1---3---5 00364 // | 1 | 2 | 00365 // 2---4---6 00366 // 00367 // To test this, we use the mesh above, with elem 1 going on rank 0 and 00368 // elem 2 going on rank 1. Nodes 3,4 are shared along with the edge between 00369 // nodes 3 and 4. On both procs we declare relations from the shared edge 00370 // to the shared nodes on both procs. 00371 // 00372 // TODO: If we change how declare_relation works, not requiring all 00373 // sharers to declare the same relations, but instead allowing just 00374 // the owner to declare relations, that should be tested here. 00375 00376 stk_classic::ParallelMachine pm = MPI_COMM_WORLD; 00377 MPI_Barrier( MPI_COMM_WORLD ); 00378 00379 // Set up meta and bulk data 00380 const unsigned spatial_dim = 2; 00381 FEMMetaData meta_data(spatial_dim); 00382 meta_data.commit(); 00383 BulkData mesh(FEMMetaData::get_meta_data(meta_data), pm); 00384 unsigned p_rank = mesh.parallel_rank(); 00385 unsigned p_size = mesh.parallel_size(); 00386 00387 // Bail if we only have one proc 00388 if (p_size == 1) { 00389 return; 00390 } 00391 00392 // Begin modification cycle so we can create the entities and relations 00393 mesh.modification_begin(); 00394 00395 Entity* elem_ptr = NULL; 00396 Entity* edge_ptr = NULL; 00397 EntityVector nodes; 00398 const unsigned nodes_per_elem = 4, nodes_per_side = 2; 00399 00400 if (p_rank < 2) { 00401 // We're just going to add everything to the universal part 00402 stk_classic::mesh::PartVector empty_parts; 00403 00404 // Create element 00405 const EntityRank entity_rank = meta_data.element_rank(); 00406 Entity & elem = mesh.declare_entity(entity_rank, p_rank+1 /*elem_id*/, empty_parts); 00407 elem_ptr = &elem; 00408 00409 // Create nodes 00410 const unsigned starting_node_id = p_rank * nodes_per_side + 1; 00411 for (unsigned id = starting_node_id; id < starting_node_id + nodes_per_elem; ++id) { 00412 nodes.push_back(&mesh.declare_entity(NODE_RANK, id, empty_parts)); 00413 } 00414 00415 // Add relations to nodes 00416 unsigned rel_id = 0; 00417 for (EntityVector::iterator itr = nodes.begin(); itr != nodes.end(); ++itr, ++rel_id) { 00418 mesh.declare_relation( elem, **itr, rel_id ); 00419 } 00420 00421 // Create edge 00422 const EntityRank edge_rank = meta_data.side_rank(); 00423 Entity & edge = mesh.declare_entity(edge_rank, 1 /*id*/, empty_parts); 00424 edge_ptr = &edge; 00425 00426 // Set up relation from elem to edge 00427 mesh.declare_relation( *elem_ptr, *edge_ptr, 0 /*rel-id*/ ); 00428 } 00429 00430 mesh.modification_end(); 00431 00432 mesh.modification_begin(); 00433 00434 if (p_rank < 2) { 00435 // Set up relations from edge to nodes 00436 unsigned rel_id = 0; 00437 const unsigned starting_node_idx = (1 - p_rank) * nodes_per_side; 00438 for (unsigned node_idx = starting_node_idx; 00439 node_idx < starting_node_idx + nodes_per_side; 00440 ++node_idx, ++rel_id) { 00441 mesh.declare_relation( *edge_ptr, *nodes[node_idx], rel_id ); 00442 } 00443 } 00444 00445 mesh.modification_end(); 00446 } 00447 00448 }