Sierra Toolkit Version of the Day
UnitTestFieldImpl.cpp
00001 /*------------------------------------------------------------------------*/
00002 /*                 Copyright 2010, 2011 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 
00010 #include <sstream>
00011 #include <stdexcept>
00012 
00013 #include <stk_util/unit_test_support/stk_utest_macros.hpp>
00014 
00015 #include <stk_util/parallel/Parallel.hpp>
00016 
00017 #include <stk_mesh/base/MetaData.hpp>
00018 #include <stk_mesh/base/FieldRelation.hpp>
00019 #include <stk_mesh/base/PartRelation.hpp>
00020 #include <stk_mesh/base/FieldData.hpp>
00021 
00022 #include <stk_mesh/baseImpl/PartRepository.hpp>
00023 #include <stk_mesh/baseImpl/EntityRepository.hpp>
00024 #include <stk_mesh/baseImpl/FieldBaseImpl.hpp>
00025 
00026 #include <Shards_BasicTopologies.hpp>
00027 
00028 namespace stk {
00029 namespace mesh {
00030 
00031 class UnitTestFieldImpl {
00032 public:
00033   UnitTestFieldImpl() {}
00034 
00035   void testField();
00036   void testFieldRestriction();
00037   void testFieldRelation();
00038 
00039 };
00040 
00041 }//namespace mesh
00042 }//namespace stk
00043 
00044 namespace {
00045 
00046 STKUNIT_UNIT_TEST(UnitTestField, testUnit)
00047 {
00048   stk::mesh::UnitTestFieldImpl ufield;
00049   ufield.testField();
00050 }
00051 
00052 STKUNIT_UNIT_TEST(UnitTestFieldRestriction, testUnit)
00053 {
00054   stk::mesh::UnitTestFieldImpl ufield;
00055   ufield.testFieldRestriction();
00056 }
00057 
00058 STKUNIT_UNIT_TEST(UnitTestFieldRelation, testUnit)
00059 {
00060   stk::mesh::UnitTestFieldImpl ufield;
00061   ufield.testFieldRelation();
00062 }
00063 
00064 }//namespace <anonymous>
00065 
00066 //----------------------------------------------------------------------
00067 
00068 namespace stk {
00069 namespace mesh {
00070 
00071 namespace {
00072 
00073 // Simple tags for testing field dimensions
00074 
00075 SHARDS_ARRAY_DIM_TAG_SIMPLE_DECLARATION( ATAG )
00076 SHARDS_ARRAY_DIM_TAG_SIMPLE_DECLARATION( BTAG )
00077 SHARDS_ARRAY_DIM_TAG_SIMPLE_DECLARATION( CTAG )
00078 SHARDS_ARRAY_DIM_TAG_SIMPLE_DECLARATION( DTAG )
00079 
00080 SHARDS_ARRAY_DIM_TAG_SIMPLE_IMPLEMENTATION( ATAG )
00081 SHARDS_ARRAY_DIM_TAG_SIMPLE_IMPLEMENTATION( BTAG )
00082 SHARDS_ARRAY_DIM_TAG_SIMPLE_IMPLEMENTATION( CTAG )
00083 SHARDS_ARRAY_DIM_TAG_SIMPLE_IMPLEMENTATION( DTAG )
00084 
00085 }
00086 
00087 void UnitTestFieldImpl::testField()
00088 {
00089   MetaData meta_data;
00090 
00091   // Declaration of a field allocates one field object
00092   // per state of the field.  These fields are inserted
00093   // into a vector of fields of the base class.
00094 
00095   impl::FieldRepository field_repo;
00096   const FieldVector  & allocated_fields = field_repo.get_fields();
00097 
00098   //------------------------------
00099   // Declare a double precision scalar field of one state.
00100   // Not an array; therefore, is rank zero.
00101   // Test the query methods for accuracy.
00102   FieldBase * const fA =
00103     field_repo.declare_field( std::string("A"),
00104                               data_traits<double>() ,
00105                               0     /* # Ranks */ ,
00106                               NULL  /* dimension tags */ ,
00107                               1     /* # States */ ,
00108                               &meta_data );
00109 
00110   STKUNIT_ASSERT( allocated_fields.size() == 1 );
00111   STKUNIT_ASSERT( fA != NULL );
00112   STKUNIT_ASSERT( fA == allocated_fields[0] );
00113   STKUNIT_ASSERT( fA->name() == std::string("A") );
00114   STKUNIT_ASSERT( fA->type_is<double>() );
00115   STKUNIT_ASSERT( fA->state() == StateNone );
00116   STKUNIT_ASSERT( fA->rank()  == 0 );
00117 
00118   //------------------------------
00119   // Declare a field with an invalid suffix in its name.
00120   // Suffixes corresponding to "OLD" "N" "NM1" "NM2" "NM3" "NM4"
00121   // are not allowed as these are automatically appended to
00122   // the declared variable name for multistate fields.
00123   {
00124     STKUNIT_ASSERT_THROW(
00125       field_repo.declare_field( "A_STKFS_OLD" ,
00126                                 data_traits<double>() ,
00127                                 0     /* # Ranks */ ,
00128                                 NULL  /* dimension tags */ ,
00129                                 1     /* # States */ ,
00130                                 &meta_data ),
00131       std::runtime_error);
00132     STKUNIT_ASSERT( allocated_fields.size() == 1 );
00133   }
00134 
00135   //------------------------------
00136   // Declare a double precision scalar field of two states.
00137   // Not an array; therefore, is rank zero.
00138   // Test that two fields: "B" and "B_OLD" were created.
00139   // Test the query methods for accuracy.
00140 
00141   FieldBase * const fB =
00142     field_repo.declare_field( std::string("B"),
00143                               data_traits<int>(),
00144                               0     /* # Ranks */ ,
00145                               NULL  /* dimension tags */ ,
00146                               2     /* # States */ ,
00147                               &meta_data );
00148 
00149   STKUNIT_ASSERT( allocated_fields.size() == 3 );
00150   STKUNIT_ASSERT( fB != NULL );
00151   STKUNIT_ASSERT( fB == allocated_fields[1] );
00152   STKUNIT_ASSERT( fB->name() == std::string("B") );
00153   STKUNIT_ASSERT( fB->type_is<int>() );
00154   STKUNIT_ASSERT( fB->state() == StateNew );
00155   STKUNIT_ASSERT( fB->rank() == 0 );
00156 
00157   const FieldBase * const fB_old = allocated_fields[2] ;
00158   STKUNIT_ASSERT( fB_old->name() == std::string("B_STKFS_OLD") );
00159   STKUNIT_ASSERT( fB_old->type_is<int>() );
00160   STKUNIT_ASSERT( fB_old->state() == StateOld );
00161   STKUNIT_ASSERT( fB_old->rank() == 0 );
00162 
00163   //------------------------------
00164   // Redeclare field must give back the previous field:
00165 
00166   FieldBase * const fB_redundant =
00167     field_repo.declare_field( std::string("B"),
00168                               data_traits<int>(),
00169                               0     /* # Ranks */ ,
00170                               NULL  /* dimension tags */ ,
00171                               2     /* # States */ ,
00172                               &meta_data );
00173 
00174   STKUNIT_ASSERT( allocated_fields.size() == 3 );
00175   STKUNIT_ASSERT( fB == fB_redundant );
00176 
00177   //------------------------------
00178   // Declare a double precision array field of four states.
00179   // Test that four fields: were created.
00180   // Test the query methods for accuracy.
00181 
00182   const shards::ArrayDimTag * dim_tags[] =
00183     { & ATAG::tag() , & BTAG::tag() , & CTAG::tag() , & DTAG::tag() };
00184 
00185   FieldBase * const fC =
00186     field_repo.declare_field( std::string("C"),
00187                               data_traits<double>(),
00188                               3         /* # Ranks */ ,
00189                               dim_tags  /* dimension tags */ ,
00190                               4         /* # States */ ,
00191                               &meta_data );
00192 
00193   STKUNIT_ASSERT( allocated_fields.size() == 7 );
00194   STKUNIT_ASSERT( fC != NULL );
00195   STKUNIT_ASSERT( fC == allocated_fields[3] );
00196   STKUNIT_ASSERT( fC->name() == std::string("C") );
00197   STKUNIT_ASSERT( fC->type_is<double>() );
00198   STKUNIT_ASSERT( fC->state() == StateNew );
00199   STKUNIT_ASSERT( fC->rank() == 3 );
00200 
00201   const FieldBase * const fC_n = allocated_fields[4] ;
00202   const FieldBase * const fC_nm1 = allocated_fields[5] ;
00203   const FieldBase * const fC_nm2 = allocated_fields[6] ;
00204 
00205   STKUNIT_ASSERT( fC     == fC->field_state( StateNP1 ) );
00206   STKUNIT_ASSERT( fC_n   == fC->field_state( StateN ) );
00207   STKUNIT_ASSERT( fC_nm1 == fC->field_state( StateNM1 ) );
00208   STKUNIT_ASSERT( fC_nm2 == fC->field_state( StateNM2 ) );
00209 
00210   STKUNIT_ASSERT( fC     == fC_n->field_state( StateNP1 ) );
00211   STKUNIT_ASSERT( fC_n   == fC_n->field_state( StateN ) );
00212   STKUNIT_ASSERT( fC_nm1 == fC_n->field_state( StateNM1 ) );
00213   STKUNIT_ASSERT( fC_nm2 == fC_n->field_state( StateNM2 ) );
00214 
00215   STKUNIT_ASSERT( fC     == fC_nm1->field_state( StateNP1 ) );
00216   STKUNIT_ASSERT( fC_n   == fC_nm1->field_state( StateN ) );
00217   STKUNIT_ASSERT( fC_nm1 == fC_nm1->field_state( StateNM1 ) );
00218   STKUNIT_ASSERT( fC_nm2 == fC_nm1->field_state( StateNM2 ) );
00219 
00220   STKUNIT_ASSERT( fC     == fC_nm2->field_state( StateNP1 ) );
00221   STKUNIT_ASSERT( fC_n   == fC_nm2->field_state( StateN ) );
00222   STKUNIT_ASSERT( fC_nm1 == fC_nm2->field_state( StateNM1 ) );
00223   STKUNIT_ASSERT( fC_nm2 == fC_nm2->field_state( StateNM2 ) );
00224 
00225   STKUNIT_ASSERT( fC_n->name() == std::string("C_STKFS_N") );
00226   STKUNIT_ASSERT( fC_n->type_is<double>() );
00227   STKUNIT_ASSERT( fC_n->state() == StateN );
00228   STKUNIT_ASSERT( fC_n->rank() == 3 );
00229 
00230   STKUNIT_ASSERT( fC_nm1->name() == std::string("C_STKFS_NM1") );
00231   STKUNIT_ASSERT( fC_nm1->type_is<double>() );
00232   STKUNIT_ASSERT( fC_nm1->state() == StateNM1 );
00233   STKUNIT_ASSERT( fC_nm1->rank() == 3 );
00234 
00235   STKUNIT_ASSERT( fC_nm2->name() == std::string("C_STKFS_NM2") );
00236   STKUNIT_ASSERT( fC_nm2->type_is<double>() );
00237   STKUNIT_ASSERT( fC_nm2->state() == StateNM2 );
00238   STKUNIT_ASSERT( fC_nm2->rank() == 3 );
00239 
00240   //------------------------------
00241   // Redeclare field must give back the previous field:
00242   //------------------------------
00243 
00244   for ( unsigned i = 0 ; i < allocated_fields.size() ; ++i ) {
00245     FieldBase * const f = allocated_fields[i] ;
00246     STKUNIT_ASSERT( f->mesh_meta_data_ordinal() == i );
00247   }
00248 
00249   //Coverage of EntityDimension::name in FieldData.cpp
00250   {
00251     const stk::mesh::EntityDimension&  entity_dimension_tag = stk::mesh::EntityDimension::tag();
00252     // static const char * name();
00253 
00254     entity_dimension_tag.name();
00255   }
00256 }
00257 
00258 
00259 //----------------------------------------------------------------------
00260 // Test field restrictions: the mapping of ( field , part ) -> dimensions
00261 
00262 void UnitTestFieldImpl::testFieldRestriction()
00263 {
00264   const char method[] = "UnitTestFieldImpl::testFieldRestriction" ;
00265 
00266   // Arrays for array dimension tags and dimension values
00267   const shards::ArrayDimTag * dim_tags[] =
00268     { & ATAG::tag() , & BTAG::tag() , & CTAG::tag() , & DTAG::tag() ,
00269       & ATAG::tag() , & BTAG::tag() , & CTAG::tag() , & DTAG::tag() };
00270 
00271   unsigned stride[8] ;
00272 
00273   stride[0] = 10 ;
00274   for ( unsigned i = 1 ; i < 8 ; ++i ) {
00275     stride[i] = ( i + 1 ) * stride[i-1] ;
00276   }
00277 
00278   MetaData meta_data;
00279 
00280   impl::FieldRepository field_repo;
00281   const FieldVector  & allocated_fields = field_repo.get_fields();
00282 
00283   //------------------------------
00284   // Declare a rank two and one state:
00285 
00286   FieldBase * const f2 =
00287     field_repo.declare_field( std::string("F2"),
00288                               data_traits<int>(),
00289                               2         /* # ranks */ ,
00290                               dim_tags  /* dimension tags */ ,
00291                               1         /* # states */ ,
00292                               &meta_data );
00293 
00294   //------------------------------
00295   // Declare a rank three and two states:
00296 
00297   FieldBase * const f3 =
00298     field_repo.declare_field( std::string("F3"),
00299                               data_traits<int>(),
00300                               3         /* # ranks */ ,
00301                               dim_tags  /* dimension tags */ ,
00302                               2         /* # states */ ,
00303                               &meta_data );
00304 
00305   FieldBase * const f3_old = f3->m_impl.field_state( StateOld ) ;
00306 
00307   //------------------------------
00308   // Test for correctness of vector of declared fields.
00309   STKUNIT_ASSERT( allocated_fields.size() == 3 );
00310   STKUNIT_ASSERT( f2 == allocated_fields[0] );
00311   STKUNIT_ASSERT( f3 == allocated_fields[1] );
00312 
00313   //------------------------------
00314   // Test for correctness of field internal state access:
00315 
00316   STKUNIT_ASSERT( f2     == f2->field_state( StateNone ) );
00317   STKUNIT_ASSERT( NULL   == f2->field_state( StateOld ) );
00318   STKUNIT_ASSERT( f3     == f3->field_state( StateNew ) );
00319   STKUNIT_ASSERT( f3_old == f3->field_state( StateOld ) );
00320   STKUNIT_ASSERT( NULL   == f3->field_state( StateNM1 ) );
00321   STKUNIT_ASSERT( f3     == f3_old->field_state( StateNew ) );
00322   STKUNIT_ASSERT( f3_old == f3_old->field_state( StateOld ) );
00323   STKUNIT_ASSERT( NULL   == f3_old->field_state( StateNM1 ) );
00324 
00325   STKUNIT_ASSERT( f2->rank() == 2 );
00326   STKUNIT_ASSERT( f3->rank() == 3 );
00327   STKUNIT_ASSERT( f3_old->rank() == 3 );
00328 
00329   //------------------------------
00330   // Declare some parts for restrictions:
00331 
00332   std::vector< std::string > dummy_names(1);
00333   dummy_names[0].assign("dummy");
00334 
00335   stk::mesh::MetaData m( dummy_names );
00336 
00337   impl::PartRepository partRepo( &m );
00338 
00339   Part & pA = * partRepo.declare_part( std::string("A") , 0 );
00340   Part & pB = * partRepo.declare_part( std::string("B") , 0 );
00341   Part & pC = * partRepo.declare_part( std::string("C") , 0 );
00342   Part & pD = * partRepo.declare_part( std::string("D") , 0 );
00343 
00344   // Declare three restrictions:
00345 
00346   f3->m_impl.insert_restriction( method , 0 , pA , stride );
00347   f3->m_impl.insert_restriction( method , 1 , pB , stride + 1 );
00348   f3->m_impl.insert_restriction( method , 2 , pC , stride + 2 );
00349 
00350   // Check for correctness of restrictions:
00351 
00352   STKUNIT_ASSERT( f3->restrictions().size() == 3 );
00353   STKUNIT_ASSERT( f3->restrictions()[0] ==
00354                   FieldRestriction( 0 , pA.mesh_meta_data_ordinal() ) );
00355   STKUNIT_ASSERT( f3->restrictions()[1] ==
00356                   FieldRestriction( 1 , pB.mesh_meta_data_ordinal() ) );
00357   STKUNIT_ASSERT( f3->restrictions()[2] ==
00358                   FieldRestriction( 2 , pC.mesh_meta_data_ordinal() ) );
00359 
00360   f3->m_impl.insert_restriction( method , 0 , pB , stride + 1 );
00361 
00362   STKUNIT_ASSERT_EQUAL( f3->max_size( 0 ) , stride[3] );
00363 
00364   //------------------------------
00365   // Check for error detection of bad stride:
00366   {
00367     unsigned bad_stride[4] = { 5 , 4 , 6 , 3 };
00368     STKUNIT_ASSERT_THROW(
00369       f3->m_impl.insert_restriction( method , 0 , pA , bad_stride ),
00370       std::runtime_error
00371     );
00372     STKUNIT_ASSERT( f3->restrictions().size() == 4 );
00373   }
00374 
00375   // Check for error detection in re-declaring an incompatible
00376   // field restriction.
00377   {
00378     STKUNIT_ASSERT_THROW(
00379       f3->m_impl.insert_restriction( method , 0 , pA , stride + 1 ),
00380       std::runtime_error
00381     );
00382     STKUNIT_ASSERT( f3->restrictions().size() == 4 );
00383   }
00384 
00385   // Verify and clean out any redundant restructions:
00386 
00387   f2->m_impl.verify_and_clean_restrictions( method , partRepo.get_all_parts() );
00388   f3->m_impl.verify_and_clean_restrictions( method , partRepo.get_all_parts() );
00389 
00390   STKUNIT_ASSERT( f3->restrictions().size() == 4 );
00391 
00392   //------------------------------
00393   // Introduce a redundant restriction, clean it, and
00394   // check that it was cleaned.
00395 
00396   partRepo.declare_subset( pD, pA );
00397   f2->m_impl.insert_restriction( method , 0 , pA , stride );
00398   f2->m_impl.insert_restriction( method , 0 , pD , stride );
00399 
00400   STKUNIT_ASSERT( f2->restrictions().size() == 2 );
00401 
00402   f2->m_impl.verify_and_clean_restrictions( method , partRepo.get_all_parts() );
00403 
00404   STKUNIT_ASSERT( f2->restrictions().size() == 1 );
00405 
00406   {
00407     const FieldBase::Restriction & rA = f2->restriction( 0 , pA );
00408     const FieldBase::Restriction & rD = f2->restriction( 0 , pD );
00409     STKUNIT_ASSERT( & rA == & rD );
00410     STKUNIT_ASSERT( rA.part_ordinal() == pD.mesh_meta_data_ordinal() );
00411   }
00412 
00413   //------------------------------
00414   // Introduce a new restriction, then introduce a
00415   // subset-superset relationship that renders the new restriction
00416   // redundant and incompatible.
00417   // Check that the verify_and_clean_restrictions method detects
00418   // this error condition.
00419   {
00420     f2->m_impl.insert_restriction( method , 0 , pB , stride + 1 );
00421     f2->m_impl.verify_and_clean_restrictions( method , partRepo.get_all_parts() );
00422     partRepo.declare_subset( pD, pB );
00423     STKUNIT_ASSERT_THROW(
00424       f2->m_impl.verify_and_clean_restrictions( method , partRepo.get_all_parts() ),
00425       std::runtime_error
00426     );
00427   }
00428 
00429   //Test to cover print function in FieldBaseImpl.cpp and FieldBase.cpp
00430   {
00431     //Create a new field with MetaData m and two restrictions
00432 
00433     FieldBase * const f4 =
00434       field_repo.declare_field( std::string("F4"),
00435                                 data_traits<int>(),
00436                                 3         /* # ranks */ ,
00437                                 dim_tags  /* dimension tags */ ,
00438                                 2         /* # states */ ,
00439                                 &m );
00440 
00441     partRepo.declare_subset( pD, pA );
00442     partRepo.declare_subset( pC, pB );
00443 
00444     f4->m_impl.insert_restriction( method , 0 , pA , stride );
00445     f4->m_impl.insert_restriction( method , 1 , pB , stride + 1 );
00446     stk::mesh::impl::print(std::cout, "Field f4", *f4);
00447 
00448     //test stride[i] / stride[i-1] section of else-if
00449     stk::mesh::print(std::cout, "Field f4", *f4);
00450   }
00451 
00452   //Further tests to cover print function in FieldBase.cpp
00453   {
00454     //test stride[i] % stride[i-1] section of else-if
00455 
00456     //Create a new field with MetaData m and two restrictions
00457 
00458     FieldBase * const f5 =
00459       field_repo.declare_field( std::string("F5"),
00460                                 data_traits<int>(),
00461                                 3         /* # ranks */ ,
00462                                 dim_tags  /* dimension tags */ ,
00463                                 2         /* # states */ ,
00464                                 &m );
00465 
00466     unsigned stride2[8] ;
00467     stride2[0] = 10 ;
00468     for ( unsigned i = 1 ; i < 3 ; ++i ) {
00469       stride2[i] = stride[i-1];
00470     }
00471     for ( unsigned i = 3 ; i < 8 ; ++i ) {
00472       stride2[i] = 0;
00473     }
00474     //  STKUNIT_ASSERT_THROW(
00475     f5->m_impl.insert_restriction( method , 0 , pA, stride2 );
00476     //  std::runtime_error
00477     //  );
00478 
00479     // f5->m_impl.insert_restriction( method , 1 , pB ,stride2 );
00480 
00481     stk::mesh::print(std::cout, "Field f5", *f5);
00482 
00483   }
00484 
00485   //Coverage for error from print_restriction in FieldBaseImpl.cpp when there is no stride (!stride[i])
00486   //Call print_restriction from insert_restriction
00487   {
00488     unsigned arg_no_stride[2];
00489 
00490     arg_no_stride[0] = 1;
00491     arg_no_stride[1] = 0;
00492 
00493     STKUNIT_ASSERT_THROW(
00494       f2->m_impl.insert_restriction(method, 0, pA, arg_no_stride),
00495       std::runtime_error
00496     );
00497   }
00498 
00499   //Coverage of ordinal in FieldRestriction.hpp:
00500   {
00501     const FieldRestrictionVector & rMap = f3->restrictions();
00502     const FieldRestrictionVector::const_iterator ie = rMap.end() ;
00503           FieldRestrictionVector::const_iterator i = rMap.begin();
00504 
00505     EntityId entity_id = 0;
00506     unsigned max = 0 ;
00507 
00508     for ( ; i != ie ; ++i ) {
00509       if ( i->part_ordinal() == entity_id ) {
00510   const unsigned len = pA.mesh_meta_data_ordinal() ? i->stride( pA.mesh_meta_data_ordinal() - 1 ) : 1 ;
00511         if ( max < len ) { max = len ; }
00512       }
00513     }
00514   }
00515 }
00516 
00517 // Unit test the FieldRelation copy constructor:
00518 void UnitTestFieldImpl::testFieldRelation()
00519 {
00520 
00521   FieldRelation rA;
00522   FieldRelation rB(rA);
00523 
00524   rA = rB;
00525 
00526 }
00527 
00528 }
00529 }
00530 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends