如何有效地组装FEM稀疏矩阵

时间:2017-11-03 10:43:39

标签: c++ matrix sparse-matrix eigen eigen3

全部交易, 感谢您抽出时间阅读我的问题。 我使用Eigen3.3.4(http://eigen.tuxfamily.org/index.php?title=Main_Page)来编写一些FEM代码。

我读了Eigen3.3.4文件,在这个网站(http://eigen.tuxfamily.org/dox/TopicFunctionTakingEigenTypes.html)中 我们应该使用Ref<MatrixBase>来避免附加副本并获得高性能。

所以在我的FEM代码中,对于稀疏矩阵汇编部分,让我们说函数是:

FormFE(const Ref<VectorXd> &U,const Ref<VectorXd> &V,
Ref<SparseMatrix<double> > AMATRIX,Ref<VectorXd> RHS)

其中U代表位移,V代表速度项。 AMATRIX是我的稀疏矩阵,RHS是剩余项。

然后我尝试在汇编之前首先初始化我的AMATRIX(我有一个包含所有非零元素及其值的tripletList(我将值设置为零以进行初始化)) 所以我试过了:

AMATRIX.setFromTriplets(ZeroTripList.begin(),ZeroTripList.end());

但我有一个错误:

class Eigen::Ref<Eigen::SparseMatrix<double, 0, int> >’ has no member named ‘setFromTriplets

那么我怎么能解决这个问题呢?

我的一个解决方案是使用:

FormFE(const Ref<VectorXd> &U,const Ref<VectorXd> &V,
SparseMatrix<double> &AMATRIX,Ref<VectorXd> RHS)

这工作得非常好,但我不确定它是否有效。 我不太擅长cpp:P

实际上,我的问题是:

  1. 如何有效地使用特征(特别是对于FEM计算),我在每个与FEM相关的函数中几乎无处不在使用Eigen的VectorXd和MatrixXd。
  2. 如何有效地组装SparseMatrix?
  3. 是否可以为FEM汇编进行一些OpenMP并行化?
  4. 欢迎任何有关基于C ++的FEM编码的有用建议(图书馆推荐或任何有用的想法)!
  5. 谢谢。 最好的问候。

1 个答案:

答案 0 :(得分:2)

是的,传递SparseMatrix<double> &是正确的做法。 Ref<SparseMatrix>的目的是传递已重新组合为SparseMatrix的已组合对象,如子稀疏矩阵,Map<SparseMatrix> ......

使用setFromTriplets也是正确的做法,以确保获得良好的性能。如果你正确地使用mat.insert(i,j) = val;直接插入元素可能会快达x2(即正确调用保留和正确的插入顺序)。但如果你弄错了,它也可能慢了x100倍......请参阅文档。使用SparseMatrix::insert,也可以使用OpenMP填充矩阵,但这需要更加小心和严格,这是典型的模式:

int n_cols = ??, n_rows = ??;
std::vector<int> nnz_per_col(n_cols);
// set each nnz_per_col[j] to the exact number
// of non-zero entries in the j-th column (or more, but NOT less)
SparseMatrix<double> mat(n_rows, n_cols);
#pragma omp parallel for
for(int j=0; j<cols; ++j) {
  for each non zero entry i in the j-th column {
    // preferably with increasing i
    double val_i_j = ...;
    mat.insert(i,j) = val_i_j;
  }
}

当然,如果对您来说更容易,您也可以按行进行。在这种情况下,请使用SparseMatrix<double,RowMajor>。当然,您可以调整此模式以处理列/行等块

如果对于装配你需要使用一些密集矩阵/向量,那么我相信它们非常小,具有固定大小。然后,不要使用MatrixXd / VectorXd,更好地使用静态分配的Matrix<double,N,M>Matrix<double,N,1>类型。这将阻止大量内存分配/释放。

最后,最重要的推荐:如果您关心效果,请不要忘记配置代码,然后再调查优化代码的时间和精力。此外,始终使用编译器优化开启工作台/配置文件。