在插入顺序已知时填充 Eigen3 稀疏矩阵的策略

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

本文关键字:策略 Eigen3 填充 顺序 插入      更新时间:2023-10-16

所以在我的非线性有限元求解器中,我使用了 Eigen3 稀疏矩阵和 LDLT 分解。

问题是,这种因式分解需要在动态模拟期间多次执行,并且花费大量时间在基于三元组的迭代矩阵中插入系数(存储是保留的(。

关于如何利用稀疏性不变且插入顺序相同的事实,是否有任何好的策略?当形成这个矩阵,循环模型中的元素、耦合等时,在仿真过程中的每个时间步的插入顺序都是相同的。

使用 coeffref 将仿真时间延长了大约 10 倍。

我一直在考虑对模型进行单次传递并形成指向系数矩阵中相应位置的指针,但这似乎有点危险,特别是因为 LDLT 分解介于两者之间。

如果矩阵的稀疏模式没有在每个时间步长都改变,那么您可以使用valuePtr()直接更改原始数据数组的值。这非常简单,如果需要,可以并行完成。如果你能弄清楚如何以线性方式做到这一点,即

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

然后它会愚蠢地快速(与避免缓存未命中和其他黑魔法有关(。至于之前关于LDLT分解不会改变的评论,从理论角度来看是正确的。但是,根据特征文档:

"在因式分解((中,计算系数矩阵的因子。每次矩阵的值更改时,都应调用此步骤。但是,矩阵的结构模式不应在多次调用之间更改。

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

我认为这是因为因子存储在求解器对象中,尽管我可能是错的。测试应该很容易以一种或另一种方式确认。也就是说,我认为您必须在更改值后调用factorize()。不过,您仍然可以通过仅调用一次analyzePattern()例程来节省大量时间。