|
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_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_classic { 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_classic::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_classic::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_classic::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_classic::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_classic 00323