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   const void     * arg_init_value )
00296 {
00297   static const char method[] =
00298     "std::mesh::MetaData::declare_field_restriction" ;
00299 
00300   //require_not_committed(); // Moved to FieldBaseImpl::declare_field_restriction
00301   require_same_mesh_meta_data( MetaData::get(arg_field) );
00302   require_same_mesh_meta_data( MetaData::get(arg_part) );
00303 
00304   m_field_repo.declare_field_restriction(
00305       method,
00306       arg_field,
00307       arg_entity_rank,
00308       arg_part,
00309       m_part_repo.get_all_parts(),
00310       arg_stride,
00311       arg_init_value
00312       );
00313 }
00314 
00315 
00316 void MetaData::internal_declare_field_relation(
00317   FieldBase & pointer_field ,
00318   relation_stencil_ptr stencil ,
00319   FieldBase & referenced_field )
00320 {
00321   FieldRelation tmp ;
00322   tmp.m_root   = & pointer_field ;
00323   tmp.m_target = & referenced_field ;
00324   tmp.m_function = stencil ;
00325 
00326   m_field_relations.push_back( tmp );
00327 }
00328 
00329 //----------------------------------------------------------------------
00330 
00331 void MetaData::commit()
00332 {
00333   require_not_committed();
00334 
00335   m_commit = true ; // Cannot add or change parts or fields now
00336 }
00337 
00338 MetaData::~MetaData()
00339 {
00340   // Destroy the properties, used 'new' to allocate so now use 'delete'
00341 
00342   try {
00343     std::vector<PropertyBase * >::iterator j = m_properties.begin();
00344 
00345     for ( ; j != m_properties.end() ; ++j ) { delete *j ; }
00346 
00347     m_properties.clear();
00348   } catch(...) {}
00349 
00350   // PartRepository is member data
00351   // FieldRepository is member data
00352 }
00353 
00354 //----------------------------------------------------------------------
00355 //----------------------------------------------------------------------
00356 // Verify parallel consistency of fields and parts
00357 
00358 namespace {
00359 
00360 void pack( CommBuffer & b , const PartVector & pset )
00361 {
00362   PartVector::const_iterator i , j ;
00363   for ( i = pset.begin() ; i != pset.end() ; ++i ) {
00364     const Part & p = **i ;
00365     const PartVector & subsets   = p.subsets();
00366     const PartVector & intersect = p.intersection_of();
00367 
00368     const size_t       name_len = p.name().size() + 1 ;
00369     const char * const name_ptr = p.name().c_str();
00370 
00371     {
00372       const unsigned ord = p.mesh_meta_data_ordinal();
00373       b.pack<unsigned>( ord );
00374     }
00375 
00376     b.pack<unsigned>( name_len );
00377     b.pack<char>( name_ptr , name_len );
00378 
00379     const unsigned subset_size = static_cast<unsigned>(subsets.size());
00380     b.pack<unsigned>( subset_size );
00381     for ( j = subsets.begin() ; j != subsets.end() ; ++j ) {
00382       const Part & s = **j ;
00383       const unsigned ord = s.mesh_meta_data_ordinal();
00384       b.pack<unsigned>( ord );
00385     }
00386     const unsigned intersect_size = static_cast<unsigned>(intersect.size());
00387     b.pack<unsigned>( intersect_size );
00388     for ( j = intersect.begin() ; j != intersect.end() ; ++j ) {
00389       const Part & s = **j ;
00390       const unsigned ord = s.mesh_meta_data_ordinal();
00391       b.pack<unsigned>( ord );
00392     }
00393   }
00394 }
00395 
00396 bool unpack_verify( CommBuffer & b , const PartVector & pset )
00397 {
00398   enum { MAX_TEXT_LEN = 4096 };
00399   char b_text[ MAX_TEXT_LEN ];
00400   unsigned b_tmp = 0;
00401 
00402   bool ok = true ;
00403   PartVector::const_iterator i , j ;
00404   for ( i = pset.begin() ; ok && i != pset.end() ; ++i ) {
00405     const Part & p = **i ;
00406     const PartVector & subsets   = p.subsets();
00407     const PartVector & intersect = p.intersection_of();
00408     const unsigned     name_len = static_cast<unsigned>(p.name().size()) + 1 ;
00409     const char * const name_ptr = p.name().c_str();
00410 
00411     if ( ok ) {
00412       b.unpack<unsigned>( b_tmp );
00413       ok = b_tmp == p.mesh_meta_data_ordinal();
00414     }
00415 
00416     if ( ok ) {
00417       b.unpack<unsigned>( b_tmp );
00418       ok = b_tmp == name_len ;
00419     }
00420     if ( ok ) {
00421       b.unpack<char>( b_text , name_len );
00422       ok = 0 == strcmp( name_ptr , b_text );
00423     }
00424 
00425     if ( ok ) {
00426       b.unpack<unsigned>( b_tmp );
00427       ok = b_tmp == subsets.size() ;
00428     }
00429     for ( j = subsets.begin() ; ok && j != subsets.end() ; ++j ) {
00430       const Part & s = **j ;
00431       b.unpack<unsigned>( b_tmp );
00432       ok = b_tmp == s.mesh_meta_data_ordinal();
00433     }
00434 
00435     if ( ok ) {
00436       b.unpack<unsigned>( b_tmp );
00437       ok = b_tmp == intersect.size();
00438     }
00439     for ( j = intersect.begin() ; ok && j != intersect.end() ; ++j ) {
00440       const Part & s = **j ;
00441       b.unpack<unsigned>( b_tmp );
00442       ok = b_tmp == s.mesh_meta_data_ordinal();
00443     }
00444   }
00445   return ok ;
00446 }
00447 
00448 void pack( CommBuffer & ,
00449            const std::vector< FieldBase * > & )
00450 {
00451 }
00452 
00453 bool unpack_verify( CommBuffer & ,
00454                     const std::vector< FieldBase * > & )
00455 {
00456   bool ok = true ;
00457   return ok ;
00458 }
00459 
00460 }
00461 
00462 //----------------------------------------------------------------------
00463 
00464 void verify_parallel_consistency( const MetaData & s , ParallelMachine pm )
00465 {
00466   const unsigned p_rank = parallel_machine_rank( pm );
00467 
00468   const bool is_root = 0 == p_rank ;
00469 
00470   CommBroadcast comm( pm , 0 );
00471 
00472   if ( is_root ) {
00473     pack( comm.send_buffer() , s.get_parts() );
00474     pack( comm.send_buffer() , s.get_fields() );
00475   }
00476 
00477   comm.allocate_buffer();
00478 
00479   if ( is_root ) {
00480     pack( comm.send_buffer() , s.get_parts() );
00481     pack( comm.send_buffer() , s.get_fields() );
00482   }
00483 
00484   comm.communicate();
00485 
00486   int ok[ 2 ];
00487 
00488   ok[0] = unpack_verify( comm.recv_buffer() , s.get_parts() );
00489   ok[1] = unpack_verify( comm.recv_buffer() , s.get_fields() );
00490 
00491   all_reduce( pm , ReduceMin<2>( ok ) );
00492 
00493   ThrowRequireMsg(ok[0], "P" << p_rank << ": FAILED for Parts");
00494   ThrowRequireMsg(ok[1], "P" << p_rank << ": FAILED for Fields");
00495 }
00496 
00497 //----------------------------------------------------------------------
00498 
00499 } // namespace mesh
00500 } // namespace stk
00501 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends