Ejemplo n.º 1
0
STKUNIT_UNIT_TEST(UnitTestTopology, testUnit)
{
  Ioss::StorageInitializer initialize_storage;
  Ioss::Initializer        initialize_topologies;

  Ioss::NameList elements;
  int element_count = Ioss::ElementTopology::describe(&elements);

  int errors = 0;
  for (int i=0; i < element_count; i++) {
    // FIXME: Need to totally skip tetra7 for now
    if (elements[i] == "tetra7") {
      continue;
    }

    int current_error = testElement(elements[i]);
    if (elements[i] != "node" &&
        elements[i] != "rod3d2" &&
        elements[i] != "rod3d3" &&
        elements[i] != "tri4a" /*FIXME?*/) {
      errors += current_error;
    }
    else {
      if (current_error > 0)
        std::cerr << "\t\tIGNORING " << elements[i] << " ERRORS...\n";
    }
  }
  STKUNIT_ASSERT(errors == 0);
}
STKUNIT_UNIT_TEST(UnitTestLinsysFunctions, test1)
{
    static const size_t spatial_dimension = 3;

    MPI_Barrier( MPI_COMM_WORLD );
    MPI_Comm comm = MPI_COMM_WORLD;
    //First create and fill MetaData and BulkData objects:

    const unsigned bucket_size = 100; //for a real application mesh, bucket_size would be much bigger...

    stk::mesh::fem::FEMMetaData fem_meta;
    stk::mesh::fem::FEMMetaData fem_meta2;
    fem_meta.FEM_initialize(spatial_dimension);
    fem_meta2.FEM_initialize(spatial_dimension);

    stk::mesh::MetaData & meta_data = stk::mesh::fem::FEMMetaData::get_meta_data(fem_meta);
    stk::mesh::MetaData & meta_data2 = stk::mesh::fem::FEMMetaData::get_meta_data(fem_meta2);

    const stk::mesh::EntityRank element_rank = fem_meta.element_rank();

    stk::mesh::BulkData bulk_data( meta_data, comm, bucket_size );
    stk::mesh::BulkData bulk_data2( meta_data2, comm, bucket_size );

    //create a boundary-condition part for testing later:
    stk::mesh::Part& bcpart = fem_meta.declare_part("bcpart");

    fill_utest_mesh_meta_data( fem_meta );

    bool use_temperature=false;
    fill_utest_mesh_meta_data( fem_meta2, use_temperature );

    fill_utest_mesh_bulk_data( bulk_data );
    fill_utest_mesh_bulk_data( bulk_data2 );

    //set owner-processors to lowest-sharing (stk::mesh defaults to
    //highest-sharing) If highest-sharing owns, then it isn't correct for the
    //way the fei library sets ownership of shared nodes for vectors etc.
    stk::mesh::set_owners<stk::mesh::LowestRankSharingProcOwns>( bulk_data );

    //put a node in our boundary-condition part. arbitrarily choose the
    //first locally-owned node:

    bulk_data.modification_begin();

    std::vector<stk::mesh::Entity*> local_nodes;
    stk::mesh::Selector select_owned(meta_data.locally_owned_part());
    stk::mesh::get_selected_entities(select_owned,
                                     bulk_data.buckets(NODE_RANK),
                                     local_nodes);

    stk::mesh::EntityId bc_node_id = 0;

    if (local_nodes.size() > 0) {
        stk::mesh::PartVector partvector;
        partvector.push_back(&bcpart);
        bulk_data.change_entity_parts(*local_nodes[0], partvector);
        bc_node_id = stk::linsys::impl::entityid_to_int(local_nodes[0]->identifier());
    }

    bulk_data.modification_end();

    stk::mesh::Selector selector = ( meta_data.locally_owned_part() | meta_data.globally_shared_part() ) & *meta_data.get_part("block_1");
    std::vector<unsigned> count;
    stk::mesh::count_entities(selector, bulk_data, count);

    STKUNIT_ASSERT_EQUAL( count[element_rank], (unsigned)4 );
    STKUNIT_ASSERT_EQUAL( count[NODE_RANK],     (unsigned)20 );

    ScalarField* temperature_field = meta_data.get_field<ScalarField>("temperature");

    //Create a fei Factory and stk::linsys::LinearSystem object:

    fei::SharedPtr<fei::Factory> factory(new Factory_Trilinos(comm));

    stk::linsys::LinearSystem ls(comm, factory);

    stk::linsys::add_connectivities(ls, element_rank, NODE_RANK,
                                    *temperature_field, selector, bulk_data);

    fei::SharedPtr<fei::MatrixGraph> matgraph = ls.get_fei_MatrixGraph();
    int num_blocks = matgraph->getNumConnectivityBlocks();

    STKUNIT_ASSERT_EQUAL( num_blocks, (int)1 );

    ls.synchronize_mappings_and_structure();
    ls.create_fei_LinearSystem();

    //put 0 throughout the matrix and 3 throughout the rhs:
    fei::SharedPtr<fei::Matrix> mat = ls.get_fei_LinearSystem()->getMatrix();
    ls.get_fei_LinearSystem()->getMatrix()->putScalar(0);
    ls.get_fei_LinearSystem()->getRHS()->putScalar(3.0);

    //put 10 on the matrix diagonal to ensure it will be easy to solve later.
    fei::SharedPtr<fei::VectorSpace> vspace = ls.get_fei_LinearSystem()->getRHS()->getVectorSpace();
    int numLocalRows = vspace->getNumIndices_Owned();
    std::vector<int> local_rows(numLocalRows);
    vspace->getIndices_Owned(numLocalRows, &local_rows[0], numLocalRows);

    for(size_t i=0; i<local_rows.size(); ++i) {
        int col = local_rows[i];
        double coef = 10;
        double* coefPtr = &coef;
        mat->sumIn(1, &local_rows[i], 1, &col, &coefPtr);
    }

    //now we'll impose a dirichlet bc on our one-node bcpart:
    stk::linsys::dirichlet_bc(ls, bulk_data, bcpart, NODE_RANK,
                              *temperature_field, 0, 9.0);

    ls.finalize_assembly();

    //now confirm that the rhs value for the equation corresponding to our
    //bc node is 9.0:

    fei::SharedPtr<fei::Vector> rhsvec = ls.get_fei_LinearSystem()->getRHS();
    double rhs_bc_val = 0;
    int bc_eqn_index = ls.get_DofMapper().get_global_index(NODE_RANK,
                       bc_node_id, *temperature_field);
    rhsvec->copyOut(1, &bc_eqn_index, &rhs_bc_val);

    bool bc_val_is_correct = std::abs(rhs_bc_val - 9.0) < 1.e-13;
    STKUNIT_ASSERT( bc_val_is_correct );

    stk::linsys::copy_vector_to_mesh( *rhsvec, ls.get_DofMapper(), bulk_data);

    stk::mesh::Entity* bc_node = bulk_data.get_entity(NODE_RANK, local_nodes[0]->identifier());

    stk::mesh::FieldTraits<ScalarField>::data_type* bc_node_data = stk::mesh::field_data(*temperature_field, *bc_node);

    bool bc_node_data_is_correct = std::abs(bc_node_data[0] - 9.0) < 1.e-13;
    STKUNIT_ASSERT( bc_node_data_is_correct );

    //now make sure we get a throw if we use the wrong bulk-data (that doesn't have the
    //temperature field defined)
    STKUNIT_ASSERT_THROW(stk::linsys::copy_vector_to_mesh( *rhsvec, ls.get_DofMapper(), bulk_data2), std::runtime_error);

    //obtain and zero the solution vector
    fei::SharedPtr<fei::Vector> solnvec = ls.get_fei_LinearSystem()->getSolutionVector();
    solnvec->putScalar(0);

    //copy the vector of zeros into the mesh:
    stk::linsys::copy_vector_to_mesh( *solnvec, ls.get_DofMapper(), bulk_data);

    //assert that our bc node's data is now zero.
    bc_node_data_is_correct = std::abs(bc_node_data[0] - 0) < 1.e-13;
    STKUNIT_ASSERT( bc_node_data_is_correct );

    //call the linear-system solve function.
    //(note that when we add options to the solve method, we'll need to enhance this
    //testing to exercise various specific solves.)
    Teuchos::ParameterList params;

    int status = 0;
    ls.solve(status, params);

    //copy the solution-vector into the mesh:
    stk::linsys::copy_vector_to_mesh( *solnvec, ls.get_DofMapper(), bulk_data);

    //now assert that the value 9 (bc value) produced by the solve is in this
    //node's data.
    //note that we use a loose tolerance, because the default solver tolerance
    //is (I think) only 1.e-6.
    bc_node_data_is_correct = std::abs(bc_node_data[0] - 9.0) < 1.e-6;
    STKUNIT_ASSERT( bc_node_data_is_correct );
    STKUNIT_ASSERT(bc_node_data_is_correct);
}
STKUNIT_UNIT_TEST(UnitTestLinsysFunctions, test3)
{
    static const size_t spatial_dimension = 3;

    MPI_Barrier( MPI_COMM_WORLD );
    MPI_Comm comm = MPI_COMM_WORLD;
    //First create and fill MetaData and BulkData objects:

    const unsigned bucket_size = 100; //for a real application mesh, bucket_size would be much bigger...

    stk::mesh::fem::FEMMetaData fem_meta;
    fem_meta.FEM_initialize(spatial_dimension);
    stk::mesh::MetaData & meta_data = stk::mesh::fem::FEMMetaData::get_meta_data(fem_meta);
    stk::mesh::BulkData bulk_data( meta_data, comm, bucket_size );

    fill_utest_mesh_meta_data( fem_meta );

    fill_utest_mesh_bulk_data( bulk_data );

    //set owner-processors to lowest-sharing (stk::mesh defaults to
    //highest-sharing) If highest-sharing owns, then it isn't correct for the
    //way the fei library sets ownership of shared nodes for vectors etc.
    stk::mesh::set_owners<stk::mesh::LowestRankSharingProcOwns>( bulk_data );

    stk::mesh::Selector selector = ( meta_data.locally_owned_part() | meta_data.globally_shared_part() ) & *meta_data.get_part("block_1");
    std::vector<unsigned> count;
    stk::mesh::count_entities(selector, bulk_data, count);
    const stk::mesh::EntityRank element_rank = fem_meta.element_rank();

    STKUNIT_ASSERT_EQUAL( count[element_rank], (unsigned)4 );
    STKUNIT_ASSERT_EQUAL( count[NODE_RANK],     (unsigned)20 );

    ScalarField* temperature_field = meta_data.get_field<ScalarField>("temperature");

    //Create a fei Factory and stk::linsys::LinearSystem object:

    fei::SharedPtr<fei::Factory> factory(new Factory_Trilinos(comm));

    stk::linsys::LinearSystem ls(comm, factory);

    stk::linsys::add_connectivities(ls, element_rank, NODE_RANK,
                                    *temperature_field, selector, bulk_data);

    fei::SharedPtr<fei::MatrixGraph> matgraph = ls.get_fei_MatrixGraph();
    int num_blocks = matgraph->getNumConnectivityBlocks();

    STKUNIT_ASSERT_EQUAL( num_blocks, (int)1 );

    ls.synchronize_mappings_and_structure();
    ls.create_fei_LinearSystem();

    //put 3 throughout the matrix and 3 throughout the rhs:
    fei::SharedPtr<fei::Matrix> mat = ls.get_fei_LinearSystem()->getMatrix();
    mat->putScalar(3.0);
    ls.get_fei_LinearSystem()->getRHS()->putScalar(3.0);

    fei::SharedPtr<fei::Vector> rhsvec = ls.get_fei_LinearSystem()->getRHS();

    stk::linsys::scale_vector(2, *rhsvec);
    stk::linsys::scale_matrix(2, *mat);

    //now the rhs and matrix contain 6.

    //create another matrix and vector:
    fei::SharedPtr<fei::Matrix> mat2 = factory->createMatrix(matgraph);
    fei::SharedPtr<fei::Vector> vec2 = factory->createVector(matgraph);
    mat2->putScalar(3.0);
    vec2->putScalar(3.0);

    //add 3*mat to mat2
    stk::linsys::add_matrix_to_matrix(3.0, *mat, *mat2);

    //confirm that mat2 contains 21:
    bool result = confirm_matrix_values(*mat2, 21);
    STKUNIT_ASSERT(result);

    //add 3*rhsvec to vec2:
    stk::linsys::add_vector_to_vector(3.0, *rhsvec, *vec2);

    //confirm that vec2 contains 21:
    result = confirm_vector_values(*vec2, 21);
    STKUNIT_ASSERT(result);
}
Ejemplo n.º 4
0
STKUNIT_UNIT_TEST(UnitTestTimer, UnitTest)
{
  stk_classic::diag::TimeBlock root_time_block(unitTestTimer());

  std::ostringstream strout;
  
  // Create subtimer and test lap time
  {
    static stk_classic::diag::Timer lap_timer("One second Wall time twice", unitTestTimer());
    
    stk_classic::diag::TimeBlock _time(lap_timer);
    double x = quick_work();
    x = x;
    std::ostringstream oss;
    oss << x << std::endl;
    
    ::sleep(1);

    lap_timer.lap();
    
    stk_classic::diag::MetricTraits<stk_classic::diag::WallTime>::Type lap_time = lap_timer.getMetric<stk_classic::diag::WallTime>().getLap();
  
    STKUNIT_ASSERT(lap_time >= 1.0);

    ::sleep(1);

    lap_timer.stop();
    
    lap_time = lap_timer.getMetric<stk_classic::diag::WallTime>().getLap();
  
    STKUNIT_ASSERT(lap_time >= 2.0);
  }

  // 
  {
    static stk_classic::diag::Timer run_timer("Run 100 times twice", unitTestTimer());
    
    for (int i = 0; i < 100; ++i) {
      stk_classic::diag::TimeBlock _time(run_timer);
      work();
    }

    stk_classic::diag::MetricTraits<stk_classic::diag::LapCount>::Type lap_count = run_timer.getMetric<stk_classic::diag::LapCount>().getAccumulatedLap(false);
  
    STKUNIT_ASSERT(lap_count == 100);
  }

  // Create second timer set
  {
    static stk_classic::diag::Timer second_timer("Second timer set", unitTestTimer(), unitTestSecondTimerSet());
    static stk_classic::diag::Timer second_timer_on_default("On default", second_timer);
    static stk_classic::diag::Timer second_timer_on("On", TIMER_APP_3, second_timer);
    static stk_classic::diag::Timer second_timer_off("Off", TIMER_APP_1, second_timer);
    
    stk_classic::diag::TimeBlock _time(second_timer);
    stk_classic::diag::TimeBlock _time1(second_timer_on_default);
    stk_classic::diag::TimeBlock _time2(second_timer_on);
    stk_classic::diag::TimeBlock _time3(second_timer_off);

    ::sleep(1);
  }

  // Grab previous subtimer and run 100 laps
  {
    static stk_classic::diag::Timer run_timer("Run 100 times twice", unitTestTimer());
    
    for (int i = 0; i < 100; ++i) {
      stk_classic::diag::TimeBlock _time(run_timer);
      work();
    }

    stk_classic::diag::MetricTraits<stk_classic::diag::LapCount>::Type lap_count = run_timer.getMetric<stk_classic::diag::LapCount>().getAccumulatedLap(false);
  
    STKUNIT_ASSERT(lap_count == 200);
  }

  // Create root object
  RootObject root_object;
    
  {
    stk_classic::diag::MetricTraits<stk_classic::diag::LapCount>::Type lap_count = root_object.m_timer.getMetric<stk_classic::diag::LapCount>().getAccumulatedLap(false);
  
    STKUNIT_ASSERT(lap_count == 0);
  }

  // Create object
  {
    Object time_object("One object", root_object);
    
    for (int i = 0; i < 100; ++i) {
      time_object.run();
    }

    stk_classic::diag::MetricTraits<stk_classic::diag::LapCount>::Type lap_count = time_object.m_timer.getMetric<stk_classic::diag::LapCount>().getAccumulatedLap(false);
  
    STKUNIT_ASSERT(lap_count == 100);
  }

  // Create object tree
  {
    std::vector<Object> object_vector;
    object_vector.push_back(Object("Object Tree", root_object));

    int id = 0;
    for (size_t i = 0; i < 2; ++i) {
      size_t ix = object_vector.size();
      object_vector.push_back(Object(id++, object_vector[0]));
      for (size_t j = 0; j < 2; ++j) {
        size_t jx = object_vector.size();
        object_vector.push_back(Object(id++, object_vector[ix]));
        for (int k = 0; k < 2; ++k) {    
          object_vector.push_back(Object(id++, object_vector[jx]));
        }
      }
    }
    
    stk_classic::diag::printTimersTable(strout, unitTestTimer(), stk_classic::diag::METRICS_ALL, false);
    
    stk_classic::diag::MetricTraits<stk_classic::diag::LapCount>::Type lap_count = 0;
    for (size_t j = 0; j < object_vector.size(); ++j) 
      lap_count += object_vector[j].m_timer.getMetric<stk_classic::diag::LapCount>().getAccumulatedLap(false);

    STKUNIT_ASSERT_EQUAL(lap_count, stk_classic::diag::MetricTraits<stk_classic::diag::LapCount>::Type(0));

    for (size_t j = 0; j < object_vector.size(); ++j) 
      object_vector[j].run();

    stk_classic::diag::printTimersTable(strout, unitTestTimer(), stk_classic::diag::METRICS_ALL, false);    

    lap_count = 0;
    for (size_t j = 0; j < object_vector.size(); ++j) 
      lap_count += object_vector[j].m_timer.getMetric<stk_classic::diag::LapCount>().getAccumulatedLap(false);

    STKUNIT_ASSERT_EQUAL(lap_count, stk_classic::diag::MetricTraits<stk_classic::diag::LapCount>::Type(object_vector.size()));

    for (size_t i = 1; i < 100; ++i) 
      for (size_t j = 0; j < object_vector.size(); ++j) 
        object_vector[j].run();

    stk_classic::diag::printTimersTable(strout, unitTestTimer(), stk_classic::diag::METRICS_ALL, false);    

    lap_count = 0;
    for (size_t j = 0; j < object_vector.size(); ++j) 
      lap_count += object_vector[j].m_timer.getMetric<stk_classic::diag::LapCount>().getAccumulatedLap(false);
  
    STKUNIT_ASSERT_EQUAL(lap_count, stk_classic::diag::MetricTraits<stk_classic::diag::LapCount>::Type(100*object_vector.size()));

    stk_classic::diag::printTimersTable(strout, unitTestTimer(), stk_classic::diag::METRICS_ALL, true);

    for (size_t i = 1; i < 100; ++i) 
      for (size_t j = 0; j < object_vector.size(); ++j) 
        object_vector[j].run();

    stk_classic::diag::printTimersTable(strout, unitTestTimer(), stk_classic::diag::METRICS_ALL, true);

    std::cout << strout.str() << std::endl;
    
//    dw().m(LOG_TIMER) << strout.str() << stk_classic::diag::dendl;
  }
}
Ejemplo n.º 5
0
STKUNIT_UNIT_TEST(UnitTestingOfThrowMacros, testUnit)
{
  // Setting assert handler to NULL should cause exception
  STKUNIT_ASSERT_THROW(stk::set_assert_handler(0), std::runtime_error);

  // Check that Throw*Msg works
  STKUNIT_ASSERT_THROW(force_throw_require_trigger(), std::logic_error);
  STKUNIT_ASSERT_THROW(force_throw_error_trigger(), std::runtime_error);
  STKUNIT_ASSERT_THROW(force_throw_invarg_trigger(), std::invalid_argument);

  // Check that Throw* works
  STKUNIT_ASSERT_THROW(force_throw_require_trigger(false), std::logic_error);
  STKUNIT_ASSERT_THROW(force_throw_error_trigger(false), std::runtime_error);
  STKUNIT_ASSERT_THROW(force_throw_invarg_trigger(false), std::invalid_argument);

  // Check that macro interacts appropriately with if statements
  STKUNIT_ASSERT_THROW(check_interaction_with_if(), std::logic_error);
  STKUNIT_ASSERT_THROW(check_interaction_with_if(false), std::logic_error);

  // Check that usage of ThrowRequireMsg/ThrowAssertMsg does not change program
  // semantics. Code blocks that are not contained within braces seem to be
  // the most likely to be problematic.

  bool expected_execution_path = false;
  if (false)
    ThrowRequireMsg(false, "test");
  else
    expected_execution_path = true;
  STKUNIT_ASSERT(expected_execution_path);

  expected_execution_path = false;
  if (false)
    ThrowAssertMsg(false, "test");
  else
    expected_execution_path = true;
  STKUNIT_ASSERT(expected_execution_path);

  expected_execution_path = false;
  if (false)
    ThrowErrorMsg("test");
  else
    expected_execution_path = true;
  STKUNIT_ASSERT(expected_execution_path);

  // These next four statements are to check compilation success

  if (false)
    ThrowRequireMsg(false, "test");

  if (false)
    ThrowAssertMsg(false, "test");

  if (false)
    ThrowRequire(false);

  if (false)
    ThrowAssert(false);

  // Check that do-while still works, again, we are mostly checking compilation
  // success here.

  do ThrowRequireMsg(true, "test");
  while (false);

  do ThrowAssertMsg(true, "test");
  while (false);

  // Check that message with put-tos compiles

  int temp = 0;
  ThrowRequireMsg(true, "test: " << temp << " blah");
  ThrowAssertMsg(true, "test: " << temp << " blah");

  // Check that assert behaves as expected (throws in debug, not in opt)
#ifdef NDEBUG
  force_throw_assert();
#else
  STKUNIT_ASSERT_THROW(force_throw_assert(), std::logic_error);
#endif

  // Check that ThrowErrorMsg works

  STKUNIT_ASSERT_THROW(test_no_expr_error(), std::runtime_error);
  
  // Check that setting handler for asserts works.

  stk::ErrorHandler orig = stk::set_assert_handler(test_assert_handler);

  ThrowRequireMsg(false, "test");

  STKUNIT_ASSERT(test_assert_handler_called);

  stk::set_assert_handler(orig);

  STKUNIT_ASSERT_THROW(force_throw_require_trigger(), std::logic_error);

  // Check that setting handler for errors works.

  orig = stk::set_error_handler(test_error_handler);

  ThrowErrorMsgIf(true, "test");

  STKUNIT_ASSERT(test_error_handler_called);

  stk::set_error_handler(orig);

  STKUNIT_ASSERT_THROW(force_throw_error_trigger(), std::runtime_error);

  // Check that setting handler for invalid args works.

  orig = stk::set_invalid_arg_handler(test_invarg_handler);

  ThrowInvalidArgMsgIf(true, "test");

  STKUNIT_ASSERT(test_invarg_handler_called);

  stk::set_invalid_arg_handler(orig);

  STKUNIT_ASSERT_THROW(force_throw_invarg_trigger(), std::invalid_argument);
}
void UnitTestBulkData::testChangeParts( ParallelMachine pm )
{
  static const char method[] =
    "stk::mesh::UnitTestBulkData::testChangeParts" ;

  std::cout << std::endl << method << std::endl ;

  const unsigned p_size = parallel_machine_size( pm );
  const unsigned p_rank = parallel_machine_rank( pm );

  if ( 1 < p_size ) return ;

  // Single process, no sharing

  // Meta data with entity ranks [0..9]
  std::vector<std::string> entity_names(10);
  for ( size_t i = 0 ; i < 10 ; ++i ) {
    std::ostringstream name ;
    name << "EntityRank_" << i ;
    entity_names[i] = name.str();
  }

  MetaData meta( entity_names );
  BulkData bulk( meta , pm , 100 );

  Part & part_univ = meta.universal_part();
  Part & part_owns = meta.locally_owned_part();

  Part & part_A_0 = meta.declare_part( std::string("A_0") , 0 );
  Part & part_A_1 = meta.declare_part( std::string("A_1") , 1 );
  Part & part_A_2 = meta.declare_part( std::string("A_2") , 2 );
  Part & part_A_3 = meta.declare_part( std::string("A_3") , 3 );

  Part & part_B_0 = meta.declare_part( std::string("B_0") , 0 );
  // Part & part_B_1 = meta.declare_part( std::string("B_1") , 1 );
  Part & part_B_2 = meta.declare_part( std::string("B_2") , 2 );
  // Part & part_B_3 = meta.declare_part( std::string("B_3") , 3 );

  meta.commit();
  bulk.modification_begin();

  PartVector tmp(1);

  tmp[0] = & part_A_0 ;
  Entity & entity_0_1 = bulk.declare_entity(  0 , 1 , tmp );

  tmp[0] = & part_A_1 ;
  Entity & entity_1_1 = bulk.declare_entity(  1 , 1 , tmp );

  tmp[0] = & part_A_2 ;
  Entity & entity_2_1 = bulk.declare_entity(  2 , 1 , tmp );

  tmp[0] = & part_A_3 ;
  Entity & entity_3_1 = bulk.declare_entity( 3 , 1 , tmp );

  entity_0_1.bucket().supersets( tmp );
  STKUNIT_ASSERT_EQUAL( size_t(3) , tmp.size() );
  STKUNIT_ASSERT( tmp[0] == & part_univ );
  STKUNIT_ASSERT( tmp[1] == & part_owns );
  STKUNIT_ASSERT( tmp[2] == & part_A_0 );

  entity_1_1.bucket().supersets( tmp );
  STKUNIT_ASSERT_EQUAL( size_t(3) , tmp.size() );
  STKUNIT_ASSERT( tmp[0] == & part_univ );
  STKUNIT_ASSERT( tmp[1] == & part_owns );
  STKUNIT_ASSERT( tmp[2] == & part_A_1 );

  entity_2_1.bucket().supersets( tmp );
  STKUNIT_ASSERT_EQUAL( size_t(3) , tmp.size() );
  STKUNIT_ASSERT( tmp[0] == & part_univ );
  STKUNIT_ASSERT( tmp[1] == & part_owns );
  STKUNIT_ASSERT( tmp[2] == & part_A_2 );

  entity_3_1.bucket().supersets( tmp );
  STKUNIT_ASSERT_EQUAL( size_t(3) , tmp.size() );
  STKUNIT_ASSERT( tmp[0] == & part_univ );
  STKUNIT_ASSERT( tmp[1] == & part_owns );
  STKUNIT_ASSERT( tmp[2] == & part_A_3 );

  {
    tmp.resize(1);
    tmp[0] = & part_A_0 ;
    bulk.change_entity_parts( entity_0_1 , tmp );
    entity_0_1.bucket().supersets( tmp );
    STKUNIT_ASSERT_EQUAL( size_t(3) , tmp.size() );
    STKUNIT_ASSERT( tmp[0] == & part_univ );
    STKUNIT_ASSERT( tmp[1] == & part_owns );
    STKUNIT_ASSERT( tmp[2] == & part_A_0 );
  }

  { // Add a new part:
    tmp.resize(1);
    tmp[0] = & part_B_0 ;
    bulk.change_entity_parts( entity_0_1 , tmp );
    entity_0_1.bucket().supersets( tmp );
    STKUNIT_ASSERT_EQUAL( size_t(4) , tmp.size() );
    STKUNIT_ASSERT( tmp[0] == & part_univ );
    STKUNIT_ASSERT( tmp[1] == & part_owns );
    STKUNIT_ASSERT( tmp[2] == & part_A_0 );
    STKUNIT_ASSERT( tmp[3] == & part_B_0 );
  }

  { // Remove the part just added:
    tmp.resize(1);
    tmp[0] = & part_B_0 ;
    bulk.change_entity_parts( entity_0_1 , PartVector() , tmp );
    entity_0_1.bucket().supersets( tmp );
    STKUNIT_ASSERT_EQUAL( size_t(3) , tmp.size() );
    STKUNIT_ASSERT( tmp[0] == & part_univ );
    STKUNIT_ASSERT( tmp[1] == & part_owns );
    STKUNIT_ASSERT( tmp[2] == & part_A_0 );
  }

  { // Relationship induced membership:
    bulk.declare_relation( entity_1_1 , entity_0_1 , 0 );
    entity_0_1.bucket().supersets( tmp );
    STKUNIT_ASSERT_EQUAL( size_t(4) , tmp.size() );
    STKUNIT_ASSERT( tmp[0] == & part_univ );
    STKUNIT_ASSERT( tmp[1] == & part_owns );
    STKUNIT_ASSERT( tmp[2] == & part_A_0 );
    STKUNIT_ASSERT( tmp[3] == & part_A_1 );
  }

  { // Remove relationship induced membership:
    bulk.destroy_relation( entity_1_1 , entity_0_1 );
    entity_0_1.bucket().supersets( tmp );
    STKUNIT_ASSERT_EQUAL( size_t(3) , tmp.size() );
    STKUNIT_ASSERT( tmp[0] == & part_univ );
    STKUNIT_ASSERT( tmp[1] == & part_owns );
    STKUNIT_ASSERT( tmp[2] == & part_A_0 );
  }

  { // Add a new part:
    tmp.resize(1);
    tmp[0] = & part_B_2 ;
    bulk.change_entity_parts( entity_2_1 , tmp );
    entity_2_1.bucket().supersets( tmp );
    STKUNIT_ASSERT_EQUAL( size_t(4) , tmp.size() );
    STKUNIT_ASSERT( tmp[0] == & part_univ );
    STKUNIT_ASSERT( tmp[1] == & part_owns );
    STKUNIT_ASSERT( tmp[2] == & part_A_2 );
    STKUNIT_ASSERT( tmp[3] == & part_B_2 );
  }

  { // Relationship induced membership:
    bulk.declare_relation( entity_2_1 , entity_0_1 , 0 );
    entity_0_1.bucket().supersets( tmp );
    STKUNIT_ASSERT_EQUAL( size_t(5) , tmp.size() );
    STKUNIT_ASSERT( tmp[0] == & part_univ );
    STKUNIT_ASSERT( tmp[1] == & part_owns );
    STKUNIT_ASSERT( tmp[2] == & part_A_0 );
    STKUNIT_ASSERT( tmp[3] == & part_A_2 );
    STKUNIT_ASSERT( tmp[4] == & part_B_2 );
  }

  { // Remove relationship induced membership:
    bulk.destroy_relation( entity_2_1 , entity_0_1 );
    entity_0_1.bucket().supersets( tmp );
    STKUNIT_ASSERT_EQUAL( size_t(3) , tmp.size() );
    STKUNIT_ASSERT( tmp[0] == & part_univ );
    STKUNIT_ASSERT( tmp[1] == & part_owns );
    STKUNIT_ASSERT( tmp[2] == & part_A_0 );
  }

  bulk.modification_end();

  //------------------------------
  // Now the parallel fun.  Existing entities should be shared
  // by all processes since they have the same identifiers.
  // They should also have the same parts.

  entity_0_1.bucket().supersets( tmp );
  if ( entity_0_1.owner_rank() == p_rank ) {
    STKUNIT_ASSERT_EQUAL( size_t(3) , tmp.size() );
    STKUNIT_ASSERT( tmp[0] == & part_univ );
    STKUNIT_ASSERT( tmp[1] == & part_owns );
    STKUNIT_ASSERT( tmp[2] == & part_A_0 );
  }
  else {
    STKUNIT_ASSERT_EQUAL( size_t(2) , tmp.size() );
    STKUNIT_ASSERT( tmp[0] == & part_univ );
    STKUNIT_ASSERT( tmp[1] == & part_A_0 );
  }

  entity_2_1.bucket().supersets( tmp );
  if ( entity_2_1.owner_rank() == p_rank ) {
    STKUNIT_ASSERT_EQUAL( size_t(4) , tmp.size() );
    STKUNIT_ASSERT( tmp[0] == & part_univ );
    STKUNIT_ASSERT( tmp[1] == & part_owns );
    STKUNIT_ASSERT( tmp[2] == & part_A_2 );
    STKUNIT_ASSERT( tmp[3] == & part_B_2 );
  }
  else {
    STKUNIT_ASSERT_EQUAL( size_t(3) , tmp.size() );
    STKUNIT_ASSERT( tmp[0] == & part_univ );
    STKUNIT_ASSERT( tmp[1] == & part_A_2 );
    STKUNIT_ASSERT( tmp[2] == & part_B_2 );
  }

  if (bulk.parallel_size() > 1) {
    STKUNIT_ASSERT_EQUAL( size_t(p_size - 1) , entity_0_1.sharing().size() );
    STKUNIT_ASSERT_EQUAL( size_t(p_size - 1) , entity_1_1.sharing().size() );
    STKUNIT_ASSERT_EQUAL( size_t(p_size - 1) , entity_2_1.sharing().size() );
    STKUNIT_ASSERT_EQUAL( size_t(p_size - 1) , entity_3_1.sharing().size() );
  }

  bulk.modification_begin();

  // Add a new part on the owning process:

  int ok_to_modify = entity_0_1.owner_rank() == p_rank ;

  try {
    tmp.resize(1);
    tmp[0] = & part_B_0 ;
    bulk.change_entity_parts( entity_0_1 , tmp );
    STKUNIT_ASSERT( ok_to_modify );
  }
  catch( const std::exception & x ) {
    STKUNIT_ASSERT( ! ok_to_modify );
  }

  entity_0_1.bucket().supersets( tmp );
  if ( entity_0_1.owner_rank() == p_rank ) {
    STKUNIT_ASSERT_EQUAL( size_t(4) , tmp.size() );
    STKUNIT_ASSERT( tmp[0] == & part_univ );
    STKUNIT_ASSERT( tmp[1] == & part_owns );
    STKUNIT_ASSERT( tmp[2] == & part_A_0 );
    STKUNIT_ASSERT( tmp[3] == & part_B_0 );
  }
  else {
    STKUNIT_ASSERT_EQUAL( size_t(2) , tmp.size() );
    STKUNIT_ASSERT( tmp[0] == & part_univ );
    STKUNIT_ASSERT( tmp[1] == & part_A_0 );
  }

  bulk.modification_end();

  entity_0_1.bucket().supersets( tmp );
  if ( entity_0_1.owner_rank() == p_rank ) {
    STKUNIT_ASSERT_EQUAL( size_t(4) , tmp.size() );
    STKUNIT_ASSERT( tmp[0] == & part_univ );
    STKUNIT_ASSERT( tmp[1] == & part_owns );
    STKUNIT_ASSERT( tmp[2] == & part_A_0 );
    STKUNIT_ASSERT( tmp[3] == & part_B_0 );
  }
  else {
    STKUNIT_ASSERT_EQUAL( size_t(3) , tmp.size() );
    STKUNIT_ASSERT( tmp[0] == & part_univ );
    STKUNIT_ASSERT( tmp[1] == & part_A_0 );
    STKUNIT_ASSERT( tmp[2] == & part_B_0 );
  }
}
void UnitTestBulkData::testChangeParts_loop( ParallelMachine pm )
{
  enum { nPerProc = 10 };
  const unsigned p_rank = parallel_machine_rank( pm );
  const unsigned p_size = parallel_machine_size( pm );
  const unsigned nLocalNode = nPerProc + ( 1 < p_size ? 1 : 0 );
  const unsigned nLocalEdge = nPerProc ;

  UnitTestRingMeshFixture ring_mesh( pm , nPerProc , true /* generate parts */ );
  ring_mesh.m_meta_data.commit();
  ring_mesh.generate_mesh( false /* no aura */ );

  Part & part_owns = ring_mesh.m_meta_data.locally_owned_part();
  Part & part_univ = ring_mesh.m_meta_data.universal_part();

  Selector select_owned( ring_mesh.m_meta_data.locally_owned_part() );
  Selector select_used = select_owned | ring_mesh.m_meta_data.globally_shared_part();
  Selector select_all(   ring_mesh.m_meta_data.universal_part() );

  std::vector<unsigned> local_count ;

  for ( unsigned i = 0 ; i < nLocalEdge ; ++i ) {
    const unsigned n = i + nPerProc * p_rank ;
    Entity * const edge = ring_mesh.m_bulk_data.get_entity( 1 , ring_mesh.m_edge_ids[n] );
    STKUNIT_ASSERT( edge != NULL );
    STKUNIT_ASSERT( edge->bucket().member( part_univ ) );
    STKUNIT_ASSERT( edge->bucket().member( part_owns ) );
    STKUNIT_ASSERT( edge->bucket().member( * ring_mesh.m_edge_parts[ n % ring_mesh.m_edge_parts.size() ] ) );
  }

  for ( unsigned i = 0 ; i < nLocalNode ; ++i ) {
    const unsigned n = ( i + nPerProc * p_rank ) % ring_mesh.m_node_ids.size();
    const unsigned e0 = n ;
    const unsigned e1 = ( n + ring_mesh.m_edge_ids.size() - 1 ) % ring_mesh.m_edge_ids.size();
    const unsigned ns = ring_mesh.m_edge_parts.size();
    const unsigned n0 = e0 % ns ;
    const unsigned n1 = e1 % ns ;
    Part * const epart_0 = ring_mesh.m_edge_parts[ n0 < n1 ? n0 : n1 ];
    Part * const epart_1 = ring_mesh.m_edge_parts[ n0 < n1 ? n1 : n0 ];

    Entity * const node = ring_mesh.m_bulk_data.get_entity( 0 , ring_mesh.m_node_ids[n] );
    STKUNIT_ASSERT( node != NULL );
    if ( node->owner_rank() == p_rank ) {
      STKUNIT_ASSERT( node->bucket().member( part_univ ) );
      STKUNIT_ASSERT( node->bucket().member( part_owns ) );
      STKUNIT_ASSERT( node->bucket().member( *epart_0 ) );
      STKUNIT_ASSERT( node->bucket().member( *epart_1 ) );
    }
    else {
      STKUNIT_ASSERT( node->bucket().member( part_univ ) );
      STKUNIT_ASSERT( ! node->bucket().member( part_owns ) );
      STKUNIT_ASSERT( node->bucket().member( * epart_0 ) );
      STKUNIT_ASSERT( node->bucket().member( * epart_1 ) );
    }
  }

  ring_mesh.m_bulk_data.modification_begin();

  if ( 0 == p_rank ) {

    for ( unsigned i = 0 ; i < nLocalEdge ; ++i ) {
      const unsigned n = i + nPerProc * p_rank ;

      PartVector add(1); add[0] = & ring_mesh.m_edge_part_extra ;
      PartVector rem(1); rem[0] = ring_mesh.m_edge_parts[ n % ring_mesh.m_edge_parts.size() ];

      Entity * const edge = ring_mesh.m_bulk_data.get_entity( 1 , ring_mesh.m_edge_ids[n] );
      ring_mesh.m_bulk_data.change_entity_parts( *edge , add , rem );
      STKUNIT_ASSERT( edge->bucket().member( part_univ ) );
      STKUNIT_ASSERT( edge->bucket().member( part_owns ) );
      STKUNIT_ASSERT( edge->bucket().member(ring_mesh.m_edge_part_extra ) );
    }
  }

  ring_mesh.m_bulk_data.modification_end();

  for ( unsigned i = 0 ; i < nLocalNode ; ++i ) {
    const unsigned n = ( i + nPerProc * p_rank ) % ring_mesh.m_node_ids.size();
    const unsigned e0 = n ;
    const unsigned e1 = ( n + ring_mesh.m_edge_ids.size() - 1 ) % ring_mesh.m_edge_ids.size();
    const unsigned ns = ring_mesh.m_edge_parts.size();
    const unsigned n0 = e0 % ns ;
    const unsigned n1 = e1 % ns ;
    Part * ep_0 = e0 < nLocalEdge ? & ring_mesh.m_edge_part_extra : ring_mesh.m_edge_parts[n0] ;
    Part * ep_1 = e1 < nLocalEdge ? & ring_mesh.m_edge_part_extra : ring_mesh.m_edge_parts[n1] ;

    Part * epart_0 = ep_0->mesh_meta_data_ordinal() < ep_1->mesh_meta_data_ordinal() ? ep_0 : ep_1 ;
    Part * epart_1 = ep_0->mesh_meta_data_ordinal() < ep_1->mesh_meta_data_ordinal() ? ep_1 : ep_0 ;

    Entity * const node = ring_mesh.m_bulk_data.get_entity( 0 , ring_mesh.m_node_ids[n] );
    STKUNIT_ASSERT( node != NULL );
    if ( node->owner_rank() == p_rank ) {
      STKUNIT_ASSERT( node->bucket().member( part_owns ) );
    }
    else {
      STKUNIT_ASSERT( ! node->bucket().member( part_owns ) );
    }

    STKUNIT_ASSERT( node->bucket().member( part_univ ) );
    STKUNIT_ASSERT( node->bucket().member( *epart_0 ) );
    STKUNIT_ASSERT( node->bucket().member( *epart_1 ) );
  }
}
Ejemplo n.º 8
0
STKUNIT_UNIT_TEST(UnitTestZoltanSimple, testUnit)
{
#ifdef STK_HAS_MPI
  stk::ParallelMachine comm(MPI_COMM_WORLD);
#else
  stk::ParallelMachine comm(0);
#endif

  unsigned spatial_dimension = 2;
  std::vector<std::string> rank_names = stk::mesh::fem::entity_rank_names(spatial_dimension);
  const stk::mesh::EntityRank constraint_rank = rank_names.size();
  rank_names.push_back("Constraint");

  stk::mesh::fem::FEMMetaData fem_meta;
  fem_meta.FEM_initialize( spatial_dimension, rank_names );
  stk::mesh::MetaData & meta_data = stk::mesh::fem::FEMMetaData::get_meta_data(fem_meta);
  stk::mesh::BulkData bulk_data( meta_data , comm , 100 );
  const stk::mesh::EntityRank element_rank    = fem_meta.element_rank();

  stk::mesh::fem::CellTopology quad_top(shards::getCellTopologyData<shards::Quadrilateral<4> >());
  stk::mesh::Part & quad_part( fem_meta.declare_part("quad", quad_top ) );
  VectorField & coord_field( fem_meta.declare_field< VectorField >( "coordinates" ) );
  ScalarField & weight_field( fem_meta.declare_field< ScalarField >( "element_weights" ) );

  stk::mesh::put_field( coord_field , NODE_RANK , fem_meta.universal_part() );
  stk::mesh::put_field(weight_field , element_rank , fem_meta.universal_part() );

  fem_meta.commit();

  const unsigned p_size = bulk_data.parallel_size();
  const unsigned p_rank = bulk_data.parallel_rank();

  bulk_data.modification_begin();

  if ( p_rank == 0 ) {

    std::vector<std::vector<stk::mesh::Entity*> > quads(nx);
    for ( unsigned ix = 0 ; ix < nx ; ++ix ) quads[ix].resize(ny);

    const unsigned nnx = nx + 1 ;
    const unsigned nny = ny + 1 ;
    for ( unsigned iy = 0 ; iy < ny ; ++iy ) {
      for ( unsigned ix = 0 ; ix < nx ; ++ix ) {
        stk::mesh::EntityId elem = 1 + ix + iy * nx ;
        stk::mesh::EntityId nodes[4] ;
        nodes[0] = 1 + ix + iy * nnx ;
        nodes[1] = 2 + ix + iy * nnx ;
        nodes[2] = 2 + ix + ( iy + 1 ) * nnx ;
        nodes[3] = 1 + ix + ( iy + 1 ) * nnx ;

        stk::mesh::Entity &q = stk::mesh::fem::declare_element( bulk_data , quad_part , elem , nodes );
        quads[ix][iy] = &q; 
      }
    }

    for ( unsigned iy = 0 ; iy < ny ; ++iy ) {
      for ( unsigned ix = 0 ; ix < nx ; ++ix ) {
        stk::mesh::EntityId elem = 1 + ix + iy * nx ;
        stk::mesh::Entity * e = bulk_data.get_entity( element_rank, elem );
        double * const e_weight = stk::mesh::field_data( weight_field , *e );
        *e_weight = 1.0;
      }
    }

    for ( unsigned iy = 0 ; iy <= ny ; ++iy ) {
      for ( unsigned ix = 0 ; ix <= nx ; ++ix ) {
        stk::mesh::EntityId nid = 1 + ix + iy * nnx ;
        stk::mesh::Entity * n = bulk_data.get_entity( NODE_RANK, nid );
        double * const coord = stk::mesh::field_data( coord_field , *n );
        coord[0] = .1*ix;
        coord[1] = .1*iy;
        coord[2] = 0;
      }
    }

    {
      const unsigned iy_left  =  0; 
      const unsigned iy_right = ny; 
      stk::mesh::PartVector add(1, &fem_meta.locally_owned_part());
      for ( unsigned ix = 0 ; ix <= nx ; ++ix ) {
        stk::mesh::EntityId nid_left  = 1 + ix + iy_left  * nnx ;
        stk::mesh::EntityId nid_right = 1 + ix + iy_right * nnx ;
        stk::mesh::Entity * n_left  = bulk_data.get_entity( NODE_RANK, nid_left  );
        stk::mesh::Entity * n_right = bulk_data.get_entity( NODE_RANK, nid_right );
        const stk::mesh::EntityId constraint_entity_id =  1 + ix + nny * nnx;
        stk::mesh::Entity & c = bulk_data.declare_entity( constraint_rank, constraint_entity_id, add );
        bulk_data.declare_relation( c , *n_left  , 0 );
        bulk_data.declare_relation( c , *n_right , 1 );
      }
    }

  }

  // Only P0 has any nodes or elements
  if ( p_rank == 0 ) {
    STKUNIT_ASSERT( ! bulk_data.buckets( NODE_RANK ).empty() );
    STKUNIT_ASSERT( ! bulk_data.buckets( element_rank ).empty() );
  }
  else {
    STKUNIT_ASSERT( bulk_data.buckets( NODE_RANK ).empty() );
    STKUNIT_ASSERT( bulk_data.buckets( element_rank ).empty() );
  }


  bulk_data.modification_end();

  // create some sides and faces to rebalance.
  stk::mesh::PartVector add_parts;
  stk::mesh::create_adjacent_entities(bulk_data, add_parts);

  // Zoltan partition is specialized fomm a virtual base class, stk::rebalance::Partition.
  // Other specializations are possible.
  Teuchos::ParameterList emptyList;
  stk::rebalance::Zoltan zoltan_partition(comm, spatial_dimension, emptyList);

  {
    stk::mesh::Selector selector(fem_meta.universal_part());

    stk::rebalance::rebalance(bulk_data, selector, &coord_field, &weight_field, zoltan_partition);
  }

  const double imbalance_threshold = stk::rebalance::check_balance(bulk_data, &weight_field, element_rank);
  const bool do_rebal = 1.5 < imbalance_threshold;

  // Check that we satisfy our threshhold
  STKUNIT_ASSERT( !do_rebal );
  if( (2 == p_size) || (4 == p_size) )
  {
    STKUNIT_ASSERT_NEAR(imbalance_threshold, 1.0, 1.e-8);
  }
  else
  {
    STKUNIT_ASSERT_LE(imbalance_threshold, 1.5);
  }

  // And verify that all dependent entities are on the same proc as their parent element
  {
    stk::mesh::EntityVector entities;
    stk::mesh::Selector selector = fem_meta.locally_owned_part();

    get_selected_entities(selector, bulk_data.buckets(NODE_RANK), entities);
    bool result = stk::rebalance::verify_dependent_ownership(element_rank, entities);
    //get_selected_entities(selector, bulk_data.buckets(constraint_rank), entities);
    //result &= stk::rebalance::verify_dependent_ownership(element_rank, entities);
    STKUNIT_ASSERT( result );
  }
}