I am trying the following:
Eigen::SparseMatrix<double> bijection(2 * face_count, 2 * vert_count);
/* initialization */
Eigen::VectorXd toggles(2 * vert_count);
toggles.setOnes();
Eigen::SparseMatrix<double> deformed;
deformed = bijection * toggles;
Eigen is returning an error claiming:
error: static assertion failed: THE_EVAL_EVALTO_FUNCTION_SHOULD_NEVER_BE_CALLED_FOR_DENSE_OBJECTS
586 | EIGEN_STATIC_ASSERT((internal::is_same<Dest,void>::value),THE_EVAL_EVALTO_FUNCTION_SHOULD_NEVER_BE_CALLED_FOR_DENSE_OBJECTS);
According to the eigen documentaion
Sparse matrix and vector products are allowed. What am I doing wrong?
The problem is you have the wrong output type for that product.
The Eigen documentations says the following type of multiplication is legal:
dv2 = sm1 * dv1;
Sparse matrix times dense vector equals dense vector. I think you can just convert the dense vector with the sparseView
member function though. eg
Eigen::SparseMatrix<double> bijection(2 * face_count, 2 * vert_count);
/* initialization */
Eigen::VectorXd toggles(2 * vert_count);
toggles.setOnes();
Eigen::VectorXd deformedDense = bijection * toggles;
Eigen::SparseMatrix<double> deformedSparse = deformedDense.sparseView();
This can be faster than outputting to a dense vector if it is very sparse. Otherwise, 99/100 times the conventional product is faster.
void sparsem_densev_sparsev(const SparseMatrix<double>& A, const VectorX<double>& x, SparseVector<double>& Ax)
{
Ax.resize(x.size());
for (int j = 0; j < A.outerSize(); ++j)
{
if (A.outerIndexPtr()[j + 1] - A.outerIndexPtr()[j] > 0)
{
Ax.insertBack(j) = 0;
}
}
for (int j_idx = 0; j_idx < Ax.nonZeros(); j_idx++)
{
int j = Ax.innerIndexPtr()[j_idx];
for (int k = A.outerIndexPtr()[j]; k < A.outerIndexPtr()[j + 1]; ++k)
{
int i = A.innerIndexPtr()[k];
Ax.valuePtr()[j_idx] += A.valuePtr()[k] * x.coeff(i);
}
}
}
For a (probably not optimal) self-adjoint version (lower triangle), change the j_idx
loop to:
for (int j_idx = 0; j_idx < Ax.nonZeros(); j_idx++)
{
int j = Ax.innerIndexPtr()[j_idx];
int i_idx = j_idx;//i>= j, trick to improve binary search
for (int k = A.outerIndexPtr()[j]; k < A.outerIndexPtr()[j + 1]; ++k)
{
int i = A.innerIndexPtr()[k];
Ax.valuePtr()[j_idx] += A.valuePtr()[k] * x.coeff(i);
if (i != j)
{
i_idx = std::distance(Ax.innerIndexPtr(), std::lower_bound(Ax.innerIndexPtr() + i_idx, Ax.innerIndexPtr() + Ax.nonZeros(), i));
Ax.valuePtr()[i_idx] += A.valuePtr()[k] * x.coeff(j);
}
}
}
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.