|
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 <stk_mesh/baseImpl/FieldBaseImpl.hpp> 00010 00011 #include <cstring> 00012 #include <stdexcept> 00013 #include <iostream> 00014 #include <sstream> 00015 #include <algorithm> 00016 00017 #include <stk_util/util/SimpleArrayOps.hpp> 00018 00019 #include <stk_mesh/base/Types.hpp> 00020 #include <stk_mesh/base/FieldBase.hpp> 00021 #include <stk_mesh/base/Part.hpp> 00022 #include <stk_mesh/base/MetaData.hpp> 00023 00024 namespace stk { 00025 namespace mesh { 00026 namespace impl { 00027 00028 //---------------------------------------------------------------------- 00029 00030 namespace { 00031 00032 struct FieldRestrictionLess { 00033 bool operator()( const FieldRestriction & lhs , 00034 const FieldRestriction & rhs ) const 00035 { return lhs.key < rhs.key ; } 00036 00037 bool operator()( const FieldRestriction & lhs , 00038 const EntityKey & rhs ) const 00039 { return lhs.key < rhs ; } 00040 }; 00041 00042 FieldRestrictionVector::const_iterator 00043 find( const FieldRestrictionVector & v , const EntityKey & key ) 00044 { 00045 FieldRestrictionVector::const_iterator 00046 i = std::lower_bound( v.begin() , v.end() , key , FieldRestrictionLess() ); 00047 00048 if ( i != v.end() && i->key != key ) { i = v.end(); } 00049 00050 return i ; 00051 } 00052 00053 } 00054 00055 //---------------------------------------------------------------------- 00056 00057 FieldBaseImpl::FieldBaseImpl( 00058 MetaData * arg_mesh_meta_data , 00059 unsigned arg_ordinal , 00060 const std::string & arg_name , 00061 const DataTraits & arg_traits , 00062 unsigned arg_rank, 00063 const shards::ArrayDimTag * const * arg_dim_tags, 00064 unsigned arg_number_of_states , 00065 FieldState arg_this_state 00066 ) 00067 : m_name( arg_name ), 00068 m_attribute(), 00069 m_data_traits( arg_traits ), 00070 m_meta_data( arg_mesh_meta_data ), 00071 m_ordinal( arg_ordinal ), 00072 m_num_states( arg_number_of_states ), 00073 m_this_state( arg_this_state ), 00074 m_rank( arg_rank ), 00075 m_dim_map() 00076 { 00077 FieldBase * const pzero = NULL ; 00078 const shards::ArrayDimTag * const dzero = NULL ; 00079 Copy<MaximumFieldStates>( m_field_states , pzero ); 00080 Copy<MaximumFieldDimension>( m_dim_tags , dzero ); 00081 00082 for ( unsigned i = 0 ; i < arg_rank ; ++i ) { 00083 m_dim_tags[i] = arg_dim_tags[i]; 00084 } 00085 } 00086 00087 const FieldRestrictionVector & FieldBaseImpl::restrictions() const 00088 { return m_field_states[0]->m_impl.m_dim_map ; } 00089 00090 FieldRestrictionVector & FieldBaseImpl::restrictions() 00091 { return m_field_states[0]->m_impl.m_dim_map ; } 00092 00093 00094 //---------------------------------------------------------------------- 00095 00096 namespace { 00097 00098 void print_restriction( std::ostream & os , 00099 unsigned type , 00100 const Part & part , 00101 unsigned rank , 00102 const FieldRestriction::size_type * stride ) 00103 { 00104 os << "{ entity_rank(" << type << ") part(" << part.name() << ") : " ; 00105 os << stride[0] ; 00106 for ( unsigned i = 1 ; i < rank ; ++i ) { 00107 if ( ! stride[i] ) { 00108 os << " , 0 " ; 00109 } 00110 else if ( stride[i] % stride[i-1] ) { 00111 os << " , " << stride[i] << " / " << stride[i-1] ; 00112 } 00113 else { 00114 os << " , " << stride[i] / stride[i-1] ; 00115 } 00116 } 00117 os << " }" ; 00118 } 00119 00120 } 00121 00122 00123 // Setting the dimension for one field sets the dimension 00124 // for the corresponding fields of the FieldState array. 00125 // If subset exists then replace it. 00126 // If exists or superset exists then do nothing. 00127 00128 void FieldBaseImpl::insert_restriction( 00129 const char * arg_method , 00130 EntityRank arg_entity_rank , 00131 const Part & arg_part , 00132 const unsigned * arg_stride ) 00133 { 00134 FieldRestriction tmp ; 00135 00136 tmp.key = EntityKey( arg_entity_rank , arg_part.mesh_meta_data_ordinal() ); 00137 00138 { 00139 unsigned i = 0 ; 00140 if ( m_rank ) { 00141 for ( i = 0 ; i < m_rank ; ++i ) { tmp.stride[i] = arg_stride[i] ; } 00142 } 00143 else { // Scalar field is 0 == m_rank 00144 i = 1 ; 00145 tmp.stride[0] = 1 ; 00146 } 00147 // Remaining dimensions are 1, no change to stride 00148 for ( ; i < MaximumFieldDimension ; ++i ) { 00149 tmp.stride[i] = tmp.stride[i-1] ; 00150 } 00151 00152 for ( i = 1 ; i < m_rank ; ++i ) { 00153 if ( 0 == tmp.stride[i] || 0 != tmp.stride[i] % tmp.stride[i-1] ) { 00154 std::ostringstream msg ; 00155 msg << arg_method << " FAILED for " << *this ; 00156 msg << " WITH BAD STRIDE " ; 00157 print_restriction( msg, arg_entity_rank, arg_part, m_rank, tmp.stride); 00158 throw std::runtime_error( msg.str() ); 00159 } 00160 } 00161 } 00162 00163 { 00164 FieldRestrictionVector & rMap = restrictions(); 00165 00166 FieldRestrictionVector::iterator i = rMap.begin(), j = rMap.end(); 00167 00168 i = std::lower_bound(i,j,tmp,FieldRestrictionLess()); 00169 00170 if ( i == j || i->key != tmp.key ) { 00171 rMap.insert( i , tmp ); 00172 } 00173 else if ( Compare<MaximumFieldDimension>::not_equal(i->stride,tmp.stride) ){ 00174 std::ostringstream msg ; 00175 msg << arg_method << " FAILED for " << *this << " " ; 00176 print_restriction( msg, arg_entity_rank, arg_part, m_rank, i->stride ); 00177 msg << " WITH INCOMPATIBLE REDECLARATION " ; 00178 print_restriction( msg, arg_entity_rank, arg_part, m_rank, tmp.stride ); 00179 throw std::runtime_error( msg.str() ); 00180 } 00181 } 00182 } 00183 00184 void FieldBaseImpl::verify_and_clean_restrictions( 00185 const char * arg_method , 00186 const PartVector & arg_all_parts ) 00187 { 00188 const EntityKey invalid_key ; 00189 FieldRestrictionVector & rMap = restrictions(); 00190 FieldRestrictionVector::iterator i , j ; 00191 00192 for ( i = rMap.begin() ; i != rMap.end() ; ++i ) { 00193 if ( i->key != invalid_key ) { 00194 const unsigned typeI = entity_rank( i->key ); 00195 const Part & partI = * arg_all_parts[ entity_id( i->key ) ]; 00196 bool found_superset = false ; 00197 00198 for ( j = i + 1 ; j != rMap.end() && ! found_superset ; ++j ) { 00199 if ( j->key != invalid_key ) { 00200 const unsigned typeJ = entity_rank( j->key ); 00201 const Part & partJ = * arg_all_parts[ entity_id( j->key ) ]; 00202 00203 if ( typeI == typeJ ) { 00204 const bool found_subset = contain( partI.subsets() , partJ ); 00205 found_superset = ! found_subset && 00206 contain( partI.supersets() , partJ ); 00207 00208 if ( found_subset || found_superset ) { 00209 if ( Compare< MaximumFieldDimension >::not_equal( i->stride , 00210 j->stride ) ) { 00211 std::ostringstream msg ; 00212 msg << arg_method << "[" ; 00213 msg << *this ; 00214 msg << "] FAILED: " ; 00215 print_restriction( msg, typeI, partI, m_rank, i->stride ); 00216 if ( found_subset ) { msg << " INCOMPATIBLE SUBSET " ; } 00217 else { msg << " INCOMPATIBLE SUPERSET " ; } 00218 print_restriction( msg, typeJ, partJ, m_rank, j->stride ); 00219 throw std::runtime_error( msg.str() ); 00220 } 00221 } 00222 00223 if ( found_subset ) { j->key = invalid_key; } 00224 } 00225 } 00226 if ( found_superset ) { i->key = invalid_key; } 00227 } 00228 } 00229 } 00230 00231 // Clean out redundant entries: 00232 // NOTE: test for 'i != rMap.end()' not needed since i is 00233 // incremented no more than j and j is checked. Keeping check in 00234 // silences klocwork and guards against future change... 00235 for ( j = i = rMap.begin() ; j != rMap.end() && i != rMap.end(); ++j ) { 00236 if ( j->key != invalid_key ) { 00237 if ( i->key == invalid_key ) { 00238 *i = *j ; 00239 } 00240 ++i ; 00241 } 00242 } 00243 00244 rMap.erase( i , j ); 00245 } 00246 00247 00248 //---------------------------------------------------------------------- 00249 //---------------------------------------------------------------------- 00250 // This part or any superset of this part 00251 00252 const FieldRestriction & 00253 FieldBaseImpl::restriction( unsigned entity_rank , const Part & part ) const 00254 { 00255 static const FieldRestriction empty ; 00256 00257 const FieldRestrictionVector & rMap = restrictions(); 00258 const FieldRestrictionVector::const_iterator ie = rMap.end() ; 00259 FieldRestrictionVector::const_iterator i ; 00260 00261 const PartVector::const_iterator ipe = part.supersets().end(); 00262 PartVector::const_iterator ip = part.supersets().begin() ; 00263 00264 // Start with this part: 00265 EntityKey key = EntityKey( entity_rank , part.mesh_meta_data_ordinal() ); 00266 00267 while ( ie == ( i = find( rMap , key ) ) && ipe != ip ) { 00268 // Not found try another superset part: 00269 key = EntityKey( entity_rank , (*ip)->mesh_meta_data_ordinal() ); 00270 ++ip ; 00271 } 00272 00273 return ie == i ? empty : *i ; 00274 } 00275 00276 unsigned FieldBaseImpl::max_size( unsigned entity_rank ) const 00277 { 00278 unsigned max = 0 ; 00279 00280 const FieldRestrictionVector & rMap = restrictions(); 00281 const FieldRestrictionVector::const_iterator ie = rMap.end() ; 00282 FieldRestrictionVector::const_iterator i = rMap.begin(); 00283 00284 for ( ; i != ie ; ++i ) { 00285 if ( i->type() == entity_rank ) { 00286 const unsigned len = m_rank ? i->stride[ m_rank - 1 ] : 1 ; 00287 if ( max < len ) { max = len ; } 00288 } 00289 } 00290 00291 return max ; 00292 } 00293 00294 //---------------------------------------------------------------------- 00295 00296 //---------------------------------------------------------------------- 00297 00298 std::ostream & operator << ( std::ostream & s , const FieldBaseImpl & field ) 00299 { 00300 s << "FieldBaseImpl<" ; 00301 s << field.data_traits().name ; 00302 for ( unsigned i = 0 ; i < field.rank() ; ++i ) { 00303 s << "," << field.dimension_tags()[i]->name(); 00304 } 00305 s << ">" ; 00306 00307 s << "[ name = \"" ; 00308 s << field.name() ; 00309 s << "\" , #states = " ; 00310 s << field.number_of_states(); 00311 s << " ]" ; 00312 return s ; 00313 } 00314 00315 std::ostream & print( std::ostream & s , 00316 const char * const b , 00317 const FieldBase & field ) 00318 { 00319 const PartVector & all_parts = field.mesh_meta_data().get_parts(); 00320 const std::vector<FieldBase::Restriction> & rMap = field.restrictions(); 00321 s << field.name() ; 00322 s << " {" ; 00323 for ( FieldBase::RestrictionVector::const_iterator 00324 i = rMap.begin() ; i != rMap.end() ; ++i ) { 00325 s << std::endl << b << " " ; 00326 print_restriction( s, entity_rank( i->key ), 00327 * all_parts[ entity_id( i->key ) ], 00328 field.rank(), i->stride); 00329 s << std::endl; 00330 } 00331 s << std::endl << b << "}" ; 00332 return s ; 00333 } 00334 00335 //---------------------------------------------------------------------- 00336 00337 00338 00339 00340 } // namespace impl 00341 } // namespace mesh 00342 } // namespace stk