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