From 3638d7e4f931da3ec5761a54b6632348b5d61602 Mon Sep 17 00:00:00 2001 From: labourasse <labourassee@gmail.com> Date: Fri, 8 Nov 2024 19:06:58 +0100 Subject: [PATCH] partial commit, eigenvectors calculation --- src/algebra/EigenvalueSolver.cpp | 1 - src/algebra/TinyMatrix.hpp | 72 ++++++++++++++++ src/scheme/HyperplasticSolver.cpp | 131 +++++++++++++++++++++++++++--- tests/test_EigenvalueSolver.cpp | 41 ++++++++++ 4 files changed, 234 insertions(+), 11 deletions(-) diff --git a/src/algebra/EigenvalueSolver.cpp b/src/algebra/EigenvalueSolver.cpp index 842150bb5..40659530f 100644 --- a/src/algebra/EigenvalueSolver.cpp +++ b/src/algebra/EigenvalueSolver.cpp @@ -188,7 +188,6 @@ EigenvalueSolver::computeExpForSymmetricMatrix(const PETScAijMatrixEmbedder& A, expA = P * D * transpose(P); EPSDestroy(&eps); } - #endif // PUGS_HAS_SLEPC EigenvalueSolver::EigenvalueSolver() {} diff --git a/src/algebra/TinyMatrix.hpp b/src/algebra/TinyMatrix.hpp index 12122a874..29c70bc44 100644 --- a/src/algebra/TinyMatrix.hpp +++ b/src/algebra/TinyMatrix.hpp @@ -573,4 +573,76 @@ inverse(const TinyMatrix<3, 3, T>& A) return A_cofactors_T *= 1. / determinent; } +// template <size_t N, typename T> +// PUGS_INLINE constexpr TinyMatrix<N, N, T> +// rowReduce(const TinyMatrix<N, N, T>& matrix) +// { +// for (size_t i = 0; i < N; ++i) { +// size_t pivotRow = i; +// while (pivotRow < N && std::fabs(matrix[pivotRow][i]) < 1e-10) { +// ++pivotRow; +// } +// if (pivotRow == N) { +// continue; +// } + +// std::swap(matrix[i], matrix[pivotRow]); + +// double pivotValue = matrix[i][i]; +// for (size_t j = i; j < N; ++j) { +// matrix[i][j] /= pivotValue; +// } + +// for (size_t k = i + 1; k < N; ++k) { +// double factor = matrix[k][i]; +// for (size_t j = i; j < N; ++j) { +// matrix[k][j] -= factor * matrix[i][j]; +// } +// } +// } +// } + +// template <size_t N, typename T> +// PUGS_INLINE constexpr TinyMatrix<N, N, T> +// findEigenvectors(const TinyMatrix<N, N, T>& A, double eigenvalue) +// { +// TinyMatrix<N, N, T> B = A; + +// for (size_t i = 0; i < N; ++i) { +// B(i, i) -= eigenvalue; +// } + +// rowReduce(B); +// TinyMatrix<N, N, T> eigenvectors; + +// for (int i = 0; i < N; ++i) { +// bool isFreeVariableRow = true; +// for (int j = 0; j < N; ++j) { +// if (std::abs(B[i][j]) > 1e-10) { +// isFreeVariableRow = false; +// break; +// } +// } + +// if (isFreeVariableRow) { +// TinyVector<N, T> eigenvector(0.0); +// eigenvector[i] = 1.0; + +// for (int k = i - 1; k >= 0; --k) { +// double sum = 0.0; +// for (int j = i; j < N; ++j) { +// sum += B[k][j] * eigenvector[j]; +// } +// eigenvector[k] = -sum; +// } + +// eigenvector /= L2Norm(eigenvector); + +// eigenvectors.push_back(eigenvector); +// } +// } + +// return eigenvectors; +// } + #endif // TINYMATRIX_HPP diff --git a/src/scheme/HyperplasticSolver.cpp b/src/scheme/HyperplasticSolver.cpp index e56c12c39..d1d999b57 100644 --- a/src/scheme/HyperplasticSolver.cpp +++ b/src/scheme/HyperplasticSolver.cpp @@ -165,29 +165,139 @@ class HyperplasticSolverHandler::HyperplasticSolver final : public HyperplasticS R3x3 matrix_exp(const R3x3 A) const { - R3x3 expA = zero; + double normA = frobeniusNorm(A); + R3x3 expA = identity; + if (normA <= 1.e-12) { + return expA; + } SmallMatrix<double> expB{3}; - Array<int> non_zeros(3); - non_zeros.fill(3); - CRSMatrixDescriptor<double> S{3, 3, non_zeros}; + SmallMatrix<double> B(3, 3); + // B.fill(0.); for (size_t i = 0; i < 3; i++) { for (size_t j = 0; j < 3; j++) { - S(i, j) = A(i, j); + B(i, i) = A(i, j); } } - CRSMatrix B{S.getCRSMatrix()}; + + std::cout << B << "\n"; + std::cout << std::flush; + EigenvalueSolver{}.computeExpForSymmetricMatrix(B, expB); for (size_t i = 0; i < 3; i++) { for (size_t j = 0; j < 3; j++) { expA(i, j) = expB(i, j); } } + std::cout << expA << "\n"; return expA; } + template <size_t N, typename T> + PUGS_INLINE TinyMatrix<N, N, T> + swap(TinyMatrix<N, N, T>& matrix, size_t i, size_t j) const + { + TinyMatrix<N, N, T> swapMat = matrix; + for (size_t k = 0; k < N; k++) { + double valuei = matrix(i, k); + swapMat(i, k) = matrix(j, k); + swapMat(j, k) = valuei; + } + std::cout << "In swap " << swapMat << "\n"; + return swapMat; + } + template <size_t N, typename T> + PUGS_INLINE constexpr TinyMatrix<N, N, T> + rowReduce(const TinyMatrix<N, N, T>& matrix) const + { + TinyMatrix<N, N> redmat = matrix; + for (size_t i = 0; i < N; ++i) { + size_t pivotRow = i; + while (pivotRow < N && std::fabs(redmat(pivotRow, i)) < 1e-10) { + ++pivotRow; + } + if (pivotRow == N) { + continue; + } + std::cout << "before: " + << "i = " << i << " pivotRow = " << pivotRow << " " << redmat << "\n"; + redmat = swap(redmat, i, pivotRow); + std::cout << "after: " << redmat << "\n"; + + double pivotValue = redmat(i, i); + for (size_t j = i; j < N; ++j) { + redmat(i, j) /= pivotValue; + } + + for (size_t k = i + 1; k < N; ++k) { + double factor = redmat(k, i); + for (size_t j = i; j < N; ++j) { + redmat(k, j) -= factor * redmat(i, j); + } + } + } + return redmat; + } + + template <size_t N> + PUGS_INLINE constexpr TinyMatrix<N, N> + findEigenvectors(const TinyMatrix<N, N>& A, const double eigenvalue) const + { + TinyMatrix<N, N> B = A; + + for (size_t i = 0; i < N; ++i) { + B(i, i) -= eigenvalue; + } + + std::cout << " Avant " << B << "\n" + << "\n"; + + B = rowReduce(B); + + std::cout << " Après " << B << "\n" + << "\n"; + TinyMatrix<N, N> eigenvectors = zero; + + for (size_t i = 0; i < N; ++i) { + bool isFreeVariableRow = true; + for (size_t j = 0; j < N; ++j) { + if (std::fabs(B(i, j)) > 1e-10) { + isFreeVariableRow = false; + break; + } + } + + if (isFreeVariableRow) { + TinyVector<N> eigenvector = zero; + eigenvector[i] = 1.0; + + for (int k = i - 1; k >= 0; --k) { + double sum = 0.0; + for (size_t j = i; j < N; ++j) { + sum += B(k, j) * eigenvector[j]; + } + eigenvector[k] = -sum; + } + + eigenvector = 1. / l2Norm(eigenvector) * eigenvector; + + for (size_t j = 0; j < N; ++j) { + eigenvectors(i, j) = eigenvector[j]; + } + } + } + + return eigenvectors; + } + double _compute_chi(const R3x3 S, const double yield) const { + double vp = 2; + TinyMatrix<3> A{1, -1, 0, -1, 1, 0, 0, 0, 3}; + std::cout << A << "\n"; + TinyMatrix<3> Try = findEigenvectors(A, vp); + std::cout << Try << "\n"; + exit(0); const R3x3 Id = identity; const R3x3 Sbar = S - 1. / 3 * trace(S) * Id; double chi = 0; @@ -591,7 +701,8 @@ class HyperplasticSolverHandler::HyperplasticSolver final : public HyperplasticS CellValue<double> new_zeta = copy(zeta.cellValues()); CellValue<double> new_yield = copy(yield.cellValues()); CellValue<R3x3> sigma_s = copy(sigma.cellValues()); - + CellValue<double> chi{mesh.connectivity()}; + chi.fill(0.); parallel_for( mesh.numberOfCells(), PUGS_LAMBDA(CellId j) { const auto& cell_nodes = cell_to_node_matrix[j]; @@ -612,11 +723,11 @@ class HyperplasticSolverHandler::HyperplasticSolver final : public HyperplasticS new_u[j] += dt_over_Mj * momentum_fluxes; new_E[j] += dt_over_Mj * energy_fluxes; new_Fe[j] += dt_over_Vj * elastic_fluxes; - double chi = _compute_chi(sigma[j], yield[j]); - const R3x3 M = dt_over_Vj * chi * new_Fe[j]; + chi[j] = _compute_chi(sigma[j], yield[j]); + const R3x3 M = dt * chi[j] * zeta[j] * new_Fe[j]; new_Fe[j] = new_Fe[j] * matrix_exp(M); }); - + std::cout << "sum_chi " << sum(chi) << "\n"; CellValue<const double> new_Vj = MeshDataManager::instance().getMeshData(*new_mesh).Vj(); parallel_for( diff --git a/tests/test_EigenvalueSolver.cpp b/tests/test_EigenvalueSolver.cpp index 11c630479..0cd3da4a0 100644 --- a/tests/test_EigenvalueSolver.cpp +++ b/tests/test_EigenvalueSolver.cpp @@ -5,6 +5,7 @@ #include <algebra/CRSMatrixDescriptor.hpp> #include <algebra/EigenvalueSolver.hpp> #include <algebra/SmallMatrix.hpp> +#include <algebra/TinyMatrix.hpp> #include <utils/pugs_config.hpp> @@ -34,6 +35,24 @@ TEST_CASE("EigenvalueSolver", "[algebra]") CRSMatrix A{S.getCRSMatrix()}; + Array<int> non_zeros2(3); + non_zeros2.fill(3); + CRSMatrixDescriptor<double> S2{3, 3, non_zeros}; + + S2(0, 0) = 1; + S2(0, 1) = 0; + S2(0, 2) = 0; + + S2(1, 0) = 0; + S2(1, 1) = 0; + S2(1, 2) = 0; + + S2(2, 0) = 0; + S2(2, 1) = 0; + S2(2, 2) = 1; + + CRSMatrix B{S2.getCRSMatrix()}; + SECTION("eigenvalues") { SmallArray<double> eigenvalues; @@ -73,6 +92,8 @@ TEST_CASE("EigenvalueSolver", "[algebra]") } D(i, i) = eigenvalue_list[i]; } + SmallMatrix<double> eigen{3}; + eigen = zero; SmallMatrix PDPT = P * D * PT; for (size_t i = 0; i < 3; ++i) { @@ -104,6 +125,15 @@ TEST_CASE("EigenvalueSolver", "[algebra]") D(i, i) = eigenvalue_list[i]; } SmallMatrix PT = transpose(P); + // double eigenval = -1.; + + TinyMatrix<3, 3, double> TinyA; + for (size_t i = 0; i < 3; ++i) { + for (size_t j = 0; j < 3; ++j) { + TinyA(i, j) = S(i, j); + } + } + // auto E = findEigenvectors(TinyA, eigenval); SmallMatrix PDPT = P * D * PT; for (size_t i = 0; i < 3; ++i) { @@ -120,6 +150,8 @@ TEST_CASE("EigenvalueSolver", "[algebra]") { SmallMatrix<double> expA{}; SmallMatrix<double> expS{3}; + SmallMatrix<double> expB{}; + // SmallMatrix<double> expS2{3}; expS(0, 0) = 1325.074593930307812; expS(0, 1) = 662.353357244568285; @@ -139,6 +171,15 @@ TEST_CASE("EigenvalueSolver", "[algebra]") REQUIRE(expA(i, j) - expS(i, j) == Catch::Approx(0).margin(1E-12)); } } + + // EigenvalueSolver{}.computeExpForSymmetricMatrix(B, expB); + + for (size_t i = 0; i < 3; ++i) { + for (size_t j = 0; j < 3; ++j) { + REQUIRE(expB(i, j) - expS(i, j) == Catch::Approx(0).margin(1E-12)); + } + } + #else // PUGS_HAS_SLEPC REQUIRE_THROWS_WITH(EigenvalueSolver{}.computeExpForSymmetricMatrix(A, expA), "not implemented yet: SLEPc is required to solve eigenvalue problems"); -- GitLab