Skip to content

Commit 703c2ca

Browse files
authored
Add all built-in solvers and several ordering methods (#1)
* Introduce LLT, LU and QR solvers * Choice of the ordering method * Add metis support * Optimal plugins * Link with Metis * find package metis * File encoding * Another try * Find metis for v21.12 * Fix CMakeLists.txt * unused variable * Remove find_package of metis * Missing template keyword * find_package SofaFramework * Make sure the linear solver module is found * Replace hard-coded value * Condition on finding the metis include file * Fix missing guard * Remove warning directive
1 parent f807b77 commit 703c2ca

28 files changed

+710
-121
lines changed

CMakeLists.txt

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,55 @@
11
cmake_minimum_required(VERSION 3.12)
22
project(EigenLinearSolvers VERSION 1.0 LANGUAGES CXX)
33

4-
find_package(Sofa.Component.LinearSolver QUIET)
5-
if (NOT Sofa.Component.LinearSolver_FOUND)
6-
find_package(SofaBaseLinearSolver QUIET)
4+
find_package(SofaFramework REQUIRED)
5+
find_package(Sofa.Component.LinearSolver.Direct QUIET)
6+
if (NOT Sofa.Component.LinearSolver.Direct_FOUND)
7+
find_package(SofaSparseSolver QUIET)
8+
endif()
9+
10+
if (NOT Sofa.Component.LinearSolver.Direct_FOUND AND NOT SofaSparseSolver_FOUND)
11+
message(FATAL "Cannot find the linear solver module in SOFA")
712
endif()
813

914
# List all files
1015
set(EIGENLINEARSOLVERS_SRC_DIR src/${PROJECT_NAME})
1116
set(HEADER_FILES
1217
${EIGENLINEARSOLVERS_SRC_DIR}/config.h.in
18+
${EIGENLINEARSOLVERS_SRC_DIR}/FindMetis.h
19+
20+
${EIGENLINEARSOLVERS_SRC_DIR}/SimplicialLDLTTraits.h
21+
${EIGENLINEARSOLVERS_SRC_DIR}/SimplicialLLTTraits.h
22+
${EIGENLINEARSOLVERS_SRC_DIR}/SparseLUTraits.h
23+
${EIGENLINEARSOLVERS_SRC_DIR}/SparseQRTraits.h
1324

1425
${EIGENLINEARSOLVERS_SRC_DIR}/EigenConjugateGradient.h
1526
${EIGENLINEARSOLVERS_SRC_DIR}/EigenConjugateGradient[CRS].h
1627
${EIGENLINEARSOLVERS_SRC_DIR}/EigenConjugateGradient[CRS].inl
1728

29+
${EIGENLINEARSOLVERS_SRC_DIR}/EigenDirectSparseSolver.h
30+
${EIGENLINEARSOLVERS_SRC_DIR}/EigenDirectSparseSolver[CRS].h
31+
${EIGENLINEARSOLVERS_SRC_DIR}/EigenDirectSparseSolver[CRS].inl
32+
1833
${EIGENLINEARSOLVERS_SRC_DIR}/EigenSimplicialLDLT.h
1934
${EIGENLINEARSOLVERS_SRC_DIR}/EigenSimplicialLDLT[CRS].h
20-
${EIGENLINEARSOLVERS_SRC_DIR}/EigenSimplicialLDLT[CRS].inl
35+
36+
${EIGENLINEARSOLVERS_SRC_DIR}/EigenSimplicialLLT.h
37+
${EIGENLINEARSOLVERS_SRC_DIR}/EigenSimplicialLLT[CRS].h
38+
39+
${EIGENLINEARSOLVERS_SRC_DIR}/EigenSparseLU.h
40+
${EIGENLINEARSOLVERS_SRC_DIR}/EigenSparseLU[CRS].h
41+
42+
${EIGENLINEARSOLVERS_SRC_DIR}/EigenSparseQR.h
43+
${EIGENLINEARSOLVERS_SRC_DIR}/EigenSparseQR[CRS].h
2144
)
2245
set(SOURCE_FILES
2346
${EIGENLINEARSOLVERS_SRC_DIR}/init.cpp
2447

2548
${EIGENLINEARSOLVERS_SRC_DIR}/EigenConjugateGradient[CRS].cpp
2649
${EIGENLINEARSOLVERS_SRC_DIR}/EigenSimplicialLDLT[CRS].cpp
50+
${EIGENLINEARSOLVERS_SRC_DIR}/EigenSimplicialLLT[CRS].cpp
51+
${EIGENLINEARSOLVERS_SRC_DIR}/EigenSparseLU[CRS].cpp
52+
${EIGENLINEARSOLVERS_SRC_DIR}/EigenSparseQR[CRS].cpp
2753
)
2854
set(README_FILES
2955
README.md
@@ -33,10 +59,10 @@ set(README_FILES
3359
add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES} ${README_FILES})
3460

3561
# Link the plugin library to its dependency(ies).
36-
if (Sofa.Component.LinearSolver_FOUND)
37-
target_link_libraries(${PROJECT_NAME} Sofa.Component.LinearSolver)
38-
elseif(SofaBaseLinearSolver_FOUND)
39-
target_link_libraries(${PROJECT_NAME} SofaBaseLinearSolver)
62+
if (Sofa.Component.LinearSolver.Direct_FOUND)
63+
target_link_libraries(${PROJECT_NAME} Sofa.Component.LinearSolver.Direct)
64+
elseif(SofaSparseSolver_FOUND)
65+
target_link_libraries(${PROJECT_NAME} SofaSparseSolver)
4066
endif()
4167

4268
# Create package Config, Version & Target files.

scenes/Cylinder_EigenSimplicialLDLT.scn

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
<Node name="root" gravity="-1.8 0 100" dt="0.001">
2-
<RequiredPlugin name="SofaBoundaryCondition"/>
3-
<RequiredPlugin name="SofaImplicitOdeSolver"/>
4-
<RequiredPlugin name="SofaLoader"/>
5-
<RequiredPlugin name="SofaMiscForceField"/>
6-
<RequiredPlugin name="SofaOpenglVisual"/>
7-
<RequiredPlugin name="SofaSimpleFem"/>
8-
<RequiredPlugin name="EigenLinearSolvers"/>
2+
<RequiredPlugin name="EigenLinearSolvers"/> <!-- Needed to use components [EigenSimplicialLDLT] -->
3+
<RequiredPlugin name="Sofa.Component.Constraint.Projective"/> <!-- Needed to use components [FixedConstraint] -->
4+
<RequiredPlugin name="Sofa.Component.Mapping.Linear"/> <!-- Needed to use components [BarycentricMapping] -->
5+
<RequiredPlugin name="Sofa.Component.Mass"/> <!-- Needed to use components [MeshMatrixMass] -->
6+
<RequiredPlugin name="Sofa.Component.ODESolver.Backward"/> <!-- Needed to use components [EulerImplicitSolver] -->
7+
<RequiredPlugin name="Sofa.Component.SolidMechanics.FEM.Elastic"/> <!-- Needed to use components [TetrahedronFEMForceField] -->
8+
<RequiredPlugin name="Sofa.Component.StateContainer"/> <!-- Needed to use components [MechanicalObject] -->
9+
<RequiredPlugin name="Sofa.GL.Component.Rendering3D"/> <!-- Needed to use components [OglModel] -->
910

1011
<Node name="DeformableObject">
1112

1213
<EulerImplicitSolver name="odeImplicitSolver" />
1314

14-
<EigenSimplicialLDLT template="CompressedRowSparseMatrixMat3x3d"/>
15+
<EigenSimplicialLDLT template="CompressedRowSparseMatrixMat3x3d" ordering="Metis"/>
1516

1617
<MeshGmshLoader name="loader" filename="mesh/truthcylinder1.msh" />
1718
<TetrahedronSetTopologyContainer src="@loader" name="topologyContainer"/>

scenes/FEMBAR_EigenConjugateGradient.scn

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
<Node name="root" dt="0.02" gravity="0 -10 0">
22

33
<Node name="plugins">
4-
<RequiredPlugin name="SofaBoundaryCondition"/>
5-
<RequiredPlugin name="SofaImplicitOdeSolver"/>
6-
<RequiredPlugin name="SofaEngine"/>
4+
<RequiredPlugin name="EigenLinearSolvers"/> <!-- Needed to use components [EigenConjugateGradient] -->
5+
<RequiredPlugin name="Sofa.Component.Constraint.Projective"/> <!-- Needed to use components [FixedConstraint] -->
6+
<RequiredPlugin name="Sofa.Component.Mass"/> <!-- Needed to use components [UniformMass] -->
7+
<RequiredPlugin name="Sofa.Component.ODESolver.Backward"/> <!-- Needed to use components [EulerImplicitSolver] -->
8+
<RequiredPlugin name="Sofa.Component.SolidMechanics.FEM.Elastic"/> <!-- Needed to use components [HexahedronFEMForceField] -->
9+
<RequiredPlugin name="Sofa.Component.StateContainer"/> <!-- Needed to use components [MechanicalObject] -->
10+
<RequiredPlugin name="Sofa.Component.Topology.Container.Grid"/> <!-- Needed to use components [RegularGridTopology] -->
11+
<RequiredPlugin name="Sofa.Component.Visual"/> <!-- Needed to use components [VisualStyle] -->
12+
<RequiredPlugin name="SofaEngine"/> <!-- Needed to use components [BoxROI] -->
713

8-
<RequiredPlugin name="SofaSimpleFem"/>
9-
<RequiredPlugin name="SofaPreconditioner"/>
10-
<RequiredPlugin name="EigenLinearSolvers"/>
1114
</Node>
1215

1316
<VisualStyle displayFlags="showBehaviorModels showForceFields" />
@@ -16,7 +19,7 @@
1619
<DefaultVisualManagerLoop name="visualLoop"/>
1720

1821
<EulerImplicitSolver name="odesolver" rayleighStiffness="0.1" rayleighMass="0.1" />
19-
<EigenConjugateGradient template="EigenSparseMatrixd" iterations="1000" tolerance="1e-9" preconditioner="diagonal"/>
22+
<EigenConjugateGradient template="CompressedRowSparseMatrixMat3x3d" iterations="1000" tolerance="1e-9" preconditioner="diagonal"/>
2023

2124
<RegularGridTopology name="grid" nx="4" ny="4" nz="20" xmin="-9" xmax="-6" ymin="0" ymax="3" zmin="0" zmax="19" />
2225
<MechanicalObject name="DoFs" />

scenes/FEMBAR_EigenSimplicialLDLT.scn

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
<Node name="root" dt="0.02" gravity="0 -10 0">
22

33
<Node name="plugins">
4-
<RequiredPlugin name="SofaBoundaryCondition"/>
5-
<RequiredPlugin name="SofaImplicitOdeSolver"/>
6-
<RequiredPlugin name="SofaEngine"/>
4+
<RequiredPlugin name="EigenLinearSolvers"/> <!-- Needed to use components [EigenSimplicialLDLT] -->
5+
<RequiredPlugin name="Sofa.Component.Constraint.Projective"/> <!-- Needed to use components [FixedConstraint] -->
6+
<RequiredPlugin name="Sofa.Component.Mass"/> <!-- Needed to use components [UniformMass] -->
7+
<RequiredPlugin name="Sofa.Component.ODESolver.Backward"/> <!-- Needed to use components [EulerImplicitSolver] -->
8+
<RequiredPlugin name="Sofa.Component.SolidMechanics.FEM.Elastic"/> <!-- Needed to use components [HexahedronFEMForceField] -->
9+
<RequiredPlugin name="Sofa.Component.StateContainer"/> <!-- Needed to use components [MechanicalObject] -->
10+
<RequiredPlugin name="Sofa.Component.Topology.Container.Grid"/> <!-- Needed to use components [RegularGridTopology] -->
11+
<RequiredPlugin name="Sofa.Component.Visual"/> <!-- Needed to use components [VisualStyle] -->
12+
<RequiredPlugin name="SofaEngine"/> <!-- Needed to use components [BoxROI] -->
713

8-
<RequiredPlugin name="SofaSimpleFem"/>
9-
<RequiredPlugin name="SofaPreconditioner"/>
10-
<RequiredPlugin name="EigenLinearSolvers"/>
1114
</Node>
1215

1316
<VisualStyle displayFlags="showBehaviorModels showForceFields" />
@@ -16,7 +19,7 @@
1619
<DefaultVisualManagerLoop name="visualLoop"/>
1720

1821
<EulerImplicitSolver name="odesolver" rayleighStiffness="0.1" rayleighMass="0.1" />
19-
<EigenSimplicialLDLT template="CompressedRowSparseMatrixMat3x3d"/>
22+
<EigenSimplicialLDLT template="CompressedRowSparseMatrixMat3x3d" ordering="Natural"/>
2023

2124
<RegularGridTopology name="grid" nx="4" ny="4" nz="20" xmin="-9" xmax="-6" ymin="0" ymax="3" zmin="0" zmax="19" />
2225
<MechanicalObject name="DoFs" />
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<Node name="root" dt="0.02" gravity="0 -10 0">
2+
3+
<Node name="plugins">
4+
<RequiredPlugin name="EigenLinearSolvers"/> <!-- Needed to use components [EigenSimplicialLLT] -->
5+
<RequiredPlugin name="Sofa.Component.Constraint.Projective"/> <!-- Needed to use components [FixedConstraint] -->
6+
<RequiredPlugin name="Sofa.Component.Mass"/> <!-- Needed to use components [UniformMass] -->
7+
<RequiredPlugin name="Sofa.Component.ODESolver.Backward"/> <!-- Needed to use components [EulerImplicitSolver] -->
8+
<RequiredPlugin name="Sofa.Component.SolidMechanics.FEM.Elastic"/> <!-- Needed to use components [HexahedronFEMForceField] -->
9+
<RequiredPlugin name="Sofa.Component.StateContainer"/> <!-- Needed to use components [MechanicalObject] -->
10+
<RequiredPlugin name="Sofa.Component.Topology.Container.Grid"/> <!-- Needed to use components [RegularGridTopology] -->
11+
<RequiredPlugin name="Sofa.Component.Visual"/> <!-- Needed to use components [VisualStyle] -->
12+
<RequiredPlugin name="SofaEngine"/> <!-- Needed to use components [BoxROI] -->
13+
14+
</Node>
15+
16+
<VisualStyle displayFlags="showBehaviorModels showForceFields" />
17+
18+
<DefaultAnimationLoop name="animationLoop"/>
19+
<DefaultVisualManagerLoop name="visualLoop"/>
20+
21+
<EulerImplicitSolver name="odesolver" rayleighStiffness="0.1" rayleighMass="0.1" />
22+
<EigenSimplicialLLT template="CompressedRowSparseMatrixMat3x3d" ordering="AMD"/>
23+
24+
<RegularGridTopology name="grid" nx="4" ny="4" nz="20" xmin="-9" xmax="-6" ymin="0" ymax="3" zmin="0" zmax="19" />
25+
<MechanicalObject name="DoFs" />
26+
27+
<UniformMass name="mass" totalMass="320" />
28+
<HexahedronFEMForceField name="FEM" youngModulus="4000" poissonRatio="0.45" method="large" />
29+
30+
<BoxROI name="box" box="-10 -1 -0.0001 -5 4 0.0001"/>
31+
<FixedConstraint indices="@box.indices" />
32+
33+
</Node>

scenes/FEMBAR_EigenSparseLU.scn

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<Node name="root" dt="0.02" gravity="0 -10 0">
2+
3+
<Node name="plugins">
4+
<RequiredPlugin name="EigenLinearSolvers"/> <!-- Needed to use components [EigenSparseLU] -->
5+
<RequiredPlugin name="Sofa.Component.Constraint.Projective"/> <!-- Needed to use components [FixedConstraint] -->
6+
<RequiredPlugin name="Sofa.Component.Mass"/> <!-- Needed to use components [UniformMass] -->
7+
<RequiredPlugin name="Sofa.Component.ODESolver.Backward"/> <!-- Needed to use components [EulerImplicitSolver] -->
8+
<RequiredPlugin name="Sofa.Component.SolidMechanics.FEM.Elastic"/> <!-- Needed to use components [HexahedronFEMForceField] -->
9+
<RequiredPlugin name="Sofa.Component.StateContainer"/> <!-- Needed to use components [MechanicalObject] -->
10+
<RequiredPlugin name="Sofa.Component.Topology.Container.Grid"/> <!-- Needed to use components [RegularGridTopology] -->
11+
<RequiredPlugin name="Sofa.Component.Visual"/> <!-- Needed to use components [VisualStyle] -->
12+
<RequiredPlugin name="SofaEngine"/> <!-- Needed to use components [BoxROI] -->
13+
14+
</Node>
15+
16+
<VisualStyle displayFlags="showBehaviorModels showForceFields" />
17+
18+
<DefaultAnimationLoop name="animationLoop"/>
19+
<DefaultVisualManagerLoop name="visualLoop"/>
20+
21+
<EulerImplicitSolver name="odesolver" rayleighStiffness="0.1" rayleighMass="0.1" />
22+
<EigenSparseLU template="CompressedRowSparseMatrixMat3x3d" ordering="Natural"/>
23+
24+
<RegularGridTopology name="grid" nx="4" ny="4" nz="20" xmin="-9" xmax="-6" ymin="0" ymax="3" zmin="0" zmax="19" />
25+
<MechanicalObject name="DoFs" />
26+
27+
<UniformMass name="mass" totalMass="320" />
28+
<HexahedronFEMForceField name="FEM" youngModulus="4000" poissonRatio="0.45" method="large" />
29+
30+
<BoxROI name="box" box="-10 -1 -0.0001 -5 4 0.0001"/>
31+
<FixedConstraint indices="@box.indices" />
32+
33+
</Node>

src/EigenLinearSolvers/EigenConjugateGradient.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ namespace EigenLinearSolvers
55
{
66

77
/**
8-
* EigenConjugateGradient is a SOFA component allowing to solve a of linear equations. This is an essential component
8+
* EigenConjugateGradient is a SOFA component allowing to solve a set of linear equations. This is an essential component
99
* in a SOFA simulation.
1010
*
1111
* The class is empty because it is partially specialized in other files.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#pragma once
2+
#include <EigenLinearSolvers/config.h>
3+
4+
namespace EigenLinearSolvers
5+
{
6+
7+
template<class TMatrix, class TVector, class EigenSolver>
8+
class EigenDirectSparseSolver
9+
{
10+
public:
11+
virtual ~EigenDirectSparseSolver() = default;
12+
};
13+
14+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
#pragma once
2+
#include <EigenLinearSolvers/config.h>
3+
4+
#include <EigenLinearSolvers/EigenDirectSparseSolver.h>
5+
6+
#if __has_include(<sofa/component/linearsolver/iterative/MatrixLinearSolver.h>)
7+
#include <sofa/component/linearsolver/iterative/MatrixLinearSolver.h>
8+
#else
9+
#include <SofaBaseLinearSolver/MatrixLinearSolver.h>
10+
#endif
11+
12+
#include <variant>
13+
#include <Eigen/SparseCore>
14+
15+
#include <sofa/helper/OptionsGroup.h>
16+
#include <EigenLinearSolvers/FindMetis.h>
17+
18+
namespace EigenLinearSolvers
19+
{
20+
21+
/**
22+
* Partial template specialization of EigenDirectSparseSolver for a matrix of type CompressedRowSparseMatrix
23+
*/
24+
template<class TBlockType, class EigenSolver>
25+
class EigenDirectSparseSolver<
26+
sofa::linearalgebra::CompressedRowSparseMatrix<TBlockType>,
27+
sofa::linearalgebra::FullVector<typename sofa::linearalgebra::CompressedRowSparseMatrix<TBlockType>::Real>,
28+
EigenSolver >
29+
: public sofa::component::linearsolver::MatrixLinearSolver<
30+
sofa::linearalgebra::CompressedRowSparseMatrix<TBlockType>,
31+
sofa::linearalgebra::FullVector<typename sofa::linearalgebra::CompressedRowSparseMatrix<TBlockType>::Real> >
32+
{
33+
public:
34+
typedef sofa::linearalgebra::CompressedRowSparseMatrix<TBlockType> Matrix;
35+
using Real = typename Matrix::Real;
36+
typedef sofa::linearalgebra::FullVector<Real> Vector;
37+
38+
SOFA_ABSTRACT_CLASS(SOFA_TEMPLATE3(EigenDirectSparseSolver, Matrix, Vector, EigenSolver),
39+
SOFA_TEMPLATE2(sofa::component::linearsolver::MatrixLinearSolver, Matrix, Vector));
40+
41+
using NaturalOrderSolver = typename EigenSolver::NaturalOrderSolver;
42+
using AMDOrderSolver = typename EigenSolver::AMDOrderSolver;
43+
using COLAMDOrderSolver = typename EigenSolver::COLAMDOrderSolver;
44+
#if EIGENLINEARSOLVERS_HAS_METIS_INCLUDE == 1
45+
using MetisOrderSolver = typename EigenSolver::MetisOrderSolver;
46+
#endif
47+
48+
~EigenDirectSparseSolver() override = default;
49+
50+
void init() override;
51+
void reinit() override;
52+
53+
using EigenSparseMatrix = Eigen::SparseMatrix<Real, Eigen::RowMajor>;
54+
using EigenSparseMatrixMap = Eigen::Map<EigenSparseMatrix>;
55+
using EigenVectorXdMap = Eigen::Map<Eigen::Matrix<Real, Eigen::Dynamic, 1> >;
56+
57+
void solve (Matrix& A, Vector& x, Vector& b) override;
58+
void invert(Matrix& A) override;
59+
60+
protected:
61+
62+
sofa::core::objectmodel::Data<sofa::helper::OptionsGroup> d_orderingMethod;
63+
unsigned int m_selectedOrderingMethod { std::numeric_limits<unsigned int>::max() };
64+
65+
std::variant<NaturalOrderSolver, AMDOrderSolver, COLAMDOrderSolver
66+
#if EIGENLINEARSOLVERS_HAS_METIS_INCLUDE == 1
67+
, MetisOrderSolver
68+
#endif
69+
> m_solver;
70+
71+
Eigen::ComputationInfo getSolverInfo() const;
72+
void updateSolverOderingMethod();
73+
74+
sofa::linearalgebra::CompressedRowSparseMatrix<Real> Mfiltered;
75+
std::unique_ptr<EigenSparseMatrixMap> m_map;
76+
77+
typename sofa::linearalgebra::CompressedRowSparseMatrix<Real>::VecIndex MfilteredrowBegin;
78+
typename sofa::linearalgebra::CompressedRowSparseMatrix<Real>::VecIndex MfilteredcolsIndex;
79+
80+
EigenDirectSparseSolver();
81+
};
82+
83+
}

0 commit comments

Comments
 (0)