|
Sierra Toolkit Version of the Day
|
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 }