简体   繁体   中英

Strategies for filling an Eigen3 sparse matrix when the order of insertion is known

So in my nonlinear finite element solver i use Eigen3 sparse matrices and the LDLT factorization.

The thing is, this factorization needs to be performed many times during a dynamic simulation, and a lot of time is spent inserting the coefficients in the iteration matrix based on triplets (storage is reserved).

Is there any good strategies on how to utilize the fact that the sparsity is unchanged and the order of insertions are the same? When forming this matrix, looping over the elements, coupligs etc. in the model, the order of insertion are the same at every time step during the simulation.

Using coeffref increased simulation time with about 10x.

I've been thinking of making a single pass of the model and forming pointers directly to the respective location in the coefficient matrix, but this seems a bit dangerous, especially since the LDLT factorisation is run in between.

If the sparsity pattern of your matrix is not changing each time step, then you can directly change the values of the raw data array with valuePtr() . This is extremely simple and can be done in parallel if needed. If you can figure out how to do this in a linear fashion, ie

SparseMatrix<double> A;

for(int i = 0; i < n; i++)
   A.valuePtr()[i] = ...

then it will stupid fast (something to do with avoiding cache misses and other black magic). As for the previous comment that the LDLT factorization will not change, that is true from a theoretical standpoint. However, according to the Eigen documentation:

"In factorize(), the factors of the coefficient matrix are computed. This step should be called each time the values of the matrix change . However, the structural pattern of the matrix should not change between multiple calls."

https://eigen.tuxfamily.org/dox/group__TopicSparseSystems.html

I think this is because the factors are stored within the solver object, though I could be wrong. A test should be pretty easy to confirm one way or another. That said, I think you have to call factorize() after you change the values. Still though, you can save considerable time by only calling the analyzePattern() routine once.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM