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     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::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
00538 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines