This forum has been archived. All content is frozen. Please use KDE Discuss instead.

Link Sparse matrix with External data

Tags: None
(comma "," separated)
sergeyostu
Registered Member
Posts
2
Karma
0

Link Sparse matrix with External data

Mon Dec 05, 2016 10:01 pm
Hi, developers!
I was used Eigen in my project.
I have Sparse Matrix data in CRS or CCS format like next structre
Code: Select all
struct MySpMatr
{
    int iNNZ - number of non-zero elements
    int *ia - pointer like Eigen::SparseMatrix::m_outerIndex
    int  *ja - pointer like CompressedStorage::m_indices
    type  *a - pointer like CompressedStorage::m_values
    int rows - number of matrix rows
   int cols - number of matrix columns
}

I woudn't use new memory like use SparseMatrix::setFromTriplets or
SparseMatrix::resize(newsize1, newsize2);
StorageIndex* pIn = SparseMatrix::outerIndexPtr();
Code: Select all
for (int ii=0; ii<newsize1; ii++)
{
     pIn[ii] = ia[ii];
}
Storage Stor = SparseMatrix::data();
Stor.clear();
Stor.resize(  /// etc

I want use my stored data in Eigen::SparseMatrix
In my project was created litle fake wrapper, this code
Code: Select all
namespace Eigen {
namespace internal {
// This fake class with access to protected members of  CompressedStorage
template<typename _Scalar, typename _StorageIndex>
class CompressedStorage2 : public CompressedStorage <_Scalar, _StorageIndex>
{
 public:
       CompressedStorage2():CompressedStorage(){};
   void setExternalData(_StorageIndex* innerIndex, _Scalar* values, int iNNZ)
   {
      m_size = iNNZ;
      m_values = values;
      m_indices = innerIndex;
      m_allocatedSize = iNNZ;
   }
   void freeExternalData()
   {
      m_size = 0;
      m_values = 0;
      m_indices = 0;
      m_allocatedSize = 0;
   }

};
}
}


namespace Eigen {
template<typename _Scalar, int _Options, typename _Index>
class SparseMatrix2 : public SparseMatrix<_Scalar, _Options, _Index>
{
public:
   typedef internal::CompressedStorage2<Scalar,StorageIndex> Storage2;
   inline SparseMatrix2():SparseMatrix(){};
   inline SparseMatrix2(Index rows, Index cols):SparseMatrix(rows, cols){};
   inline SparseMatrix2(Index rows, Index cols, StorageIndex* outerIndex):SparseMatrix()
   {
      m_outerSize =IsRowMajor ? rows : cols;
      m_innerSize = IsRowMajor ? cols : rows;
      m_outerIndex = outerIndex;
   };
   inline SparseMatrix2(Index rows, Index cols, StorageIndex* outerIndex, StorageIndex* innerIndex, Scalar* values, int iNNZ):SparseMatrix()
   {
      m_outerSize =IsRowMajor ? rows : cols;
      m_innerSize = IsRowMajor ? cols : rows;
      m_outerIndex = outerIndex;
      ((Storage2*) &m_data)->setExternalData(innerIndex, values, iNNZ);// Acces to protected members of CompressedStorage
   };
   ~SparseMatrix2()
   {
      In destructor we need set NULL pointers for external data. This reasons keep external data from delete operator 
               m_outerSize = 0;
      m_innerSize = 0;
      m_outerIndex = 0;
      ((Storage2*) &m_data)->freeExternalData();// Acces to protected members of CompressedStorage
   };
};
}



This fake wrapper is work in project for future solving System Linear Algebraic Equation like
Code: Select all
int iDOF = solution.Size();
Eigen::SparseMatrix2<double,1,int> A(iDOF, iDOF, ia, ja, a, iNNZ);
Eigen::VectorXd b(iDOF);
for (int ii=0; ii<iDOF; ii++)
{
   b(ii) = rhs[ii];
}
Eigen::ConjugateGradient < CRS, Eigen::Upper, Eigen::DiagonalPreconditioner<double> > solver;
solver.setTolerance(dErr);
solver.setMaxIterations(iIter);
solver.compute(A);
Eigen::VectorXd x = solver.solve(b);


On my opinion using external data in Eigen::SparseMatrix maнbe useful many people.
But using fake wrapper for it is not very good !
I think that in future realeases you create new special template classes for this feature.
Best regards, Majorov S.
User avatar
ggael
Moderator
Posts
3447
Karma
19
OS
You can use Map<SparseMatrix> which is similar in spirit to your wrapper. Then you should still pass SparseMatrix to the solver template parameter:
Code: Select all
Ref<SparseMatrix<double,RowMajor> > mat(rows, cols, nnz, ., ., .);

ConjugateGradient<SparseMatrix<double,RowMajor>, ... > cg(mat);
x = cg.solve(b);


this won't make any copy.
sergeyostu
Registered Member
Posts
2
Karma
0
Hi, ggael!
Thank's for answer.
But I understand, that is mean your code
Code: Select all
Ref<SparseMatrix<double,RowMajor> > mat(rows, cols, nnz, ., ., .);

Let I have matrix
[1 0;
0 1];
In code
Code: Select all
int rows = 2;
int cols = 2;
int iNNZ = 2;
int ia[3] = {0, 1, 2};
int ja[2] = {0, 1};
double a[2] ={1,1};

Can you write working code for construct Ref<SparseMatrix<double,RowMajor> >?
User avatar
ggael
Moderator
Posts
3447
Karma
19
OS
oops, I wrote Ref instead of Map (I've edited my previous comment to fix it, then please refer to the doc: http://eigen.tuxfamily.org/dox-devel/cl ... _01_4.html to see the constructor argument order.


Bookmarks



Who is online

Registered users: Bing [Bot], Google [Bot], Sogou [Bot]