Sierra Toolkit Version of the Day
FieldBaseImpl.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 <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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends