Sierra Toolkit Version of the Day
UnitTestRelation.cpp
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::mesh::Entity;
00035 using stk::mesh::EntityRank;
00036 using stk::mesh::EntityVector;
00037 using stk::mesh::Part;
00038 using stk::mesh::Relation;
00039 using stk::mesh::Selector;
00040 using stk::mesh::EntityId;
00041 using stk::mesh::fem::FEMMetaData;
00042 using stk::mesh::BulkData;
00043 using stk::mesh::Ghosting;
00044 using stk::mesh::fixtures::BoxFixture;
00045 using stk::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::ParallelMachine pm = MPI_COMM_WORLD;
00057   MPI_Barrier ( MPI_COMM_WORLD );
00058 
00059   typedef stk::mesh::Field<double>  ScalarFieldType;
00060  // static const char method[] = "stk::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::mesh::put_field ( temperature , NODE_RANK , universal );
00096   stk::mesh::put_field ( volume , element_rank  , universal );
00097   meta.commit();
00098   stk::mesh::put_field ( temperature2 , NODE_RANK , universal2 );
00099   stk::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::mesh::get_entities(bulk, NODE_RANK, nodes);
00119     std::vector<unsigned> procs ;
00120     STKUNIT_ASSERT(!nodes.empty());
00121     stk::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::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::parallel_machine_rank( pm );
00173   const unsigned p_size = stk::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::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::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::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::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::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::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::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::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::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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines