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); }
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; } }
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 ) ); } }
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 ); } }