Sierra Toolkit Version of the Day
MetaData.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 <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 {
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 {
00123   ThrowErrorMsgIf( entity_rank_names.empty(), "entity ranks empty" );
00124 
00125   // Declare the predefined parts
00126 
00127   m_universal_part = m_part_repo.universal_part();
00128   m_owns_part = & declare_part( std::string("{OWNS}") );
00129   m_shares_part = & declare_part( std::string("{SHARES}") );
00130 }
00131 
00132 MetaData::MetaData()
00133   : m_commit( false ),
00134     m_part_repo( this ),
00135     m_attributes(),
00136     m_universal_part( NULL ),
00137     m_owns_part( NULL ),
00138     m_shares_part( NULL ),
00139     m_field_repo(),
00140     m_field_relations( ),
00141     m_properties( ),
00142     m_entity_rank_names( )
00143 {
00144   // Declare the predefined parts
00145 
00146   m_universal_part = m_part_repo.universal_part();
00147   m_owns_part = & declare_part( std::string("{OWNS}") );
00148   m_shares_part = & declare_part( std::string("{SHARES}") );
00149 }
00150 
00151 //----------------------------------------------------------------------
00152 
00153 void MetaData::set_entity_rank_names(const std::vector<std::string> &entity_rank_names)
00154 {
00155   ThrowErrorMsgIf( entity_rank_names.empty(), "entity ranks empty" );
00156 
00157   m_entity_rank_names = entity_rank_names;
00158 }
00159 
00160 const std::string& MetaData::entity_rank_name( EntityRank entity_rank ) const
00161 {
00162   ThrowErrorMsgIf( entity_rank >= m_entity_rank_names.size(),
00163       "entity-rank " << entity_rank <<
00164       " out of range. Must be in range 0.." << m_entity_rank_names.size());
00165 
00166   return m_entity_rank_names[entity_rank];
00167 }
00168 
00169 EntityRank MetaData::entity_rank( const std::string &name ) const
00170 {
00171   EntityRank entity_rank = InvalidEntityRank;
00172 
00173   for (size_t i = 0; i < m_entity_rank_names.size(); ++i)
00174     if (equal_case(name, m_entity_rank_names[i])) {
00175       entity_rank = i;
00176       break;
00177     }
00178   return entity_rank;
00179 }
00180 
00181 //----------------------------------------------------------------------
00182 
00183 Part * MetaData::get_part( const std::string & p_name ,
00184                            const char * required_by ) const
00185 {
00186   const PartVector & all_parts = m_part_repo.get_all_parts();
00187 
00188   Part * const p = find( all_parts , p_name );
00189 
00190   ThrowErrorMsgIf( required_by && NULL == p,
00191                    "Failed to find part with name " << p_name <<
00192                    " for method " << required_by );
00193 
00194   return p ;
00195 }
00196 
00197 Part & MetaData::declare_part( const std::string & p_name )
00198 {
00199   require_not_committed();
00200 
00201   const EntityRank rank = InvalidEntityRank;
00202 
00203   return *m_part_repo.declare_part( p_name, rank );
00204 }
00205 
00206 
00207 Part & MetaData::declare_part( const std::string & p_name , EntityRank rank )
00208 {
00209   require_not_committed();
00210   require_valid_entity_rank(rank);
00211 
00212   return *m_part_repo.declare_part( p_name , rank );
00213 }
00214 
00215 Part & MetaData::declare_part( const PartVector & part_intersect )
00216 {
00217   require_not_committed();
00218 
00219   for ( PartVector::const_iterator
00220         i = part_intersect.begin() ; i != part_intersect.end() ; ++i ) {
00221     require_not_relation_target(*i);
00222   }
00223 
00224   return *m_part_repo.declare_part( part_intersect );
00225 }
00226 
00227 void MetaData::declare_part_subset( Part & superset , Part & subset )
00228 {
00229   static const char method[] = "stk::mesh::MetaData::declare_part_subset" ;
00230 
00231   require_not_committed();
00232   require_same_mesh_meta_data( MetaData::get(superset) );
00233   require_same_mesh_meta_data( MetaData::get(subset) );
00234   require_not_relation_target( &superset );
00235   require_not_relation_target( &subset );
00236 
00237   m_part_repo.declare_subset( superset, subset );
00238 
00239   // The new superset / subset relationship can cause a
00240   // field restriction to become incompatible or redundant.
00241   m_field_repo.verify_and_clean_restrictions(method, m_part_repo.get_all_parts());
00242 }
00243 
00244 void MetaData::declare_part_relation(
00245   Part & root_part ,
00246   relation_stencil_ptr stencil ,
00247   Part & target_part )
00248 {
00249   require_not_committed();
00250   require_not_relation_target( &root_part );
00251 
00252   ThrowErrorMsgIf( !stencil, "stencil function pointer cannot be NULL" );
00253 
00254   ThrowErrorMsgIf( 0 != target_part.subsets().size() ||
00255                    0 != target_part.intersection_of().size() ||
00256                    1 != target_part.supersets().size(),
00257                    "target Part[" << target_part.name() <<
00258                    "] cannot be a superset or subset" );
00259 
00260   PartRelation tmp ;
00261   tmp.m_root = & root_part ;
00262   tmp.m_target = & target_part ;
00263   tmp.m_function = stencil ;
00264 
00265   m_part_repo.declare_part_relation( root_part, tmp, target_part );
00266 }
00267 
00268 //----------------------------------------------------------------------
00269 
00270 FieldBase *
00271 MetaData::declare_field_base(
00272   const std::string & arg_name ,
00273   const DataTraits  & arg_traits ,
00274   unsigned            arg_rank ,
00275   const shards::ArrayDimTag * const * arg_dim_tags ,
00276   unsigned            arg_num_states )
00277 {
00278   require_not_committed();
00279 
00280   return m_field_repo.declare_field(
00281                 arg_name,
00282                 arg_traits,
00283                 arg_rank,
00284                 arg_dim_tags,
00285                 arg_num_states,
00286                 this
00287                );
00288 }
00289 
00290 void MetaData::declare_field_restriction(
00291   FieldBase      & arg_field ,
00292   EntityRank       arg_entity_rank ,
00293   const Part     & arg_part ,
00294   const unsigned * arg_stride )
00295 {
00296   static const char method[] =
00297     "std::mesh::MetaData::declare_field_restriction" ;
00298 
00299   //require_not_committed(); // Moved to FieldBaseImpl::declare_field_restriction
00300   require_same_mesh_meta_data( MetaData::get(arg_field) );
00301   require_same_mesh_meta_data( MetaData::get(arg_part) );
00302 
00303   m_field_repo.declare_field_restriction(
00304       method,
00305       arg_field,
00306       arg_entity_rank,
00307       arg_part,
00308       m_part_repo.get_all_parts(),
00309       arg_stride
00310       );
00311 }
00312 
00313 
00314 void MetaData::internal_declare_field_relation(
00315   FieldBase & pointer_field ,
00316   relation_stencil_ptr stencil ,
00317   FieldBase & referenced_field )
00318 {
00319   FieldRelation tmp ;
00320   tmp.m_root   = & pointer_field ;
00321   tmp.m_target = & referenced_field ;
00322   tmp.m_function = stencil ;
00323 
00324   m_field_relations.push_back( tmp );
00325 }
00326 
00327 //----------------------------------------------------------------------
00328 
00329 void MetaData::commit()
00330 {
00331   require_not_committed();
00332 
00333   m_commit = true ; // Cannot add or change parts or fields now
00334 }
00335 
00336 MetaData::~MetaData()
00337 {
00338   // Destroy the properties, used 'new' to allocate so now use 'delete'
00339 
00340   try {
00341     std::vector<PropertyBase * >::iterator j = m_properties.begin();
00342 
00343     for ( ; j != m_properties.end() ; ++j ) { delete *j ; }
00344 
00345     m_properties.clear();
00346   } catch(...) {}
00347 
00348   // PartRepository is member data
00349   // FieldRepository is member data
00350 }
00351 
00352 //----------------------------------------------------------------------
00353 //----------------------------------------------------------------------
00354 // Verify parallel consistency of fields and parts
00355 
00356 namespace {
00357 
00358 void pack( CommBuffer & b , const PartVector & pset )
00359 {
00360   PartVector::const_iterator i , j ;
00361   for ( i = pset.begin() ; i != pset.end() ; ++i ) {
00362     const Part & p = **i ;
00363     const PartVector & subsets   = p.subsets();
00364     const PartVector & intersect = p.intersection_of();
00365 
00366     const size_t       name_len = p.name().size() + 1 ;
00367     const char * const name_ptr = p.name().c_str();
00368 
00369     {
00370       const unsigned ord = p.mesh_meta_data_ordinal();
00371       b.pack<unsigned>( ord );
00372     }
00373 
00374     b.pack<unsigned>( name_len );
00375     b.pack<char>( name_ptr , name_len );
00376 
00377     const unsigned subset_size = static_cast<unsigned>(subsets.size());
00378     b.pack<unsigned>( subset_size );
00379     for ( j = subsets.begin() ; j != subsets.end() ; ++j ) {
00380       const Part & s = **j ;
00381       const unsigned ord = s.mesh_meta_data_ordinal();
00382       b.pack<unsigned>( ord );
00383     }
00384     const unsigned intersect_size = static_cast<unsigned>(intersect.size());
00385     b.pack<unsigned>( intersect_size );
00386     for ( j = intersect.begin() ; j != intersect.end() ; ++j ) {
00387       const Part & s = **j ;
00388       const unsigned ord = s.mesh_meta_data_ordinal();
00389       b.pack<unsigned>( ord );
00390     }
00391   }
00392 }
00393 
00394 bool unpack_verify( CommBuffer & b , const PartVector & pset )
00395 {
00396   enum { MAX_TEXT_LEN = 4096 };
00397   char b_text[ MAX_TEXT_LEN ];
00398   unsigned b_tmp = 0;
00399 
00400   bool ok = true ;
00401   PartVector::const_iterator i , j ;
00402   for ( i = pset.begin() ; ok && i != pset.end() ; ++i ) {
00403     const Part & p = **i ;
00404     const PartVector & subsets   = p.subsets();
00405     const PartVector & intersect = p.intersection_of();
00406     const unsigned     name_len = static_cast<unsigned>(p.name().size()) + 1 ;
00407     const char * const name_ptr = p.name().c_str();
00408 
00409     if ( ok ) {
00410       b.unpack<unsigned>( b_tmp );
00411       ok = b_tmp == p.mesh_meta_data_ordinal();
00412     }
00413 
00414     if ( ok ) {
00415       b.unpack<unsigned>( b_tmp );
00416       ok = b_tmp == name_len ;
00417     }
00418     if ( ok ) {
00419       b.unpack<char>( b_text , name_len );
00420       ok = 0 == strcmp( name_ptr , b_text );
00421     }
00422 
00423     if ( ok ) {
00424       b.unpack<unsigned>( b_tmp );
00425       ok = b_tmp == subsets.size() ;
00426     }
00427     for ( j = subsets.begin() ; ok && j != subsets.end() ; ++j ) {
00428       const Part & s = **j ;
00429       b.unpack<unsigned>( b_tmp );
00430       ok = b_tmp == s.mesh_meta_data_ordinal();
00431     }
00432 
00433     if ( ok ) {
00434       b.unpack<unsigned>( b_tmp );
00435       ok = b_tmp == intersect.size();
00436     }
00437     for ( j = intersect.begin() ; ok && j != intersect.end() ; ++j ) {
00438       const Part & s = **j ;
00439       b.unpack<unsigned>( b_tmp );
00440       ok = b_tmp == s.mesh_meta_data_ordinal();
00441     }
00442   }
00443   return ok ;
00444 }
00445 
00446 void pack( CommBuffer & ,
00447            const std::vector< FieldBase * > & )
00448 {
00449 }
00450 
00451 bool unpack_verify( CommBuffer & ,
00452                     const std::vector< FieldBase * > & )
00453 {
00454   bool ok = true ;
00455   return ok ;
00456 }
00457 
00458 }
00459 
00460 //----------------------------------------------------------------------
00461 
00462 void verify_parallel_consistency( const MetaData & s , ParallelMachine pm )
00463 {
00464   const unsigned p_rank = parallel_machine_rank( pm );
00465 
00466   const bool is_root = 0 == p_rank ;
00467 
00468   CommBroadcast comm( pm , 0 );
00469 
00470   if ( is_root ) {
00471     pack( comm.send_buffer() , s.get_parts() );
00472     pack( comm.send_buffer() , s.get_fields() );
00473   }
00474 
00475   comm.allocate_buffer();
00476 
00477   if ( is_root ) {
00478     pack( comm.send_buffer() , s.get_parts() );
00479     pack( comm.send_buffer() , s.get_fields() );
00480   }
00481 
00482   comm.communicate();
00483 
00484   int ok[ 2 ];
00485 
00486   ok[0] = unpack_verify( comm.recv_buffer() , s.get_parts() );
00487   ok[1] = unpack_verify( comm.recv_buffer() , s.get_fields() );
00488 
00489   all_reduce( pm , ReduceMin<2>( ok ) );
00490 
00491   ThrowRequireMsg(ok[0], "P" << p_rank << ": FAILED for Parts");
00492   ThrowRequireMsg(ok[1], "P" << p_rank << ": FAILED for Fields");
00493 }
00494 
00495 //----------------------------------------------------------------------
00496 
00497 } // namespace mesh
00498 } // namespace stk
00499 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends