Sierra Toolkit Version of the Day
UnitTestZoltanGraph.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(UnitTestZoltanGraph, testUnit)
00038 void disabled_unit_test()
00039 {
00040 #ifdef STK_HAS_MPI
00041   stk::ParallelMachine comm(MPI_COMM_WORLD);
00042 #else
00043   stk::ParallelMachine comm(0);
00044 #endif
00045 
00046   unsigned spatial_dimension = 2;
00047   std::vector<std::string> rank_names = stk::mesh::fem::entity_rank_names(spatial_dimension);
00048   const stk::mesh::EntityRank constraint_rank = rank_names.size();
00049   rank_names.push_back("Constraint");
00050 
00051   stk::mesh::fem::FEMMetaData fem_meta;
00052   fem_meta.FEM_initialize(spatial_dimension, rank_names);
00053   stk::mesh::MetaData & meta_data = stk::mesh::fem::FEMMetaData::get_meta_data(fem_meta);
00054   stk::mesh::BulkData bulk_data( meta_data , comm , 100 );
00055   const stk::mesh::EntityRank element_rank    = fem_meta.element_rank();
00056 
00057   stk::mesh::fem::CellTopology quad_top(shards::getCellTopologyData<shards::Quadrilateral<4> >());
00058   stk::mesh::Part & quad_part( fem_meta.declare_part("quad", quad_top ) );
00059   VectorField & coord_field( fem_meta.declare_field< VectorField >( "coordinates" ) );
00060 
00061   stk::mesh::put_field( coord_field , NODE_RANK , fem_meta.universal_part() );
00062 
00063   fem_meta.commit();
00064 
00065   const unsigned p_size = bulk_data.parallel_size();
00066   const unsigned p_rank = bulk_data.parallel_rank();
00067 
00068   bulk_data.modification_begin();
00069 
00070   if ( p_rank == 0 ) {
00071 
00072     std::vector<std::vector<stk::mesh::Entity*> > quads(nx);
00073     for ( unsigned ix = 0 ; ix < nx ; ++ix ) quads[ix].resize(ny);
00074 
00075     const unsigned nnx = nx + 1 ;
00076     const unsigned nny = ny + 1 ;
00077     for ( unsigned iy = 0 ; iy < ny ; ++iy ) {
00078       for ( unsigned ix = 0 ; ix < nx ; ++ix ) {
00079         stk::mesh::EntityId elem = 1 + ix + iy * nx ;
00080         stk::mesh::EntityId nodes[4] ;
00081         nodes[0] = 1 + ix + iy * nnx ;
00082         nodes[1] = 2 + ix + iy * nnx ;
00083         nodes[2] = 2 + ix + ( iy + 1 ) * nnx ;
00084         nodes[3] = 1 + ix + ( iy + 1 ) * nnx ;
00085 
00086         stk::mesh::Entity &q = stk::mesh::fem::declare_element( bulk_data , quad_part , elem , nodes );
00087         quads[ix][iy] = &q; 
00088       }
00089     }
00090 
00091     for ( unsigned iy = 0 ; iy <= ny ; ++iy ) {
00092       for ( unsigned ix = 0 ; ix <= nx ; ++ix ) {
00093         stk::mesh::EntityId nid = 1 + ix + iy * nnx ;
00094         stk::mesh::Entity * n = bulk_data.get_entity( NODE_RANK, nid );
00095         double * const coord = stk::mesh::field_data( coord_field , *n );
00096         coord[0] = .1*ix;
00097         coord[1] = .1*iy;
00098         coord[2] = 0;
00099       }
00100     }
00101 
00102     {
00103       const unsigned iy_left  =  0; 
00104       const unsigned iy_right = ny; 
00105       stk::mesh::PartVector add(1, &fem_meta.locally_owned_part());
00106       for ( unsigned ix = 0 ; ix <= nx ; ++ix ) {
00107         stk::mesh::EntityId nid_left  = 1 + ix + iy_left  * nnx ;
00108         stk::mesh::EntityId nid_right = 1 + ix + iy_right * nnx ;
00109         stk::mesh::Entity * n_left  = bulk_data.get_entity( NODE_RANK, nid_left  );
00110         stk::mesh::Entity * n_right = bulk_data.get_entity( NODE_RANK, nid_right );
00111         const stk::mesh::EntityId constraint_entity_id =  1 + ix + nny * nnx;
00112         stk::mesh::Entity & c = bulk_data.declare_entity( constraint_rank, constraint_entity_id, add );
00113         bulk_data.declare_relation( c , *n_left  , 0 );
00114         bulk_data.declare_relation( c , *n_right , 1 );
00115       }
00116     }
00117 
00118   }
00119 
00120   // Only P0 has any nodes or elements
00121   if ( p_rank == 0 ) {
00122     STKUNIT_ASSERT( ! bulk_data.buckets( NODE_RANK ).empty() );
00123     STKUNIT_ASSERT( ! bulk_data.buckets( element_rank ).empty() );
00124   }
00125   else {
00126     STKUNIT_ASSERT( bulk_data.buckets( NODE_RANK ).empty() );
00127     STKUNIT_ASSERT( bulk_data.buckets( element_rank ).empty() );
00128   }
00129 
00130 
00131   bulk_data.modification_end();
00132 
00133   // create some sides and faces to rebalance.
00134   stk::mesh::PartVector add_parts;
00135   stk::mesh::create_adjacent_entities(bulk_data, add_parts);
00136 
00137   // Zoltan partition is specialized form a virtual base class, stk::rebalance::Partition.
00138   // Other specializations are possible.
00139   // Configure Zoltan to use graph-based partitioning
00140   Teuchos::ParameterList graph;
00141   Teuchos::ParameterList lb_method;
00142   lb_method.set("LOAD BALANCING METHOD"      , "4");
00143   graph.sublist(stk::rebalance::Zoltan::default_parameters_name())=lb_method;
00144   stk::rebalance::Zoltan zoltan_partition(comm, spatial_dimension, graph);
00145   // end configure snippet
00146   stk::mesh::Selector selector(fem_meta.universal_part());
00147 
00148   // Coordinates are passed to support geometric-based load balancing algorithms
00149   stk::rebalance::rebalance(bulk_data, selector, &coord_field, NULL, zoltan_partition, fem_meta.node_rank());
00150 
00151   const double imbalance_threshold = stk::rebalance::check_balance(bulk_data, NULL, fem_meta.node_rank(), &selector);
00152   const bool do_rebal = 1.5 < imbalance_threshold;
00153 
00154   // Check that we satisfy our threshhold
00155   STKUNIT_ASSERT( !do_rebal );
00156   if( (2 == p_size) || (4 == p_size) )
00157   {
00158     STKUNIT_ASSERT_NEAR(imbalance_threshold, 1.0, .1);
00159   }
00160   else
00161   {
00162     STKUNIT_ASSERT_LE(imbalance_threshold, 1.5);
00163   }
00164 
00165   // And verify that all dependent entities are on the same proc as their parent element
00166   {
00167     stk::mesh::EntityVector entities;
00168     stk::mesh::Selector selector1 = fem_meta.universal_part();
00169 
00170     get_selected_entities(selector1, bulk_data.buckets(element_rank), entities);
00171     bool result = stk::rebalance::verify_dependent_ownership(NODE_RANK, entities);
00172     STKUNIT_ASSERT( result );
00173   }
00174 }
00175 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends