-
Notifications
You must be signed in to change notification settings - Fork 269
[LinearSolvers] Adding CG factorization for Spectra #13619
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
base: master
Are you sure you want to change the base?
[LinearSolvers] Adding CG factorization for Spectra #13619
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably not the best person to review this but just a couple of comments.
If we merge this, please, be sure to update these files with the new configuration option:
- Kratos/applications/LinearSolversApplication/README.md
- Kratos/applications/LinearSolversApplication/tests/test_eigensystem_solver.py
- Kratos/applications/StructuralMechanicsApplication/python_scripts/structural_mechanics_eigensolver.py
Or make custom_factorization
parameter optional. Otherwise it will crash on
https://github.com/KratosMultiphysics/Kratos/pull/13619/files#diff-a3d66cf319f1be32a63cf1686e3a86a71c328e4798458a27ba83550f55ae19a1R103.
On a side note #13587 is still not merged, so there should not be any effect from that PR.
if (m_cust_fact == "CG"){ | ||
|
||
MapConstVec x(x_in, m_n); | ||
MapVec y(y_out, m_n); | ||
y.noalias() = m_solverCG.solve(x); | ||
|
||
} else { | ||
MapConstVec x(x_in, m_n); | ||
MapVec y(y_out, m_n); | ||
y.noalias() = m_solver.solve(x); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
x
and y
declarations can remain outside the branch
|
||
namespace Kratos | ||
{ | ||
|
||
class OwnSymShiftInvert; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you need a forward declaration here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the idea, but I think it would benefit from more generality than hard-coding CG.
I don't have much experience with eigensolvers so call me out if I'm writing something stupid. What I'd do is use our LinearSolver
interface and its related factory
Kratos/kratos/solving_strategies/builder_and_solvers/p_multigrid/p_grid.cpp
Lines 87 to 93 in c69adba
const std::string solver_name = SmootherSettings["solver_type"].Get<std::string>(); | |
using SolverFactoryRegistry = KratosComponents<LinearSolverFactory<TSparse,TDense>>; | |
KRATOS_ERROR_IF_NOT(SolverFactoryRegistry::Has(solver_name)) | |
<< "\"" << solver_name << "\" is not a valid linear solver name in the registry. " | |
<< "Make sure you imported the application it is defined in and that the spelling is correct."; | |
const auto& r_factory = SolverFactoryRegistry::Get(solver_name); | |
mpSolver = r_factory.Create(SmootherSettings); |
LinearSolver::InitializeSolutionStep
is supposed to do factorization-like tasks that can later be reused for different right hand sides with LinearSolver::PerformSolutionStep
.
P.S.: the benefit is that you could use any linear solver we have in Kratos instead of just CG or LU.
#if !defined(BOOST_BIND_GLOBAL_PLACEHOLDERS) | ||
#define BOOST_BIND_GLOBAL_PLACEHOLDERS |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's this for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh this is for suppressing some warnings in old versions of boosts (1.63 to 1.74 or so), but agree, that should be defined globally in any case, not per file.
@@ -24,15 +27,22 @@ | |||
#include "linear_solvers/iterative_solver.h" | |||
#include "custom_utilities/ublas_wrapper.h" | |||
#include "utilities/builtin_timer.h" | |||
#include "linear_solvers/amgcl_solver.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a chunky include, and as far as I can tell you don't need it here.
|
||
namespace Kratos | ||
{ | ||
|
||
class OwnSymShiftInvert; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where's this forward declaration needed?
Cool stuff, I will comment probably on the weekend, have a bunch of comments and suggestions |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Global question aside from the one regarding the factory:
Afaik the advantage of a direct solver is also when computing many eigenvalues. The factorization can be done once and reused, whereas with an iterative solver you have to recompute the entire solution.
How many eigenvalues did you compute in your comparisons?
I have not yet done a detailed review because I would like to clarify the global questions first
@@ -60,7 +70,8 @@ class SpectraSymGEigsShiftSolver | |||
"normalize_eigenvectors": false, | |||
"max_iteration": 1000, | |||
"shift": 0.0, | |||
"echo_level": 1 | |||
"echo_level": 1, | |||
"custom_factorization": "sparse_lu" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why only limit this to two solvers? I.e. you can construct a linear solver via the factory, thus leaving it completely up to the user
Basically same comment as @matekelemen
Check out how this is done here: Kratos/kratos/linear_solvers/monotonicity_preserving_solver.h Lines 114 to 118 in a83ea2a
|
I guess the problem here is not performance but feasibility. He wrote he ran out of memory, in which case an iterative solver really is the only way to go, even if it scales worse with the number of requested eigenvalues. |
If you make the changes to support That said, they're unlikely to help you much in this case. Sure they're pretty efficient for the methods they implement, but they still have the memory complexity inherent to direct methods. For large systems, I recommend you give |
Thank you for the answers. |
📝 Description
OBS: not sure if related to #13587
Problem
Kratos crashes and returns a "Killed" message when trying to calculate the eigenvalues for structural mechanics problems for very large meshes.
Cause
By default, Kratosuses direct solvers to perform matrix operations in eigenvalue problems.
Fix
Modified
spectra_sym_g_eigs_shift_solver.h
in LinearSolversApplication to make it work with large meshes. Now the user can add a custom setting in theProjectParameters.json
file when using the"solver_type": "spectra_sym_g_eigs_shift"
. Example:"custom_factorization": "sparse_lu"
was the (implicit) default choice implemented in Kratos. This employs the sparse_lu direct solver to perform operations with matrices. However, direct methods require a lot of memory, causing the simulations to get killed when using large meshes (even with only"custom_factorization": "CG"
, which allows to use an iterative solver to perform such operations, reducing significantly the amount of memory required. Example:For now these are the only two options.
Recommendations
For small meshes ($\lesssim \mathcal{O}(10^5)$ nodes), the option $\mathcal{O}(10^5)$ nodes) and above, use
"custom_factorization": "sparse_lu"
is the quickest; for large meshes ("custom_factorization": "CG"
.