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