|
Sierra Toolkit Version of the Day
|
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