|
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 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