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