Sierra Toolkit Version of the Day
BoundaryAnalysis.cpp
00001 /*------------------------------------------------------------------------*/
00002 /*                 Copyright 2010 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 <vector>
00010 #include <set>
00011 #include <algorithm>
00012 
00013 #include <stk_mesh/fem/BoundaryAnalysis.hpp>
00014 
00015 #include <stk_mesh/base/BulkData.hpp>
00016 #include <stk_mesh/base/Entity.hpp>
00017 #include <stk_mesh/base/Part.hpp>
00018 #include <stk_mesh/fem/FEMTypes.hpp>
00019 #include <stk_mesh/fem/TopologyHelpers.hpp>
00020 #include <stk_mesh/fem/TopologicalMetaData.hpp>
00021 
00022 namespace stk {
00023 namespace mesh {
00024 
00025 void boundary_analysis(const BulkData& bulk_data,
00026                        const std::vector< Entity *> & entities_closure,
00027                        EntityRank closure_rank,
00028                        EntitySideVector& boundary)
00029 {
00030   const Selector locally_used = bulk_data.mesh_meta_data().locally_owned_part()
00031                               | bulk_data.mesh_meta_data().globally_shared_part();
00032 
00033   // find an iterator that points to the last item in the closure that is of a
00034   // lower-order than the closure_rank
00035   std::vector<Entity*>::const_iterator itr =
00036     std::lower_bound(entities_closure.begin(),
00037                      entities_closure.end(),
00038                      EntityKey(closure_rank, 0),
00039                      EntityLess());
00040 
00041   // iterate over all the entities in the closure up to the iterator we computed above
00042   for ( ; itr != entities_closure.end() && (*itr)->entity_rank() == closure_rank; ++itr) {
00043     // some temporaries for clarity
00044     std::vector<EntitySideComponent > adjacent_entities;
00045     Entity& curr_entity = **itr;
00046     const CellTopologyData* celltopology = TopologicalMetaData::get_cell_topology(curr_entity);
00047     if (celltopology == NULL) {
00048       continue;
00049     }
00050 
00051     unsigned subcell_rank = closure_rank - 1;
00052     PairIterRelation relations = curr_entity.relations(NodeRank);
00053 
00054     // iterate over the subcells of the current entity
00055     for (unsigned nitr = 0; nitr < celltopology->subcell_count[subcell_rank]; ++nitr) {
00056       // find the entities (same rank as subcell) adjacent to this subcell
00057       unsigned subcell_identifier = nitr;
00058       get_adjacent_entities(curr_entity,
00059                             closure_rank - 1,
00060                             subcell_identifier,
00061                             adjacent_entities);
00062 
00063       // try to figure out if we want to keep ((curr_entity, subcell_identifier),
00064       //                                       (adjacent_entity, [k]))
00065       // if so, push into boundary
00066 
00067       // it is a keeper if adjacent entities[k] is not in the entities closure
00068       // AND if either curr_entity OR adjacent entities[k] is a member of the
00069       //               bulk_data.locally_used
00070 
00071       if (adjacent_entities.empty()) {
00072         EntitySide keeper;
00073         keeper.inside.entity = &curr_entity;
00074         keeper.inside.side_ordinal = subcell_identifier;
00075         keeper.outside.entity = NULL;
00076         keeper.outside.side_ordinal = 0;
00077         boundary.push_back(keeper);
00078         continue;
00079       }
00080 
00081       // iterate over adjacent entities (our neighbors)
00082       for (std::vector<EntitySideComponent >::const_iterator
00083            adj_itr = adjacent_entities.begin();
00084            adj_itr != adjacent_entities.end(); ++adj_itr) {
00085         // grab a reference to this neighbor for clarity
00086         const Entity& neighbor = *(adj_itr->entity);
00087 
00088         // see if this neighbor is in the closure, if so, not a keeper
00089         bool neighbor_is_in_closure =
00090           std::binary_search(entities_closure.begin(),
00091                              entities_closure.end(),
00092                              neighbor,
00093                              EntityLess());
00094 
00095         if (neighbor_is_in_closure) {
00096           continue;
00097         }
00098 
00099         // if neighbor or curr_entity is locally-used, add it to keeper
00100         if ( locally_used( neighbor.bucket()) || locally_used( curr_entity.bucket() ) ) {
00101           EntitySide keeper;
00102           keeper.inside.entity = &curr_entity;
00103           keeper.inside.side_ordinal = subcell_identifier;
00104           keeper.outside = *adj_itr;
00105 
00106           boundary.push_back(keeper);
00107         }
00108       }
00109     }
00110   }
00111 }
00112 
00113 void get_adjacent_entities( const Entity & entity ,
00114                             unsigned subcell_rank ,
00115                             unsigned subcell_identifier ,
00116                             std::vector< EntitySideComponent> & adjacent_entities )
00117 {
00118   adjacent_entities.clear();
00119 
00120   // get cell topology
00121   const CellTopologyData* celltopology = TopologicalMetaData::get_cell_topology(entity);
00122   if (celltopology == NULL) {
00123     return;
00124   }
00125 
00126   // valid ranks fall within the dimension of the cell topology
00127   bool bad_rank = subcell_rank >= celltopology->dimension;
00128 
00129   // local id should be < number of entities of the desired type
00130   // (if you have 4 edges, their ids should be 0-3)
00131   bool bad_id = false;
00132   if (!bad_rank) {
00133     bad_id = subcell_identifier >= celltopology->subcell_count[subcell_rank];
00134   }
00135 
00136   if (bad_rank || bad_id) {
00137     std::ostringstream msg;
00138     //parallel consisent throw
00139     if (bad_rank) {
00140       msg << "stk::mesh::get_adjacent_entities( const Entity& entity, unsigned subcell_rank, ... ) subcell_rank is >= celltopology dimension\n";
00141     }
00142     else if (bad_id) {
00143       msg << "stk::mesh::get_adjacent_entities( const Entity& entity, unsigned subcell_rank, unsigned subcell_identifier, ... ) subcell_identifier is >= subcell count\n";
00144     }
00145 
00146     throw std::runtime_error(msg.str());
00147   }
00148 
00149   // For the potentially common subcell, get it's nodes and num_nodes
00150   const unsigned* side_node_local_ids =
00151     celltopology->subcell[subcell_rank][subcell_identifier].node;
00152 
00153   const CellTopologyData * side_topology =
00154     celltopology->subcell[subcell_rank][subcell_identifier].topology;
00155   int num_nodes_in_side = side_topology->node_count;
00156 
00157   // Get all the nodal relationships for this entity. We are guaranteed
00158   // that, if we make it this far, the entity is guaranteed to have
00159   // some relationship to nodes (we know it is a higher-order entity
00160   // than Node).
00161 
00162   // Get the node entities for the nodes that make up the side. We put these
00163   // in in reverse order so that it has the correct orientation with respect
00164   // the potential adjacent entities we are evaluating. The relations are
00165   // right-hand-rule ordered for the owning entity, but we need something
00166   // that's compatible w/ the adjacent entities.
00167   std::vector<Entity*> side_node_entities;
00168   side_node_entities.reserve(num_nodes_in_side);
00169   {
00170     PairIterRelation irel = entity.relations(NodeRank);
00171     for (int itr = num_nodes_in_side; itr > 0; ) {
00172       --itr;
00173       side_node_entities.push_back(irel[side_node_local_ids[itr]].entity());
00174     }
00175   }
00176 
00177   // Get the node entities for the nodes that make up the entity
00178   std::vector<Entity*> entity_nodes;
00179   {
00180     PairIterRelation irel = entity.relations(NodeRank);
00181     entity_nodes.reserve(irel.size());
00182     for ( ; !irel.empty(); ++irel ) {
00183       entity_nodes.push_back(irel->entity());
00184     }
00185   }
00186   std::sort(entity_nodes.begin(), entity_nodes.end());
00187 
00188   // Given the nodes related to the side, find all entities
00189   // of similar rank that have some relation to one or more of these nodes
00190   std::vector<Entity*> elements;
00191   elements.reserve(8); //big enough that resizing should be rare
00192   get_entities_through_relations(side_node_entities,
00193                                  entity.entity_rank(),
00194                                  elements);
00195 
00196   // Make sure to remove the all superimposed entities from the list
00197 
00198   unsigned num_nodes_in_orig_entity = entity_nodes.size();
00199   std::vector<Entity*> current_nodes;
00200   current_nodes.resize(num_nodes_in_orig_entity);
00201   std::vector<Entity*>::iterator itr = elements.begin();
00202   while ( itr != elements.end() ) {
00203     Entity * current_entity = *itr;
00204     PairIterRelation relations = current_entity->relations(NodeRank);
00205 
00206     if (current_entity == &entity) {
00207       // We do not want to be adjacent to ourself
00208       itr = elements.erase(itr);
00209     }
00210     else if (relations.size() != num_nodes_in_orig_entity) {
00211       // current_entity has a different number of nodes than entity, they
00212       // cannot be superimposed
00213       ++itr;
00214     }
00215     else {
00216       for (unsigned i = 0; relations.first != relations.second;
00217            ++relations.first, ++i ) {
00218         current_nodes[i] = relations.first->entity();
00219       }
00220       std::sort(current_nodes.begin(), current_nodes.end());
00221 
00222       bool entities_are_superimposed = entity_nodes == current_nodes;
00223       if (entities_are_superimposed) {
00224         itr = elements.erase(itr);
00225       }
00226       else {
00227         ++itr;
00228       }
00229     }
00230   }
00231 
00232   // Add the local ids, from the POV of the adj entitiy, to the return value
00233   for (std::vector<Entity*>::const_iterator itr = elements.begin();
00234        itr != elements.end(); ++itr) {
00235     int local_side_num = element_local_side_id(**itr,
00236                                                side_topology,
00237                                                side_node_entities);
00238     if ( local_side_num != -1) {
00239       adjacent_entities.push_back(EntitySideComponent(*itr, local_side_num));
00240     }
00241   }
00242 }
00243 
00244 }
00245 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends