Sierra Toolkit Version of the Day
UnitTestZoltanSimple.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 <stk_util/parallel/Parallel.hpp>
00010 #include <stk_util/parallel/ParallelReduce.hpp>
00011 #include <stk_util/unit_test_support/stk_utest_macros.hpp>
00012 
00013 #include <stk_mesh/base/Types.hpp>
00014 #include <stk_mesh/base/MetaData.hpp>
00015 #include <stk_mesh/base/BulkData.hpp>
00016 #include <stk_mesh/base/FieldData.hpp>
00017 #include <stk_mesh/base/GetEntities.hpp>
00018 
00019 #include <stk_mesh/fem/CreateAdjacentEntities.hpp>
00020 #include <stk_mesh/fem/TopologyDimensions.hpp>
00021 #include <stk_mesh/fem/FEMMetaData.hpp>
00022 #include <stk_mesh/fem/FEMHelpers.hpp>
00023 
00024 #include <stk_rebalance/Rebalance.hpp>
00025 #include <stk_rebalance/Partition.hpp>
00026 #include <stk_rebalance/ZoltanPartition.hpp>
00027 
00028 #include <stk_rebalance_utils/RebalanceUtils.hpp>
00029 
00030 static const size_t NODE_RANK = stk::mesh::fem::FEMMetaData::NODE_RANK;
00031 
00032 typedef stk::mesh::Field<double> ScalarField ;
00033 typedef stk::mesh::Field<double, stk::mesh::Cartesian> VectorField ;
00034 
00035 enum { nx = 2, ny = 2 };
00036 
00037 STKUNIT_UNIT_TEST(UnitTestZoltanSimple, testUnit)
00038 {
00039 #ifdef STK_HAS_MPI
00040   stk::ParallelMachine comm(MPI_COMM_WORLD);
00041 #else
00042   stk::ParallelMachine comm(0);
00043 #endif
00044 
00045   unsigned spatial_dimension = 2;
00046   std::vector<std::string> rank_names = stk::mesh::fem::entity_rank_names(spatial_dimension);
00047   const stk::mesh::EntityRank constraint_rank = rank_names.size();
00048   rank_names.push_back("Constraint");
00049 
00050   stk::mesh::fem::FEMMetaData fem_meta;
00051   fem_meta.FEM_initialize( spatial_dimension, rank_names );
00052   stk::mesh::MetaData & meta_data = stk::mesh::fem::FEMMetaData::get_meta_data(fem_meta);
00053   stk::mesh::BulkData bulk_data( meta_data , comm , 100 );
00054   const stk::mesh::EntityRank element_rank    = fem_meta.element_rank();
00055 
00056   stk::mesh::fem::CellTopology quad_top(shards::getCellTopologyData<shards::Quadrilateral<4> >());
00057   stk::mesh::Part & quad_part( fem_meta.declare_part("quad", quad_top ) );
00058   VectorField & coord_field( fem_meta.declare_field< VectorField >( "coordinates" ) );
00059   ScalarField & weight_field( fem_meta.declare_field< ScalarField >( "element_weights" ) );
00060 
00061   stk::mesh::put_field( coord_field , NODE_RANK , fem_meta.universal_part() );
00062   stk::mesh::put_field(weight_field , element_rank , fem_meta.universal_part() );
00063 
00064   fem_meta.commit();
00065 
00066   const unsigned p_size = bulk_data.parallel_size();
00067   const unsigned p_rank = bulk_data.parallel_rank();
00068 
00069   bulk_data.modification_begin();
00070 
00071   if ( p_rank == 0 ) {
00072 
00073     std::vector<std::vector<stk::mesh::Entity*> > quads(nx);
00074     for ( unsigned ix = 0 ; ix < nx ; ++ix ) quads[ix].resize(ny);
00075 
00076     const unsigned nnx = nx + 1 ;
00077     const unsigned nny = ny + 1 ;
00078     for ( unsigned iy = 0 ; iy < ny ; ++iy ) {
00079       for ( unsigned ix = 0 ; ix < nx ; ++ix ) {
00080         stk::mesh::EntityId elem = 1 + ix + iy * nx ;
00081         stk::mesh::EntityId nodes[4] ;
00082         nodes[0] = 1 + ix + iy * nnx ;
00083         nodes[1] = 2 + ix + iy * nnx ;
00084         nodes[2] = 2 + ix + ( iy + 1 ) * nnx ;
00085         nodes[3] = 1 + ix + ( iy + 1 ) * nnx ;
00086 
00087         stk::mesh::Entity &q = stk::mesh::fem::declare_element( bulk_data , quad_part , elem , nodes );
00088         quads[ix][iy] = &q; 
00089       }
00090     }
00091 
00092     for ( unsigned iy = 0 ; iy < ny ; ++iy ) {
00093       for ( unsigned ix = 0 ; ix < nx ; ++ix ) {
00094         stk::mesh::EntityId elem = 1 + ix + iy * nx ;
00095         stk::mesh::Entity * e = bulk_data.get_entity( element_rank, elem );
00096         double * const e_weight = stk::mesh::field_data( weight_field , *e );
00097         *e_weight = 1.0;
00098       }
00099     }
00100 
00101     for ( unsigned iy = 0 ; iy <= ny ; ++iy ) {
00102       for ( unsigned ix = 0 ; ix <= nx ; ++ix ) {
00103         stk::mesh::EntityId nid = 1 + ix + iy * nnx ;
00104         stk::mesh::Entity * n = bulk_data.get_entity( NODE_RANK, nid );
00105         double * const coord = stk::mesh::field_data( coord_field , *n );
00106         coord[0] = .1*ix;
00107         coord[1] = .1*iy;
00108         coord[2] = 0;
00109       }
00110     }
00111 
00112     {
00113       const unsigned iy_left  =  0; 
00114       const unsigned iy_right = ny; 
00115       stk::mesh::PartVector add(1, &fem_meta.locally_owned_part());
00116       for ( unsigned ix = 0 ; ix <= nx ; ++ix ) {
00117         stk::mesh::EntityId nid_left  = 1 + ix + iy_left  * nnx ;
00118         stk::mesh::EntityId nid_right = 1 + ix + iy_right * nnx ;
00119         stk::mesh::Entity * n_left  = bulk_data.get_entity( NODE_RANK, nid_left  );
00120         stk::mesh::Entity * n_right = bulk_data.get_entity( NODE_RANK, nid_right );
00121         const stk::mesh::EntityId constraint_entity_id =  1 + ix + nny * nnx;
00122         stk::mesh::Entity & c = bulk_data.declare_entity( constraint_rank, constraint_entity_id, add );
00123         bulk_data.declare_relation( c , *n_left  , 0 );
00124         bulk_data.declare_relation( c , *n_right , 1 );
00125       }
00126     }
00127 
00128   }
00129 
00130   // Only P0 has any nodes or elements
00131   if ( p_rank == 0 ) {
00132     STKUNIT_ASSERT( ! bulk_data.buckets( NODE_RANK ).empty() );
00133     STKUNIT_ASSERT( ! bulk_data.buckets( element_rank ).empty() );
00134   }
00135   else {
00136     STKUNIT_ASSERT( bulk_data.buckets( NODE_RANK ).empty() );
00137     STKUNIT_ASSERT( bulk_data.buckets( element_rank ).empty() );
00138   }
00139 
00140 
00141   bulk_data.modification_end();
00142 
00143   // create some sides and faces to rebalance.
00144   stk::mesh::PartVector add_parts;
00145   stk::mesh::create_adjacent_entities(bulk_data, add_parts);
00146 
00147   // Zoltan partition is specialized fomm a virtual base class, stk::rebalance::Partition.
00148   // Other specializations are possible.
00149   Teuchos::ParameterList emptyList;
00150   stk::rebalance::Zoltan zoltan_partition(comm, spatial_dimension, emptyList);
00151 
00152   {
00153     stk::mesh::Selector selector(fem_meta.universal_part());
00154 
00155     stk::rebalance::rebalance(bulk_data, selector, &coord_field, &weight_field, zoltan_partition);
00156   }
00157 
00158   const double imbalance_threshold = stk::rebalance::check_balance(bulk_data, &weight_field, element_rank);
00159   const bool do_rebal = 1.5 < imbalance_threshold;
00160 
00161   // Check that we satisfy our threshhold
00162   STKUNIT_ASSERT( !do_rebal );
00163   if( (2 == p_size) || (4 == p_size) )
00164   {
00165     STKUNIT_ASSERT_NEAR(imbalance_threshold, 1.0, 1.e-8);
00166   }
00167   else
00168   {
00169     STKUNIT_ASSERT_LE(imbalance_threshold, 1.5);
00170   }
00171 
00172   // And verify that all dependent entities are on the same proc as their parent element
00173   {
00174     stk::mesh::EntityVector entities;
00175     stk::mesh::Selector selector = fem_meta.locally_owned_part();
00176 
00177     get_selected_entities(selector, bulk_data.buckets(NODE_RANK), entities);
00178     bool result = stk::rebalance::verify_dependent_ownership(element_rank, entities);
00179     //get_selected_entities(selector, bulk_data.buckets(constraint_rank), entities);
00180     //result &= stk::rebalance::verify_dependent_ownership(element_rank, entities);
00181     STKUNIT_ASSERT( result );
00182   }
00183 }
00184 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends