好了,谢谢你抽出时间阅读我的问题。我正在使用Eigen3.3.4(Page)编写一些有限元程序。
我阅读了Eigen3.3.4文档,在这个网站(http://eigen.tuxfamily.org/dox/TopicFunctionTakingEigenTypes.html)中,它说我们应该使用Ref<MatrixBase>
来避免额外的复制,以获得高性能。
所以在我的有限元程序中,对于稀疏矩阵组装部分,假设函数是:
FormFE(const Ref<VectorXd> &U,const Ref<VectorXd> &V,
Ref<SparseMatrix<double> > AMATRIX,Ref<VectorXd> RHS)
其中U代表位移,V代表速度项。A矩阵是我的稀疏矩阵,RHS是剩余项。
然后,我尝试在组装之前先初始化我的矩阵(我有一个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
事实上,我的问题是:
谢谢。诚挚的问候。
发布于 2017-11-03 21:35:15
是的,在这里传递SparseMatrix<double> &
是正确的。Ref<SparseMatrix>
的目的是将组装好的对象传递给SparseMatrix
,如子稀疏矩阵,Map<SparseMatrix>
.
使用setFromTriplets也是正确的做法,以确保得到良好的性能。如果正确地插入元素,直接使用mat.insert(i,j) = val;
插入元素的速度可能会更快(例如,正确调用预订和正确的插入顺序)。但如果你搞错了,它也可能是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>
。当然,您可以调整这个模式来处理列/行等块。
如果对于程序集来说,你需要处理一些密集的矩阵/向量,那么我认为它们在固定大小的情况下非常小。然后,最好使用静态分配的Matrix<double,N,M>
和Matrix<double,N,1>
类型,而不是使用MatrixXd/VectorXd。这将防止大量内存分配/取消分配。
最后,最重要的建议:如果您关心性能,在研究优化代码的时间和精力之前,不要忘记对代码进行分析。此外,始终支持编译器优化的工作台/概要文件。
https://stackoverflow.com/questions/47093836
复制相似问题