Sierra Toolkit Version of the Day
SkinMesh.cpp
00001 
00002 #include <map>
00003 
00004 #include <stk_mesh/base/BulkData.hpp>
00005 #include <stk_mesh/base/BulkModification.hpp>
00006 #include <stk_mesh/base/Entity.hpp>
00007 #include <stk_mesh/base/GetEntities.hpp>
00008 #include <stk_mesh/base/MetaData.hpp>
00009 #include <stk_mesh/base/Selector.hpp>
00010 #include <stk_mesh/base/Types.hpp>
00011 
00012 #include <stk_mesh/fem/FEMTypes.hpp>
00013 #include <stk_mesh/fem/BoundaryAnalysis.hpp>
00014 #include <stk_mesh/fem/EntityRanks.hpp>
00015 #include <stk_mesh/fem/TopologyHelpers.hpp>
00016 
00017 #include <stk_mesh/fem/SkinMesh.hpp>
00018 
00019 namespace stk {
00020 namespace mesh {
00021 
00022 namespace {
00023 
00024 typedef std::multimap< std::vector<EntityId>, EntitySideComponent>  BoundaryMap;
00025 typedef std::pair< std::vector<EntityId>, EntitySideComponent>  BoundaryValue;
00026 
00027 // \TODO Without the sorting, this would be a good general utility for 'fem'
00028 void get_elem_side_nodes( const Entity & elem,
00029                           unsigned side_ordinal,
00030                           std::vector<EntityId> & nodes
00031                         )
00032 {
00033   const CellTopologyData * const elem_top = TopologicalMetaData::get_cell_topology( elem );
00034 
00035   if (elem_top == NULL) {
00036     std::ostringstream msg ;
00037     msg << "skin_mesh" ;
00038     msg << "( Element[" << elem.identifier() << "] has no defined topology" ;
00039     throw std::runtime_error( msg.str() );
00040   }
00041 
00042   const CellTopologyData * const side_top = elem_top->side[ side_ordinal ].topology;
00043 
00044   if (side_top == NULL) {
00045     std::ostringstream msg ;
00046     msg << "skin_mesh" ;
00047     msg << "( Element[" << elem.identifier() << "]" ;
00048     msg << " , side_ordinal = " << side_ordinal << " ) FAILED: " ;
00049     msg << " Side has no defined topology" ;
00050     throw std::runtime_error( msg.str() );
00051   }
00052 
00053   const unsigned * const side_node_map = elem_top->side[ side_ordinal ].node ;
00054 
00055   PairIterRelation relations = elem.relations( NodeRank );
00056 
00057   // Find positive polarity permutation that starts with lowest entity id:
00058   // We're using this as the unique key in a map for a side.
00059   const int num_permutations = side_top->permutation_count;
00060   int lowest_entity_id_permutation = 0;
00061   for (int p = 0; p < num_permutations; ++p) {
00062 
00063     if (side_top->permutation[p].polarity ==
00064         CELL_PERMUTATION_POLARITY_POSITIVE) {
00065      
00066       const unsigned * const pot_lowest_perm_node =
00067         side_top->permutation[p].node ;
00068 
00069       const unsigned * const curr_lowest_perm_node = 
00070         side_top->permutation[lowest_entity_id_permutation].node;
00071 
00072       unsigned first_node_index = 0;
00073 
00074       unsigned current_lowest_entity_id = 
00075         relations[side_node_map[curr_lowest_perm_node[first_node_index]]].entity()->identifier();
00076 
00077       unsigned potential_lowest_entity_id = 
00078         relations[side_node_map[pot_lowest_perm_node[first_node_index]]].entity()->identifier();
00079 
00080       if ( potential_lowest_entity_id < current_lowest_entity_id ) {
00081         lowest_entity_id_permutation = p;
00082       }
00083     }
00084   }
00085   const unsigned * const perm_node = 
00086     side_top->permutation[lowest_entity_id_permutation].node;
00087 
00088   nodes.reserve(side_top->node_count);
00089   for ( unsigned i = 0 ; i < side_top->node_count ; ++i ) {
00090     unsigned node_id = relations[side_node_map[perm_node[i]]].entity()->identifier(); 
00091     nodes.push_back(node_id);
00092   }
00093 
00094 }
00095 
00096 }
00097 
00098 void skin_mesh( BulkData & mesh, EntityRank element_rank, Part * skin_part) {
00099   if (mesh.synchronized_state() ==  BulkData::MODIFIABLE) {
00100     throw std::runtime_error("stk::mesh::skin_mesh is not SYNCHRONIZED");
00101   }
00102 
00103   EntityVector owned_elements;
00104 
00105   // select owned
00106   Selector owned = mesh.mesh_meta_data().locally_owned_part();
00107   get_selected_entities( owned,
00108                          mesh.buckets(element_rank),
00109                          owned_elements);
00110 
00111   reskin_mesh(mesh, element_rank, owned_elements, skin_part);
00112 }
00113 
00114 void reskin_mesh( BulkData & mesh, EntityRank element_rank, EntityVector & owned_elements, Part * skin_part) {
00115   if (mesh.synchronized_state() ==  BulkData::MODIFIABLE) {
00116     throw std::runtime_error("stk::mesh::skin_mesh is not SYNCHRONIZED");
00117   }
00118 
00119   EntityVector elements_closure;
00120 
00121   // compute owned closure
00122   find_closure( mesh, owned_elements, elements_closure );
00123 
00124   // compute boundary
00125   EntitySideVector boundary;
00126   boundary_analysis( mesh, elements_closure, element_rank, boundary);
00127 
00128   // find the sides that need to be created to make a skin. The map below
00129   // maps sorted EntityVectors of nodes to EntitySideComponents
00130   BoundaryMap skin;
00131 
00132   int num_new_sides = 0;
00133   for (stk::mesh::EntitySideVector::const_iterator itr = boundary.begin();
00134        itr != boundary.end(); ++itr) {
00135     const EntitySideComponent & inside = itr->inside;
00136     const EntitySideComponent & outside = itr->outside;
00137     const unsigned side_ordinal = inside.side_ordinal;
00138     Entity& inside_entity = *(inside.entity);
00139 
00140     // If this process owns the inside and the outside entity does not exist,
00141     // we need to apply a skin. This means we need to ensure that the side
00142     // entity exists at this boundary.
00143     if ( inside_entity.owner_rank() == mesh.parallel_rank() &&
00144          outside.entity == NULL ) {
00145       // search through existing sides
00146       PairIterRelation existing_sides = inside_entity.relations(element_rank -1);
00147       for (; existing_sides.first != existing_sides.second &&
00148              existing_sides.first->identifier() != side_ordinal ;
00149              ++existing_sides.first);
00150 
00151       // the side we need for the skin does not exist on the inside entity,
00152       // we may need to create it
00153       if (existing_sides.first == existing_sides.second) {
00154         // Get the nodes for the inside entity
00155         std::vector<EntityId> inside_key;
00156         get_elem_side_nodes(inside_entity, side_ordinal, inside_key);
00157 
00158         //if a side for these nodes is not present in the map already increment the
00159         //number of side we need to create
00160         if (skin.count(inside_key) == 0) {
00161           ++num_new_sides;
00162         }
00163 
00164         skin.insert( BoundaryValue(inside_key, inside));
00165 
00166       }
00167     }
00168   }
00169 
00170   mesh.modification_begin();
00171 
00172   // formulate request ids for the new sides
00173   std::vector<size_t> requests(mesh.mesh_meta_data().entity_rank_count(), 0);
00174   requests[element_rank -1] = num_new_sides;
00175 
00176   // create the new sides
00177   EntityVector requested_sides;
00178   mesh.generate_new_entities(requests, requested_sides);
00179 
00180   std::vector<EntityId> previous_key;
00181   size_t current_side = 0;
00182   for ( BoundaryMap::const_iterator i = skin.begin(); i!= skin.end(); ++i) {
00183     const std::vector<EntityId> & key = i->first;
00184     Entity & entity = *(i->second.entity);
00185     const unsigned side_ordinal = i->second.side_ordinal;
00186 
00187     if (key != previous_key) {
00188       Entity & side = *(requested_sides[current_side]);
00189       declare_element_side(entity, side, side_ordinal, skin_part);
00190 
00191       previous_key = key;
00192       ++current_side;
00193     }
00194     else {
00195       Entity & side = *(requested_sides[current_side-1]);
00196       mesh.declare_relation(entity, side, side_ordinal);
00197     }
00198   }
00199 
00200   mesh.modification_end();
00201 }
00202 
00203 }
00204 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends