3#ifndef DUNE_ISTL_MATRIXMARKET_HH
4#define DUNE_ISTL_MATRIXMARKET_HH
26#include <dune/common/hybridutilities.hh>
62 namespace MatrixMarketImpl
84 struct mm_numeric_type<int>
93 static std::string str()
100 struct mm_numeric_type<double>
109 static std::string str()
116 struct mm_numeric_type<float>
125 static std::string str()
132 struct mm_numeric_type<
std::complex<double> >
141 static std::string str()
148 struct mm_numeric_type<
std::complex<float> >
157 static std::string str()
174 template<
typename T,
typename A>
177 static void print(std::ostream& os)
179 os<<
"%%MatrixMarket matrix coordinate ";
180 os<<mm_numeric_type<typename Imp::BlockTraits<T>::field_type>::str()<<
" general"<<std::endl;
184 template<
typename B,
typename A>
187 static void print(std::ostream& os)
189 os<<
"%%MatrixMarket matrix array ";
190 os<<mm_numeric_type<typename Imp::BlockTraits<B>::field_type>::str()<<
" general"<<std::endl;
194 template<
typename T,
int j>
195 struct mm_header_printer<FieldVector<T,j> >
197 static void print(std::ostream& os)
199 os<<
"%%MatrixMarket matrix array ";
200 os<<mm_numeric_type<T>::str()<<
" general"<<std::endl;
204 template<
typename T,
int i,
int j>
205 struct mm_header_printer<FieldMatrix<T,i,j> >
207 static void print(std::ostream& os)
209 os<<
"%%MatrixMarket matrix array ";
210 os<<mm_numeric_type<T>::str()<<
" general"<<std::endl;
225 template<
typename T,
typename A>
231 static void print(std::ostream& os,
const M&)
233 os<<
"% ISTL_STRUCT blocked ";
234 os<<
"1 1"<<std::endl;
238 template<
typename T,
typename A,
int i>
243 static void print(std::ostream& os,
const M&)
245 os<<
"% ISTL_STRUCT blocked ";
246 os<<i<<
" "<<1<<std::endl;
250 template<
typename T,
typename A>
251 struct mm_block_structure_header<BCRSMatrix<T,A> >
253 typedef BCRSMatrix<T,A> M;
254 static_assert(IsNumber<T>::value,
"Only scalar entries are expected here!");
256 static void print(std::ostream& os,
const M&)
258 os<<
"% ISTL_STRUCT blocked ";
259 os<<
"1 1"<<std::endl;
263 template<
typename T,
typename A,
int i,
int j>
264 struct mm_block_structure_header<BCRSMatrix<FieldMatrix<T,i,j>,A> >
266 typedef BCRSMatrix<FieldMatrix<T,i,j>,A> M;
268 static void print(std::ostream& os,
const M&)
270 os<<
"% ISTL_STRUCT blocked ";
271 os<<i<<
" "<<j<<std::endl;
276 template<
typename T,
int i,
int j>
277 struct mm_block_structure_header<FieldMatrix<T,i,j> >
279 typedef FieldMatrix<T,i,j> M;
281 static void print(std::ostream& os,
const M& m)
285 template<
typename T,
int i>
286 struct mm_block_structure_header<FieldVector<T,i> >
288 typedef FieldVector<T,i> M;
290 static void print(std::ostream& os,
const M& m)
294 enum LineType { MM_HEADER, MM_ISTLSTRUCT, DATA };
295 enum { MM_MAX_LINE_LENGTH=1025 };
297 enum MM_TYPE { coordinate_type, array_type, unknown_type };
299 enum MM_CTYPE { integer_type, double_type, complex_type, pattern, unknown_ctype };
301 enum MM_STRUCTURE { general, symmetric, skew_symmetric, hermitian, unknown_structure };
306 : type(coordinate_type), ctype(double_type), structure(general)
310 MM_STRUCTURE structure;
313 inline bool lineFeed(std::istream& file)
337 inline void skipComments(std::istream& file)
351 inline bool readMatrixMarketBanner(std::istream& file, MMHeader& mmHeader)
360 dverb<<buffer<<std::endl;
362 if(buffer!=
"%%MatrixMarket") {
375 if(buffer !=
"matrix")
392 std::transform(buffer.begin(), buffer.end(), buffer.begin(),
399 if(buffer !=
"array")
404 mmHeader.type=array_type;
408 if(buffer !=
"coordinate")
413 mmHeader.type=coordinate_type;
430 std::transform(buffer.begin(), buffer.end(), buffer.begin(),
436 if(buffer !=
"integer")
441 mmHeader.ctype=integer_type;
450 mmHeader.ctype=double_type;
454 if(buffer !=
"complex")
459 mmHeader.ctype=complex_type;
463 if(buffer !=
"pattern")
468 mmHeader.ctype=pattern;
480 std::transform(buffer.begin(), buffer.end(), buffer.begin(),
486 if(buffer !=
"general")
491 mmHeader.structure=general;
495 if(buffer !=
"hermitian")
500 mmHeader.structure=hermitian;
503 if(buffer.size()==1) {
512 if(buffer !=
"symmetric")
517 mmHeader.structure=symmetric;
521 if(buffer !=
"skew-symmetric")
526 mmHeader.structure=skew_symmetric;
543 template<std::
size_t brows, std::
size_t bcols>
544 std::tuple<std::size_t, std::size_t, std::size_t>
545 calculateNNZ(std::size_t rows, std::size_t cols, std::size_t entries,
const MMHeader& header)
547 std::size_t blockrows=rows/brows;
548 std::size_t blockcols=cols/bcols;
549 std::size_t blocksize=brows*bcols;
550 std::size_t blockentries=0;
552 switch(header.structure)
555 blockentries = entries/blocksize;
break;
556 case skew_symmetric :
557 blockentries = 2*entries/blocksize;
break;
559 blockentries = (2*entries-rows)/blocksize;
break;
561 blockentries = (2*entries-rows)/blocksize;
break;
565 return std::make_tuple(blockrows, blockcols, blockentries);
575 struct IndexData :
public T
612 std::istream&
operator>>(std::istream& is, NumericWrapper<T>& num)
614 return is>>num.number;
617 inline std::istream&
operator>>(std::istream& is, NumericWrapper<PatternDummy>& num)
629 bool operator<(
const IndexData<T>& i1,
const IndexData<T>& i2)
631 return i1.index<i2.index;
640 std::istream&
operator>>(std::istream& is, IndexData<T>& data)
645 return is>>data.number;
664 data.number = {real.number, imag.number};
674 template<
typename D,
int brows,
int bcols>
683 void operator()(
const std::vector<std::set<IndexData<D> > >& rows,
686 static_assert(
IsNumber<T>::value && brows==1 && bcols==1,
"Only scalar entries are expected here!");
687 for (
auto iter=matrix.
begin(); iter!= matrix.
end(); ++iter)
689 auto brow=iter.index();
690 for (
auto siter=rows[brow].begin(); siter != rows[brow].end(); ++siter)
691 (*iter)[siter->index] = siter->number;
701 void operator()(
const std::vector<std::set<IndexData<D> > >& rows,
704 for (
auto iter=matrix.begin(); iter!= matrix.end(); ++iter)
706 for (
auto brow=iter.index()*brows,
707 browend=iter.index()*brows+brows;
708 brow<browend; ++brow)
710 for (
auto siter=rows[brow].begin(), send=rows[brow].end();
711 siter != send; ++siter)
712 (*iter)[siter->index/bcols][brow%brows][siter->index%bcols]=siter->number;
718 template<
int brows,
int bcols>
719 struct MatrixValuesSetter<PatternDummy,brows,bcols>
722 void operator()(
const std::vector<std::set<IndexData<PatternDummy> > >& rows,
727 template<
class T>
struct is_complex : std::false_type {};
728 template<
class T>
struct is_complex<
std::complex<T>> : std::true_type {};
732 std::enable_if_t<!is_complex<T>::value, T> conj(
const T& r){
737 std::enable_if_t<is_complex<T>::value, T> conj(
const T& r){
742 struct mm_multipliers
745 template<
typename B,
typename A>
746 struct mm_multipliers<BCRSMatrix<B,A> >
754 template<
typename B,
int i,
int j,
typename A>
755 struct mm_multipliers<BCRSMatrix<FieldMatrix<B,i,j>,A> >
763 template<
typename T,
typename A,
typename D>
765 std::istream& file, std::size_t entries,
766 const MMHeader& mmHeader,
const D&)
771 constexpr int brows = mm_multipliers<Matrix>::rows;
772 constexpr int bcols = mm_multipliers<Matrix>::cols;
777 std::vector<std::set<IndexData<D> > > rows(matrix.
N()*brows);
779 auto readloop = [&] (
auto symmetryFixup) {
780 for(std::size_t i = 0; i < entries; ++i) {
786 assert(row/bcols<matrix.
N());
788 assert(data.index/bcols<matrix.
M());
789 rows[row].insert(data);
791 symmetryFixup(row, data);
795 switch(mmHeader.structure)
798 readloop([](
auto...){});
801 readloop([&](
auto row,
auto data) {
802 IndexData<D> data_sym(data);
803 data_sym.index = row;
804 rows[data.index].insert(data_sym);
807 case skew_symmetric :
808 readloop([&](
auto row,
auto data) {
809 IndexData<D> data_sym;
810 data_sym.number = -data.number;
811 data_sym.index = row;
812 rows[data.index].insert(data_sym);
816 readloop([&](
auto row,
auto data) {
817 IndexData<D> data_sym;
818 data_sym.number = conj(data.number);
819 data_sym.index = row;
820 rows[data.index].insert(data_sym);
825 "Only general, symmetric, skew-symmetric and hermitian is supported right now!");
830 for(
typename Matrix::CreateIterator iter=matrix.
createbegin();
833 for(std::size_t brow=iter.index()*brows, browend=iter.index()*brows+brows;
834 brow<browend; ++brow)
836 typedef typename std::set<IndexData<D> >::const_iterator Siter;
837 for(Siter siter=rows[brow].begin(), send=rows[brow].end();
838 siter != send; ++siter, ++nnz)
839 iter.insert(siter->index/bcols);
846 MatrixValuesSetter<D,brows,bcols> Setter;
848 Setter(rows, matrix);
856 inline void mm_read_header(std::size_t& rows, std::size_t& cols,
857 MatrixMarketImpl::MMHeader& header, std::istream& istr,
860 using namespace MatrixMarketImpl;
862 if(!readMatrixMarketBanner(istr, header)) {
863 std::cerr <<
"First line was not a correct Matrix Market banner. Using default:\n"
864 <<
"%%MatrixMarket matrix coordinate real general"<<std::endl;
867 istr.seekg(0, std::ios::beg);
869 header.type=array_type;
875 throw MatrixMarketFormatError();
880 throw MatrixMarketFormatError();
884 template<
typename T,
typename A>
889 for (
int i=0; size>0; ++i, --size)
893 template<
typename T,
typename A,
int entries>
898 for(
int i=0; size>0; ++i, --size) {
901 vector[i/entries][i%entries]=val;
912 template<
typename T,
typename A>
916 using namespace MatrixMarketImpl;
919 std::size_t rows, cols;
920 mm_read_header(rows,cols,header,istr,
true);
922 DUNE_THROW(MatrixMarketFormatError,
"cols!=1, therefore this is no vector!");
924 if(header.type!=array_type)
925 DUNE_THROW(MatrixMarketFormatError,
"Vectors have to be stored in array format!");
934 auto blocksize = id(dummy).size();
935 std::size_t size=rows/blocksize;
936 if(size*blocksize!=rows)
937 DUNE_THROW(MatrixMarketFormatError,
"Block size of vector is not correct!");
943 mm_read_vector_entries(vector, rows, istr);
952 template<
typename T,
typename A>
956 using namespace MatrixMarketImpl;
960 if(!readMatrixMarketBanner(istr, header)) {
961 std::cerr <<
"First line was not a correct Matrix Market banner. Using default:\n"
962 <<
"%%MatrixMarket matrix coordinate real general"<<std::endl;
965 istr.seekg(0, std::ios::beg);
969 std::size_t rows, cols, entries;
972 throw MatrixMarketFormatError();
977 throw MatrixMarketFormatError();
981 throw MatrixMarketFormatError();
985 std::size_t nnz, blockrows, blockcols;
988 constexpr int brows = mm_multipliers<Matrix>::rows;
989 constexpr int bcols = mm_multipliers<Matrix>::cols;
991 std::tie(blockrows, blockcols, nnz) = calculateNNZ<brows, bcols>(rows, cols, entries, header);
996 matrix.
setSize(blockrows, blockcols);
999 if(header.type==array_type)
1002 readSparseEntries(matrix, istr, entries, header, NumericWrapper<typename Matrix::field_type>());
1006 template<
typename B>
1007 void mm_print_entry(
const B& entry,
1014 ostr << rowidx <<
" " << colidx <<
" " << entry << std::endl;
1017 for (
auto row=
id(entry).begin(); row != id(entry).end(); ++row, ++rowidx) {
1019 for (
auto col = row->begin(); col != row->end(); ++col, ++coli)
1020 ostr<< rowidx<<
" "<<coli<<
" "<<*col<<std::endl;
1026 template<
typename V>
1027 void mm_print_vector_entry(
const V& entry, std::ostream& ostr,
1028 const std::integral_constant<int,1>&)
1030 ostr<<entry<<std::endl;
1034 template<
typename V>
1035 void mm_print_vector_entry(
const V& vector, std::ostream& ostr,
1036 const std::integral_constant<int,0>&)
1038 using namespace MatrixMarketImpl;
1041 const int isnumeric = mm_numeric_type<typename V::block_type>::is_numeric;
1042 typedef typename V::const_iterator VIter;
1044 for(VIter i=vector.begin(); i != vector.end(); ++i)
1046 mm_print_vector_entry(*i, ostr,
1047 std::integral_constant<int,isnumeric>());
1050 template<
typename T,
typename A>
1051 std::size_t countEntries(
const BlockVector<T,A>& vector)
1053 return vector.size();
1056 template<
typename T,
typename A,
int i>
1057 std::size_t countEntries(
const BlockVector<FieldVector<T,i>,A>& vector)
1059 return vector.size()*i;
1063 template<
typename V>
1064 void writeMatrixMarket(
const V& vector, std::ostream& ostr,
1065 const std::integral_constant<int,0>&)
1067 using namespace MatrixMarketImpl;
1069 ostr<<countEntries(vector)<<
" "<<1<<std::endl;
1070 const int isnumeric = mm_numeric_type<typename V::block_type>::is_numeric;
1071 mm_print_vector_entry(vector,ostr, std::integral_constant<int,isnumeric>());
1075 template<
typename M>
1076 void writeMatrixMarket(
const M& matrix,
1078 const std::integral_constant<int,1>&)
1080 ostr<<matrix.N()*MatrixMarketImpl::mm_multipliers<M>::rows<<
" "
1081 <<matrix.M()*MatrixMarketImpl::mm_multipliers<M>::cols<<
" "
1084 typedef typename M::const_iterator riterator;
1085 typedef typename M::ConstColIterator citerator;
1086 for(riterator row=matrix.begin(); row != matrix.end(); ++row)
1087 for(citerator col = row->begin(); col != row->end(); ++col)
1089 mm_print_entry(*col, row.index()*MatrixMarketImpl::mm_multipliers<M>::rows+1,
1090 col.index()*MatrixMarketImpl::mm_multipliers<M>::cols+1, ostr);
1097 template<
typename M>
1098 void writeMatrixMarket(
const M& matrix,
1101 using namespace MatrixMarketImpl;
1104 mm_header_printer<M>::print(ostr);
1105 mm_block_structure_header<M>::print(ostr,matrix);
1121 template<
typename M>
1123 std::string filename)
1125 std::ofstream file(filename.c_str());
1126 file.setf(std::ios::scientific,std::ios::floatfield);
1127 writeMatrixMarket(matrix, file);
1145 template<
typename M,
typename G,
typename L>
1147 std::string filename,
1149 bool storeIndices=
true)
1152 int rank = comm.communicator().rank();
1154 std::ostringstream rfilename;
1155 rfilename<<filename <<
"_"<<rank<<
".mm";
1156 dverb<< rfilename.str()<<std::endl;
1157 std::ofstream file(rfilename.str().c_str());
1158 file.setf(std::ios::scientific,std::ios::floatfield);
1159 writeMatrixMarket(matrix, file);
1167 rfilename<<filename<<
"_"<<rank<<
".idx";
1168 file.open(rfilename.str().c_str());
1169 file.setf(std::ios::scientific,std::ios::floatfield);
1171 typedef typename IndexSet::const_iterator Iterator;
1174 file << iter->global()<<
" "<<(std::size_t)iter->local()<<
" "
1175 <<(int)iter->local().attribute()<<
" "<<(int)iter->local().isPublic()<<std::endl;
1178 file<<
"neighbours:";
1179 const std::set<int>& neighbours=comm.
remoteIndices().getNeighbours();
1180 typedef std::set<int>::const_iterator SIter;
1181 for(SIter neighbour=neighbours.begin(); neighbour != neighbours.end(); ++neighbour) {
1182 file<<
" "<< *neighbour;
1201 template<
typename M,
typename G,
typename L>
1203 const std::string& filename,
1205 bool readIndices=
true)
1207 using namespace MatrixMarketImpl;
1210 typedef typename LocalIndex::Attribute Attribute;
1212 int rank = comm.communicator().rank();
1214 std::ostringstream rfilename;
1215 rfilename<<filename <<
"_"<<rank<<
".mm";
1217 file.open(rfilename.str().c_str(), std::ios::in);
1232 rfilename<<filename<<
"_"<<rank<<
".idx";
1233 file.open(rfilename.str().c_str());
1238 while(!file.eof() && file.peek()!=
'n') {
1255 if(s!=
"neighbours:")
1256 DUNE_THROW(MatrixMarketFormatError,
"was expecting the string: \"neighbours:\"");
1258 while(!file.eof()) {
1264 comm.ri.setNeighbours(nb);
1266 comm.ri.template rebuild<false>();
1281 template<
typename M>
1283 const std::string& filename)
1286 file.open(filename.c_str(), std::ios::in);
Implementation of the BCRSMatrix class.
This file implements a vector space as a tensor product of a given vector space. The number of compon...
A sparse block matrix with compressed row storage.
Definition: bcrsmatrix.hh:426
Iterator begin()
Get iterator to first row.
Definition: bcrsmatrix.hh:634
Iterator end()
Get iterator to one beyond last row.
Definition: bcrsmatrix.hh:640
CreateIterator createend()
get create iterator pointing to one after the last block
Definition: bcrsmatrix.hh:1062
size_type M() const
number of columns (counted in blocks)
Definition: bcrsmatrix.hh:1937
CreateIterator createbegin()
get initial create iterator
Definition: bcrsmatrix.hh:1056
size_type N() const
number of rows (counted in blocks)
Definition: bcrsmatrix.hh:1931
void setBuildMode(BuildMode bm)
Sets the build mode of the matrix.
Definition: bcrsmatrix.hh:792
void setSize(size_type rows, size_type columns, size_type nnz=0)
Set the size of the matrix.
Definition: bcrsmatrix.hh:820
A vector of blocks with memory management.
Definition: bvector.hh:403
void resize(size_type size)
Resize the vector.
Definition: bvector.hh:536
Base class for Dune-Exceptions.
Definition: exceptions.hh:94
A dense n x m matrix.
Definition: fmatrix.hh:69
vector space out of a tensor product of fields.
Definition: fvector.hh:96
Default exception class for I/O errors.
Definition: exceptions.hh:229
Index Set Interface base class.
Definition: indexidset.hh:76
IndexType size(GeometryType type) const
Return total number of entities of given geometry type in entity set .
Definition: indexidset.hh:220
Exception indicating that the index set is not in the expected state.
Definition: indexset.hh:204
An index present on the local process.
Definition: localindex.hh:33
A generic dynamic dense matrix.
Definition: matrix.hh:558
Default exception for dummy implementations.
Definition: exceptions.hh:261
A class setting up standard communication for a two-valued attribute set with owner/overlap/copy sema...
Definition: owneroverlapcopy.hh:172
const ParallelIndexSet & indexSet() const
Get the underlying parallel index set.
Definition: owneroverlapcopy.hh:472
const RemoteIndices & remoteIndices() const
Get the underlying remote indices.
Definition: owneroverlapcopy.hh:481
A few common exception classes.
Implements a matrix constructed from a given type representing a field and compile-time given number ...
Implements a vector constructed from a given type representing a field and a compile-time given size.
iterator begin()
Get an iterator over the indices positioned at the first index.
iterator end()
Get an iterator over the indices positioned after the last index.
LI LocalIndex
The type of the local index, e.g. ParallelLocalIndex.
Definition: indexset.hh:238
Stream & operator>>(Stream &stream, std::tuple< Ts... > &t)
Read a std::tuple.
Definition: streamoperators.hh:41
#define DUNE_UNUSED_PARAMETER(parm)
A macro to mark intentionally unused function parameters with.
Definition: unused.hh:25
#define DUNE_THROW(E, m)
Definition: exceptions.hh:216
decltype(auto) ifElse(const Condition &condition, IfFunc &&ifFunc, ElseFunc &&elseFunc)
A conditional expression.
Definition: hybridutilities.hh:355
void readMatrixMarket(Dune::BlockVector< T, A > &vector, std::istream &istr)
Reads a BlockVector from a matrix market file.
Definition: matrixmarket.hh:913
void loadMatrixMarket(M &matrix, const std::string &filename, OwnerOverlapCopyCommunication< G, L > &comm, bool readIndices=true)
Load a parallel matrix/vector stored in matrix market format.
Definition: matrixmarket.hh:1202
void storeMatrixMarket(const M &matrix, std::string filename)
Stores a parallel matrix/vector in matrix market format in a file.
Definition: matrixmarket.hh:1122
auto countNonZeros(const M &matrix, typename std::enable_if_t< Dune::IsNumber< M >::value > *sfinae=nullptr)
Get the number of nonzero fields in the matrix.
Definition: matrixutils.hh:119
EnableIfInterOperable< T1, T2, bool >::type operator<(const RandomAccessIteratorFacade< T1, V1, R1, D > &lhs, const RandomAccessIteratorFacade< T2, V2, R2, D > &rhs)
Comparison operator.
Definition: iteratorfacades.hh:635
auto max(ADLTag< 0 >, const V &v1, const V &v2)
implements binary Simd::max()
Definition: defaults.hh:79
DVerbType dverb(std::cout)
Singleton of verbose debug stream.
Definition: stdstreams.hh:114
Some handy generic functions for ISTL matrices.
Dune namespace.
Definition: alignedallocator.hh:14
Classes providing communication interfaces for overlapping Schwarz methods.
Standard Dune debug streams.
Test whether a type is an ISTL Matrix.
Definition: matrixutils.hh:502
Whether this type acts as a scalar in the context of (hierarchically blocked) containers.
Definition: typetraits.hh:163
Functor to the data values of the matrix.
Definition: matrixmarket.hh:676
void operator()(const std::vector< std::set< IndexData< D > > > &rows, BCRSMatrix< T > &matrix)
Sets the matrix values.
Definition: matrixmarket.hh:683
void operator()(const std::vector< std::set< IndexData< D > > > &rows, BCRSMatrix< FieldMatrix< T, brows, bcols > > &matrix)
Sets the matrix values.
Definition: matrixmarket.hh:701
a wrapper class of numeric values.
Definition: matrixmarket.hh:593
Utility class for marking the pattern type of the MatrixMarket matrices.
Definition: matrixmarket.hh:605
Helper metaprogram to get the matrix market string representation of the numeric type.
Definition: matrixmarket.hh:74
@ is_numeric
Whether T is a supported numeric type.
Definition: matrixmarket.hh:79
Definition of the DUNE_UNUSED macro for the case that config.h is not available.