|
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 <string> 00010 #include <vector> 00011 #include <sstream> 00012 #include <stdexcept> 00013 #include <algorithm> 00014 00015 #include <Shards_BasicTopologies.hpp> 00016 00017 #include <stk_mesh/base/MetaData.hpp> 00018 #include <stk_mesh/base/BulkData.hpp> 00019 #include <stk_mesh/base/Bucket.hpp> 00020 #include <stk_mesh/base/Entity.hpp> 00021 00022 #include <stk_mesh/fem/TopologicalMetaData.hpp> 00023 00024 namespace stk { 00025 namespace mesh { 00026 00027 void TopologicalMetaData::verify_spatial_dimension( 00028 unsigned spatial_dimension , const char * method ) 00029 { 00030 if ( spatial_dimension < 1 || 3 < spatial_dimension ) { 00031 std::ostringstream msg ; 00032 msg << method << " ERRONEOUS spatial dimension = " 00033 << spatial_dimension ; 00034 throw std::logic_error( msg.str() ); 00035 } 00036 } 00037 00038 std::vector<std::string> 00039 TopologicalMetaData::entity_rank_names( unsigned spatial_dimension ) 00040 { 00041 static const char method[] = 00042 "stk::mesh::TopologicalMetaData::entity_rank_names" ; 00043 00044 verify_spatial_dimension( spatial_dimension , method ); 00045 00046 std::vector< std::string > names ; 00047 00048 names.reserve( spatial_dimension + 1 ); 00049 00050 names.push_back( std::string( "NODE" ) ); 00051 00052 if ( 1 < spatial_dimension ) { names.push_back( std::string("EDGE") ); } 00053 if ( 2 < spatial_dimension ) { names.push_back( std::string("FACE") ); } 00054 00055 names.push_back( std::string("ELEMENT") ); 00056 names.push_back( std::string("PATCH") ); 00057 00058 return names ; 00059 } 00060 00061 const TopologicalMetaData * 00062 TopologicalMetaData::internal_get( const MetaData & meta_data ) 00063 { 00064 return meta_data.get_attribute< TopologicalMetaData >(); 00065 } 00066 00067 TopologicalMetaData::~TopologicalMetaData() 00068 { 00069 m_meta_data.remove_attribute( this ); 00070 } 00071 00072 TopologicalMetaData::TopologicalMetaData( 00073 MetaData & arg_meta_data , 00074 unsigned arg_spatial_dimension ) 00075 : spatial_dimension( arg_spatial_dimension ) 00076 , node_rank( 0 ) 00077 , edge_rank( 1 < spatial_dimension ? 1 : 0 ) 00078 , side_rank( 2 < spatial_dimension ? 2 : edge_rank ) 00079 , element_rank( spatial_dimension ) 00080 , patch_rank( spatial_dimension + 1 ) 00081 , m_meta_data( arg_meta_data ) 00082 , m_top_rank() 00083 , m_part_top_map() 00084 { 00085 static const char method[] = "stk::mesh::TopologicalMetaData::TopologicalMetaData" ; 00086 00087 verify_spatial_dimension( spatial_dimension , method ); 00088 00089 // Attach to the meta data 00090 m_meta_data.declare_attribute_no_delete< TopologicalMetaData >( this ); 00091 00092 // Load up appropriate standard cell topologies. 00093 00094 declare_cell_topology( shards::getCellTopologyData< shards::Node >() , 0 ); 00095 00096 declare_cell_topology( shards::getCellTopologyData< shards::Line<2> >() , 1 ); 00097 declare_cell_topology( shards::getCellTopologyData< shards::Line<3> >() , 1 ); 00098 00099 declare_cell_topology( shards::getCellTopologyData< shards::Particle >() , spatial_dimension ); 00100 00101 if ( 1 < spatial_dimension ) { 00102 declare_cell_topology( shards::getCellTopologyData< shards::Triangle<3> >() , 2 ); 00103 declare_cell_topology( shards::getCellTopologyData< shards::Triangle<6> >() , 2 ); 00104 declare_cell_topology( shards::getCellTopologyData< shards::Triangle<4> >() , 2 ); 00105 00106 declare_cell_topology( shards::getCellTopologyData< shards::Quadrilateral<4> >() , 2 ); 00107 declare_cell_topology( shards::getCellTopologyData< shards::Quadrilateral<8> >() , 2 ); 00108 declare_cell_topology( shards::getCellTopologyData< shards::Quadrilateral<9> >() , 2 ); 00109 00110 declare_cell_topology( shards::getCellTopologyData< shards::Beam<2> >() , spatial_dimension ); 00111 declare_cell_topology( shards::getCellTopologyData< shards::Beam<3> >() , spatial_dimension ); 00112 } 00113 00114 if ( 2 == spatial_dimension ) { 00115 declare_cell_topology( shards::getCellTopologyData< shards::ShellLine<2> >() , 2 ); 00116 declare_cell_topology( shards::getCellTopologyData< shards::ShellLine<3> >() , 2 ); 00117 } 00118 00119 if ( 2 < spatial_dimension ) { 00120 declare_cell_topology( shards::getCellTopologyData< shards::Tetrahedron<4> >() , 3 ); 00121 declare_cell_topology( shards::getCellTopologyData< shards::Tetrahedron<10> >() , 3 ); 00122 declare_cell_topology( shards::getCellTopologyData< shards::Tetrahedron<8> >() , 3 ); 00123 00124 declare_cell_topology( shards::getCellTopologyData< shards::Pyramid<5> >() , 3 ); 00125 declare_cell_topology( shards::getCellTopologyData< shards::Pyramid<13> >() , 3 ); 00126 declare_cell_topology( shards::getCellTopologyData< shards::Pyramid<14> >() , 3 ); 00127 00128 declare_cell_topology( shards::getCellTopologyData< shards::Wedge<6> >() , 3 ); 00129 declare_cell_topology( shards::getCellTopologyData< shards::Wedge<15> >() , 3 ); 00130 declare_cell_topology( shards::getCellTopologyData< shards::Wedge<18> >() , 3 ); 00131 00132 declare_cell_topology( shards::getCellTopologyData< shards::Hexahedron<8> >() , 3 ); 00133 declare_cell_topology( shards::getCellTopologyData< shards::Hexahedron<20> >() , 3 ); 00134 declare_cell_topology( shards::getCellTopologyData< shards::Hexahedron<27> >() , 3 ); 00135 00136 declare_cell_topology( shards::getCellTopologyData< shards::ShellTriangle<3> >() , 3 ); 00137 declare_cell_topology( shards::getCellTopologyData< shards::ShellTriangle<6> >() , 3 ); 00138 00139 declare_cell_topology( shards::getCellTopologyData< shards::ShellQuadrilateral<4> >() , 3 ); 00140 declare_cell_topology( shards::getCellTopologyData< shards::ShellQuadrilateral<8> >() , 3 ); 00141 declare_cell_topology( shards::getCellTopologyData< shards::ShellQuadrilateral<9> >() , 3 ); 00142 } 00143 } 00144 00145 //---------------------------------------------------------------------------- 00146 00147 EntityRank TopologicalMetaData::get_entity_rank( const CellTopologyData * top ) const 00148 { 00149 typedef std::pair< const CellTopologyData * , EntityRank > ValueType ; 00150 00151 std::vector< ValueType >::const_iterator i ; 00152 00153 for ( i = m_top_rank.begin() ; i != m_top_rank.end() && top != i->first ; ++i ); 00154 00155 if (i == m_top_rank.end()) { 00156 throw std::runtime_error("stk::mesh::TopologicalMetaData::get_entity_rank ERROR, topology not found."); 00157 } 00158 00159 return i->second ; 00160 } 00161 00162 void TopologicalMetaData::internal_set_entity_rank( const CellTopologyData * top , EntityRank rank ) 00163 { 00164 typedef std::pair< const CellTopologyData * , EntityRank > ValueType ; 00165 00166 m_top_rank.push_back( ValueType( top , rank ) ); 00167 } 00168 00169 //---------------------------------------------------------------------------- 00170 00171 void TopologicalMetaData::declare_cell_topology( 00172 const CellTopologyData * top , EntityRank rank ) 00173 { 00174 static const char method[] = "stk::mesh::TopologicalMetaData::declare_cell_topology" ; 00175 00176 typedef std::pair< const CellTopologyData * , EntityRank > ValueType ; 00177 00178 std::vector< ValueType >::const_iterator i = m_top_rank.begin() ; 00179 for ( ; i != m_top_rank.end() && top != i->first ; ++i ); 00180 00181 const bool duplicate = i != m_top_rank.end(); 00182 const EntityRank existing_rank = duplicate ? i->second : 0 ; 00183 00184 const bool error_change = duplicate && existing_rank != rank ; 00185 const bool error_rank = spatial_dimension < rank ; 00186 00187 if ( error_rank || error_change ) { 00188 std::ostringstream msg ; 00189 msg << method << "( " << top->name 00190 << " , rank = " << rank << " ) ERROR " ; 00191 if ( error_rank ) { 00192 msg << ": rank exceeds maximum spatial_dimension = " 00193 << spatial_dimension ; 00194 } 00195 if ( error_change ) { 00196 msg << ": previously declared rank = " << existing_rank ; 00197 } 00198 throw std::runtime_error( msg.str() ); 00199 } 00200 00201 if ( ! duplicate ) { 00202 internal_set_entity_rank( top , rank ); 00203 } 00204 } 00205 00206 //---------------------------------------------------------------------------- 00207 00208 Part & TopologicalMetaData::declare_part( 00209 const std::string & name , const CellTopologyData * top ) 00210 { 00211 //static const char method[] = "stk::mesh::TopologicalMetaData::declare_part" ; 00212 00213 EntityRank entity_rank; 00214 try { 00215 entity_rank = get_entity_rank( top ); 00216 } 00217 catch(std::runtime_error& /*x*/) { 00218 internal_set_entity_rank( top , top->dimension ); 00219 entity_rank = top->dimension ; 00220 } 00221 00222 Part & part = m_meta_data.declare_part( name , entity_rank ); 00223 00224 internal_set_cell_topology(part, entity_rank, top); 00225 return part ; 00226 } 00227 00228 //---------------------------------------------------------------------------- 00229 00230 void TopologicalMetaData::internal_set_cell_topology( 00231 Part & part, 00232 unsigned entity_rank, 00233 const CellTopologyData * top 00234 ) 00235 { 00236 static const char method[] = "stk::mesh::TopologicalMetaData::internal_set_cell_topology" ; 00237 typedef std::pair< PartOrdinal , const CellTopologyData * > ValueType ; 00238 ValueType value( part.mesh_meta_data_ordinal() , top ); 00239 00240 std::vector< ValueType >::iterator 00241 i = std::lower_bound( m_part_top_map.begin() , m_part_top_map.end() , value ); 00242 00243 const bool duplicate = i != m_part_top_map.end() && i->first == value.first ; 00244 const bool error_rank = part.primary_entity_rank() != entity_rank ; 00245 const bool error_top = duplicate && i->second != value.second ; 00246 00247 if ( error_rank || error_top ) { 00248 std::ostringstream msg ; 00249 msg << method << "( " << part.name() 00250 << " , " << top->name << " ) ERROR " ; 00251 if ( error_rank ) { 00252 msg << ": different entity_rank " << part.primary_entity_rank() 00253 << " != " << entity_rank ; 00254 } 00255 if ( error_top ) { 00256 msg << ": different topology " << i->second->name 00257 << " != " << top->name ; 00258 } 00259 throw msg.str(); 00260 } 00261 00262 if ( ! duplicate ) { 00263 m_part_top_map.insert( i , value ); 00264 } 00265 00266 } 00267 00268 //---------------------------------------------------------------------------- 00269 00270 const CellTopologyData * 00271 TopologicalMetaData::internal_get_cell_topology( PartOrdinal part_ordinal ) const 00272 { 00273 typedef std::pair< PartOrdinal , const CellTopologyData * > ValueType ; 00274 00275 ValueType tmp( part_ordinal , NULL ); 00276 00277 std::vector< ValueType >::const_iterator 00278 i = std::lower_bound( m_part_top_map.begin() , m_part_top_map.end() , tmp ); 00279 00280 return i != m_part_top_map.end() && i->first == part_ordinal ? i->second : NULL ; 00281 } 00282 00283 //---------------------------------------------------------------------------- 00284 00285 void TopologicalMetaData::throw_ambiguous( const Part & part ) const 00286 { 00287 static const char method[] = "stk::mesh::get_cell_topology" ; 00288 00289 const PartVector & supersets = part.supersets(); 00290 00291 std::ostringstream msg ; 00292 00293 msg << method << "( Part[" << part.name() 00294 << "] ) has ambiguous cell topology {" ; 00295 00296 for ( PartVector::const_iterator 00297 j = supersets.begin(); j != supersets.end() ; ++j ) { 00298 00299 const CellTopologyData * const top = 00300 internal_get_cell_topology( (*j)->mesh_meta_data_ordinal() ); 00301 00302 if ( top ) { 00303 msg << " ( Superset[" << (*j)->name() 00304 << "] -> " << top->name << " )" ; 00305 } 00306 } 00307 00308 msg << " }" ; 00309 throw std::runtime_error( msg.str() ); 00310 } 00311 00312 void TopologicalMetaData::throw_ambiguous( const Bucket & bucket ) const 00313 { 00314 static const char method[] = "stk::mesh::get_cell_topology" ; 00315 00316 const PartVector & all_parts = m_meta_data.get_parts(); 00317 00318 std::ostringstream msg ; 00319 00320 msg << method << "( Bucket ) has ambiguous cell topology {" ; 00321 00322 const std::pair< const unsigned * , const unsigned * > 00323 supersets = bucket.superset_part_ordinals(); 00324 00325 for ( const unsigned * j = supersets.first ; j != supersets.second ; ++j ) { 00326 const CellTopologyData * const top = 00327 internal_get_cell_topology( *j ); 00328 if ( top ) { 00329 msg << " ( Superset[" << all_parts[*j]->name() 00330 << "] -> " << top->name << " )" ; 00331 } 00332 } 00333 msg << " }" ; 00334 throw std::runtime_error( msg.str() ); 00335 } 00336 00337 void TopologicalMetaData::throw_required( const Part & part , 00338 const char * required_by ) 00339 { 00340 static const char method[] = "stk::mesh::get_cell_topology" ; 00341 00342 std::ostringstream msg ; 00343 00344 msg << required_by << " Failed to obtain cell topology from " 00345 << method << "( Part[" << part.name() << "] );" ; 00346 00347 throw std::runtime_error( msg.str() ); 00348 } 00349 00350 void TopologicalMetaData::throw_required( const Bucket & bucket , 00351 const char * required_by ) 00352 { 00353 static const char method[] = "stk::mesh::get_cell_topology" ; 00354 00355 std::ostringstream msg ; 00356 00357 msg << required_by << " Failed to obtain cell topology from " 00358 << method << "( Bucket[" ; 00359 00360 const BulkData & bulk_data = bucket.mesh(); 00361 const MetaData & meta_data = bulk_data.mesh_meta_data(); 00362 const PartVector & all_parts = meta_data.get_parts(); 00363 00364 const std::pair< const unsigned * , const unsigned * > 00365 supersets = bucket.superset_part_ordinals(); 00366 00367 for ( const unsigned * j = supersets.first ; j != supersets.second ; ++j ) { 00368 msg << " " << all_parts[*j]->name(); 00369 } 00370 00371 msg << " ] )" ; 00372 00373 throw std::runtime_error( msg.str() ); 00374 } 00375 00376 //---------------------------------------------------------------------------- 00377 00378 const CellTopologyData * 00379 TopologicalMetaData::get_cell_topology( const Part & part , 00380 const char * required_by ) 00381 { 00382 const TopologicalMetaData * const self = internal_get( part.mesh_meta_data() ); 00383 00384 const CellTopologyData * cell_top = NULL ; 00385 00386 if ( self ) { 00387 cell_top = self->internal_get_cell_topology( part.mesh_meta_data_ordinal() ); 00388 00389 if ( ! cell_top ) { 00390 const PartVector & supersets = part.supersets(); 00391 00392 for ( PartVector::const_iterator 00393 j = supersets.begin(); j != supersets.end() ; ++j ) { 00394 00395 const CellTopologyData * const top = 00396 self->internal_get_cell_topology( (*j)->mesh_meta_data_ordinal() ); 00397 00398 if ( ! cell_top ) { 00399 cell_top = top ; 00400 } 00401 else if ( top && top != cell_top ) { 00402 self->throw_ambiguous( part ); 00403 } 00404 } 00405 } 00406 } 00407 00408 if ( ! cell_top && required_by ) { 00409 throw_required( part , required_by ); 00410 } 00411 00412 return cell_top ; 00413 } 00414 00415 //---------------------------------------------------------------------------- 00416 00417 const CellTopologyData * 00418 TopologicalMetaData::get_cell_topology( const Bucket & bucket , 00419 const char * required_by ) 00420 { 00421 const BulkData & bulk_data = bucket.mesh(); 00422 const MetaData & meta_data = bulk_data.mesh_meta_data(); 00423 const PartVector & all_parts = meta_data.get_parts(); 00424 00425 const TopologicalMetaData * const self = internal_get( meta_data ); 00426 00427 const CellTopologyData * cell_top = NULL ; 00428 00429 if ( self ) { 00430 const std::pair< const unsigned * , const unsigned * > 00431 supersets = bucket.superset_part_ordinals(); 00432 00433 for ( const unsigned * j = supersets.first ; j != supersets.second ; ++j ) { 00434 00435 const Part & part = * all_parts[*j] ; 00436 00437 if ( part.primary_entity_rank() == bucket.entity_rank() ) { 00438 00439 const CellTopologyData * const top = 00440 self->internal_get_cell_topology( *j ); 00441 00442 if ( ! cell_top ) { 00443 cell_top = top ; 00444 } 00445 else if ( top && top != cell_top ) { 00446 self->throw_ambiguous( bucket ); 00447 } 00448 } 00449 } 00450 } 00451 00452 if ( ! cell_top && required_by ) { 00453 throw_required( bucket , required_by ); 00454 } 00455 00456 return cell_top ; 00457 } 00458 00459 //---------------------------------------------------------------------------- 00460 00461 const CellTopologyData * 00462 TopologicalMetaData::get_cell_topology( const Entity & entity , 00463 const char * required_by ) 00464 { 00465 return get_cell_topology( entity.bucket(), required_by ); 00466 } 00467 00468 } 00469 } 00470