Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[LinearSolvers] new solver for (symmetric) generalized eigenproblems using the spectra library #8440

Merged
merged 23 commits into from
Apr 15, 2021

Conversation

armingeiser
Copy link
Member

@armingeiser armingeiser commented Mar 5, 2021

Description
Inclusion of the spectra lib and a interface to its more efficient solver for generalized eigensystems of real symmetric matrices.

What is Spectra

  • A header-only C++ library for large scale eigenvalue problems
  • License: MPL2 (same as Eigen)
  • From the spectra github page:

    Spectra stands for Sparse Eigenvalue Computation Toolkit as a Redesigned ARPACK. It is a C++ library for large scale eigenvalue problems, built on top of Eigen, an open source linear algebra library.

    Spectra is implemented as a header-only C++ library, whose only dependency, Eigen, is also header-only. Hence Spectra can be easily embedded in C++ projects that require calculating eigenvalues of large matrices.

In a very first test it seems to be faster then the eigen_eigensystem (except if only 1-2 eigenvalues are searched)

  • Eigenfrequency of solid model
  • with MKL support (both solvers use PardisoLU internally)
n-dofs n-eigenvalues time eigen_eigensystem [s] time spectra_sym_g_eigs_shift [s] speed up
~110k 1 2.77 5.0 0.5x
~110k 2 6.3 4.3 1.5x
~110k 5 18.513 5.8906 3x
~110k 20 418.165 17.3014 24x

The speed up becomes more prominent when more then just a few eigenvalues are searched, since that is a known limitation of the eigen_eigensystem solver - see #2286

Changelog

  • Added header only library Spectra to LinearSolversApplication
  • Added new solver for generalized sparse eigensystems: spectra_sym_g_eigs_shift
  • Removed -DEIGEN_DEFAULT_TO_ROW_MAJOR and explicitly specify ordering in Eigen types when interfacing with KRatos matrices.

@@ -16,7 +16,7 @@ message( "**** configuring KratosLinearSolversApplication ****" )
################### PYBIND11
include(pybind11Tools)

add_definitions( -DEIGEN_DEFAULT_TO_ROW_MAJOR -DEIGEN_MPL2_ONLY )
# TODO add_definitions( -DEIGEN_MPL2_ONLY)
Copy link
Member Author

@armingeiser armingeiser Mar 5, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Spectra internally uses the Eigen::Cholesky, that however is not available with MPL2_ONLY. I will try to write an interface to another Eigen solver instead, ev, even MKL Edit: Cholesky is not needed, the MPL2 flag can remain unchanged.
  • We have tried Spectra before without success: I think it was because it does not work with -DEIGEN_DEFAULT_TO_ROW_MAJOR. That does not have to be used however, as long as we specify the RowMajor ordering explicitly when interfacing Eigen matrices with Kratos matrices.

Copy link
Member

@RiccardoRossi RiccardoRossi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dear @armingeiser i see myself obliged to block this PR since we are attempting to be restrictive with new libraries to be included.

Can u describe what is this library and why it is needed?

what is its license?

@RiccardoRossi
Copy link
Member

just to add that adding a library to this Application is even more restricted since it is a default app used by everyone else

@armingeiser
Copy link
Member Author

@RiccardoRossi i have updated the description, that should hopefully answer your questions.

@armingeiser
Copy link
Member Author

@philbucher @emiroglu feel free to try this solver with your problems, would be interesting to see how it compares to the existing eigen_eigensystem solver. Note however that also this solver expects symmetric input matrices.

@armingeiser armingeiser changed the title Linear solvers/spectra eigenvalue [LinearSolvers] new solver for (symmetric) generalized eigenproblems using the spectra library Mar 6, 2021
@armingeiser
Copy link
Member Author

Does anyone have an idea why compilation works with gcc but not with clang or on windows? The error is always similar:

In file included from /__w/Kratos/Kratos/build/FullDebug/applications/LinearSolversApplication/cotire/KratosLinearSolversApplication_CXX_unity.cxx:4:
/__w/Kratos/Kratos/applications/LinearSolversApplication/custom_python/add_custom_solvers_to_python.cpp:148:43: error: no template named 'SpectraSymGEigsShiftSolver'
    using SpectraSymGEigsRealSolverType = SpectraSymGEigsShiftSolver<>;

@philbucher
Copy link
Member

do you need the guards?

@armingeiser
Copy link
Member Author

armingeiser commented Mar 7, 2021

do you need the guards?

Yes.

Thanks for the hint. should be solved now.

I have not activted spectra for centos, windows, clang and nightly - since they also did not have MKL or Feast activated. Could be done however if desired.

@armingeiser armingeiser marked this pull request as ready for review March 7, 2021 09:51
@armingeiser armingeiser requested review from a team as code owners March 7, 2021 09:51
@oberbichler
Copy link
Member

@armingeiser do you remember the problems we had some years ago? Are they solved?

@@ -80,7 +80,7 @@ def _create_mechanical_solution_strategy(self):
computing_model_part = self.GetComputingModelPart()

solver_type = self.settings["eigensolver_settings"]["solver_type"].GetString()
if solver_type == "eigen_eigensystem":
if solver_type in ["eigen_eigensystem", "spectra_sym_g_eigs_shift"]: # TODO evaluate what has to be used for spectra
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ping did you confirm this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not yet, good catch.

Copy link
Member

@philbucher philbucher left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • why did you call it spectra1?
  • spectra offers many more solvers right? Do you have plans to expose those too?

@philbucher
Copy link
Member

I just checked this with my shell turbine model (~415K dofs) and it is much faster that the current solver
for me when computing 10 eigenvalues it was more than 10 times faster, independent of number of threads

@KratosMultiphysics/technical-committee I recommend to approve this, this is a very valuable addition IMO

@RiccardoRossi RiccardoRossi dismissed their stale review April 14, 2021 10:19

decision reached in @technicalcommittee

RiccardoRossi
RiccardoRossi previously approved these changes Apr 14, 2021
Copy link
Member

@RiccardoRossi RiccardoRossi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

approving on behalf of @KratosMultiphysics/technical-committee , on the assuption that it has the same license as Eigen

@armingeiser
Copy link
Member Author

@philbucher I have updated the PR with the things we discussed last time:

  • reuse the existing test
  • add a "define.h" where the Eigen matrix types are predefined using the row-major ordering. All other places in the app use these types now.

Copy link
Member

@philbucher philbucher left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice work!

Please use the Kratos error macro to also get the stack trace when throwing, otherwise very nice!

template<typename _Scalar> using EigenDynamicMatrix = Eigen::Matrix<_Scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
template<typename _Scalar> using EigenDynamicVector = Eigen::Matrix<_Scalar, Eigen::Dynamic, 1>;

template<typename _Scalar> using EigenSparseMatrix = Eigen::SparseMatrix<_Scalar, Eigen::RowMajor, int>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not for this PR but why int and not size_t?

@oberbichler

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pardiso is expecting signed integers. Therefore the max size of a matrix is ‚only’ 2,147,483,647 which should be more then enough. Eigen is also using signed ints for dense matrices as unsigned ints are very error prone for algorithms.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that means that with shell elements we are limited to ~ 350 nodes (6dofs/node) which I agree is pretty big :)

eigvecs = eigs.eigenvectors().transpose().colwise().reverse();

// --- normalization
// TODO seems to be normalized by Spectra already -> confirm!
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it would be nice if you could take a look in a followup PR


OpType op(a, b);
BOpType Bop(b);
const int ncv = 3 * nroot; // TODO find a good value
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same

@philbucher
Copy link
Member

* add a "define.h" where the Eigen matrix types are predefined using the row-major ordering.  All other places in the app use these types now.

this is very cool!

armingeiser and others added 2 commits April 14, 2021 17:57
…ym_g_eigs_shift_solver.h

Co-authored-by: Philipp Bucher <[email protected]>
…ym_g_eigs_shift_solver.h

Co-authored-by: Philipp Bucher <[email protected]>
philbucher
philbucher previously approved these changes Apr 14, 2021
@armingeiser
Copy link
Member Author

* why did you call it spectra**1**?

Because this is the current master branch, which will soon become spectra version 1.0 (yixuan/spectra#113)

* spectra offers many more solvers right? Do you have plans to expose those too?

It has many more features, however, currently i don't have any plans to further extend.
But i think with this first version, it will be easy to extend in case anyone needs further features from spectra.

namespace Kratos
{

// IMPORTANT:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is the other way round no?
Eigen default is column major while Kratos is row major

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🙈 fixed the comment

@armingeiser armingeiser merged commit 261a3d5 into master Apr 15, 2021
@armingeiser armingeiser deleted the LinearSolvers/spectra-eigenvalue branch April 15, 2021 10:43
@RiccardoRossi
Copy link
Member

RiccardoRossi commented Apr 15, 2021 via email

@philbucher
Copy link
Member

Seems like you didn’t check the latest changes

can you check master?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants