|
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 <cmath> 00010 #include <sstream> 00011 #include <stdexcept> 00012 #include <limits> 00013 #include <iostream> 00014 #include <set> 00015 00016 #include <stk_mesh/base/Types.hpp> 00017 #include <stk_mesh/base/MetaData.hpp> 00018 #include <stk_mesh/base/FieldData.hpp> 00019 #include <stk_mesh/base/FieldParallel.hpp> 00020 #include <stk_mesh/base/Entity.hpp> 00021 #include <stk_mesh/base/BulkData.hpp> 00022 #include <stk_mesh/base/BulkModification.hpp> 00023 #include <stk_mesh/base/Selector.hpp> 00024 #include <stk_mesh/base/GetEntities.hpp> 00025 #include <stk_mesh/base/GetBuckets.hpp> 00026 00027 #include <stk_mesh/fixtures/GearsFixture.hpp> 00028 #include <stk_mesh/fixtures/Gear.hpp> 00029 00030 #include <stk_mesh/fem/Stencils.hpp> 00031 #include <stk_mesh/fem/FEMHelpers.hpp> 00032 #include <stk_mesh/fem/BoundaryAnalysis.hpp> 00033 00034 #include <Shards_BasicTopologies.hpp> 00035 00036 namespace { 00037 00038 const stk_classic::mesh::EntityRank NODE_RANK = stk_classic::mesh::fem::FEMMetaData::NODE_RANK; 00039 00040 const unsigned ONE_STATE = 1; 00041 const unsigned TWO_STATE = 2; 00042 00043 typedef shards::Hexahedron<8> Hex8 ; 00044 typedef shards::Wedge<6> Wedge6 ; 00045 00046 } // namespace 00047 00048 namespace stk_classic { 00049 namespace mesh { 00050 namespace fixtures { 00051 00052 GearsFixture::GearsFixture( ParallelMachine pm, size_t num_gears, GearParams gear_params) 00053 : NUM_GEARS(num_gears) 00054 , meta_data( SpatialDimension ) 00055 , bulk_data( fem::FEMMetaData::get_meta_data(meta_data) , pm ) 00056 , element_rank( meta_data.element_rank() ) 00057 , cylindrical_coord_part( meta_data.declare_part("cylindrical_coord_part", element_rank)) 00058 , hex_part( fem::declare_part<Hex8>(meta_data, "hex8_part")) 00059 , wedge_part( fem::declare_part<Wedge6>(meta_data, "wedge6_part")) 00060 , cartesian_coord_field( meta_data.declare_field<CartesianField>("coordinates", ONE_STATE)) 00061 , displacement_field( meta_data.declare_field<CartesianField>("displacement", TWO_STATE)) 00062 , translation_field( meta_data.declare_field<CartesianField>("translation", ONE_STATE)) 00063 , cylindrical_coord_field( meta_data.declare_field<CylindricalField>("cylindrical_coordinates", ONE_STATE)) 00064 , m_gears() 00065 { 00066 00067 put_field( 00068 cartesian_coord_field, 00069 NODE_RANK, 00070 meta_data.universal_part(), 00071 SpatialDimension 00072 ); 00073 00074 put_field( 00075 displacement_field, 00076 NODE_RANK, 00077 meta_data.universal_part(), 00078 SpatialDimension 00079 ); 00080 00081 put_field( 00082 translation_field, 00083 NODE_RANK, 00084 cylindrical_coord_part, 00085 SpatialDimension 00086 ); 00087 00088 put_field( 00089 cylindrical_coord_field, 00090 NODE_RANK, 00091 cylindrical_coord_part, 00092 SpatialDimension 00093 ); 00094 00095 m_gears.resize(NUM_GEARS); 00096 00097 for ( size_t i = 0; i < NUM_GEARS; ++i) { 00098 std::ostringstream oss; 00099 oss << "Gear_" << i ; 00100 m_gears[i] = new Gear ( 00101 meta_data, 00102 bulk_data, 00103 meta_data.declare_part(oss.str(),SpatialDimension), 00104 cylindrical_coord_part, 00105 hex_part, 00106 wedge_part, 00107 cartesian_coord_field, 00108 displacement_field, 00109 translation_field, 00110 cylindrical_coord_field, 00111 gear_params.element_size, 00112 gear_params.radius_min, 00113 gear_params.radius_max, 00114 gear_params.height_min, 00115 gear_params.height_max 00116 ); 00117 } 00118 } 00119 00120 GearsFixture::~GearsFixture() 00121 { 00122 for( std::vector<Gear *>::iterator i = m_gears.begin(); 00123 i != m_gears.end(); 00124 ++i ) 00125 { 00126 delete *i; 00127 *i = NULL; 00128 } 00129 } 00130 00131 void GearsFixture::generate_mesh() { 00132 00133 // Parallel collective call: 00134 bulk_data.modification_begin(); 00135 00136 const unsigned p_size = bulk_data.parallel_size(); 00137 const unsigned p_rank = bulk_data.parallel_rank(); 00138 00139 //create the gears on a line 00140 for( size_t i = 0; i < m_gears.size(); ++i) { 00141 if (( (i*p_size)/m_gears.size()) == p_rank) { 00142 Gear & gear = get_gear(i); 00143 gear.generate_gear(); 00144 } else { 00145 // Parallel synchronization: 00146 std::vector<size_t> empty_requests(meta_data.entity_rank_count(), 0); 00147 EntityVector empty_entities; 00148 bulk_data.generate_new_entities(empty_requests, empty_entities); 00149 } 00150 } 00151 00152 // Parallel collective call: 00153 bulk_data.modification_end(); 00154 00155 // Parallel collective call: 00156 communicate_model_fields(); 00157 00158 for ( size_t i = 0 ; i < m_gears.size() ; ++i ) { 00159 // Parallel collective call: 00160 distribute_gear_across_processors(get_gear(i),cylindrical_coord_field); 00161 } 00162 00163 } 00164 00165 void GearsFixture::communicate_model_fields() 00166 { 00167 //copy the field data to the aura nodes 00168 00169 std::vector< const FieldBase *> fields; 00170 00171 fields.push_back(& cartesian_coord_field); 00172 fields.push_back(& translation_field); 00173 fields.push_back(& cylindrical_coord_field); 00174 fields.push_back(& displacement_field.field_of_state(stk_classic::mesh::StateNew)); 00175 fields.push_back(& displacement_field.field_of_state(stk_classic::mesh::StateOld)); 00176 00177 // Parallel collective call: 00178 communicate_field_data(bulk_data.shared_aura(), fields); 00179 } 00180 00181 00182 double scale_angle_2pi(double angle) { 00183 while ( angle < 0.0 ) { 00184 angle += TWO_PI; 00185 } 00186 while ( angle >= TWO_PI) { 00187 angle -= TWO_PI; 00188 } 00189 return angle; 00190 } 00191 00192 00193 void select_nodal_data( 00194 GearsFixture::CylindricalField & cylindrical_coord_field, 00195 Entity & element, 00196 double & radius, 00197 double & angle, 00198 double & height 00199 ) 00200 { 00201 radius = 0.0; 00202 angle = TWO_PI; 00203 height = 0.0; 00204 PairIterRelation node_relations = element.relations(NODE_RANK); 00205 int numNodes = node_relations.second - node_relations.first; 00206 for ( ; node_relations.first != node_relations.second ; ++(node_relations.first) ) { 00207 Entity * node = node_relations.first->entity(); 00208 EntityArray<GearsFixture::CylindricalField> cylindrical_data( cylindrical_coord_field, *node); 00209 radius += cylindrical_data(0); 00210 angle = std::min(angle,cylindrical_data(1)); 00211 height += cylindrical_data(2); 00212 } 00213 radius /= numNodes; 00214 height /= numNodes; 00215 } 00216 00217 // Parallel collective call: 00218 void distribute_gear_across_processors(Gear & gear, GearsFixture::CylindricalField & cylindrical_coord_field) 00219 { 00220 BulkData & bulk_data = gear.bulk_data; 00221 00222 const unsigned p_size = bulk_data.parallel_size(); 00223 const unsigned p_rank = bulk_data.parallel_rank(); 00224 00225 EntityProcVec elements_to_change_owner; 00226 00227 Selector locally_owned = gear.meta_data.locally_owned_part(); 00228 if (p_rank == 0) { 00229 BucketVector all_elements; 00230 stk_classic::mesh::get_buckets(locally_owned,bulk_data.buckets(gear.meta_data.element_rank()),all_elements); 00231 std::set<Entity *> node_set; // First come first serve nodal movement. 00232 for (BucketVector::iterator it = all_elements.begin() ; it != all_elements.end() ; ++it) { 00233 Bucket & b = **it; 00234 for (size_t i=0 ; i<b.size() ; ++i) { 00235 Entity * element = &b[i]; 00236 double radius = 0.0; 00237 double angle = 0.0; 00238 double height = 0.0; 00239 select_nodal_data(cylindrical_coord_field, *element,radius,angle,height); 00240 unsigned destination_processor_rank = destination_processor(gear,radius,angle,height,p_rank,p_size); 00241 elements_to_change_owner.push_back(EntityProc(element,destination_processor_rank)); 00242 // Now add all related nodes to list to move to this processor: 00243 PairIterRelation node_relations = element->relations(stk_classic::mesh::fem::FEMMetaData::NODE_RANK); 00244 for ( ; node_relations.first != node_relations.second ; ++(node_relations.first) ) { 00245 Entity * node = node_relations.first->entity(); 00246 if (node_set.count(node)==0) { 00247 elements_to_change_owner.push_back(EntityProc(node,destination_processor_rank)); 00248 node_set.insert(node); 00249 } 00250 } 00251 } 00252 } 00253 } 00254 00255 // Parallel collective call: 00256 bulk_data.modification_begin(); 00257 bulk_data.change_entity_owner(elements_to_change_owner); 00258 // Parallel collective call: 00259 bulk_data.modification_end(); 00260 00261 // Print out how many ended up on each processor: 00262 //{ 00263 // BucketVector local_elements; 00264 // stk_classic::mesh::get_buckets(locally_owned,bulk_data.buckets(Element),local_elements); 00265 // BucketVector local_nodes; 00266 // stk_classic::mesh::get_buckets(locally_owned,bulk_data.buckets(Node),local_nodes); 00267 // size_t element_count = 0; 00268 // for (BucketVector::iterator it = local_elements.begin() ; it != local_elements.end() ; ++it) { 00269 // Bucket & b = **it; 00270 // element_count += b.size(); 00271 // } 00272 // size_t node_count = 0; 00273 // for (BucketVector::iterator it = local_nodes.begin() ; it != local_nodes.end() ; ++it) { 00274 // Bucket & b = **it; 00275 // node_count += b.size(); 00276 // } 00277 // std::cout << "Proc " << p_rank << ": element count = " << element_count << " node count = " << node_count << std::endl; 00278 //} 00279 00280 } 00281 00282 00283 double floor0(double value) 00284 { 00285 double result = std::floor( std::fabs( value ) ); 00286 return (value < 0.0) ? -result : result; 00287 } 00288 00289 00290 void scale_p_rank(unsigned & p_rank, unsigned p_size) 00291 { 00292 if (p_rank >= p_size) { 00293 p_rank = p_size-1; 00294 } 00295 } 00296 00297 unsigned destination_processor(const Gear & gear, double rad, double angle, double height, unsigned p_rank, unsigned p_size) 00298 { 00299 unsigned result = 0; 00300 // Distribute elements across angles: (not working perfectly yet) 00301 angle = scale_angle_2pi(angle); 00302 result = static_cast<unsigned>(floor0((angle/TWO_PI)*p_size)); 00303 00304 // Distribute elements across radius: 00305 //result = static_cast<unsigned>(floor0((rad-gear.rad_min)/(gear.rad_max-gear.rad_min)*p_size)); 00306 00307 // Distribute elements across height: 00308 //result = static_cast<unsigned>(floor0((height-gear.height_min)/(gear.height_max-gear.height_min)*p_size)); 00309 00310 // Distribute elements randomly: 00311 //result = std::rand() % p_size; 00312 00313 // Distribute in round-robin fashion: 00314 //static unsigned dest_proc = 0; 00315 //result = dest_proc++ % p_size; 00316 00317 // Distribute all to processor 2: 00318 //result = 1; 00319 00320 scale_p_rank(result,p_size); 00321 00322 //std::cout << "P"<<p_rank<<"("<<p_size<<"): (r,t,z) = ("<<rad<<", "<<angle<<", "<<height<<"), dest = " << result << std::endl; 00323 00324 return result; 00325 } 00326 00327 } // fixtures 00328 } // mesh 00329 } // stk 00330 00331 00332