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