|
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 <string.h> 00014 #include <stdexcept> 00015 #include <iostream> 00016 #include <sstream> 00017 #include <algorithm> 00018 00019 #include <stk_util/util/string_case_compare.hpp> 00020 #include <stk_util/parallel/ParallelComm.hpp> 00021 #include <stk_util/parallel/ParallelReduce.hpp> 00022 #include <stk_mesh/base/MetaData.hpp> 00023 #include <stk_mesh/base/Comm.hpp> 00024 00025 00026 #include <stk_mesh/baseImpl/FieldRepository.hpp> 00027 00028 namespace stk { 00029 namespace mesh { 00030 00031 //---------------------------------------------------------------------- 00032 00033 void MetaData::assert_not_committed( const char * method ) const 00034 { 00035 if ( m_commit ) { 00036 std::string msg ; 00037 msg.append( method ) 00038 .append( " FAILED: mesh MetaData has been committed." ); 00039 throw std::logic_error( msg ); 00040 } 00041 } 00042 00043 void MetaData::assert_committed( const char * method ) const 00044 { 00045 if ( ! m_commit ) { 00046 std::string msg ; 00047 msg.append( method ) 00048 .append( " FAILED: mesh MetaData has not been committed." ); 00049 throw std::logic_error( msg ); 00050 } 00051 } 00052 00053 void MetaData::assert_same_mesh_meta_data( const char * method , 00054 const MetaData & rhs ) const 00055 { 00056 if ( this != & rhs ) { 00057 std::string msg ; 00058 msg.append( method ) 00059 .append( " FAILED: Different mesh_meta_data." ); 00060 throw std::logic_error( msg ); 00061 } 00062 } 00063 00064 void MetaData::assert_entity_rank( const char * method , 00065 unsigned rank ) const 00066 { 00067 if ( m_entity_rank_names.size() <= rank ) { 00068 std::ostringstream msg ; 00069 msg << method ; 00070 msg << " FAILED: entity_rank( " << rank ; 00071 msg << " ) >= maximum_value( " << m_entity_rank_names.size(); 00072 msg << " )" ; 00073 throw std::logic_error( msg.str() ); 00074 } 00075 } 00076 00077 //---------------------------------------------------------------------- 00078 00079 MetaData::MetaData(const std::vector<std::string>& entity_rank_names) 00080 : m_commit( false ), 00081 m_part_repo( this ), 00082 m_attributes(), 00083 m_universal_part( NULL ), 00084 m_owns_part( NULL ), 00085 m_shares_part( NULL ), 00086 m_field_repo(), 00087 m_field_relations( ), 00088 m_properties( ), 00089 m_entity_rank_names( entity_rank_names ) 00090 { 00091 if ( entity_rank_names.empty() ) { 00092 std::string msg( "stk::mesh::MetaData constructor FAILED: no entity types" ); 00093 throw std::runtime_error( msg ); 00094 } 00095 00096 // Declare the predefined parts 00097 00098 m_universal_part = m_part_repo.universal_part(); 00099 m_owns_part = & declare_part( std::string("{OWNS}") ); 00100 m_shares_part = & declare_part( std::string("{SHARES}") ); 00101 } 00102 00103 //---------------------------------------------------------------------- 00104 00105 const std::string& MetaData::entity_rank_name( unsigned ent_type ) const 00106 { 00107 if (ent_type >= m_entity_rank_names.size()) { 00108 std::ostringstream msg; 00109 msg << "Error in MetaData::entity_rank_name: entity-type (" << ent_type 00110 << ") out of range. Must be in range [0 .. " << m_entity_rank_names.size() 00111 << ")."; 00112 throw std::runtime_error( msg.str() ); 00113 } 00114 00115 return m_entity_rank_names[ent_type]; 00116 } 00117 00118 //---------------------------------------------------------------------- 00119 00120 Part * MetaData::get_part( const std::string & p_name , 00121 const char * required_by ) const 00122 { 00123 const PartVector & all_parts = m_universal_part->subsets(); 00124 00125 Part * const p = find( all_parts , p_name ); 00126 00127 if ( required_by && NULL == p ) { // ERROR 00128 static const char method[] = "stk::mesh::MetaData::get_part" ; 00129 std::string msg ; 00130 msg.append( method ) 00131 .append( "( " ) 00132 .append( p_name ) 00133 .append( " , " ) 00134 .append( required_by ) 00135 .append( " ) FAILED to find part" ); 00136 throw std::runtime_error( msg ); 00137 } 00138 00139 return p ; 00140 } 00141 00142 Part & MetaData::declare_part( const std::string & p_name ) 00143 { 00144 static const char method[] = "stk::mesh::MetaData::declare_part" ; 00145 00146 const unsigned rank = std::numeric_limits<unsigned>::max(); 00147 00148 assert_not_committed( method ); 00149 00150 return *m_part_repo.declare_part( p_name, rank ); 00151 } 00152 00153 00154 Part & MetaData::declare_part( const std::string & p_name , EntityRank rank ) 00155 { 00156 static const char method[] = "stk::mesh::MetaData::declare_part" ; 00157 00158 assert_not_committed( method ); 00159 assert_entity_rank( method , rank ); 00160 00161 return *m_part_repo.declare_part( p_name , rank ); 00162 } 00163 00164 namespace { 00165 00166 void assert_not_relation_target( 00167 const char * const method , 00168 const Part * const part ) 00169 { 00170 std::vector<PartRelation>::const_iterator i_end = part->relations().end(); 00171 std::vector<PartRelation>::const_iterator i = part->relations().begin(); 00172 for ( ; i != i_end ; ++i ) { 00173 if ( part == i->m_target ) { 00174 std::string msg ; 00175 msg.append( method ); 00176 msg.append( "(...) FAILED Requirement that Part[" ); 00177 msg.append( part->name() ); 00178 msg.append( "] is not a PartRelation target" ); 00179 throw std::runtime_error(msg); 00180 } 00181 } 00182 } 00183 00184 } 00185 00186 Part & MetaData::declare_part( const PartVector & part_intersect ) 00187 { 00188 static const char method[] = "stk::mesh::MetaData::declare_part" ; 00189 00190 assert_not_committed( method ); 00191 00192 for ( PartVector::const_iterator 00193 i = part_intersect.begin() ; i != part_intersect.end() ; ++i ) { 00194 assert_not_relation_target( method , *i ); 00195 } 00196 00197 return *m_part_repo.declare_part( part_intersect ); 00198 } 00199 00200 void MetaData::declare_part_subset( Part & superset , Part & subset ) 00201 { 00202 static const char method[] = "stk::mesh::MetaData::declare_part_subset" ; 00203 00204 assert_not_committed( method ); 00205 assert_same_mesh_meta_data( method , superset.mesh_meta_data() ); 00206 assert_same_mesh_meta_data( method , subset.mesh_meta_data() ); 00207 assert_not_relation_target( method , & superset ); 00208 assert_not_relation_target( method , & subset ); 00209 00210 m_part_repo.declare_subset( superset, subset ); 00211 00212 // The new superset / subset relationship can cause a 00213 // field restriction to become incompatible or redundant. 00214 m_field_repo.verify_and_clean_restrictions( method , m_part_repo.all_parts() ); 00215 } 00216 00217 void MetaData::declare_part_relation( 00218 Part & root_part , 00219 relation_stencil_ptr stencil , 00220 Part & target_part ) 00221 { 00222 static const char method[] = "stk::mesh::MetaData::declare_part_relation" ; 00223 00224 assert_not_committed( method ); 00225 assert_not_relation_target( method , & root_part ); 00226 00227 if (!stencil) { 00228 std::string msg ; 00229 msg.append( method ); 00230 msg.append( "stencil function pointer cannott be NULL" ); 00231 throw std::runtime_error( msg ); 00232 } 00233 00234 if ( 0 != target_part.subsets().size() || 00235 0 != target_part.intersection_of().size() || 00236 1 != target_part.supersets().size() ) { 00237 std::string msg ; 00238 msg.append( method ); 00239 msg.append( ": FAILED Requirement that target Part[" ); 00240 msg.append( target_part.name() ); 00241 msg.append( "] is not a superset or subset" ); 00242 throw std::runtime_error( msg ); 00243 } 00244 00245 PartRelation tmp ; 00246 tmp.m_root = & root_part ; 00247 tmp.m_target = & target_part ; 00248 tmp.m_function = stencil ; 00249 00250 m_part_repo.declare_part_relation( root_part, tmp, target_part ); 00251 } 00252 00253 //---------------------------------------------------------------------- 00254 00255 FieldBase * 00256 MetaData::declare_field_base( 00257 const std::string & arg_name , 00258 const DataTraits & arg_traits , 00259 unsigned arg_rank , 00260 const shards::ArrayDimTag * const * arg_dim_tags , 00261 unsigned arg_num_states ) 00262 { 00263 static const char method[] = "std::mesh::MetaData::declare_field" ; 00264 00265 assert_not_committed( method ); 00266 00267 return m_field_repo.declare_field( 00268 arg_name, 00269 arg_traits, 00270 arg_rank, 00271 arg_dim_tags, 00272 arg_num_states, 00273 this 00274 ); 00275 } 00276 00277 void MetaData::declare_field_restriction( 00278 FieldBase & arg_field , 00279 unsigned arg_entity_rank , 00280 const Part & arg_part , 00281 const unsigned * arg_stride ) 00282 { 00283 static const char method[] = 00284 "std::mesh::MetaData::declare_field_restriction" ; 00285 00286 assert_not_committed( method ); 00287 assert_same_mesh_meta_data( method , arg_field.mesh_meta_data() ); 00288 assert_same_mesh_meta_data( method , arg_part.mesh_meta_data() ); 00289 00290 m_field_repo.declare_field_restriction( 00291 method, 00292 arg_field, 00293 arg_entity_rank, 00294 arg_part, 00295 m_part_repo.all_parts(), 00296 arg_stride 00297 ); 00298 } 00299 00300 00301 void MetaData::internal_declare_field_relation( 00302 FieldBase & pointer_field , 00303 relation_stencil_ptr stencil , 00304 FieldBase & referenced_field ) 00305 { 00306 FieldRelation tmp ; 00307 tmp.m_root = & pointer_field ; 00308 tmp.m_target = & referenced_field ; 00309 tmp.m_function = stencil ; 00310 00311 m_field_relations.push_back( tmp ); 00312 } 00313 00314 //---------------------------------------------------------------------- 00315 00316 void MetaData::commit() 00317 { 00318 static const char method[] = "stk::mesh::MetaData::commit" ; 00319 00320 assert_not_committed( method ); 00321 00322 m_commit = true ; // Cannot add or change parts or fields now 00323 } 00324 00325 MetaData::~MetaData() 00326 { 00327 // Destroy the properties, used 'new' to allocate so now use 'delete' 00328 00329 try { 00330 std::vector<PropertyBase * >::iterator j = m_properties.begin(); 00331 00332 for ( ; j != m_properties.end() ; ++j ) { delete *j ; } 00333 00334 m_properties.clear(); 00335 } catch(...) {} 00336 00337 // PartRepository is member data 00338 // FieldRepository is member data 00339 } 00340 00341 //---------------------------------------------------------------------- 00342 //---------------------------------------------------------------------- 00343 // Verify parallel consistency of fields and parts 00344 00345 namespace { 00346 00347 void pack( CommBuffer & b , const PartVector & pset ) 00348 { 00349 PartVector::const_iterator i , j ; 00350 for ( i = pset.begin() ; i != pset.end() ; ++i ) { 00351 const Part & p = **i ; 00352 const PartVector & subsets = p.subsets(); 00353 const PartVector & intersect = p.intersection_of(); 00354 00355 const size_t name_len = p.name().size() + 1 ; 00356 const char * const name_ptr = p.name().c_str(); 00357 00358 { 00359 const unsigned ord = p.mesh_meta_data_ordinal(); 00360 b.pack<unsigned>( ord ); 00361 } 00362 00363 b.pack<unsigned>( name_len ); 00364 b.pack<char>( name_ptr , name_len ); 00365 00366 const unsigned subset_size = static_cast<unsigned>(subsets.size()); 00367 b.pack<unsigned>( subset_size ); 00368 for ( j = subsets.begin() ; j != subsets.end() ; ++j ) { 00369 const Part & s = **j ; 00370 const unsigned ord = s.mesh_meta_data_ordinal(); 00371 b.pack<unsigned>( ord ); 00372 } 00373 const unsigned intersect_size = static_cast<unsigned>(intersect.size()); 00374 b.pack<unsigned>( intersect_size ); 00375 for ( j = intersect.begin() ; j != intersect.end() ; ++j ) { 00376 const Part & s = **j ; 00377 const unsigned ord = s.mesh_meta_data_ordinal(); 00378 b.pack<unsigned>( ord ); 00379 } 00380 } 00381 } 00382 00383 bool unpack_verify( CommBuffer & b , const PartVector & pset ) 00384 { 00385 enum { MAX_TEXT_LEN = 4096 }; 00386 char b_text[ MAX_TEXT_LEN ]; 00387 unsigned b_tmp = 0; 00388 00389 bool ok = true ; 00390 PartVector::const_iterator i , j ; 00391 for ( i = pset.begin() ; ok && i != pset.end() ; ++i ) { 00392 const Part & p = **i ; 00393 const PartVector & subsets = p.subsets(); 00394 const PartVector & intersect = p.intersection_of(); 00395 const unsigned name_len = static_cast<unsigned>(p.name().size()) + 1 ; 00396 const char * const name_ptr = p.name().c_str(); 00397 00398 if ( ok ) { 00399 b.unpack<unsigned>( b_tmp ); 00400 ok = b_tmp == p.mesh_meta_data_ordinal(); 00401 } 00402 00403 if ( ok ) { 00404 b.unpack<unsigned>( b_tmp ); 00405 ok = b_tmp == name_len ; 00406 } 00407 if ( ok ) { 00408 b.unpack<char>( b_text , name_len ); 00409 ok = 0 == strcmp( name_ptr , b_text ); 00410 } 00411 00412 if ( ok ) { 00413 b.unpack<unsigned>( b_tmp ); 00414 ok = b_tmp == subsets.size() ; 00415 } 00416 for ( j = subsets.begin() ; ok && j != subsets.end() ; ++j ) { 00417 const Part & s = **j ; 00418 b.unpack<unsigned>( b_tmp ); 00419 ok = b_tmp == s.mesh_meta_data_ordinal(); 00420 } 00421 00422 if ( ok ) { 00423 b.unpack<unsigned>( b_tmp ); 00424 ok = b_tmp == intersect.size(); 00425 } 00426 for ( j = intersect.begin() ; ok && j != intersect.end() ; ++j ) { 00427 const Part & s = **j ; 00428 b.unpack<unsigned>( b_tmp ); 00429 ok = b_tmp == s.mesh_meta_data_ordinal(); 00430 } 00431 } 00432 return ok ; 00433 } 00434 00435 void pack( CommBuffer & , 00436 const std::vector< FieldBase * > & ) 00437 { 00438 } 00439 00440 bool unpack_verify( CommBuffer & , 00441 const std::vector< FieldBase * > & ) 00442 { 00443 bool ok = true ; 00444 return ok ; 00445 } 00446 00447 } 00448 00449 //---------------------------------------------------------------------- 00450 00451 void verify_parallel_consistency( const MetaData & s , ParallelMachine pm ) 00452 { 00453 static const char method[] = "stk::mesh::verify_parallel_consistency(MetaData)" ; 00454 00455 const unsigned p_rank = parallel_machine_rank( pm ); 00456 00457 const bool is_root = 0 == p_rank ; 00458 00459 CommBroadcast comm( pm , 0 ); 00460 00461 if ( is_root ) { 00462 pack( comm.send_buffer() , s.get_parts() ); 00463 pack( comm.send_buffer() , s.get_fields() ); 00464 } 00465 00466 comm.allocate_buffer(); 00467 00468 if ( is_root ) { 00469 pack( comm.send_buffer() , s.get_parts() ); 00470 pack( comm.send_buffer() , s.get_fields() ); 00471 } 00472 00473 comm.communicate(); 00474 00475 int ok[ 2 ]; 00476 00477 ok[0] = unpack_verify( comm.recv_buffer() , s.get_parts() ); 00478 ok[1] = unpack_verify( comm.recv_buffer() , s.get_fields() ); 00479 00480 all_reduce( pm , ReduceMin<2>( ok ) ); 00481 00482 if ( ! ok[0] || ! ok[1] ) { 00483 std::ostringstream msg ; 00484 msg << "P" << p_rank ; 00485 msg << ": " << method ; 00486 msg << " : FAILED for:" ; 00487 if ( ! ok[0] ) { msg << " Parts" ; } 00488 if ( ! ok[1] ) { msg << " Fields" ; } 00489 throw std::logic_error( msg.str() ); 00490 } 00491 } 00492 00493 00494 //---------------------------------------------------------------------- 00495 00496 00497 00498 } // namespace mesh 00499 } // namespace stk 00500