Sierra Toolkit Version of the Day
UnitTestSimple.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 
00010 #include <stk_util/parallel/Parallel.hpp>
00011 #include <stk_util/parallel/ParallelReduce.hpp>
00012 #include <stk_util/unit_test_support/stk_utest_macros.hpp>
00013 
00014 #include <stk_mesh/base/Types.hpp>
00015 #include <stk_mesh/base/MetaData.hpp>
00016 #include <stk_mesh/base/BulkData.hpp>
00017 #include <stk_mesh/base/FieldData.hpp>
00018 
00019 #include <stk_mesh/fem/CoordinateSystems.hpp>
00020 #include <stk_mesh/fem/FEMMetaData.hpp>
00021 #include <stk_mesh/fem/FEMHelpers.hpp>
00022 
00023 // relevant headers
00024 #include <stk_rebalance/Rebalance.hpp>
00025 #include <stk_rebalance/Partition.hpp>
00026 #include <stk_rebalance_utils/RebalanceUtils.hpp>
00027 // end relevant headers
00028 
00029 static const size_t NODE_RANK = stk::mesh::fem::FEMMetaData::NODE_RANK;
00030 
00031 typedef stk::mesh::Field<double> ScalarField ;
00032 typedef stk::mesh::Field<double, stk::mesh::Cartesian> VectorField ;
00033 
00034 static const int spatial_dimension = 2;
00035 
00036 enum { nx = 2, ny = 2 };
00037 
00038 class MockPartition : public stk::rebalance::Partition
00039 {
00040   public:
00041 
00042     enum BALANCE_TEST_STEP
00043       { FIRST,
00044         SECOND,
00045         THIRD   };
00046 
00047   MockPartition( stk::mesh::fem::FEMMetaData & fmd, stk::mesh::BulkData & bd ) :
00048       stk::rebalance::Partition(bd.parallel()),
00049       m_fem_meta(fmd),
00050       m_bulk_data(bd),
00051       m_step(FIRST)
00052     {  }
00053 
00054     ~MockPartition() { }
00055 
00056     void set_balance_step(BALANCE_TEST_STEP step)
00057     { m_step = step; }
00058 
00059     void set_mesh_info ( const std::vector<stk::mesh::Entity *> &mesh_entities,
00060                          const VectorField   * nodal_coord_ref,
00061                          const ScalarField   * elem_weight_ref)
00062     { total_number_entities_ = mesh_entities.size(); }
00063 
00064   unsigned num_elems() const
00065   { return total_number_entities_; }
00066 
00067     void determine_new_partition(bool &RebalancingNeeded)
00068     { RebalancingNeeded = (m_bulk_data.parallel_size() > 1); }
00069 
00070     int get_new_partition(std::vector<stk::mesh::EntityProc> &new_partition);
00071 
00072     bool partition_dependents_needed() const
00073     { return false; /* I handle both element and dependent node partitioning */ }
00074 
00075   private:
00076 
00077     unsigned total_number_entities_;
00078     stk::mesh::fem::FEMMetaData & m_fem_meta;
00079     stk::mesh::BulkData & m_bulk_data;
00080     BALANCE_TEST_STEP m_step;
00081 };
00082 
00083 int
00084 MockPartition::get_new_partition(std::vector<stk::mesh::EntityProc> &new_partition)
00085 {
00086   const unsigned p_size = m_bulk_data.parallel_size();
00087   const unsigned p_rank = m_bulk_data.parallel_rank();
00088   const stk::mesh::EntityRank element_rank = m_fem_meta.element_rank();
00089 
00090   new_partition.clear();
00091 
00092   if ( 1 < p_size ) {
00093 
00094     if( FIRST == m_step )
00095     {
00096       if ( p_rank == 0 ) {
00097         if ( p_size == 3 ) {
00098           const unsigned nnx = nx + 1 ;
00099           const unsigned nny = ny + 1 ;
00100           for ( unsigned iy = nny / 2 ; iy < nny ; ++iy ) {
00101             for ( unsigned ix = 0 ; ix < nnx ; ++ix ) {
00102               stk::mesh::EntityId id = 1 + ix + iy * nnx ;
00103               unsigned proc = ix < nx/2 ? 1 : 2;
00104               stk::mesh::EntityProc tmp( m_bulk_data.get_entity( NODE_RANK , id ) , proc );
00105               new_partition.push_back( tmp );
00106             }
00107           }
00108           for ( unsigned iy = ny / 2 ; iy < ny ; ++iy ) {
00109             for ( unsigned ix = 0 ; ix < nx ; ++ix ) {
00110               stk::mesh::EntityId id = 1 + ix + iy * nx ;
00111               unsigned proc = ix < nx/2 ? 1 : 2;
00112               stk::mesh::EntityProc tmp( m_bulk_data.get_entity( element_rank , id ) , proc );
00113               new_partition.push_back( tmp );
00114             }
00115           }
00116         }
00117         else
00118         {
00119           const unsigned nnx = nx + 1 ;
00120           const unsigned nny = ny + 1 ;
00121           for ( unsigned iy = nny / 2 ; iy < nny ; ++iy ) {
00122             for ( unsigned ix = 0 ; ix < nnx ; ++ix ) {
00123               stk::mesh::EntityId id = 1 + ix + iy * nnx ;
00124               stk::mesh::EntityProc tmp( m_bulk_data.get_entity( NODE_RANK , id ) , 1 );
00125               new_partition.push_back( tmp );
00126             }
00127           }
00128           for ( unsigned iy = ny / 2 ; iy < ny ; ++iy ) {
00129             for ( unsigned ix = 0 ; ix < nx ; ++ix ) {
00130               stk::mesh::EntityId id = 1 + ix + iy * nx ;
00131               stk::mesh::EntityProc tmp( m_bulk_data.get_entity( element_rank , id ) , 1 );
00132               new_partition.push_back( tmp );
00133             }
00134           }
00135         }
00136       }
00137     }
00138 
00139     else if( SECOND == m_step )
00140     {
00141       if ( p_rank == 0 ) {
00142         const unsigned nnx = nx + 1 ;
00143         const unsigned nny = ny + 1 ;
00144         for ( unsigned iy = 0 ; iy < nny / 2 ; ++iy ) {
00145           for ( unsigned ix = 0 ; ix < nnx ; ++ix ) {
00146             stk::mesh::EntityId id = 1 + ix + iy * nnx ;
00147             stk::mesh::EntityProc tmp( m_bulk_data.get_entity( NODE_RANK , id ) , 1 );
00148             new_partition.push_back( tmp );
00149           }
00150         }
00151         for ( unsigned iy = 0 ; iy < ny / 2 ; ++iy ) {
00152           for ( unsigned ix = 0 ; ix < nx ; ++ix ) {
00153             stk::mesh::EntityId id = 1 + ix + iy * nx ;
00154             stk::mesh::EntityProc tmp( m_bulk_data.get_entity( element_rank , id ) , 1 );
00155             new_partition.push_back( tmp );
00156           }
00157         }
00158       }
00159     }
00160 
00161     else if( THIRD == m_step )
00162     {
00163       if ( p_size == 3 ) {
00164         new_partition.clear();
00165 
00166         if ( p_rank == 2 ) {
00167           const unsigned nnx = nx + 1 ;
00168           const unsigned nny = ny + 1 ;
00169           for ( unsigned iy = nny / 2 ; iy < nny ; ++iy ) {
00170             for ( unsigned ix = nx / 2 ; ix < nnx ; ++ix ) {
00171               stk::mesh::EntityId id = 1 + ix + iy * nnx ;
00172               unsigned proc = 1;
00173               stk::mesh::EntityProc tmp( m_bulk_data.get_entity( NODE_RANK , id ) , proc );
00174               new_partition.push_back( tmp );
00175             }
00176           }
00177           for ( unsigned iy = ny / 2 ; iy < ny ; ++iy ) {
00178             for ( unsigned ix = nx / 2 ; ix < nx ; ++ix ) {
00179               stk::mesh::EntityId id = 1 + ix + iy * nx ;
00180               unsigned proc = 1;
00181               stk::mesh::EntityProc tmp( m_bulk_data.get_entity( element_rank , id ) , proc );
00182               new_partition.push_back( tmp );
00183             }
00184           }
00185         }
00186       }
00187     }
00188   }
00189 
00190   return 0;
00191 }
00192 
00193 
00194 STKUNIT_UNIT_TEST(UnitTestRebalanceSimple, testUnit)
00195 {
00196 #ifdef STK_HAS_MPI
00197   stk::ParallelMachine comm(MPI_COMM_WORLD);
00198 #else
00199   stk::ParallelMachine comm(0);
00200 #endif
00201 
00202   unsigned spatial_dimension = 2;
00203   stk::mesh::fem::FEMMetaData fem_meta;
00204   fem_meta.FEM_initialize(spatial_dimension, stk::mesh::fem::entity_rank_names(spatial_dimension) );
00205   stk::mesh::MetaData & meta_data = stk::mesh::fem::FEMMetaData::get_meta_data(fem_meta);
00206   stk::mesh::BulkData bulk_data( meta_data , comm , 100 );
00207   const stk::mesh::EntityRank element_rank = fem_meta.element_rank();
00208   stk::mesh::fem::CellTopology quad_top(shards::getCellTopologyData<shards::Quadrilateral<4> >());
00209   stk::mesh::Part & quad_part( fem_meta.declare_part("quad", quad_top ) );
00210   VectorField & coord_field( fem_meta.declare_field< VectorField >( "coordinates" ) );
00211   ScalarField & weight_field( fem_meta.declare_field< ScalarField >( "element_weights" ) );
00212 
00213   stk::mesh::put_field( coord_field , NODE_RANK , fem_meta.universal_part() );
00214   stk::mesh::put_field(weight_field , element_rank , fem_meta.universal_part() );
00215 
00216   fem_meta.commit();
00217 
00218   const unsigned p_size = bulk_data.parallel_size();
00219   const unsigned p_rank = bulk_data.parallel_rank();
00220 
00221   // create initial mesh
00222   bulk_data.modification_begin();
00223 
00224   if ( p_rank == 0 ) {
00225     const unsigned nnx = nx + 1 ;
00226     for ( unsigned iy = 0 ; iy < ny ; ++iy ) {
00227       for ( unsigned ix = 0 ; ix < nx ; ++ix ) {
00228         stk::mesh::EntityId elem = 1 + ix + iy * nx ;
00229         stk::mesh::EntityId nodes[4] ;
00230         nodes[0] = 1 + ix + iy * nnx ;
00231         nodes[1] = 2 + ix + iy * nnx ;
00232         nodes[2] = 2 + ix + ( iy + 1 ) * nnx ;
00233         nodes[3] = 1 + ix + ( iy + 1 ) * nnx ;
00234 
00235         stk::mesh::fem::declare_element( bulk_data , quad_part , elem , nodes );
00236       }
00237     }
00238     // end create initial mesh
00239 
00240     // assign element weights
00241     for ( unsigned iy = 0 ; iy < ny ; ++iy ) {
00242       for ( unsigned ix = 0 ; ix < nx ; ++ix ) {
00243         stk::mesh::EntityId elem = 1 + ix + iy * nx ;
00244         stk::mesh::Entity * e = bulk_data.get_entity( element_rank, elem );
00245         double * const e_weight = stk::mesh::field_data( weight_field , *e );
00246         *e_weight = 1.0;
00247       }
00248     }
00249     // end assign element weights
00250   }
00251 
00252   // Only P0 has any nodes or elements
00253   if ( p_rank == 0 ) {
00254     STKUNIT_ASSERT( ! bulk_data.buckets( NODE_RANK ).empty() );
00255     STKUNIT_ASSERT( ! bulk_data.buckets( element_rank ).empty() );
00256   }
00257   else {
00258     STKUNIT_ASSERT( bulk_data.buckets( NODE_RANK ).empty() );
00259     STKUNIT_ASSERT( bulk_data.buckets( element_rank ).empty() );
00260   }
00261 
00262   bulk_data.modification_end();
00263 
00264   // Create our Partition and Selector objects
00265   MockPartition partition(fem_meta, bulk_data);
00266   stk::mesh::Selector selector(fem_meta.universal_part());
00267 
00268   partition.set_balance_step(MockPartition::FIRST);
00269   // Exercise the threshhold calculation by using imblance_threshhold > 1.0
00270   bool do_rebal = 1.5 < stk::rebalance::check_balance(bulk_data, &weight_field, element_rank);
00271   if( do_rebal )
00272   {
00273     // Pick a few values as negative to exercise a check in rebalance::rebalance(...)
00274     // which converts negative weights to 1.0
00275     if ( p_rank == 0 )
00276     {
00277       for ( unsigned iy = 0 ; iy < ny ; ++iy )
00278       {
00279         stk::mesh::EntityId elem = 1 + iy * nx ;
00280         stk::mesh::Entity * e = bulk_data.get_entity( element_rank, elem );
00281         double * const e_weight = stk::mesh::field_data( weight_field , *e );
00282         *e_weight = -2.0;
00283       }
00284     }
00285     // Do the actual rebalance
00286     stk::rebalance::rebalance(bulk_data, selector, NULL, &weight_field, partition);
00287   }
00288 
00289   partition.set_balance_step(MockPartition::SECOND);
00290   stk::rebalance::rebalance(bulk_data, selector, NULL, &weight_field, partition);
00291 
00292   partition.set_balance_step(MockPartition::THIRD);
00293   stk::rebalance::rebalance(bulk_data, selector, NULL, &weight_field, partition);
00294 
00295   if ( 1 < p_size ) {
00296     // Only P1 has any nodes or elements
00297     if ( p_rank == 1 ) {
00298       STKUNIT_ASSERT( ! bulk_data.buckets( NODE_RANK ).empty() );
00299       STKUNIT_ASSERT( ! bulk_data.buckets( element_rank ).empty() );
00300     }
00301     else {
00302       STKUNIT_ASSERT( bulk_data.buckets( NODE_RANK ).empty() );
00303       STKUNIT_ASSERT( bulk_data.buckets( element_rank ).empty() );
00304     }
00305   }
00306 }
00307 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends