|
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(UnitTestZoltanSimple, testUnit) 00038 { 00039 #ifdef STK_HAS_MPI 00040 stk_classic::ParallelMachine comm(MPI_COMM_WORLD); 00041 #else 00042 stk_classic::ParallelMachine comm(0); 00043 #endif 00044 00045 unsigned spatial_dimension = 2; 00046 std::vector<std::string> rank_names = stk_classic::mesh::fem::entity_rank_names(spatial_dimension); 00047 const stk_classic::mesh::EntityRank constraint_rank = rank_names.size(); 00048 rank_names.push_back("Constraint"); 00049 00050 stk_classic::mesh::fem::FEMMetaData fem_meta; 00051 fem_meta.FEM_initialize( spatial_dimension, rank_names ); 00052 stk_classic::mesh::MetaData & meta_data = stk_classic::mesh::fem::FEMMetaData::get_meta_data(fem_meta); 00053 stk_classic::mesh::BulkData bulk_data( meta_data , comm , 100 ); 00054 const stk_classic::mesh::EntityRank element_rank = fem_meta.element_rank(); 00055 00056 stk_classic::mesh::fem::CellTopology quad_top(shards::getCellTopologyData<shards::Quadrilateral<4> >()); 00057 stk_classic::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_classic::mesh::put_field( coord_field , NODE_RANK , fem_meta.universal_part() ); 00062 stk_classic::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_classic::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_classic::mesh::EntityId elem = 1 + ix + iy * nx ; 00081 stk_classic::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_classic::mesh::Entity &q = stk_classic::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_classic::mesh::EntityId elem = 1 + ix + iy * nx ; 00095 stk_classic::mesh::Entity * e = bulk_data.get_entity( element_rank, elem ); 00096 double * const e_weight = stk_classic::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_classic::mesh::EntityId nid = 1 + ix + iy * nnx ; 00104 stk_classic::mesh::Entity * n = bulk_data.get_entity( NODE_RANK, nid ); 00105 double * const coord = stk_classic::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_classic::mesh::PartVector add(1, &fem_meta.locally_owned_part()); 00116 for ( unsigned ix = 0 ; ix <= nx ; ++ix ) { 00117 stk_classic::mesh::EntityId nid_left = 1 + ix + iy_left * nnx ; 00118 stk_classic::mesh::EntityId nid_right = 1 + ix + iy_right * nnx ; 00119 stk_classic::mesh::Entity * n_left = bulk_data.get_entity( NODE_RANK, nid_left ); 00120 stk_classic::mesh::Entity * n_right = bulk_data.get_entity( NODE_RANK, nid_right ); 00121 const stk_classic::mesh::EntityId constraint_entity_id = 1 + ix + nny * nnx; 00122 stk_classic::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_classic::mesh::PartVector add_parts; 00145 stk_classic::mesh::create_adjacent_entities(bulk_data, add_parts); 00146 00147 // Zoltan partition is specialized fomm a virtual base class, stk_classic::rebalance::Partition. 00148 // Other specializations are possible. 00149 Teuchos::ParameterList emptyList; 00150 stk_classic::rebalance::Zoltan zoltan_partition(comm, spatial_dimension, emptyList); 00151 00152 { 00153 stk_classic::mesh::Selector selector(fem_meta.universal_part()); 00154 00155 stk_classic::rebalance::rebalance(bulk_data, selector, &coord_field, &weight_field, zoltan_partition); 00156 } 00157 00158 const double imbalance_threshold = stk_classic::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_classic::mesh::EntityVector entities; 00175 stk_classic::mesh::Selector selector = fem_meta.locally_owned_part(); 00176 00177 get_selected_entities(selector, bulk_data.buckets(NODE_RANK), entities); 00178 bool result = stk_classic::rebalance::verify_dependent_ownership(element_rank, entities); 00179 //get_selected_entities(selector, bulk_data.buckets(constraint_rank), entities); 00180 //result &= stk_classic::rebalance::verify_dependent_ownership(element_rank, entities); 00181 STKUNIT_ASSERT( result ); 00182 } 00183 } 00184