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 #include <stk_mesh/base/Trace.hpp>
00024 
00025 namespace stk {
00026 namespace mesh {
00027 namespace impl {
00028 
00029 //----------------------------------------------------------------------
00030 
00031 namespace {
00032 
00033 FieldRestrictionVector::const_iterator
00034   find( const FieldRestrictionVector & v , const FieldRestriction & restr )
00035 {
00036   FieldRestrictionVector::const_iterator
00037     i = std::lower_bound( v.begin() , v.end() , restr );
00038 
00039   if ( i != v.end() && !(*i == restr) ) { i = v.end(); }
00040 
00041   return i ;
00042 }
00043 
00044 }
00045 
00046 //----------------------------------------------------------------------
00047 
00048 FieldBaseImpl::FieldBaseImpl(
00049     MetaData                   * arg_mesh_meta_data ,
00050     unsigned                     arg_ordinal ,
00051     const std::string          & arg_name ,
00052     const DataTraits           & arg_traits ,
00053     unsigned                     arg_rank,
00054     const shards::ArrayDimTag  * const * arg_dim_tags,
00055     unsigned                     arg_number_of_states ,
00056     FieldState                   arg_this_state
00057     )
00058 : m_name( arg_name ),
00059   m_attribute(),
00060   m_data_traits( arg_traits ),
00061   m_meta_data( arg_mesh_meta_data ),
00062   m_ordinal( arg_ordinal ),
00063   m_num_states( arg_number_of_states ),
00064   m_this_state( arg_this_state ),
00065   m_rank( arg_rank ),
00066   m_dim_map()
00067 {
00068   TraceIfWatching("stk::mesh::impl::FieldBaseImpl::FieldBaseImpl", LOG_FIELD, m_ordinal);
00069 
00070   FieldBase * const pzero = NULL ;
00071   const shards::ArrayDimTag * const dzero = NULL ;
00072   Copy<MaximumFieldStates>(    m_field_states , pzero );
00073   Copy<MaximumFieldDimension>( m_dim_tags ,     dzero );
00074 
00075   for ( unsigned i = 0 ; i < arg_rank ; ++i ) {
00076     m_dim_tags[i] = arg_dim_tags[i];
00077   }
00078 }
00079 
00080 const FieldRestrictionVector & FieldBaseImpl::restrictions() const
00081 { return m_field_states[0]->m_impl.m_dim_map ; }
00082 
00083 FieldRestrictionVector & FieldBaseImpl::restrictions()
00084 { return m_field_states[0]->m_impl.m_dim_map ; }
00085 
00086 
00087 //----------------------------------------------------------------------
00088 
00089 // Setting the dimension for one field sets the dimension
00090 // for the corresponding fields of the FieldState array.
00091 // If subset exists then replace it.
00092 // If exists or superset exists then do nothing.
00093 
00094 void FieldBaseImpl::insert_restriction(
00095   const char     * arg_method ,
00096   EntityRank       arg_entity_rank ,
00097   const Part     & arg_part ,
00098   const unsigned * arg_stride )
00099 {
00100   TraceIfWatching("stk::mesh::impl::FieldBaseImpl::insert_restriction", LOG_FIELD, m_ordinal);
00101 
00102   FieldRestriction tmp( arg_entity_rank , arg_part.mesh_meta_data_ordinal() );
00103 
00104   {
00105     unsigned i = 0 ;
00106     if ( m_rank ) {
00107       for ( i = 0 ; i < m_rank ; ++i ) { tmp.stride(i) = arg_stride[i] ; }
00108     }
00109     else { // Scalar field is 0 == m_rank
00110       i = 1 ;
00111       tmp.stride(0) = 1 ;
00112     }
00113     // Remaining dimensions are 1, no change to stride
00114     for ( ; i < MaximumFieldDimension ; ++i ) {
00115       tmp.stride(i) = tmp.stride(i-1) ;
00116     }
00117 
00118     for ( i = 1 ; i < m_rank ; ++i ) {
00119       const bool bad_stride = 0 == tmp.stride(i) ||
00120                               0 != tmp.stride(i) % tmp.stride(i-1);
00121       ThrowErrorMsgIf( bad_stride,
00122           arg_method << " FAILED for " << *this <<
00123           " WITH BAD STRIDE " <<
00124           print_restriction( tmp, arg_entity_rank, arg_part, m_rank ));;
00125     }
00126   }
00127 
00128   {
00129     FieldRestrictionVector & rMap = restrictions();
00130 
00131     FieldRestrictionVector::iterator restr = rMap.begin();
00132     FieldRestrictionVector::iterator last_restriction = rMap.end();
00133 
00134     restr = std::lower_bound(restr,last_restriction,tmp);
00135 
00136     const bool new_restriction = ( ( restr == last_restriction ) || !(*restr == tmp) );
00137 
00138     if ( new_restriction ) {
00139       // New field restriction, verify we are not committed:
00140       ThrowRequireMsg(!m_meta_data->is_commit(), "mesh MetaData has been committed.");
00141       rMap.insert( restr , tmp );
00142     }
00143     else {
00144       ThrowErrorMsgIf( restr->not_equal_stride(tmp),
00145           arg_method << " FAILED for " << *this << " " <<
00146           print_restriction( *restr, arg_entity_rank, arg_part, m_rank ) <<
00147           " WITH INCOMPATIBLE REDECLARATION " <<
00148           print_restriction( tmp, arg_entity_rank, arg_part, m_rank ));
00149     }
00150   }
00151 }
00152 
00153 void FieldBaseImpl::verify_and_clean_restrictions(
00154   const char       * arg_method ,
00155   const PartVector & arg_all_parts )
00156 {
00157   TraceIfWatching("stk::mesh::impl::FieldBaseImpl::verify_and_clean_restrictions", LOG_FIELD, m_ordinal);
00158 
00159   const FieldRestriction invalid_restr ;
00160   FieldRestrictionVector & rMap = restrictions();
00161 
00162   // Search for redundant field restrictions. A restriction R is redundant if there exists
00163   // another restriction on a superset of R's part that is for entities of the same rank as R.
00164   for (FieldRestrictionVector::iterator i = rMap.begin() ; i != rMap.end() ; ++i ) {
00165     if ( *i != invalid_restr ) {
00166       const EntityRank rankI = i->entity_rank();
00167       const Part     & partI = * arg_all_parts[ i->part_ordinal() ];
00168       bool    found_superset = false ;
00169 
00170       for (FieldRestrictionVector::iterator j = i + 1 ; j != rMap.end() && ! found_superset ; ++j ) {
00171         if ( *j != invalid_restr ) {
00172           const EntityRank rankJ = j->entity_rank();
00173           const Part     & partJ = * arg_all_parts[ j->part_ordinal() ];
00174 
00175           if ( rankI == rankJ ) {
00176             const bool found_subset = contain( partI.subsets() , partJ );
00177             found_superset = ! found_subset &&
00178                              contain( partI.supersets() , partJ );
00179 
00180             if ( found_subset || found_superset ) {
00181               ThrowErrorMsgIf( i->not_equal_stride(*j),
00182                   arg_method << "[" << *this << "] FAILED: " <<
00183                   print_restriction( *i, rankI, partI, m_rank ) <<
00184                   ( found_subset ? " INCOMPATIBLE SUBSET " : " INCOMPATIBLE SUPERSET ") <<
00185                   print_restriction( *j, rankJ, partJ, m_rank ));
00186             }
00187 
00188             if ( found_subset ) { *j = invalid_restr; }
00189           }
00190         }
00191         if ( found_superset ) { *i = invalid_restr; }
00192       }
00193     }
00194   }
00195 
00196   // Clean out redundant entries:
00197   FieldRestrictionVector::iterator new_end = std::remove(rMap.begin(), rMap.end(), invalid_restr);
00198   rMap.erase(new_end, rMap.end());
00199 }
00200 
00201 
00202 //----------------------------------------------------------------------
00203 //----------------------------------------------------------------------
00204 // This part or any superset of this part
00205 
00206 const FieldRestriction &
00207 FieldBaseImpl::restriction( unsigned entity_rank , const Part & part ) const
00208 {
00209   static const FieldRestriction empty ;
00210 
00211   const FieldRestrictionVector & rMap = restrictions();
00212   const FieldRestrictionVector::const_iterator ie = rMap.end() ;
00213         FieldRestrictionVector::const_iterator i ;
00214 
00215   const PartVector::const_iterator ipe = part.supersets().end();
00216         PartVector::const_iterator ip  = part.supersets().begin() ;
00217 
00218   // Start with this part:
00219   FieldRestriction restr( entity_rank , part.mesh_meta_data_ordinal() );
00220 
00221   while ( ie == ( i = find( rMap , restr ) ) && ipe != ip ) {
00222     // Not found try another superset part:
00223     restr = FieldRestriction( entity_rank , (*ip)->mesh_meta_data_ordinal() );
00224     ++ip ;
00225   }
00226 
00227   return ie == i ? empty : *i ;
00228 }
00229 
00230 unsigned FieldBaseImpl::max_size( unsigned entity_rank ) const
00231 {
00232   unsigned max = 0 ;
00233 
00234   const FieldRestrictionVector & rMap = restrictions();
00235   const FieldRestrictionVector::const_iterator ie = rMap.end() ;
00236         FieldRestrictionVector::const_iterator i = rMap.begin();
00237 
00238   for ( ; i != ie ; ++i ) {
00239     if ( i->entity_rank() == entity_rank ) {
00240       const unsigned len = m_rank ? i->stride( m_rank - 1 ) : 1 ;
00241       if ( max < len ) { max = len ; }
00242     }
00243   }
00244 
00245   return max ;
00246 }
00247 
00248 void FieldBaseImpl::set_field_states( FieldBase ** field_states)
00249 {
00250   TraceIfWatching("stk::mesh::impl::FieldBaseImpl::set_field_states", LOG_FIELD, m_ordinal);
00251 
00252   for (unsigned i = 0; i < m_num_states; ++i) {
00253     m_field_states[i] = field_states[i];
00254   }
00255 }
00256 
00257 //----------------------------------------------------------------------
00258 
00259 //----------------------------------------------------------------------
00260 
00261 std::ostream & operator << ( std::ostream & s , const FieldBaseImpl & field )
00262 {
00263   s << "FieldBaseImpl<" ;
00264   s << field.data_traits().name ;
00265   for ( unsigned i = 0 ; i < field.rank() ; ++i ) {
00266     s << "," << field.dimension_tags()[i]->name();
00267   }
00268   s << ">" ;
00269 
00270   s << "[ name = \"" ;
00271   s << field.name() ;
00272   s << "\" , #states = " ;
00273   s << field.number_of_states();
00274   s << " ]" ;
00275   return s ;
00276 }
00277 
00278 std::ostream & print( std::ostream & s ,
00279                       const char * const b ,
00280                       const FieldBase & field )
00281 {
00282   const PartVector & all_parts = MetaData::get(field).get_parts();
00283   const std::vector<FieldBase::Restriction> & rMap = field.restrictions();
00284   s << field.name() ;
00285   s << " {" ;
00286   for ( FieldBase::RestrictionVector::const_iterator
00287         i = rMap.begin() ; i != rMap.end() ; ++i ) {
00288     s << std::endl << b << "  " ;
00289     i->print( s, i->entity_rank(), * all_parts[ i->part_ordinal() ], field.rank() );
00290     s << std::endl;
00291   }
00292   s << std::endl << b << "}" ;
00293   return s ;
00294 }
00295 
00296 //----------------------------------------------------------------------
00297 
00298 
00299 
00300 
00301 } // namespace impl
00302 } // namespace mesh
00303 } // namespace stk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends