Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
63514a4
Start removing assembly function from linear solvers
alxbilger Aug 6, 2025
3f0c14f
move internal functions to protected
alxbilger Aug 6, 2025
5f4c3a7
cache factorization + cache invalidation
alxbilger Aug 7, 2025
181bd27
remove more "assembly" functions
alxbilger Aug 7, 2025
68ae25a
fix AsyncSparseLDLSolver
alxbilger Aug 7, 2025
79c49e8
add missing templates to the factory
alxbilger Aug 7, 2025
b2beca4
CompositeLinearSystem can support multiple types of linear systems
alxbilger Aug 7, 2025
dcc559f
introduce preconditioned systems
alxbilger Aug 7, 2025
505c882
a bit of cleaning
alxbilger Aug 8, 2025
6daf4f3
convert double to Real
alxbilger Aug 8, 2025
134fd4d
add an error if wrong type
alxbilger Aug 8, 2025
294cc4f
Restoration of the parameter controlling the assembly rate of the pre…
alxbilger Aug 8, 2025
74783e3
restore removed Data with a deprecation layer
alxbilger Aug 8, 2025
4bcf3dd
restore initial parameter for regression tests
alxbilger Aug 8, 2025
ae0577c
fix PrecomputedLinearSolver
alxbilger Aug 8, 2025
3536bbc
mark WarpPreconditioner destructor as `override`
alxbilger Sep 15, 2025
bd2dccc
minor cleaning
alxbilger Sep 15, 2025
949beda
simplify `checkLinearSystem` in WarpPreconditioner implementation
alxbilger Sep 15, 2025
bea6494
add license header to RotationMatrixSystem header file
alxbilger Sep 15, 2025
310b266
fix typo in registration description of RotationMatrixSystem
alxbilger Sep 15, 2025
8f8e030
modernize code style
alxbilger Sep 16, 2025
d00e57b
add missing `RotationMatrixSystem.inl` to CMakeLists.txt
alxbilger Sep 16, 2025
978df39
replace `addSlave` with `addObject` in MatrixLinearSolver
alxbilger Sep 16, 2025
29dc747
add SOFA class macros for proper class hierarchy
alxbilger Sep 16, 2025
db72324
Missing space
alxbilger Sep 16, 2025
cd5ef41
proper initialization of systems and solvers
alxbilger Sep 16, 2025
48f707b
validate `l_linearSystem` type in `PCGLinearSolver`
alxbilger Sep 17, 2025
cc4cd1b
fix typo in error message of `PCGLinearSolver`
alxbilger Sep 17, 2025
8c24874
validate `l_mainAssembledSystem` and handle missing or invalid linear…
alxbilger Sep 17, 2025
1774746
validate `l_linearSystem` type and ensure compatibility with `Rotatio…
alxbilger Sep 17, 2025
51d5f2a
don't link to itself
alxbilger Sep 17, 2025
733afcf
refactor `RotationMatrixSystem` and `WarpPreconditioner` for clearer …
alxbilger Sep 17, 2025
d31ed92
some comments
alxbilger Sep 18, 2025
cdfbd46
proper deprecation
alxbilger Sep 18, 2025
d828970
update scene
alxbilger Sep 18, 2025
581d345
minor changes
alxbilger Sep 18, 2025
223262a
add `template` keyword to `get` and `getObjects` calls in `RotationMa…
alxbilger Sep 18, 2025
539c5ec
invert includes order to allow object factory to find the component m…
alxbilger Sep 19, 2025
fa2e52b
apply changes
alxbilger Sep 19, 2025
e0aee69
deprecation
alxbilger Oct 9, 2025
dae0bbc
forgot a file
alxbilger Oct 10, 2025
e4d0d9b
simplify `checkLinearSystem` logic using `doCheckLinearSystem`
alxbilger Oct 13, 2025
43c5df1
add components that are created implicitly in the scene
alxbilger Oct 13, 2025
9f2932c
add a description to a class member
alxbilger Oct 13, 2025
3a8b168
see if regression test is happy
alxbilger Oct 13, 2025
e81b8ae
rename `d_authorizeAssembly` to `d_enableAssembly`
alxbilger Oct 16, 2025
446edf9
rename Data name
alxbilger Oct 16, 2025
cd7c3d3
fix call to MechanicalMultiVectorPeqBaseVectorVisitor but actually it…
alxbilger Oct 16, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ void LinearSolverConstraintCorrection<DataTypes>::addComplianceInConstraintSpace
}

// use the Linear solver to compute J*A^-1*J^T, where A is the mechanical linear system matrix
l_linearSolver->setSystemLHVector(sofa::core::MultiVecDerivId::null());
l_linearSolver->getLinearSystem()->setSystemSolution(sofa::core::MultiVecDerivId::null());
l_linearSolver->addJMInvJt(W, &m_constraintJacobian, factor);

addRegularization(W);
Expand Down Expand Up @@ -247,9 +247,10 @@ void LinearSolverConstraintCorrection< DataTypes >::computeMotionCorrection(cons
{
if (mstate && l_linearSolver.get())
{
l_linearSolver->setSystemRHVector(f);
l_linearSolver->setSystemLHVector(dx);
l_linearSolver->getLinearSystem()->setRHS(f);
l_linearSolver->getLinearSystem()->setSystemSolution(dx);
l_linearSolver->solveSystem();
l_linearSolver->getLinearSystem()->dispatchSystemSolution(dx);
}
}

Expand Down Expand Up @@ -373,9 +374,10 @@ void LinearSolverConstraintCorrection<DataTypes>::applyContactForce(const linear
}
}
}
l_linearSolver->setSystemRHVector(forceID);
l_linearSolver->setSystemLHVector(dxID);
l_linearSolver->getLinearSystem()->setRHS(forceID);
l_linearSolver->getLinearSystem()->setSystemSolution(dxID);
l_linearSolver->solveSystem();
l_linearSolver->getLinearSystem()->dispatchSystemSolution(dxID);

//TODO: tell the solver not to recompute the matrix

Expand Down Expand Up @@ -541,13 +543,13 @@ void LinearSolverConstraintCorrection<DataTypes>::resetForUnbuiltResolution(SRea
core::VecDerivId forceID(core::VecDerivId::V_FIRST_DYNAMIC_INDEX);
core::VecDerivId dxID = core::vec_id::write_access::dx;

l_linearSolver->setSystemRHVector(forceID);
l_linearSolver->setSystemLHVector(dxID);
l_linearSolver->getLinearSystem()->setRHS(forceID);
l_linearSolver->getLinearSystem()->setSystemSolution(dxID);


systemMatrix_buf = l_linearSolver->getSystemBaseMatrix();
systemRHVector_buf = l_linearSolver->getSystemRHBaseVector();
systemLHVector_buf = l_linearSolver->getSystemLHBaseVector();
systemMatrix_buf = l_linearSolver->getLinearSystem()->getSystemBaseMatrix();
systemRHVector_buf = l_linearSolver->getLinearSystem()->getSystemRHSBaseVector();
systemLHVector_buf = l_linearSolver->getLinearSystem()->getSystemSolutionBaseVector();
systemLHVector_buf_fullvector = dynamic_cast<linearalgebra::FullVector<Real>*>(systemLHVector_buf); // Cast checking whether the LH vector is a FullVector to improve performances

constexpr const auto derivDim = Deriv::total_size;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -355,9 +355,6 @@ void PrecomputedConstraintCorrection<DataTypes>::bwdInit()
fact *= eulerSolver->getPositionIntegrationFactor(); // here, we compute a compliance

eulerSolver->solve(core::execparams::defaultInstance(), dt, core::vec_id::write_access::position, core::vec_id::write_access::velocity);

if (linearSolver)
linearSolver->freezeSystemMatrix(); // do not recompute the matrix for the rest of the precomputation
}

for (unsigned int v = 0; v < nbNodes; v++)
Expand All @@ -374,10 +371,6 @@ void PrecomputedConstraintCorrection<DataTypes>::bwdInit()
msg_info() << tmpStr.str();
}

// Do not recompute the matrix for the rest of the precomputation
if (linearSolver)
linearSolver->freezeSystemMatrix();

saveCompliance(invName);

// Restore gravity
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,21 +62,19 @@ class AsyncSparseLDLSolver : public SparseLDLSolver<TMatrix, TVector, TThreadMan
bool isAsyncSolver() override { return true; }

void init() override;
void reset() override;

void setSystemMBKMatrix(const core::MechanicalParams* mparams) override;
void solveSystem() override;
void solve (Matrix& M, Vector& x, Vector& b) override;
void invert(TMatrix& M) override;
bool addJMInvJtLocal(TMatrix * M, ResMatrixType * result,const JMatrixType * J, SReal fact) override;

bool hasUpdatedMatrix() override;
void updateSystemMatrix() override;

AsyncSparseLDLSolver();
~AsyncSparseLDLSolver() override;

protected:

/// A second instantiation is needed to differentiate the one which is computed asynchronously, and the one which
/// A second instantiation is needed to differentiate the one that is computed asynchronously and the one that
/// is used to solve the system in the main thread
InvertData m_secondInvertData;

Expand All @@ -99,7 +97,7 @@ class AsyncSparseLDLSolver : public SparseLDLSolver<TMatrix, TVector, TThreadMan

std::atomic<bool> newInvertDataReady { false };

bool m_hasUpdatedMatrix { false };
Data< bool > d_enableAssembly;
};

#if !defined(SOFA_COMPONENT_LINEARSOLVER_ASYNCSPARSELDLSOLVER_CPP)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,44 +29,58 @@ namespace sofa::component::linearsolver::direct
{

template <class TMatrix, class TVector, class TThreadManager>
void AsyncSparseLDLSolver<TMatrix, TVector, TThreadManager>::init()
AsyncSparseLDLSolver<TMatrix, TVector, TThreadManager>::AsyncSparseLDLSolver()
: d_enableAssembly(initData(&d_enableAssembly, true, "enableAssembly", "Allow assembly of the linear system"))
{
Inherit1::init();
waitForAsyncTask = true;
m_asyncThreadInvertData = &m_secondInvertData;
m_mainThreadInvertData = static_cast<InvertData*>(this->invertData.get());
}

template <class TMatrix, class TVector, class TThreadManager>
void AsyncSparseLDLSolver<TMatrix, TVector, TThreadManager>::setSystemMBKMatrix(const core::MechanicalParams* mparams)
void AsyncSparseLDLSolver<TMatrix, TVector, TThreadManager>::init()
{
if (isAsyncFactorizationFinished() || !m_asyncResult.valid())
Inherit1::init();

if (!this->isComponentStateInvalid())
{
SCOPED_TIMER_VARNAME(setSystemMBKMatrixTimer, "setSystemMBKMatrix");
Inherit1::setSystemMBKMatrix(mparams);
m_hasUpdatedMatrix = true;
if (this->l_linearSystem)
{
this->l_linearSystem->d_enableAssembly.setParent(&d_enableAssembly);
}

waitForAsyncTask = true;
m_asyncThreadInvertData = &m_secondInvertData;
m_mainThreadInvertData = static_cast<InvertData*>(this->invertData.get());
}
}

template <class TMatrix, class TVector, class TThreadManager>
void AsyncSparseLDLSolver<TMatrix, TVector, TThreadManager>::reset()
{
d_enableAssembly.setValue(true);
waitForAsyncTask = true;
}

template <class TMatrix, class TVector, class TThreadManager>
void AsyncSparseLDLSolver<TMatrix, TVector, TThreadManager>::solveSystem()
{
SCOPED_TIMER_VARNAME(invertDataCopyTimer, "AsyncSolve");
SCOPED_TIMER_VARNAME(invertDataCopyTimer, "solveSystem");

if (newInvertDataReady)
{
swapInvertData();
}

if (this->linearSystem.needInvert)
if (this->d_factorizationInvalidation.getValue())
{
if (this->invertData == nullptr)
{
this->getMatrixInvertData(this->getSystemMatrix());
this->getMatrixInvertData(this->l_linearSystem->getSystemMatrix());
m_mainThreadInvertData = static_cast<InvertData*>(this->invertData.get());
}
launchAsyncFactorization();
this->linearSystem.needInvert = false;
this->d_factorizationInvalidation.setValue(false);

//matrix assembly is temporarily stopped until the next factorization
d_enableAssembly.setValue(false);
}

if (waitForAsyncTask)
Expand All @@ -81,15 +95,11 @@ void AsyncSparseLDLSolver<TMatrix, TVector, TThreadManager>::solveSystem()
swapInvertData();
}

this->solve(*this->getSystemMatrix(), *this->getSystemLHVector(), *this->getSystemRHVector());
auto* A = this->l_linearSystem->getSystemMatrix();
auto* b = this->l_linearSystem->getRHSVector();
auto* x = this->l_linearSystem->getSolutionVector();

if (!this->linearSystem.solutionVecId.isNull())
{
if (this->l_linearSystem)
{
this->l_linearSystem->dispatchSystemSolution(this->linearSystem.solutionVecId);
}
}
this->solve(*A, *x, *b);
}

template <class TMatrix, class TVector, class TThreadManager>
Expand All @@ -107,8 +117,8 @@ void AsyncSparseLDLSolver<TMatrix, TVector, TThreadManager>::invert(TMatrix& M)
}

template <class TMatrix, class TVector, class TThreadManager>
bool AsyncSparseLDLSolver<TMatrix, TVector, TThreadManager>::addJMInvJtLocal(TMatrix* M, ResMatrixType* result,
const JMatrixType* J, SReal fact)
bool AsyncSparseLDLSolver<TMatrix, TVector, TThreadManager>::addJMInvJtLocal(
TMatrix* M, ResMatrixType* result, const JMatrixType* J, SReal fact)
{
SOFA_UNUSED(M);

Expand All @@ -119,18 +129,6 @@ bool AsyncSparseLDLSolver<TMatrix, TVector, TThreadManager>::addJMInvJtLocal(TMa
return Inherit1::doAddJMInvJtLocal(result, J, fact, m_mainThreadInvertData);
}

template <class TMatrix, class TVector, class TThreadManager>
bool AsyncSparseLDLSolver<TMatrix, TVector, TThreadManager>::hasUpdatedMatrix()
{
return m_hasUpdatedMatrix;
}

template <class TMatrix, class TVector, class TThreadManager>
void AsyncSparseLDLSolver<TMatrix, TVector, TThreadManager>::updateSystemMatrix()
{
m_hasUpdatedMatrix = false;
}

template <class TMatrix, class TVector, class TThreadManager>
AsyncSparseLDLSolver<TMatrix, TVector, TThreadManager>::~AsyncSparseLDLSolver()
{
Expand All @@ -154,9 +152,14 @@ void AsyncSparseLDLSolver<TMatrix, TVector, TThreadManager>::launchAsyncFactoriz
template <class TMatrix, class TVector, class TThreadManager>
void AsyncSparseLDLSolver<TMatrix, TVector, TThreadManager>::asyncFactorization()
{
SCOPED_TIMER_TR("asyncFactorization");

newInvertDataReady = false;
this->invert(*this->getSystemMatrix());
this->invert(*this->l_linearSystem->getSystemMatrix());
newInvertDataReady = true;

//factorization is finished: matrix assembly is authorized once again
d_enableAssembly.setValue(true);
}

template <class TMatrix, class TVector, class TThreadManager>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,7 @@ void BTDLinearSolver<Matrix,Vector>::init_partial_solve()
{

constexpr Index bsize = Matrix::getSubMatrixDim();
const Index nb = this->getSystemRHVector()->size() / bsize;
const Index nb = this->l_linearSystem->getRHSVector()->size() / bsize;

//TODO => optimisation ??
bwdContributionOnLH.clear();
Expand All @@ -419,7 +419,7 @@ void BTDLinearSolver<Matrix,Vector>::init_partial_solve()
{
Vec_dRH[i]=0;
Vec_dRH[i].resize(bsize);
_rh_buf.asub(i,bsize) = this->getSystemRHVector()->asub(i,bsize) ;
_rh_buf.asub(i,bsize) = this->l_linearSystem->getRHSVector()->asub(i,bsize) ;

}

Expand Down Expand Up @@ -456,7 +456,7 @@ void BTDLinearSolver<Matrix,Vector>::bwdAccumulateRHinBloc(Index indMaxBloc)
{

// evaluate the Right Hand Term for the block b
RHbloc = this->getSystemRHVector()->asub(b,bsize) ;
RHbloc = this->l_linearSystem->getRHSVector()->asub(b,bsize) ;

// compute the contribution on LH created by RH
_acc_lh_bloc += Minv.asub(b,b,bsize,bsize) * RHbloc;
Expand All @@ -474,7 +474,7 @@ void BTDLinearSolver<Matrix,Vector>::bwdAccumulateRHinBloc(Index indMaxBloc)

b = current_bloc;
// compute the block which indice is current_bloc
this->getSystemLHVector()->asub(b,bsize) = Minv.asub( b, b ,bsize,bsize) * ( fwdContributionOnRH.asub(b, bsize) + this->getSystemRHVector()->asub(b,bsize) ) +
this->l_linearSystem->getSolutionVector()->asub(b,bsize) = Minv.asub( b, b ,bsize,bsize) * ( fwdContributionOnRH.asub(b, bsize) + this->l_linearSystem->getRHSVector()->asub(b,bsize) ) +
bwdContributionOnLH.asub(b, bsize);

dmsg_info_when(showProblem) << "LH[" << b << "] = Minv[" << b << "][" << b << "] * (fwdRH(" << b << ") + RH(" << b << ")) + bwdLH(" << b << ")";
Expand All @@ -500,7 +500,7 @@ void BTDLinearSolver<Matrix,Vector>::bwdAccumulateLHGlobal( )
dmsg_info_when(showProblem) << "bwdLH[" << current_bloc - 1 << "] = H[" << current_bloc - 1 << "][" << current_bloc << "] *( bwdLH[" << current_bloc << "] + Minv[" << current_bloc << "][" << current_bloc << "] * RH[" << current_bloc << "])";

// BwdLH += Minv*RH
_acc_lh_bloc += Minv.asub(current_bloc,current_bloc,bsize,bsize) * this->getSystemRHVector()->asub(current_bloc,bsize) ;
_acc_lh_bloc += Minv.asub(current_bloc,current_bloc,bsize,bsize) * this->l_linearSystem->getRHSVector()->asub(current_bloc,bsize) ;

current_bloc--;
// BwdLH(n-1) = H(n-1)(n)*BwdLH(n)
Expand Down Expand Up @@ -540,7 +540,7 @@ void BTDLinearSolver<Matrix,Vector>::fwdAccumulateRHGlobal(Index indMinBloc)
{

// fwdRH(n) += RH(n)
_acc_rh_bloc += this->getSystemRHVector()->asub(current_bloc,bsize);
_acc_rh_bloc += this->l_linearSystem->getRHSVector()->asub(current_bloc,bsize);

// fwdRH(n+1) = H(n+1)(n) * fwdRH(n)
_acc_rh_bloc = -(lambda[current_bloc].t() * _acc_rh_bloc);
Expand All @@ -556,7 +556,7 @@ void BTDLinearSolver<Matrix,Vector>::fwdAccumulateRHGlobal(Index indMinBloc)

Index b = current_bloc;
// compute the block which indice is _indMaxFwdLHComputed
this->getSystemLHVector()->asub(b,bsize) = Minv.asub( b, b ,bsize,bsize) * ( fwdContributionOnRH.asub(b, bsize) + this->getSystemRHVector()->asub(b,bsize) ) +
this->l_linearSystem->getSolutionVector()->asub(b,bsize) = Minv.asub( b, b ,bsize,bsize) * ( fwdContributionOnRH.asub(b, bsize) + this->l_linearSystem->getRHSVector()->asub(b,bsize) ) +
bwdContributionOnLH.asub(b, bsize);

dmsg_info_when(showProblem) << "LH[" << b << "] = Minv[" << b << "][" << b << "] * (fwdRH(" << b << ") + RH(" << b << ")) + bwdLH(" << b << ")";
Expand Down Expand Up @@ -584,13 +584,13 @@ void BTDLinearSolver<Matrix,Vector>::fwdComputeLHinBloc(Index indMaxBloc)
{
dmsg_info_when(showProblem) << " fwdRH[" << b + 1 << "] = H[" << b + 1 << "][" << b << "] * (fwdRH(" << b << ") + RH(" << b << "))";
// fwdRH(n+1) = H(n+1)(n) * (fwdRH(n) + RH(n))
fwdContributionOnRH.asub(b+1, bsize) = (-lambda[b].t())* ( fwdContributionOnRH.asub(b, bsize) + this->getSystemRHVector()->asub(b,bsize) ) ;
fwdContributionOnRH.asub(b+1, bsize) = (-lambda[b].t())* ( fwdContributionOnRH.asub(b, bsize) + this->l_linearSystem->getRHSVector()->asub(b,bsize) ) ;
}

_indMaxFwdLHComputed++; b++;

// compute the block which indice is _indMaxFwdLHComputed
this->getSystemLHVector()->asub(b,bsize) = Minv.asub( b, b ,bsize,bsize) * ( fwdContributionOnRH.asub(b, bsize) + this->getSystemRHVector()->asub(b,bsize) ) +
this->l_linearSystem->getSolutionVector()->asub(b,bsize) = Minv.asub( b, b ,bsize,bsize) * ( fwdContributionOnRH.asub(b, bsize) + this->l_linearSystem->getRHSVector()->asub(b,bsize) ) +
bwdContributionOnLH.asub(b, bsize);

dmsg_info_when(showProblem) << "LH["<<b<<"] = Minv["<<b<<"]["<<b<<"] * (fwdRH("<<b<< ") + RH("<<b<<")) + bwdLH("<<b<<")";
Expand Down Expand Up @@ -668,12 +668,12 @@ void BTDLinearSolver<Matrix,Vector>::partial_solve(ListIndex& Iout, ListIndex&
{
constexpr Index bsize = Matrix::getSubMatrixDim();
Vector *Result_partial_Solve = new Vector();
(*Result_partial_Solve) = (*this->getSystemLHVector());
(*Result_partial_Solve) = (*this->l_linearSystem->getSolutionVector());

solve(*this->getSystemMatrix(),*this->getSystemLHVector(), *this->getSystemRHVector());
solve(*this->l_linearSystem->getSystemMatrix(),*this->l_linearSystem->getSolutionVector(), *this->l_linearSystem->getRHSVector());

Vector *Result = new Vector();
(*Result) = (*this->getSystemLHVector());
(*Result) = (*this->l_linearSystem->getSolutionVector());

Vector *DR = new Vector();
(*DR) = (*Result);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,11 @@ class PrecomputedLinearSolver : public sofa::component::linearsolver::MatrixLine

Data<bool> d_jmjt_twostep; ///< Use two step algorithm to compute JMinvJt
Data<bool> d_use_file; ///< Dump system matrix in a file
Data<double> init_Tolerance;
Data<Real> init_Tolerance;

PrecomputedLinearSolver();
void solve (TMatrix& M, TVector& x, TVector& b) override;
void solve (TMatrix& M, TVector& solution, TVector& rh) override;
void invert(TMatrix& M) override;
void setSystemMBKMatrix(const core::MechanicalParams* mparams) override;
void loadMatrix(TMatrix& M);
void loadMatrixWithCholeskyDecomposition(TMatrix& M);
bool addJMInvJt(linearalgebra::BaseMatrix* result, linearalgebra::BaseMatrix* J, SReal fact) override;
Expand Down Expand Up @@ -120,8 +119,8 @@ protected :
private :
bool first;
unsigned systemSize;
double dt;
double factInt;
Real dt;
Real factInt;
std::vector<bool> isActiveDofs;
};

Expand Down
Loading