UnitTestRelation.cpp

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

Generated on Tue Jul 13 09:27:32 2010 for Sierra Toolkit by  doxygen 1.4.7