Sierra Toolkit Version of the Day
GearsFixture.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 <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::mesh::EntityRank NODE_RANK = stk::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 {
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::mesh::StateNew));
00175   fields.push_back(& displacement_field.field_of_state(stk::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::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::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::mesh::get_buckets(locally_owned,bulk_data.buckets(Element),local_elements);
00265   //  BucketVector local_nodes;
00266   //  stk::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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends