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