Sierra Toolkit Version of the Day
PartRepository.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 
00009 #include <stdexcept>
00010 #include <sstream>
00011 
00012 #include <stk_mesh/base/Part.hpp>
00013 #include <stk_mesh/base/Types.hpp>
00014 #include <stk_mesh/baseImpl/PartRepository.hpp>
00015 
00016 
00017 #include <stdlib.h>
00018 
00019 #include <iostream>
00020 
00021 namespace stk {
00022 namespace mesh {
00023 namespace impl {
00024 
00025 namespace {
00026 
00027 const char * universal_part_name()
00028 {
00029   static const char name[] = "{UNIVERSAL}" ;
00030   return name ;
00031 }
00032 
00033 void append_part_method(
00034   std::string & msg , const Part & part , const char * method )
00035 {
00036   msg.append( "stk::mesh::Part[" );
00037   msg.append( part.name() );
00038   msg.append( "]." );
00039   msg.append( method );
00040 }
00041 
00042 
00043 void assert_contain( Part & superset , Part & subset , const char * method )
00044 {
00045   if ( ! contain( subset.supersets() , superset ) ) {
00046     std::string msg ;
00047     append_part_method( msg , superset , method );
00048     msg.append( "(...) FAILED Requirement that " );
00049     msg.append( "Part[" );
00050     msg.append( subset.name() );
00051     msg.append( "] is a subset" );
00052     throw std::runtime_error(msg);
00053   }
00054 }
00055 
00056 void assert_same_universe( const Part & part_superset ,
00057                            const char * method ,
00058                            const Part & part_subset )
00059 {
00060   const PartVector & a = part_superset.supersets();
00061   const PartVector & b = part_subset.supersets();
00062 
00063   if ( a.empty() || b.empty() || a[0] != b[0] ) {
00064     std::string msg ;
00065     append_part_method( msg , part_superset , method );
00066     msg.append( "(...) FAILED Requirement that Part[" );
00067     msg.append( part_subset.name() );
00068     msg.append( "] are in the same " );
00069     msg.append( universal_part_name() );
00070     throw std::runtime_error(msg);
00071   }
00072 }
00073 
00074 void assert_not_same( const Part & part ,
00075                       const char * method ,
00076                       const Part & arg_part )
00077 {
00078   if ( & part == & arg_part ) {
00079     std::string msg ;
00080     append_part_method( msg , part , method );
00081     msg.append( "(...) FAILED Requirement that Part[" );
00082     msg.append( arg_part.name() );
00083     msg.append( "] is not the same" );
00084     throw std::runtime_error(msg);
00085   }
00086 }
00087 
00088 void assert_same( const Part & part ,
00089                       const char * method ,
00090                       const Part & arg_part )
00091 {
00092   if ( & part != & arg_part ) {
00093     std::string msg ;
00094     append_part_method( msg , part , method );
00095     msg.append( "(...) FAILED Requirement that Part[" );
00096     msg.append( arg_part.name() );
00097     msg.append( "] is the same" );
00098     throw std::runtime_error(msg);
00099   }
00100 }
00101 
00102 void assert_not_superset( const Part & part ,
00103                           const char * method ,
00104                           const Part & arg_part )
00105 {
00106   if ( contain( part.supersets() , arg_part ) ) {
00107     std::string msg ;
00108     append_part_method( msg , part , method );
00109     msg.append( "(...) FAILED Requirement that Part[" );
00110     msg.append( arg_part.name() );
00111     msg.append( "] is not a superset" );
00112     throw std::runtime_error(msg);
00113   }
00114 }
00115 
00116 void assert_rank_ordering( const Part & superset ,
00117                            const char * method ,
00118                            const Part & subset )
00119 {
00120   if ( superset.primary_entity_rank() < subset.primary_entity_rank() ) {
00121     std::ostringstream msg ;
00122     msg << "stk::mesh::Part[ " << superset.name();
00123     msg << " , rank(" << superset.primary_entity_rank();
00124     msg << ") ]." << method ;
00125     msg << "( Part[ " << subset.name();
00126     msg << " , rank(" << subset.primary_entity_rank();
00127     msg << ") ] ) FAILED Rank ordering requirement" ;
00128     throw std::runtime_error( msg.str() );
00129   }
00130 }
00131 
00132 } // namespace
00133 
00134 
00135 Part * PartRepository::universal_part() const
00136 {
00137   return m_universal_part;
00138 }
00139 
00140 const PartVector & PartRepository::all_parts() const
00141 {
00142   return m_universal_part->subsets();
00143 }
00144 
00145 Part * PartRepository::declare_part( const std::string & arg_name , EntityRank arg_rank )
00146 {
00147   const PartVector & all_parts = m_universal_part->subsets();
00148   Part * p = find( all_parts, arg_name );
00149 
00150   if ( p == NULL ) {
00151     p = declare_part_impl( arg_name, arg_rank );
00152   }
00153 
00154   if ( p->primary_entity_rank() != arg_rank ) {
00155     std::ostringstream msg;
00156     msg << "stk::mesh::Part[ " << arg_name ;
00157     msg << ",rank(" << p->primary_entity_rank() << ")" ;
00158     msg << "] : FAILED to declare part; " ;
00159     msg << "Part of name '" << arg_name ;
00160     msg << "' of rank " << p->primary_entity_rank() ;
00161     msg << " already exists";
00162     msg << " User cannot redeclare " << arg_name ;
00163     msg << " with different rank, " << arg_rank ;
00164     throw std::runtime_error ( msg.str() );
00165   }
00166 
00167   return p;
00168 }
00169 
00170 Part * PartRepository::declare_part( const PartVector & part_intersect )
00171 {
00172   static const char method[] = "stk::mesh::PartRepository::declare_part" ;
00173 
00174   PartVector pset_clean ;
00175 
00176   for ( PartVector::const_iterator
00177         i = part_intersect.begin() ; i != part_intersect.end() ; ++i ) {
00178     Part * const p = *i ;
00179     assert_contain( *m_universal_part, *p , method );
00180 
00181     // If 'p' is a superset of another member
00182     // then it is redundant in this intersection.
00183     // Only keep non-redundant intersections.
00184 
00185     PartVector::const_iterator j = part_intersect.begin();
00186     for ( ; j != part_intersect.end() &&
00187             ! contain( (*j)->supersets() , *p ) ; ++j );
00188     if ( j == part_intersect.end() ) {
00189       pset_clean.push_back( p );
00190     }
00191   }
00192 
00193   // Sort and unique the intersection
00194   order( pset_clean );
00195 
00196   Part * p = NULL ;
00197   if ( 1 == pset_clean.size() ) {
00198     // Only one remaining part, it is the subset.
00199     p = pset_clean[0] ;
00200   }
00201   else {
00202     const char separator[] = "^" ;
00203     // Generate a name and rank reflecting the intersection.
00204     // Rank is the minimum rank of the intersection members.
00205 
00206     std::string p_name ;
00207     EntityRank p_rank = std::numeric_limits<EntityRank>::max();
00208 
00209     p_name.assign("{");
00210     for ( PartVector::iterator
00211           i = pset_clean.begin() ; i != pset_clean.end() ; ++i ) {
00212       if ( i != pset_clean.begin() ) { p_name.append( separator ); }
00213       p_name.append( (*i)->name() );
00214       if ( (*i)->primary_entity_rank() < p_rank ) {
00215         p_rank = (*i)->primary_entity_rank();
00216       }
00217     }
00218     p_name.append("}");
00219 
00220     const PartVector & all_parts = m_universal_part->subsets();
00221     p = find( all_parts, p_name );
00222     if ( p == NULL ) {
00223       // Create the part:
00224 
00225       p = new Part( m_meta_data , p_name , p_rank , all_parts.size() );
00226       declare_subset_impl( *m_universal_part, *p );
00227 
00228       // Define the part to be an intersection of the given parts:
00229 
00230       p->m_partImpl.set_intersection_of( pset_clean );
00231 
00232       for ( PartVector::iterator
00233             i = pset_clean.begin() ; i != pset_clean.end() ; ++i ) {
00234         declare_subset( **i, *p );
00235       }
00236     }
00237     else if ( pset_clean != p->intersection_of()) {
00238       // This error is "inconceivable" and is
00239       // only possible by heroic malicious abuse.
00240       std::string msg ;
00241       msg.append(method).append(p_name).append(" FAILED FROM MALICIOUS ABUSE");
00242       throw std::invalid_argument(msg);
00243     }
00244   }
00245 
00246   return p ;
00247 }
00248 
00249 
00250 Part * PartRepository::declare_part_impl( const std::string & name, EntityRank rank)
00251 {
00252   size_t ordinal = m_universal_part->subsets().size();
00253   Part * part = new Part(m_meta_data,name,rank,ordinal);
00254   declare_subset_impl(*m_universal_part, *part);
00255   return part;
00256 }
00257 
00258 
00259 void PartRepository::declare_subset_impl( Part & superset_part, Part & subset_part )
00260 {
00261   superset_part.m_partImpl.add_part_to_subset( subset_part );
00262   subset_part.m_partImpl.add_part_to_superset( superset_part );
00263 }
00264 
00265 
00266 void PartRepository::declare_subset( Part & superset, Part & subset )
00267 {
00268   static const char method[] = "stk::mesh::PartRepository::declare_subset" ;
00269 
00270   if ( ! contain( subset.supersets() , superset ) ) {
00271 
00272     assert_not_same( superset , method , subset );
00273     assert_not_superset(  superset , method , subset );
00274     assert_same_universe( superset , method , subset );
00275     assert_rank_ordering( superset , method , subset );
00276 
00277     // Insert this symmetric relationship first
00278     // so that it does not get revisited.
00279 
00280     declare_subset_impl( superset, subset );
00281 
00282     // Transitive:
00283 
00284     const PartVector & subset_subsets = subset.subsets();
00285     for ( PartVector::const_iterator
00286           i =  subset_subsets.begin() ; i != subset_subsets.end() ; ++i ) {
00287       declare_subset( superset, **i );
00288     }
00289 
00290     const PartVector & superset_supersets = superset.supersets();
00291     for ( PartVector::const_iterator
00292           i =  superset_supersets.begin() ; i != superset_supersets.end() ; ++i ) {
00293       declare_subset( **i, subset );
00294     }
00295 
00296     // Induced intersection-part membership:
00297 
00298     const PartVector & superset_subsets = superset.subsets();
00299     for ( PartVector::const_iterator
00300           i =  superset_subsets.begin() ;
00301           i != superset_subsets.end() ; ++i ) {
00302 
00303       Part & pint = **i ;
00304 
00305       if ( ! pint.intersection_of().empty() && ( & pint != & subset ) ) {
00306 
00307         // If 'subset' is a subset of every member of 'pint.intersection_of()'
00308         // then it is by definition a subset of 'pint.
00309         if ( contain( subset.supersets() , pint.intersection_of() ) ) {
00310           declare_subset( pint, subset );
00311         }
00312       }
00313     }
00314   }
00315 }
00316 
00317 
00318 void PartRepository::declare_part_relation( Part & root_part, PartRelation relation, Part & target_part )
00319 {
00320   static const char method[] = "stk::mesh::PartRepository::declare_part_relation" ;
00321 
00322   assert_not_same( root_part , method , target_part );
00323   assert_same_universe( root_part, method, target_part );
00324   assert_same( root_part, method, *relation.m_root );
00325   assert_same( target_part, method, *relation.m_target );
00326 
00327   root_part.m_partImpl.add_relation( relation );
00328   target_part.m_partImpl.add_relation( relation );
00329 }
00330 
00331 
00332 PartRepository::PartRepository(MetaData * meta)
00333   : m_meta_data(meta)
00334 {
00335   m_universal_part = new Part( m_meta_data, universal_part_name(), ~0u, 0 );
00336   m_universal_part->m_partImpl.add_part_to_subset(*m_universal_part);
00337 }
00338 
00339 PartRepository::~PartRepository()
00340 {
00341   // The universal part is the 0^th entry in the subset vector.
00342   // Delete all but the universal part in the loop, deleting
00343   // the universal part will invalidate the universal part subset vector.
00344   // Thus delete the universal part outside of the loop.
00345 
00346   try {
00347     for ( PartVector::const_iterator
00348           i = m_universal_part->subsets().end() ;
00349           --i != m_universal_part->subsets().begin() ; ) {
00350       Part * part = *i ;
00351       try { delete part ; } catch(...) {}
00352     }
00353     try { delete m_universal_part ; } catch(...) {}
00354     m_universal_part = NULL ;
00355   } catch(...){}
00356 }
00357 
00358 } // namespace impl 
00359 } // namespace mesh 
00360 } // namespace stk 
00361 
00362 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends