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