user2231787
user2231787

Reputation: 41

Eigen Library:: How do I create a block diagonal sparse matrix out of existing sparse matrices?

I have a bunch of (n*n) sized sparse matrices called M1, M2... , Mj.

I want to create a large block-diagonal sparse matrix that looks like this:

    |M1 0  0 . . . |
    |0  M2 0 . . . |
    |.  .  . . . . |
    |.  .  . Mj-1 0|
    |0  0  0 ... Mj|

I tried the following:

    Eigen::SparseMatrix<double> MatBLK(j*n,j*n);
    MatBLK.reserve(Eigen::VectorXd::Constant(j*n,3); 
    //I know that there are at most 3 nonzero elements per row

    MatBLK.topLeftCorner(n,n) = M1.topLeftCorner(n,n);
    MatBLK.block(n,n,n,n) = M2.topLeftCorner(n,n);
    .
    .
    MatBLK(bottomRightCorner(n,n)) = Mj.topLeftCorner(n,n);
    MatBLK.makeCompressed();

This method is not working. The values in the smaller matrices aren't getting copied to the larger Block Matrix. The function:

    MatBLK.nonZeros() 

returns 0.

I am new to this library. Any help would be greatly appreciated.

Upvotes: 3

Views: 2789

Answers (1)

Sean
Sean

Reputation: 3052

Unfortunately it looks like you can't assign sparse matrices in that way due to how inefficient the resulting code would be. This forum post is almost 2 years old but it seems things are still the same (https://forum.kde.org/viewtopic.php?f=74&t=112018)

You have to assign entries one by one, either with direct assignment or triplets.

A.block(i,j,m,n) = B;

becomes

for (int ii = i; ii < i+m; ++ii) {
  for (int jj = j; jj < j+n; ++jj) {
    // direct assignment 
    A.insert(ii, jj) = B(ii - i, jj - j);

    // triplets
    triplets.push_back(Triplet(ii, jj, B(ii-i,jj-j)));
  }
}

Upvotes: 4

Related Questions