TEST_F(NumLibDistributionQuad, Linear) { // f(x,y,z) = 1 + 2x + 3y + 4z std::array<double,4> f_coeff = {{1, 2, 3, 4}}; MathLib::LinearFunction<double,3> linear_f(f_coeff); std::vector<double> expected = {{1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21}}; NumLib::SpatialFunctionLinear f(linear_f); const std::vector<std::size_t>& vec_node_ids = _mshNodesSearcher.getMeshNodesAlongPolyline(*_ply0).getNodeIDs(); std::vector<double> interpolated_values = NumLib::generateNodeValueDistribution(f, *_msh, vec_node_ids); ASSERT_ARRAY_NEAR(expected, interpolated_values, expected.size(), std::numeric_limits<double>::epsilon()); }
TEST_F(NumLibDistributionHex, InterpolationPolyline) { const std::vector<std::size_t> vec_point_ids = {{0, 4}}; const std::vector<double> vec_point_values = {{0., 100.}}; std::vector<double> expected = {{0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100}}; NumLib::LinearInterpolationAlongPolyline interpolate( *_ply0, vec_point_ids, vec_point_values, std::numeric_limits<double>::epsilon(), std::numeric_limits<double>::max()); const std::vector<std::size_t>& vec_node_ids = _mshNodesSearcher.getMeshNodesAlongPolyline(*_ply0).getNodeIDs(); std::vector<double> interpolated_values = NumLib::generateNodeValueDistribution(interpolate, *_msh, vec_node_ids); ASSERT_ARRAY_NEAR(expected, interpolated_values, expected.size(), std::numeric_limits<double>::epsilon()); }
TEST(MathLib, NonlinearPicard_vector_x0) { Example2 f2(2); VectorType x0(2), x(2); // initial guess1 x0[0] = 2.; x0[1] = 9.; x = 0.0; MathLib::Nonlinear::Picard picard; ASSERT_TRUE(picard.solve(f2, x0, x)); double my_expect1[] = {2., 8.}; ASSERT_ARRAY_NEAR(my_expect1, x, 2, 1e-5); // initial guess2 x0 = 6.0; x = 0.0; picard.solve(f2, x0, x); double my_expect2[] = {-0.5, 0.5}; ASSERT_ARRAY_NEAR(my_expect2, x, 2, 1e-5); }
TEST_F(NumLibDistributionHex, InterpolationSurface) { const std::vector<std::size_t> vec_point_ids = {{0, 3, 7, 4}}; const std::vector<double> vec_point_values = {{0., 100., 100., 0.}}; std::vector<double> expected(static_cast<std::size_t>(std::pow(_number_of_subdivisions_per_direction+1, 2))); for (std::size_t i=0; i<expected.size(); i++) { expected[i] = static_cast<double>((i%(_number_of_subdivisions_per_direction+1)) * 10); } NumLib::LinearInterpolationOnSurface interpolate(*_sfc1, vec_point_ids, vec_point_values, std::numeric_limits<double>::max()); const std::vector<std::size_t>& vec_node_ids = _mshNodesSearcher.getMeshNodesAlongSurface(*_sfc1).getNodeIDs(); std::vector<double> interpolated_values = NumLib::generateNodeValueDistribution(interpolate, *_msh, vec_node_ids); ASSERT_ARRAY_NEAR(expected, interpolated_values, expected.size(), std::numeric_limits<float>::epsilon()); }
TEST_F(NumLibSpatialFunctionHex, InterpolationPolyline) { const std::vector<std::size_t> vec_point_ids = {{0, 4}}; const std::vector<double> vec_point_values = {{0., 100.}}; std::vector<double> expected = {{0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100}}; NumLib::LinearInterpolationAlongPolyline interpolate( *_ply0, vec_point_ids, vec_point_values, std::numeric_limits<double>::epsilon(), std::numeric_limits<double>::max()); const std::vector<std::size_t>& vec_node_ids = _mshNodesSearcher.getMeshNodesAlongPolyline(*_ply0).getNodeIDs(); std::vector<double> interpolated_values(vec_node_ids.size()); NodeIDtoNodeObject<NumLib::LinearInterpolationAlongPolyline> task(*_msh, interpolate); std::transform(vec_node_ids.begin(), vec_node_ids.end(), interpolated_values.begin(), task); ASSERT_ARRAY_NEAR(expected, interpolated_values, expected.size(), std::numeric_limits<double>::epsilon()); }
TEST_F(NumLibSpatialFunctionQuad, Linear) { // f(x,y,z) = 1 + 2x + 3y + 4z std::array<double,4> f_coeff = {{1, 2, 3, 4}}; MathLib::LinearFunction<double,3> linear_f(f_coeff); std::vector<double> expected = {{1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21}}; NumLib::SpatialFunctionLinear f(linear_f); const std::vector<std::size_t>& vec_node_ids = _mshNodesSearcher.getMeshNodesAlongPolyline(*_ply0).getNodeIDs(); std::vector<double> interpolated_values(vec_node_ids.size()); NodeIDtoNodeObject<NumLib::SpatialFunctionLinear> task(*_msh, f); std::transform(vec_node_ids.begin(), vec_node_ids.end(), interpolated_values.begin(), task); ASSERT_ARRAY_NEAR(expected, interpolated_values, expected.size(), std::numeric_limits<double>::epsilon()); }
TEST(MeshLib, CoordinatesMappingLocalLowerDimLineZ) { auto ele = TestLine2::createZ(); MeshLib::ElementCoordinatesMappingLocal mapping(*ele, MeshLib::CoordinateSystem(MeshLib::CoordinateSystemType::Z)); auto matR(mapping.getRotationMatrixToGlobal()); //debugOutput(ele, mapping); double exp_R[3*3] = {0, 0, -1, 0, 1, 0, 1, 0, 0}; const double eps(std::numeric_limits<double>::epsilon()); ASSERT_ARRAY_NEAR(exp_R, matR.data(), matR.size(), eps); CHECK_COORDS(ele,mapping); for (std::size_t n = 0; n < ele->getNumberOfNodes(); ++n) delete ele->getNode(n); }
TEST(MathLib, LocalMatrixDeterminantInverse_Eigen) { Eigen::Matrix3d fMat, fInv; fMat << 1, 2, 3, 0, 1, 4, 5, 6, 0; double fMat_det = MathLib::determinant(fMat); MathLib::inverse(fMat, fMat_det, fInv); Eigen::MatrixXd dMat(3,3), dInv(3,3); dMat = fMat; double dMat_det = MathLib::determinant(dMat); MathLib::inverse(dMat, dMat_det, dInv); ASSERT_NEAR(fMat_det, dMat_det, std::numeric_limits<double>::epsilon()); ASSERT_ARRAY_NEAR(fInv.data(), dInv.data(), fInv.size(), std::numeric_limits<double>::epsilon()); }
TEST_F(NumLibSpatialFunctionHex, InterpolationSurface) { const std::vector<std::size_t> vec_point_ids = {{0, 3, 7, 4}}; const std::vector<double> vec_point_values = {{0., 100., 100., 0.}}; std::vector<double> expected(std::pow(_number_of_subdivisions_per_direction+1, 2)); for (std::size_t i=0; i<expected.size(); i++) { expected[i] = (i%(_number_of_subdivisions_per_direction+1)) * 10; } NumLib::LinearInterpolationOnSurface interpolate(*_sfc1, vec_point_ids, vec_point_values, std::numeric_limits<double>::max()); const std::vector<std::size_t>& vec_node_ids = _mshNodesSearcher.getMeshNodesAlongSurface(*_sfc1).getNodeIDs(); std::vector<double> interpolated_values(vec_node_ids.size()); NodeIDtoNodeObject<NumLib::LinearInterpolationOnSurface> task(*_msh, interpolate); std::transform(vec_node_ids.begin(), vec_node_ids.end(), interpolated_values.begin(), task); ASSERT_ARRAY_NEAR(expected, interpolated_values, expected.size(), std::numeric_limits<float>::epsilon()); }
TEST(MeshLib, CoordinatesMappingLocalLowerDimLineXYZ) { auto ele = TestLine2::createXYZ(); MeshLib::ElementCoordinatesMappingLocal mapping(*ele, MeshLib::CoordinateSystem(*ele)); auto matR(mapping.getRotationMatrixToGlobal()); //debugOutput(ele, mapping); double exp_R[3*3] = {0.57735026918962584, -0.81649658092772626, 0, 0.57735026918962584, 0.40824829046386313, -0.70710678118654757, 0.57735026918962584, 0.40824829046386313, 0.70710678118654757}; const double eps(std::numeric_limits<double>::epsilon()); ASSERT_ARRAY_NEAR(exp_R, matR.data(), matR.size(), eps); CHECK_COORDS(ele,mapping); for (std::size_t n = 0; n < ele->getNumberOfNodes(); ++n) delete ele->getNode(n); }
TEST(MeshLib, CoordinatesMappingLocalLowerDimQuadXYZ) { auto ele = TestQuad4::createXYZ(); MeshLib::ElementCoordinatesMappingLocal mapping(*ele, MeshLib::CoordinateSystem(*ele)); auto matR(mapping.getRotationMatrixToGlobal()); //debugOutput(ele, mapping); // results when using GeoLib::ComputeRotationMatrixToXY() double exp_R[3*3] = { 1, 0, 0, 0, 0.70710678118654757, -0.70710678118654757, 0, 0.70710678118654757, 0.70710678118654757}; const double eps(std::numeric_limits<double>::epsilon()); ASSERT_ARRAY_NEAR(exp_R, matR.data(), matR.size(), eps); CHECK_COORDS(ele,mapping); for (std::size_t n = 0; n < ele->getNumberOfNodes(); ++n) delete ele->getNode(n); }
TEST_F(NumLibDistributionHex, Linear) { // f(x,y,z) = 1 + 2x + 3y + 4z std::array<double,4> f_coeff = {{1, 2, 3, 4}}; MathLib::LinearFunction<double,3> linear_f(f_coeff); std::vector<double> expected(static_cast<std::size_t>(std::pow(_number_of_subdivisions_per_direction+1, 2))); const double dL = _geometric_size / _number_of_subdivisions_per_direction; for (std::size_t i=0; i<expected.size(); i++) { double x = 0; double y = (i%(_number_of_subdivisions_per_direction+1)) * dL; double z = (i/(_number_of_subdivisions_per_direction+1)) * dL; expected[i] = f_coeff[0] + f_coeff[1]*x + f_coeff[2]*y + f_coeff[3]*z; } NumLib::SpatialFunctionLinear f(linear_f); const std::vector<std::size_t>& vec_node_ids = _mshNodesSearcher.getMeshNodesAlongSurface(*_sfc1).getNodeIDs(); std::vector<double> interpolated_values = NumLib::generateNodeValueDistribution(f, *_msh, vec_node_ids); ASSERT_ARRAY_NEAR(expected, interpolated_values, expected.size(), std::numeric_limits<double>::epsilon()); }
TEST(NumLib, TimeSteppingIterationNumberBased2) { std::vector<std::size_t> iter_times_vector = {0, 3, 5, 7}; std::vector<double> multiplier_vector = {2.0, 1.0, 0.5, 0.25}; NumLib::IterationNumberBasedAdaptiveTimeStepping alg(1, 31, 1, 10, 1, iter_times_vector, multiplier_vector); std::vector<std::size_t> nr_iterations = {2, 2, 2, 4, 6, 8, 4, 4, 2, 2}; const std::vector<double> expected_vec_t = {1, 2, 4, 8, 16, 24, 26, 28, 30, 31}; struct IterationNumberUpdate { IterationNumberUpdate(std::vector<std::size_t> vec, std::size_t& counter) : _nr_iterations(std::move(vec)), i(counter) { } std::vector<std::size_t> _nr_iterations; std::size_t& i; void operator()(NumLib::IterationNumberBasedAdaptiveTimeStepping &obj) { std::size_t n = (i<_nr_iterations.size()) ? _nr_iterations[i++] : 0; //INFO("-> NR-iterations=%d", n); obj.setIterationNumber(n); } }; std::size_t counter = 0; IterationNumberUpdate update(nr_iterations, counter); std::vector<double> vec_t = timeStepping(alg, &update); //std::cout << vec_t; ASSERT_EQ(expected_vec_t.size(), vec_t.size()); ASSERT_EQ(1u, alg.getNumberOfRepeatedSteps()); ASSERT_ARRAY_NEAR(expected_vec_t, vec_t, expected_vec_t.size(), std::numeric_limits<double>::epsilon()); }
TEST(NumLibSerialLinearSolver, Steady2DdiffusionQuadElem) { // example using Example = SteadyDiffusion2DExample1<GlobalIndexType>; Example ex1; //-------------------------------------------------------------------------- // Prepare mesh items where data are assigned //-------------------------------------------------------------------------- const MeshLib::MeshSubset mesh_items_all_nodes(*ex1.msh, &ex1.msh->getNodes()); //-------------------------------------------------------------------------- // Allocate a coefficient matrix, RHS and solution vectors //-------------------------------------------------------------------------- // define a mesh item composition in a vector std::vector<std::unique_ptr<MeshLib::MeshSubsets>> vec_comp_dis; vec_comp_dis.emplace_back(new MeshLib::MeshSubsets{&mesh_items_all_nodes}); NumLib::LocalToGlobalIndexMap local_to_global_index_map( std::move(vec_comp_dis), NumLib::ComponentOrder::BY_COMPONENT); //-------------------------------------------------------------------------- // Construct a linear system //-------------------------------------------------------------------------- // allocate a vector and matrix MathLib::MatrixSpecifications ms{local_to_global_index_map.dofSizeWithoutGhosts(), local_to_global_index_map.dofSizeWithoutGhosts(), &local_to_global_index_map.getGhostIndices(), nullptr}; auto A = MathLib::MatrixVectorTraits<GlobalMatrix>::newInstance(ms); A->setZero(); auto rhs = MathLib::MatrixVectorTraits<GlobalVector>::newInstance(ms); auto x = MathLib::MatrixVectorTraits<GlobalVector>::newInstance(ms); // TODO no setZero() for rhs, x? using LocalAssembler = Example::LocalAssemblerData; // Initializer of the local assembler data. std::vector<LocalAssembler*> local_assemblers; local_assemblers.resize(ex1.msh->getNumberOfElements()); auto local_asm_builder = [&](std::size_t const id, MeshLib::Element const& item, LocalAssembler*& item_data) { assert(local_to_global_index_map.size() > id); auto const num_local_dof = local_to_global_index_map.getNumberOfElementDOF(id); Example::initializeLocalData( item, item_data, num_local_dof, ex1); }; // Call global initializer for each mesh element. GlobalExecutor::transformDereferenced( local_asm_builder, ex1.msh->getElements(), local_assemblers); // Call global assembler for each mesh element. auto M_dummy = MathLib::MatrixVectorTraits<GlobalMatrix>::newInstance(ms); A->setZero(); auto const t = 0.0; GlobalExecutor::executeMemberOnDereferenced( &LocalAssembler::assemble, local_assemblers, local_to_global_index_map, t, *x, *M_dummy, *A, *rhs); //std::cout << "A=\n"; //A->write(std::cout); //std::cout << "rhs=\n"; //rhs->write(std::cout); // apply Dirichlet BC MathLib::applyKnownSolution(*A, *rhs, *x, ex1.vec_DirichletBC_id, ex1.vec_DirichletBC_value); //std::cout << "A=\n"; //A->write(std::cout); //std::cout << "rhs=\n"; //rhs->write(std::cout); MathLib::finalizeMatrixAssembly(*A); //-------------------------------------------------------------------------- // solve x=A^-1 rhs //-------------------------------------------------------------------------- boost::property_tree::ptree t_root; { boost::property_tree::ptree t_solver; t_solver.put("solver_type", "CG"); t_solver.put("precon_type", "NONE"); t_solver.put("error_tolerance", 1e-16); t_solver.put("max_iteration_step", 1000); t_root.put_child("eigen", t_solver); } t_root.put("lis", "-i cg -p none -tol 1e-16 -maxiter 1000"); BaseLib::ConfigTree conf(t_root, "", BaseLib::ConfigTree::onerror, BaseLib::ConfigTree::onwarning); GlobalLinearSolver ls("solver_name", &conf); ls.solve(*A, *rhs, *x); // copy solution to double vector std::vector<double> solution(x->size()); for (std::size_t i = 0; i < x->size(); ++i) solution[i] = (*x)[i]; ASSERT_ARRAY_NEAR(&ex1.exact_solutions[0], &solution[0], ex1.dim_eqs, 1.e-5); for (auto p : local_assemblers) delete p; }