Sierra Toolkit Version of the Day
FieldRepository.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/base/Trace.hpp>
00010 
00011 #include <stk_mesh/baseImpl/FieldRepository.hpp>
00012 
00013 #include <stk_util/util/string_case_compare.hpp>
00014 
00015 #include <cstring>
00016 #include <sstream>
00017 #include <stdexcept>
00018 
00019 namespace stk {
00020 namespace mesh {
00021 namespace impl {
00022 
00023 namespace {
00024 
00025 std::string print_field_type(const DataTraits                  & arg_traits ,
00026                              unsigned                            arg_rank ,
00027                              const shards::ArrayDimTag * const * arg_tags )
00028 {
00029   std::ostringstream oss;
00030   oss << "FieldBase<" ;
00031   oss << arg_traits.name ;
00032   for ( unsigned i = 0 ; i < arg_rank ; ++i ) {
00033     oss << "," << arg_tags[i]->name();
00034   }
00035   oss << ">" ;
00036   return oss.str();
00037 }
00038 
00039 // Check for compatibility:
00040 // 1) Scalar type must match
00041 // 2) Number of states must match
00042 // 3) Dimension must be different by at most one rank,
00043 //    where the tags match for the smaller rank.
00044 void verify_field_type( const char                        * arg_method ,
00045                         const FieldBase                   & arg_field ,
00046                         const DataTraits                  & arg_traits ,
00047                         unsigned                            arg_rank ,
00048                         const shards::ArrayDimTag * const * arg_dim_tags ,
00049                         unsigned                    arg_num_states )
00050 {
00051 
00052   const bool ok_traits = arg_traits.is_void
00053                       || & arg_traits == & arg_field.data_traits();
00054 
00055   const bool ok_number_states =
00056     ! arg_num_states || arg_num_states == arg_field.number_of_states();
00057 
00058   bool ok_dimension = ! arg_rank || arg_rank     == arg_field.rank() ||
00059                                     arg_rank + 1 == arg_field.rank() ||
00060                                     arg_rank - 1 == arg_field.rank() ;
00061 
00062   const unsigned check_rank = arg_rank < arg_field.rank() ?
00063                               arg_rank : arg_field.rank() ;
00064 
00065   for ( unsigned i = 0 ; i < check_rank && ok_dimension ; ++i ) {
00066     ok_dimension = arg_dim_tags[i] == arg_field.dimension_tags()[i] ;
00067   }
00068 
00069   ThrowErrorMsgIf( ! ok_traits || ! ok_number_states || ! ok_dimension,
00070                    arg_method << " FAILED: Existing field = " <<
00071                    print_field_type( arg_field.data_traits() ,
00072                                      arg_field.rank() ,
00073                                      arg_field.dimension_tags() ) <<
00074                    "[ name = \"" << arg_field.name() <<
00075                    "\" , #states = " << arg_field.number_of_states() << " ]" <<
00076                    " Expected field info = " <<
00077                    print_field_type( arg_traits , arg_rank , arg_dim_tags ) <<
00078                    "[ #states = " << arg_num_states << " ]");
00079 }
00080 
00081 } //unamed namespace
00082 
00083 //----------------------------------------------------------------------
00084 
00085 FieldBase * FieldRepository::get_field(
00086   const char                        * arg_method ,
00087   const std::string                 & arg_name ,
00088   const DataTraits                  & arg_traits ,
00089   unsigned                            arg_rank ,
00090   const shards::ArrayDimTag * const * arg_dim_tags ,
00091   unsigned                            arg_num_states ) const
00092 {
00093   FieldBase * f = NULL ;
00094 
00095   for ( std::vector<FieldBase*>::const_iterator
00096         j =  m_fields.begin() ;
00097         j != m_fields.end() && NULL == f ; ++j ) {
00098     if ( equal_case( (*j)->name() , arg_name ) ) {
00099 
00100       f = *j ;
00101 
00102       verify_field_type( arg_method , *f , arg_traits ,
00103                          arg_rank , arg_dim_tags , arg_num_states );
00104     }
00105   }
00106   return f ;
00107 }
00108 
00109 FieldBase * FieldRepository::declare_field(
00110   const std::string                 & arg_name ,
00111   const DataTraits                  & arg_traits ,
00112   unsigned                            arg_rank ,
00113   const shards::ArrayDimTag * const * arg_dim_tags ,
00114   unsigned                            arg_num_states ,
00115   MetaData                          * arg_meta_data )
00116 {
00117   TraceIf("stk::mesh::impl::FieldRepository::declare_field", LOG_FIELD);
00118 
00119   static const char* reserved_state_suffix[6] = {
00120     "_STKFS_OLD",
00121     "_STKFS_N",
00122     "_STKFS_NM1",
00123     "_STKFS_NM2",
00124     "_STKFS_NM3",
00125     "_STKFS_NM4"
00126   };
00127 
00128   // Check that the name does not have a reserved suffix
00129 
00130   for ( unsigned i = 0 ; i < 6 ; ++i ) {
00131     const int len_name   = arg_name.size();
00132     const int len_suffix = std::strlen( reserved_state_suffix[i] );
00133     const int offset     = len_name - len_suffix ;
00134     if ( 0 <= offset ) {
00135       const char * const name_suffix = arg_name.c_str() + offset ;
00136       ThrowErrorMsgIf( equal_case( name_suffix , reserved_state_suffix[i] ),
00137                        "For name = \"" << name_suffix <<
00138                        "\" CANNOT HAVE THE RESERVED STATE SUFFIX \"" <<
00139                        reserved_state_suffix[i] << "\"" );
00140     }
00141   }
00142 
00143   // Check that the field of this name has not already been declared
00144 
00145   FieldBase * f[ MaximumFieldStates ] ;
00146 
00147   f[0] = get_field(
00148                 "FieldRepository::declare_field" ,
00149                 arg_name ,
00150                 arg_traits ,
00151                 arg_rank ,
00152                 arg_dim_tags ,
00153                 arg_num_states
00154                 );
00155 
00156   if ( NULL != f[0] ) {
00157     for ( unsigned i = 1 ; i < arg_num_states ; ++i ) {
00158       f[i] = f[0]->m_impl.field_state(static_cast<FieldState>(i));
00159     }
00160   }
00161   else {
00162     // Field does not exist then create it
00163 
00164     std::string field_names[ MaximumFieldStates ];
00165 
00166     field_names[0] = arg_name ;
00167 
00168     if ( 2 == arg_num_states ) {
00169       field_names[1] = arg_name ;
00170       field_names[1].append( reserved_state_suffix[0] );
00171     }
00172     else {
00173       for ( unsigned i = 1 ; i < arg_num_states ; ++i ) {
00174         field_names[i] = arg_name ;
00175         field_names[i].append( reserved_state_suffix[i] );
00176       }
00177     }
00178 
00179     for ( unsigned i = 0 ; i < arg_num_states ; ++i ) {
00180 
00181       f[i] = new FieldBase(
00182           arg_meta_data ,
00183           m_fields.size() ,
00184           field_names[i] ,
00185           arg_traits ,
00186           arg_rank,
00187           arg_dim_tags,
00188           arg_num_states ,
00189           static_cast<FieldState>(i)
00190           );
00191 
00192       m_fields.push_back( f[i] );
00193     }
00194 
00195     for ( unsigned i = 0 ; i < arg_num_states ; ++i ) {
00196       f[i]->m_impl.set_field_states( f );
00197     }
00198   }
00199 
00200   return f[0] ;
00201 }
00202 
00203 void FieldRepository::verify_and_clean_restrictions(
00204     const char       * arg_method ,
00205     const Part& superset, const Part& subset,
00206     const PartVector & arg_all_parts )
00207 {
00208   TraceIf("stk::mesh::impl::FieldRepository::verify_and_clean_restrictions", LOG_FIELD);
00209 
00210   for ( FieldVector::iterator f = m_fields.begin() ; f != m_fields.end() ; ++f ) {
00211     (*f)->m_impl.verify_and_clean_restrictions( arg_method, superset, subset, arg_all_parts );
00212   }
00213 }
00214 
00215 FieldRepository::~FieldRepository() {
00216   try {
00217     FieldVector::iterator j = m_fields.begin();
00218     for ( ; j != m_fields.end() ; ++j ) { delete *j ; }
00219     m_fields.clear();
00220   } catch(...) {}
00221 }
00222 
00223 } // namespace impl
00224 } // namespace mesh
00225 } // namespace stk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines