|
Sierra Toolkit
Version of the Day
|
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_classic::mesh::fem::FEMMetaData::NODE_RANK; 00031 00032 typedef stk_classic::mesh::Field<double> ScalarField ; 00033 typedef stk_classic::mesh::Field<double, stk_classic::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_classic::ParallelMachine comm(MPI_COMM_WORLD); 00042 #else 00043 stk_classic::ParallelMachine comm(0); 00044 #endif 00045 00046 unsigned spatial_dimension = 2; 00047 std::vector<std::string> rank_names = stk_classic::mesh::fem::entity_rank_names(spatial_dimension); 00048 const stk_classic::mesh::EntityRank constraint_rank = rank_names.size(); 00049 rank_names.push_back("Constraint"); 00050 00051 stk_classic::mesh::fem::FEMMetaData fem_meta; 00052 fem_meta.FEM_initialize(spatial_dimension, rank_names); 00053 stk_classic::mesh::MetaData & meta_data = stk_classic::mesh::fem::FEMMetaData::get_meta_data(fem_meta); 00054 stk_classic::mesh::BulkData bulk_data( meta_data , comm , 100 ); 00055 const stk_classic::mesh::EntityRank element_rank = fem_meta.element_rank(); 00056 00057 stk_classic::mesh::fem::CellTopology quad_top(shards::getCellTopologyData<shards::Quadrilateral<4> >()); 00058 stk_classic::mesh::Part & quad_part( fem_meta.declare_part("quad", quad_top ) ); 00059 VectorField & coord_field( fem_meta.declare_field< VectorField >( "coordinates" ) ); 00060 00061 stk_classic::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_classic::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_classic::mesh::EntityId elem = 1 + ix + iy * nx ; 00080 stk_classic::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_classic::mesh::Entity &q = stk_classic::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_classic::mesh::EntityId nid = 1 + ix + iy * nnx ; 00094 stk_classic::mesh::Entity * n = bulk_data.get_entity( NODE_RANK, nid ); 00095 double * const coord = stk_classic::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_classic::mesh::PartVector add(1, &fem_meta.locally_owned_part()); 00106 for ( unsigned ix = 0 ; ix <= nx ; ++ix ) { 00107 stk_classic::mesh::EntityId nid_left = 1 + ix + iy_left * nnx ; 00108 stk_classic::mesh::EntityId nid_right = 1 + ix + iy_right * nnx ; 00109 stk_classic::mesh::Entity * n_left = bulk_data.get_entity( NODE_RANK, nid_left ); 00110 stk_classic::mesh::Entity * n_right = bulk_data.get_entity( NODE_RANK, nid_right ); 00111 const stk_classic::mesh::EntityId constraint_entity_id = 1 + ix + nny * nnx; 00112 stk_classic::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_classic::mesh::PartVector add_parts; 00135 stk_classic::mesh::create_adjacent_entities(bulk_data, add_parts); 00136 00137 // Zoltan partition is specialized form a virtual base class, stk_classic::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_classic::rebalance::Zoltan::default_parameters_name())=lb_method; 00144 stk_classic::rebalance::Zoltan zoltan_partition(comm, spatial_dimension, graph); 00145 // end configure snippet 00146 stk_classic::mesh::Selector selector(fem_meta.universal_part()); 00147 00148 // Coordinates are passed to support geometric-based load balancing algorithms 00149 stk_classic::rebalance::rebalance(bulk_data, selector, &coord_field, NULL, zoltan_partition, fem_meta.node_rank()); 00150 00151 const double imbalance_threshold = stk_classic::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_classic::mesh::EntityVector entities; 00168 stk_classic::mesh::Selector selector1 = fem_meta.universal_part(); 00169 00170 get_selected_entities(selector1, bulk_data.buckets(element_rank), entities); 00171 bool result = stk_classic::rebalance::verify_dependent_ownership(NODE_RANK, entities); 00172 STKUNIT_ASSERT( result ); 00173 } 00174 } 00175