24#include "dune/common/fmatrix.hh"
25#include "dune/istl/bcrsmatrix.hh"
34 template <
class Entry,
class Index>
55 template<
class Scalar,
class SparseIndexInt=
int>
61 typedef typename std::vector<Scalar>::iterator
iterator;
73 template <
int n,
int m,
class Allocator>
76 fillFromBCRSInterface<n,m>(other);
80 template <
int n,
int m,
class Index>
83 fillFromBCRSInterface<n,m>(other);
94 MatrixAsTriplet(std::vector<SparseIndexInt>&& row, std::vector<SparseIndexInt>&& col,
95 std::vector<Scalar>&& value)
97 assert(row.size()==col.size() && row.size()==value.size());
98 assert(*std::min_element(row.begin(),row.end()) >=0);
99 assert(*std::min_element(col.begin(),col.end()) >=0);
101 ridx = std::move(row);
102 cidx = std::move(col);
103 data = std::move(value);
113 for(
size_t i=0; i<
nrows; ++i)
114 for(
size_t k=0; k<
ncols; ++k)
118 data.push_back(value);
129 for(
size_t i=0; i<
ncols; ++i)
131 size_t rowidx=i+shift;
132 if(rowidx >= 0 && rowidx <
nrows)
134 ridx.push_back(rowidx);
136 data.push_back(value);
146 for(
int i=0; i<
ncols; ++i)
149 if(rowidx >= 0 && rowidx <
nrows)
151 ridx.push_back(rowidx);
153 data.push_back(value[i]);
167 template <
class OtherScalar,
class OtherIndex>
195 SparseIndexInt r0 = *std::min_element(
ridx.begin(),
ridx.end());
196 SparseIndexInt c0 = *std::min_element(
cidx.begin(),
cidx.end());
204 if(
ridx.size()==0)
return 0;
205 return *std::max_element(
ridx.begin(),
ridx.end())+1;
212 SparseIndexInt
N()
const {
return nrows(); }
217 if(
cidx.size()==0)
return 0;
218 return *std::max_element(
cidx.begin(),
cidx.end())+1;
225 SparseIndexInt
M()
const {
return ncols(); }
261 template <
class X,
class Y>
262 void axpy(
Y& out,
X const& in, Scalar alpha=1.0,
int nvectors=1)
const
265 assert(in.size() >=
ncols()*nvectors);
266 assert(out.size() >=
nrows()*nvectors);
267 SparseIndexInt cols=
ncols();
268 SparseIndexInt rows=
nrows();
269 for(
int j=0; j<nvectors; ++j)
270 for(
size_t i=0; i<
ridx.size(); ++i)
272 assert(
ridx[i]+j*rows < out.size());
273 assert(
cidx[i]+j*cols < in.size());
274 out[
ridx[i]+j*rows] += alpha*in[
cidx[i]+j*cols]*
data[i];
282 template <
class X,
class Y>
283 void atxpy(
Y& y,
X const& x, Scalar alpha=1.0)
const
286 assert(y.size() ==
ncols());
287 assert(x.size() ==
nrows());
295 template <
class X,
class Y>
296 void usmtv(Scalar
const alpha,
X const& x,
Y& y)
const
303 template <
class X,
class Y>
304 void usmv(Scalar
const alpha,
X const& x,
Y& y)
const
311 template <
class X,
class Y>
312 void ax(
Y& out,
X const& in)
const
315 assert(in.size() >=
ncols());
317 out.resize(
nrows(),0.0);
318 for(
size_t i=0; i<
ridx.size(); ++i)
320 assert(
ridx[i] < out.size());
321 assert(
cidx[i] < in.size());
327 template <
class X,
class Y>
328 void mv(
X const& x,
Y& y)
const
337 for(
size_t i=0; i<
ridx.size(); ++i)
341 assert(
ridx[i] >= 0 &&
cidx[i] >= 0);
349 void addEntry(SparseIndexInt row, SparseIndexInt col, Scalar
const& value)
353 data.push_back(value);
372 std::vector<SparseIndexInt> Ap, Ai;
373 std::vector<Scalar> Az;
376 std::vector<SparseIndexInt> nullInt1, nullInt2;
377 std::vector<Scalar> nullDouble;
380 data.swap(nullDouble);
383 data.insert(
data.begin(),&Az[0],&Az[Ap.back()]);
384 ridx.insert(
ridx.begin(),&Ai[0],&Ai[Ap.back()]);
403 for(
int i=s; i <
data.size(); ++i)
407 std::vector<SparseIndexInt> Ap, Ai;
408 std::vector<Scalar> Az;
411 std::vector<SparseIndexInt> nullInt1, nullInt2;
412 std::vector<Scalar> nullDouble;
415 data.swap(nullDouble);
418 data.insert(
data.begin(),&Az[0],&Az[Ap.back()]);
419 ridx.insert(
ridx.begin(),&Ai[0],&Ai[Ap.back()]);
437 return (*
this) *= 1/scalar;
448 for(
size_t i=0; i<
ridx.size();++i)
464 for(
size_t i=0; i<
ridx.size(); ++i)
468 std::vector<SparseIndexInt> r2,c2;
469 std::vector<Scalar>
d2;
473 for(
size_t i=0; i<
ridx.size(); ++i)
477 r2.push_back(
ridx[i]);
478 c2.push_back(
cidx[i]);
490 std::ostream&
print(std::ostream& out = std::cout,
double threshold=0.0)
const
492 out <<
"[" << std::endl;
493 for(
size_t i=0; i<
ridx.size(); ++i)
if(std::fabs(
data[i]) > threshold)
494 out <<
ridx[i] <<
"," <<
cidx[i] <<
"," <<
data[i] <<
";" << std::endl;
495 out <<
"]" << std::endl;
500 void toColumns(std::vector<std::vector<Scalar> >& colsvector)
const
502 SparseIndexInt rows=
nrows();
503 colsvector.resize(
ncols());
504 for(
size_t i=0; i<colsvector.size();++i)
506 colsvector[i].resize(0);
507 colsvector[i].resize(rows,0.0);
509 for(
size_t i=0; i<
data.size(); ++i)
513 void toRows(std::vector<std::vector<Scalar> >& rows)
const
515 SparseIndexInt cols =
ncols();
516 rows.resize(
nrows());
517 std::for_each(rows.begin(),rows.end(),
518 [&cols](std::vector<Scalar>& row)
521 row.resize(cols,0.0);
528 SparseIndexInt rows=
nrows();
529 colsvector.resize(0);
531 for(
size_t i=0; i<
data.size(); ++i)
536 void addColumn(std::vector<Scalar>& colsvector,
size_t position)
538 for(
size_t i=0; i<colsvector.size();++i)
541 cidx.push_back(position);
542 data.push_back(colsvector[i]);
551 for(
size_t i=0; i<
data.size(); ++i)
565 std::vector<Scalar> diagonalEntries(noRows,0);
568 for(SparseIndexInt row=0; row<noRows; ++row)
573 if(
ridx[i] == row) diagonalEntries[row] +=
data[i];
581 for(SparseIndexInt i=0; i<noRows; ++i) result.
addEntry(i,i,diagonalEntries[i]);
601 void toFile(
const char* filename,
unsigned int precision=10)
const
603 std::ofstream myfile;
604 myfile.precision(precision);
605 myfile.open(filename);
606 for(
size_t i=0; i<
data.size(); ++i)
607 myfile <<
ridx[i] <<
" " <<
cidx[i] <<
" " <<
data[i] << std::endl;
612 template <
int bcrsN=1>
613 std::unique_ptr<Dune::BCRSMatrix<Dune::FieldMatrix<Scalar,bcrsN,bcrsN>>>
toBCRS()
const
615 typedef Dune::BCRSMatrix<Dune::FieldMatrix<Scalar,bcrsN,bcrsN> > BCRSMat;
618 SparseIndexInt noRows =
nrows()/bcrsN,
619 noCols =
ncols()/bcrsN;
620 std::vector<std::vector<SparseIndexInt> > bcrsids(noRows);
621 getBCRSIndices<bcrsN>(noRows,
ridx,
cidx, bcrsids);
623 SparseIndexInt nonz = 0;
624 for (
auto const& s : bcrsids)
626 std::unique_ptr<BCRSMat> result(
new BCRSMat(noRows,noCols,nonz,BCRSMat::row_wise));
629 for (
typename BCRSMat::CreateIterator row=result->createbegin(); row!=result->createend(); ++row)
630 for(SparseIndexInt col = 0; col < bcrsids[row.index()].
size(); ++col) row.insert(bcrsids[row.index()][col]);
633 for (SparseIndexInt i=0; i<
data.size(); ++i)
635 size_t blockRow =
ridx[i]/bcrsN, blockCol =
cidx[i]/bcrsN;
636 (*result)[blockRow][blockCol][
ridx[i]-bcrsN*blockRow][
cidx[i]-bcrsN*blockCol] =
data[i];
644 for(
size_t i=0; i<
data.size(); ++i)
648 if(tmp.second ==
false || std::fabs(
data[i]-
data[tmp.first]) > 1e-6)
658 std::pair<size_t,bool>
findEntry(SparseIndexInt row, SparseIndexInt col)
const
660 for(
size_t i=0; i<
data.size(); ++i)
662 return std::make_pair(i,
true);
664 return std::make_pair(0,
false);
669 std::vector<SparseIndexInt>
ridx;
671 std::vector<SparseIndexInt>
cidx;
676 template <
int bcrsN,
class SparseInt>
677 void getBCRSIndices(SparseInt
nrows, std::vector<SparseInt>
const&
ridx, std::vector<SparseInt>
const&
cidx, std::vector<std::vector<SparseInt> >& rowColumnIndices)
const
679 rowColumnIndices.clear();
680 rowColumnIndices.resize(
nrows);
681 for(SparseInt i=0; i<
ridx.size(); ++i) rowColumnIndices[
ridx[i]/bcrsN].push_back(
cidx[i]/bcrsN);
683 for(std::vector<SparseInt>& s : rowColumnIndices)
685 std::sort(s.begin(),s.end());
686 auto last = std::unique(s.begin(),s.end());
687 s.erase(last,s.end());
691 template <
int n,
int m,
class Matrix>
692 void fillFromBCRSInterface(Matrix
const& other)
694 reserve(other.nonzeroes()*n*m);
696 auto rend = other.end();
697 for (
auto r=other.begin(); r!=rend; ++r)
699 SparseIndexInt ri = r.index() * n;
700 auto cend = r->end();
701 for (
auto c=r->begin(); c!=cend; ++c)
703 SparseIndexInt ci = c.index() * m;
704 auto const& entry = *c;
706 for(
size_t k=0; k<n; ++k)
707 for(
size_t l=0; l<m; ++l)
709 ridx.push_back(ri+k);
710 cidx.push_back(ci+l);
711 data.push_back(entry[k][l]);
717 template <
class Iterator>
720 Read(Iterator& in_): in(in_) {}
722 template <
class Element>
729 template <
class Iterator>
732 Write(Iterator& out_): out(out_) {}
734 template <
class Element>
746 template<
class Scalar>
750 for(
size_t i=0; i<ridx.size(); ++i)
751 if(ridx[i] <= cidx[i])
754 std::vector<int> r2,c2;
755 std::vector<Scalar>
d2;
760 for(
size_t i=0; i<ridx.size(); ++i)
761 if(ridx[i] <= cidx[i]) {
762 r2.push_back(ridx[i]);
763 c2.push_back(cidx[i]);
764 d2.push_back(data[i]);
772 template <
typename Scalar,
typename SparseIndexInt>
775 return mat.
print(s,0);
void atxpy(Y &y, X const &x, Scalar alpha=1.0) const
Matrix-vector multiplication.
void setStartToZero()
Shift the row and column indices such that is (structurally) nonzero.
void toFile(const char *filename, unsigned int precision=10) const
write to text file
void addEntry(SparseIndexInt row, SparseIndexInt col, Scalar const &value)
Adds the given value to the specified matrix entry. The entry is created in case it has been structur...
SparseIndexInt nrows() const
Returns number of rows (computes them, if not known)
SparseIndexInt ncols() const
Returns number of cols (computes them, if not known)
void reserve(size_t s)
Reserve memory.
MatrixAsTriplet(MatrixAsTriplet const &other)=default
Copy constructor.
MatrixAsTriplet & operator=(MatrixAsTriplet &&other)=default
Move assignment.
void deleteLowerTriangle()
Deletes all sub-diagonal entries.
std::vector< SparseIndexInt > ridx
row indices
MatrixAsTriplet & operator*=(Scalar const &scalar)
Scaling.
const_iterator end() const
get const iterator on end of data field
const_iterator begin() const
get const iterator on data field
MatrixAsTriplet(SparseIndexInt nrows, SparseIndexInt ncols, SparseIndexInt shift, std::vector< Scalar > const &value)
Constructs a diagonal matrix of size (nrows,ncols). The diagonal is shifted down shift rows (if shift...
SparseIndexInt N() const
Returns number of rows (computes them, if not known) This is a Dune ISTL compatibility method.
size_t size() const
get number of entries in sparse matrix
std::vector< SparseIndexInt > cidx
column indices
void toVector(std::vector< Scalar > &colsvector)
void erase(SparseIndexInt i)
MatrixAsTriplet(Dune::BCRSMatrix< Dune::FieldMatrix< Scalar, n, m >, Allocator > const &other)
Constructor from a Dune::BCRSMatrix.
MatrixAsTriplet(SparseIndexInt nrows, SparseIndexInt ncols, Scalar const &value)
Constructs a matrix of size (nrows,ncols), filled with value. If value==0.0, then it is an empty matr...
void mv(X const &x, Y &y) const
matrix-vector multiplication
MatrixAsTriplet & operator/=(Scalar const &scalar)
Scaling.
void clear()
Deletes the data, leaving an empty matrix of size 0 x 0.
std::unique_ptr< Dune::BCRSMatrix< Dune::FieldMatrix< Scalar, bcrsN, bcrsN > > > toBCRS() const
copy to Dune::BCRSMatrix
MatrixAsTriplet()
Constructor.
MatrixAsTriplet & operator-=(MatrixAsTriplet const &m)
MatrixAsTriplet(SparseIndexInt nrows, SparseIndexInt ncols, SparseIndexInt shift, Scalar const &value)
Constructs a diagonal matrix of size (nrows,ncols). The diagonal is shifted down shift rows (if shift...
void shiftIndices(SparseIndexInt row, SparseIndexInt col)
Shifts matrix indices. Can be used together with += to concatenate sparese matrices.
MatrixAsTriplet(std::vector< SparseIndexInt > &&row, std::vector< SparseIndexInt > &&col, std::vector< Scalar > &&value)
Move constructor taking raw data.
SparseIndexInt M() const
Returns number of columns (computes them, if not known) This is a Dune ISTL compatibility method.
std::ostream & print(std::ostream &out=std::cout, double threshold=0.0) const
Output as Matlab source code.
MatrixAsTriplet(size_t s)
Constructor that allocates memory directly.
MatrixAsTriplet(NumaBCRSMatrix< Dune::FieldMatrix< Scalar, n, m >, Index > const &other)
Constructor from a NumaBCRSMatrix.
iterator end()
get iterator on end of data field
void scaleRows(std::vector< Scalar >const &scaling)
std::pair< size_t, bool > findEntry(SparseIndexInt row, SparseIndexInt col) const
MatrixAsTriplet & transpose()
Transposition.
void addColumn(std::vector< Scalar > &colsvector, size_t position)
add a column
std::vector< Scalar > data
data
void usmtv(Scalar const alpha, X const &x, Y &y) const
Matrix-vector multiplication.
std::vector< SparseIndexInt >::const_iterator const_index_iterator
iterator begin()
get iterator on data field
void usmv(Scalar const alpha, X const &x, Y &y) const
scaled matrix-vector multiplication
MatrixAsTriplet & operator=(MatrixAsTriplet const &m)=default
Assignment.
void toColumns(std::vector< std::vector< Scalar > > &colsvector) const
transform into a set of column vectors
void axpy(Y &out, X const &in, Scalar alpha=1.0, int nvectors=1) const
Matrix-vector multiplication: out += alpha * (*this) * in.
Scalar value_type
STL-compliant typedefs.
MatrixAsTriplet & operator+=(MatrixAsTriplet const &m)
Matrix addition: (*this) += m (works also for matrices with non-matching sparsity pattern)
void ax(Y &out, X const &in) const
Matrix-vector multiplication: out = (*this) * in.
void addToMatrix(Mat &mat)
add to a dense matrix
void resize(size_t s)
Resizes the memory.
void toRows(std::vector< std::vector< Scalar > > &rows) const
MatrixAsTriplet(MatrixAsTriplet &&other)=default
Move constructor.
std::vector< SparseIndexInt >::iterator index_iterator
std::vector< Scalar >::iterator iterator
MatrixAsTriplet(MatrixAsTriplet< OtherScalar, OtherIndex > const &A)
Copy constructor from a triplet matrix with different entry and/or index types.
std::vector< Scalar >::const_iterator const_iterator
A NUMA-aware compressed row storage matrix adhering mostly to the Dune ISTL interface (to complete....
int count(Cell const &cell, int codim)
Computes the number of subentities of codimension c of a given entity.
void umfpack_triplet_to_col(int rows, int cols, std::vector< long > const &ridx, std::vector< long > const &cidx, std::vector< double > const &values, std::vector< long > &Ap, std::vector< long > &Ai, std::vector< double > &Az)
Triplet to compressed column storage conversion . This is just a frontent to DirectType::UMFPACK util...
void deleteLowerTriangle(std::vector< int > &ridx, std::vector< int > &cidx, std::vector< Scalar > &data)
removes subdiagonal entries from the matrix entries stored in elementary triplet format
void umfpack_col_to_triplet(std::vector< long > const &Ap, std::vector< long > &Ti)
Compressed column storage to triplet storage conversion. This is just a frontent to DirectType::UMFPA...
Functional::Scalar d2(Assembler &assembler, Functional const &f, typename Functional::AnsatzVars::VariableSet const &x, typename Functional::Scalar increment=1e-12, typename Functional::Scalar tolerance=1e-6, bool toFile=false, std::string const &savefilename=std::string("d2error"))
std::ostream & operator<<(std::ostream &s, std::vector< Scalar > const &vec)
OutIter vectorToSequence(double x, OutIter iter)
InIter vectorFromSequence(FunctionSpaceElement< Space, m > &v, InIter in)