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