Sierra Toolkit Version of the Day
TopologyHelpers.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 
00013 #include <algorithm>
00014 #include <stdexcept>
00015 #include <sstream>
00016 #include <cassert>
00017 
00018 #include <stk_mesh/base/MetaData.hpp>
00019 #include <stk_mesh/base/Part.hpp>
00020 #include <stk_mesh/base/BulkData.hpp>
00021 #include <stk_mesh/base/Entity.hpp>
00022 #include <stk_mesh/base/Bucket.hpp>
00023 #include <stk_mesh/fem/FEMTypes.hpp>
00024 #include <stk_mesh/fem/EntityRanks.hpp>
00025 #include <stk_mesh/fem/TopologyHelpers.hpp>
00026 
00027 #include <stk_util/util/StaticAssert.hpp>
00028 
00029 namespace stk {
00030 namespace mesh {
00031 
00032 //----------------------------------------------------------------------
00033 
00034 namespace {
00035 
00036 void verify_declare_element_side(
00037     const BulkData & mesh,
00038     const Entity & elem,
00039     const unsigned local_side_id
00040     )
00041 {
00042   static const char method[] = "stk::mesh::declare_element_side" ;
00043 #ifndef SKIP_DEPRECATED_STK_MESH_TOPOLOGY_HELPERS
00044   const CellTopologyData * const elem_top = get_cell_topology( elem );
00045 #else // SKIP_DEPRECATED_STK_MESH_TOPOLOGY_HELPERS
00046   const CellTopologyData * const elem_top = TopologicalMetaData::get_cell_topology( elem );
00047 #endif // SKIP_DEPRECATED_STK_MESH_TOPOLOGY_HELPERS
00048 
00049   const CellTopologyData * const side_top =
00050     ( elem_top && local_side_id < elem_top->side_count )
00051     ? elem_top->side[ local_side_id ].topology : NULL ;
00052 
00053   bool different_bulk_data =  &mesh != & (elem.bucket().mesh());
00054 
00055   bool no_elem_top = (side_top == NULL);
00056 
00057   bool bad_side_id = false;
00058   if( elem_top && local_side_id >= elem_top->side_count){
00059       bad_side_id = true;
00060   }
00061 
00062 
00063   if ( different_bulk_data || no_elem_top || bad_side_id ) {
00064      std::ostringstream msg ;
00065      msg << method << "( ";
00066      print_entity_key( msg , mesh.mesh_meta_data() , elem.key() );
00067      msg << " , "
00068          << local_side_id
00069          << " ) FAILED" ;
00070      if ( different_bulk_data ) {
00071        msg << " Bulkdata for 'elem' and 'side' are different" ;
00072      } else if (no_elem_top && !bad_side_id ){
00073        msg << " No element topology found" ;
00074 
00075      } else if ( no_elem_top && bad_side_id ){
00076        msg << " No element topology found and " ;
00077        msg << " cell side id ";
00078        msg << local_side_id ;
00079        msg << " exceeds " ;
00080        msg << elem_top->name ;
00081        msg << ".side_count = " ;
00082        msg << elem_top->side_count ;
00083      }
00084      throw std::runtime_error( msg.str() );
00085    }
00086 }
00087 
00088 }
00089 
00090 //----------------------------------------------------------------------
00091 
00092 Entity & declare_element_side(
00093   Entity & elem ,
00094   Entity & side,
00095   const unsigned local_side_id ,
00096   Part * part )
00097 {
00098   static const char method[] = "stk::mesh::declare_element_side" ;
00099 
00100   BulkData & mesh = side.bucket().mesh();
00101 
00102   verify_declare_element_side(mesh, elem, local_side_id);
00103 
00104 #ifndef SKIP_DEPRECATED_STK_MESH_TOPOLOGY_HELPERS
00105   const CellTopologyData * const elem_top = get_cell_topology( elem );
00106 #else // SKIP_DEPRECATED_STK_MESH_TOPOLOGY_HELPERS
00107   const CellTopologyData * const elem_top = TopologicalMetaData::get_cell_topology( elem );
00108 #endif // SKIP_DEPRECATED_STK_MESH_TOPOLOGY_HELPERS
00109 
00110   if (elem_top == NULL) {
00111     std::ostringstream msg ;
00112     msg << method ;
00113     msg << "( Element[" << elem.identifier() << "] has no defined topology" ;
00114     throw std::runtime_error( msg.str() );
00115   }
00116 
00117   const CellTopologyData * const side_top = elem_top->side[ local_side_id ].topology;
00118 
00119   if (side_top == NULL) {
00120     std::ostringstream msg ;
00121     msg << method ;
00122     msg << "( Element[" << elem.identifier() << "]" ;
00123     msg << " , local_side_id = " << local_side_id << " ) FAILED: " ;
00124     msg << " Side has no defined topology" ;
00125     throw std::runtime_error( msg.str() );
00126   }
00127 
00128   const unsigned * const side_node_map = elem_top->side[ local_side_id ].node ;
00129 
00130   PartVector add_parts ;
00131 
00132   if ( part ) { add_parts.push_back( part ); }
00133 
00134   mesh.change_entity_parts(side, add_parts);
00135 
00136   mesh.declare_relation( elem , side , local_side_id );
00137 
00138   PairIterRelation rel = elem.relations( NodeRank );
00139 
00140   for ( unsigned i = 0 ; i < side_top->node_count ; ++i ) {
00141     Entity & node = * rel[ side_node_map[i] ].entity();
00142     mesh.declare_relation( side , node , i );
00143   }
00144 
00145   return side ;
00146 }
00147 
00148 //----------------------------------------------------------------------
00149 
00150 Entity & declare_element_side(
00151   BulkData & mesh ,
00152   const stk::mesh::EntityId global_side_id ,
00153   Entity & elem ,
00154   const unsigned local_side_id ,
00155   Part * part )
00156 {
00157   static const char method[] = "stk::mesh::declare_element_side" ;
00158   verify_declare_element_side(mesh, elem, local_side_id);
00159 
00160 #ifndef SKIP_DEPRECATED_STK_MESH_TOPOLOGY_HELPERS
00161   const CellTopologyData * const elem_top = get_cell_topology( elem );
00162 #else // SKIP_DEPRECATED_STK_MESH_TOPOLOGY_HELPERS
00163   const CellTopologyData * const elem_top = TopologicalMetaData::get_cell_topology( elem );
00164 #endif // SKIP_DEPRECATED_STK_MESH_TOPOLOGY_HELPERS
00165 
00166   if (elem_top == NULL) {
00167     std::ostringstream msg ;
00168     msg << method ;
00169     msg << "( Element[" << elem.identifier() << "] has no defined topology" ;
00170     throw std::runtime_error( msg.str() );
00171   }
00172 
00173   const CellTopologyData * const side_top = elem_top->side[ local_side_id ].topology;
00174 
00175   if (side_top == NULL) {
00176     std::ostringstream msg ;
00177     msg << method ;
00178     msg << "( Element[" << elem.identifier() << "]" ;
00179     msg << " , local_side_id = " << local_side_id << " ) FAILED: " ;
00180     msg << " Side has no defined topology" ;
00181     throw std::runtime_error( msg.str() );
00182   }
00183 
00184 
00185   PartVector empty_parts ;
00186 
00187   Entity & side = mesh.declare_entity( side_top->dimension , global_side_id, empty_parts );
00188   return declare_element_side( elem, side, local_side_id, part);
00189 }
00190 
00191 //----------------------------------------------------------------------
00192 
00193 bool element_side_polarity( const Entity & elem ,
00194                             const Entity & side , int local_side_id )
00195 {
00196   static const char method[] = "stk::mesh::element_side_polarity" ;
00197 
00198   // 09/14/10:  TODO:  tscoffe:  Will this work in 1D?
00199   // 09/14/10:  TODO:  tscoffe:  We need an exception here if we don't get a TopologicalMetaData off of MetaData or we need to take one on input.
00200 #ifndef SKIP_DEPRECATED_STK_MESH_TOPOLOGY_HELPERS
00201   const bool is_side = side.entity_rank() != Edge;
00202   const CellTopologyData * const elem_top = get_cell_topology( elem );
00203 #else // SKIP_DEPRECATED_STK_MESH_TOPOLOGY_HELPERS
00204   const TopologicalMetaData& top_data = *elem.bucket().mesh().mesh_meta_data().get_attribute<TopologicalMetaData>();
00205   const bool is_side = side.entity_rank() != top_data.edge_rank;
00206   const CellTopologyData * const elem_top = TopologicalMetaData::get_cell_topology( elem );
00207 #endif // SKIP_DEPRECATED_STK_MESH_TOPOLOGY_HELPERS
00208 
00209   const unsigned side_count = ! elem_top ? 0 : (
00210                                 is_side ? elem_top->side_count
00211                                         : elem_top->edge_count );
00212 
00213   if ( NULL == elem_top ||
00214        local_side_id < 0 ||
00215        static_cast<int>(side_count) <= local_side_id ) {
00216     const MetaData & meta_data = elem.bucket().mesh().mesh_meta_data();
00217     std::ostringstream msg ;
00218     msg << method ;
00219     msg << "( Element[" << elem.identifier() << "]" ;
00220     msg << " , " << meta_data.entity_rank_names()[ side.entity_rank() ];
00221     msg << "[" << side.identifier() << "]" ;
00222     msg << " , local_side_id = " << local_side_id << " ) FAILED: " ;
00223     if ( NULL == elem_top ) {
00224       msg << " Element has no defined topology" ;
00225     }
00226     else {
00227       msg << " Unsupported local_side_id" ;
00228     }
00229     throw std::runtime_error( msg.str() );
00230   }
00231 
00232   const CellTopologyData * const side_top =
00233     is_side ? elem_top->side[ local_side_id ].topology
00234             : elem_top->edge[ local_side_id ].topology ;
00235 
00236   const unsigned * const side_map =
00237     is_side ? elem_top->side[ local_side_id ].node
00238             : elem_top->edge[ local_side_id ].node ;
00239 
00240   const PairIterRelation elem_nodes = elem.relations( NodeRank );
00241   const PairIterRelation side_nodes = side.relations( NodeRank );
00242 
00243   bool good = true ;
00244   for ( unsigned j = 0 ; good && j < side_top->node_count ; ++j ) {
00245     good = side_nodes[j].entity() == elem_nodes[ side_map[j] ].entity();
00246   }
00247   return good ;
00248 }
00249 
00250 
00251 int element_local_side_id( const Entity & elem ,
00252                            const CellTopologyData * side_topology,
00253                            const std::vector<Entity*>& side_nodes )
00254 {
00255 
00256   // get topology of elem
00257 #ifndef SKIP_DEPRECATED_STK_MESH_TOPOLOGY_HELPERS
00258   const CellTopologyData* elem_topology = get_cell_topology(elem);
00259 #else // SKIP_DEPRECATED_STK_MESH_TOPOLOGY_HELPERS
00260   const CellTopologyData* elem_topology = TopologicalMetaData::get_cell_topology(elem);
00261 #endif // SKIP_DEPRECATED_STK_MESH_TOPOLOGY_HELPERS
00262   if (elem_topology == NULL) {
00263     return -1;
00264   }
00265 
00266   // get nodal relations for elem
00267   PairIterRelation relations = elem.relations(NodeRank);
00268 
00269   const unsigned subcell_rank = elem_topology->dimension - 1;
00270 
00271   const int num_permutations = side_topology->permutation_count;
00272 
00273   // Iterate over the subcells of elem...
00274   for (unsigned itr = 0;
00275        itr < elem_topology->subcell_count[subcell_rank];
00276        ++itr) {
00277 
00278     // get topological data for this side
00279     const CellTopologyData* curr_side_topology =
00280       elem_topology->subcell[subcell_rank][itr].topology;
00281     unsigned num_nodes =
00282       elem_topology->subcell[subcell_rank][itr].topology->node_count;
00283     const unsigned* const side_node_map = elem_topology->side[itr].node;
00284 
00285     // If topologies are not the same, there is no way the sides are the same
00286     if (side_topology == curr_side_topology) {
00287 
00288       // Taking all positive permutations into account, check if this side
00289       // has the same nodes as the side_nodes argument. Note that this
00290       // implementation preserves the node-order so that we can take
00291       // entity-orientation into account.
00292       for (int p = 0; p < num_permutations; ++p) {
00293 
00294         if (curr_side_topology->permutation[p].polarity ==
00295             CELL_PERMUTATION_POLARITY_POSITIVE) {
00296 
00297           const unsigned * const perm_node =
00298             curr_side_topology->permutation[p].node ;
00299 
00300           bool all_match = true;
00301           for (unsigned j = 0 ; j < num_nodes; ++j ) {
00302             if (side_nodes[j] !=
00303                 relations[side_node_map[perm_node[j]]].entity()) {
00304               all_match = false;
00305               break;
00306             }
00307           }
00308 
00309           // all nodes were the same, we have a match
00310           if ( all_match ) {
00311             return itr ;
00312           }
00313         }
00314       }
00315     }
00316   }
00317 
00318   return -1;
00319 }
00320 
00321 //----------------------------------------------------------------------
00322 
00323 }// namespace mesh
00324 }// namespace stk
00325 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends