dune-istl 2.12-git
Loading...
Searching...
No Matches
matrixmarket.hh
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root
2// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
3// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
4// vi: set et ts=4 sw=2 sts=2:
5#ifndef DUNE_ISTL_MATRIXMARKET_HH
6#define DUNE_ISTL_MATRIXMARKET_HH
7
8#include <algorithm>
9#include <complex>
10#include <cstddef>
11#include <fstream>
12#include <ios>
13#include <iostream>
14#include <istream>
15#include <limits>
16#include <ostream>
17#include <set>
18#include <sstream>
19#include <string>
20#include <tuple>
21#include <type_traits>
22#include <vector>
23
31#include <dune/common/simd/simd.hh>
32
34#include <dune/istl/bvector.hh>
37
38namespace Dune
39{
40
66 namespace MatrixMarketImpl
67 {
77 template<class T>
79 enum {
83 is_numeric=false
84 };
85
87 {
88 return "unknown";
89 }
90 };
91
92 template<>
93 struct mm_numeric_type<int>
94 {
95 enum {
99 is_numeric=true
100 };
101
103 {
104 return "integer";
105 }
106 };
107
108 template<>
109 struct mm_numeric_type<double>
110 {
111 enum {
115 is_numeric=true
116 };
117
119 {
120 return "real";
121 }
122 };
123
124 template<>
125 struct mm_numeric_type<float>
126 {
127 enum {
131 is_numeric=true
132 };
133
135 {
136 return "real";
137 }
138 };
139
140#if HAVE_GMP
141 template<unsigned int precision>
142 struct mm_numeric_type<Dune::GMPField<precision>>
143 {
144 enum {
148 is_numeric=true
149 };
150
151 static std::string str()
152 {
153 return "real";
154 }
155 };
156#endif
157
158#if HAVE_QUADMATH
159 template<>
160 struct mm_numeric_type<Dune::Float128>
161 {
162 enum {
166 is_numeric=true
167 };
168
169 static std::string str()
170 {
171 return "real";
172 }
173 };
174#endif
175
176 template<>
177 struct mm_numeric_type<std::complex<double> >
178 {
179 enum {
183 is_numeric=true
184 };
185
187 {
188 return "complex";
189 }
190 };
191
192 template<>
193 struct mm_numeric_type<std::complex<float> >
194 {
195 enum {
199 is_numeric=true
200 };
201
203 {
204 return "complex";
205 }
206 };
207
216 template<class M>
218
219 template<typename T, typename A>
221 {
222 static void print(std::ostream& os)
223 {
224 os<<"%%MatrixMarket matrix coordinate ";
225 os<<mm_numeric_type<Simd::Scalar<typename Imp::BlockTraits<T>::field_type>>::str()<<" general"<<std::endl;
226 }
227 };
228
229 template<typename T, typename P, typename A>
230 struct mm_header_printer<Experimental::BCRSMatrix<T,P,A> >
231 {
232 static void print(std::ostream& os)
233 {
234 os<<"%%MatrixMarket matrix coordinate ";
235 os<<mm_numeric_type<Simd::Scalar<typename Imp::BlockTraits<T>::field_type>>::str()<<" general"<<std::endl;
236 }
237 };
238
239 template<typename B, typename A>
241 {
242 static void print(std::ostream& os)
243 {
244 os<<"%%MatrixMarket matrix array ";
245 os<<mm_numeric_type<Simd::Scalar<typename Imp::BlockTraits<B>::field_type>>::str()<<" general"<<std::endl;
246 }
247 };
248
249 template<typename T, int j>
251 {
252 static void print(std::ostream& os)
253 {
254 os<<"%%MatrixMarket matrix array ";
255 os<<mm_numeric_type<T>::str()<<" general"<<std::endl;
256 }
257 };
258
259 template<typename T, int i, int j>
261 {
262 static void print(std::ostream& os)
263 {
264 os<<"%%MatrixMarket matrix array ";
265 os<<mm_numeric_type<T>::str()<<" general"<<std::endl;
266 }
267 };
268
277 template<class M>
279
280 template<typename T, typename A>
282 {
284 static_assert(IsNumber<T>::value, "Only scalar entries are expected here!");
285
286 static void print(std::ostream& os, const M&)
287 {
288 os<<"% ISTL_STRUCT blocked ";
289 os<<"1 1"<<std::endl;
290 }
291 };
292
293 template<typename T, typename A, int i>
295 {
297
298 static void print(std::ostream& os, const M&)
299 {
300 os<<"% ISTL_STRUCT blocked ";
301 os<<i<<" "<<1<<std::endl;
302 }
303 };
304
305 template<typename T, typename A>
307 {
309 static_assert(IsNumber<T>::value, "Only scalar entries are expected here!");
310
311 static void print(std::ostream& os, const M&)
312 {
313 os<<"% ISTL_STRUCT blocked ";
314 os<<"1 1"<<std::endl;
315 }
316 };
317
318 template<typename T, typename P, typename A>
319 struct mm_block_structure_header<Experimental::BCRSMatrix<T,P,A> >
320 {
322 static_assert(IsNumber<T>::value, "Only scalar entries are expected here!");
323
324 static void print(std::ostream& os, const M&)
325 {
326 os<<"% ISTL_STRUCT blocked ";
327 os<<"1 1"<<std::endl;
328 }
329 };
330
331 template<typename T, typename A, int i, int j>
333 {
335
336 static void print(std::ostream& os, const M&)
337 {
338 os<<"% ISTL_STRUCT blocked ";
339 os<<i<<" "<<j<<std::endl;
340 }
341 };
342
343 template<typename T, typename P, typename A, int i, int j>
344 struct mm_block_structure_header<Experimental::BCRSMatrix<FieldMatrix<T,i,j>,P, A> >
345 {
347
348 static void print(std::ostream& os, const M&)
349 {
350 os<<"% ISTL_STRUCT blocked ";
351 os<<i<<" "<<j<<std::endl;
352 }
353 };
354
355
356 template<typename T, int i, int j>
358 {
360
361 static void print(std::ostream& /*os*/, const M& /*m*/)
362 {}
363 };
364
365 template<typename T, int i>
367 {
369
370 static void print(std::ostream& /*os*/, const M& /*m*/)
371 {}
372 };
373
375 enum { MM_MAX_LINE_LENGTH=1025 };
376
378
380
382
392
393 inline bool lineFeed(std::istream& file)
394 {
395 char c;
396 if(!file.eof())
397 c=file.peek();
398 else
399 return false;
400 // ignore whitespace
401 while(c==' ')
402 {
403 file.get();
404 if(file.eof())
405 return false;
406 c=file.peek();
407 }
408
409 if(c=='\n') {
410 /* eat the line feed */
411 file.get();
412 return true;
413 }
414 return false;
415 }
416
417 inline void skipComments(std::istream& file)
418 {
419 lineFeed(file);
420 char c=file.peek();
421 // ignore comment lines
422 while(c=='%')
423 {
424 /* discard the rest of the line */
426 c=file.peek();
427 }
428 }
429
430
431 inline bool readMatrixMarketBanner(std::istream& file, MMHeader& mmHeader)
432 {
433 std::string buffer;
434 char c;
435 file >> buffer;
436 c=buffer[0];
437 mmHeader=MMHeader();
438 if(c!='%')
439 return false;
440 dverb<<buffer<<std::endl;
441 /* read the banner */
442 if(buffer!="%%MatrixMarket") {
443 /* discard the rest of the line */
445 return false;
446 }
447
448 if(lineFeed(file))
449 /* premature end of line */
450 return false;
451
452 /* read the matrix_type */
453 file >> buffer;
454
455 if(buffer != "matrix")
456 {
457 /* discard the rest of the line */
459 return false;
460 }
461
462 if(lineFeed(file))
463 /* premature end of line */
464 return false;
465
466 /* The type of the matrix */
467 file >> buffer;
468
469 if(buffer.empty())
470 return false;
471
472 std::transform(buffer.begin(), buffer.end(), buffer.begin(),
473 ::tolower);
474
475 switch(buffer[0])
476 {
477 case 'a' :
478 /* sanity check */
479 if(buffer != "array")
480 {
482 return false;
483 }
484 mmHeader.type=array_type;
485 break;
486 case 'c' :
487 /* sanity check */
488 if(buffer != "coordinate")
489 {
491 return false;
492 }
493 mmHeader.type=coordinate_type;
494 break;
495 default :
497 return false;
498 }
499
500 if(lineFeed(file))
501 /* premature end of line */
502 return false;
503
504 /* The numeric type used. */
505 file >> buffer;
506
507 if(buffer.empty())
508 return false;
509
510 std::transform(buffer.begin(), buffer.end(), buffer.begin(),
511 ::tolower);
512 switch(buffer[0])
513 {
514 case 'i' :
515 /* sanity check */
516 if(buffer != "integer")
517 {
519 return false;
520 }
521 mmHeader.ctype=integer_type;
522 break;
523 case 'r' :
524 /* sanity check */
525 if(buffer != "real")
526 {
528 return false;
529 }
530 mmHeader.ctype=double_type;
531 break;
532 case 'c' :
533 /* sanity check */
534 if(buffer != "complex")
535 {
537 return false;
538 }
539 mmHeader.ctype=complex_type;
540 break;
541 case 'p' :
542 /* sanity check */
543 if(buffer != "pattern")
544 {
546 return false;
547 }
548 mmHeader.ctype=pattern;
549 break;
550 default :
552 return false;
553 }
554
555 if(lineFeed(file))
556 return false;
557
558 file >> buffer;
559
560 std::transform(buffer.begin(), buffer.end(), buffer.begin(),
561 ::tolower);
562 switch(buffer[0])
563 {
564 case 'g' :
565 /* sanity check */
566 if(buffer != "general")
567 {
569 return false;
570 }
571 mmHeader.structure=general;
572 break;
573 case 'h' :
574 /* sanity check */
575 if(buffer != "hermitian")
576 {
578 return false;
579 }
580 mmHeader.structure=hermitian;
581 break;
582 case 's' :
583 if(buffer.size()==1) {
585 return false;
586 }
587
588 switch(buffer[1])
589 {
590 case 'y' :
591 /* sanity check */
592 if(buffer != "symmetric")
593 {
595 return false;
596 }
597 mmHeader.structure=symmetric;
598 break;
599 case 'k' :
600 /* sanity check */
601 if(buffer != "skew-symmetric")
602 {
604 return false;
605 }
606 mmHeader.structure=skew_symmetric;
607 break;
608 default :
610 return false;
611 }
612 break;
613 default :
615 return false;
616 }
618 c=file.peek();
619 return true;
620
621 }
622
623 template<std::size_t brows, std::size_t bcols>
625 calculateNNZ(std::size_t rows, std::size_t cols, std::size_t entries, const MMHeader& header)
626 {
627 std::size_t blockrows=rows/brows;
628 std::size_t blockcols=cols/bcols;
629 std::size_t blocksize=brows*bcols;
630 std::size_t blockentries=0;
631
632 switch(header.structure)
633 {
634 case general :
635 blockentries = entries/blocksize; break;
636 case skew_symmetric :
637 blockentries = 2*entries/blocksize; break;
638 case symmetric :
639 blockentries = (2*entries-rows)/blocksize; break;
640 case hermitian :
641 blockentries = (2*entries-rows)/blocksize; break;
642 default :
643 throw Dune::NotImplemented();
644 }
645 return std::make_tuple(blockrows, blockcols, blockentries);
646 }
647
648 /*
649 * @brief Storage class for the column index and the numeric value.
650 *
651 * \tparam T Either a NumericWrapper of the numeric type or PatternDummy
652 * for MatrixMarket pattern case.
653 */
654 template<typename T>
655 struct IndexData : public T
656 {
658 };
659
660
671 template<typename T>
673 {
674 T number = {};
675 operator T&()
676 {
677 return number;
678 }
679 };
680
685 {};
686
687 template<>
690
691 template<typename T>
693 {
694 return is>>num.number;
695 }
696
698 {
699 return is;
700 }
701
707 template<typename T>
708 bool operator<(const IndexData<T>& i1, const IndexData<T>& i2)
709 {
710 return i1.index<i2.index;
711 }
712
718 template<typename T>
720 {
721 is>>data.index;
722 /* MatrixMarket indices are one based. Decrement for C++ */
723 --data.index;
724 return is>>data.number;
725 }
726
732 template<typename T>
734 {
735 is>>data.index;
736 /* MatrixMarket indices are one based. Decrement for C++ */
737 --data.index;
738 // real and imaginary part needs to be read separately as
739 // complex numbers are not provided in pair form. (x,y)
740 NumericWrapper<T> real, imag;
741 is>>real;
742 is>>imag;
743 data.number = {real.number, imag.number};
744 return is;
745 }
746
753 template<typename D, int brows, int bcols>
755 {
761 template<typename T>
763 BCRSMatrix<T>& matrix)
764 {
765 static_assert(IsNumber<T>::value && brows==1 && bcols==1, "Only scalar entries are expected here!");
766 for (auto iter=matrix.begin(); iter!= matrix.end(); ++iter)
767 {
768 auto brow=iter.index();
769 for (auto siter=rows[brow].begin(); siter != rows[brow].end(); ++siter)
770 (*iter)[siter->index] = siter->number;
771 }
772 }
773
779 template<typename T>
782 {
783 for (auto iter=matrix.begin(); iter!= matrix.end(); ++iter)
784 {
785 for (auto brow=iter.index()*brows,
786 browend=iter.index()*brows+brows;
787 brow<browend; ++brow)
788 {
789 for (auto siter=rows[brow].begin(), send=rows[brow].end();
790 siter != send; ++siter)
791 (*iter)[siter->index/bcols][brow%brows][siter->index%bcols]=siter->number;
792 }
793 }
794 }
795 };
796
797 template<int brows, int bcols>
799 {
800 template<typename M>
802 M& /*matrix*/)
803 {}
804 };
805
806 template<class T> struct is_complex : std::false_type {};
807 template<class T> struct is_complex<std::complex<T>> : std::true_type {};
808
809 // wrapper for std::conj. Returns T if T is not complex.
810 template<class T>
812 return r;
813 }
814
815 template<class T>
817 return std::conj(r);
818 }
819
820 template<typename M>
822 {};
823
824 template<typename B, typename A>
826 {
827 enum {
828 rows = 1,
829 cols = 1
830 };
831 };
832
833 template<typename B, typename P, typename A>
834 struct mm_multipliers<Experimental::BCRSMatrix<B,P,A> >
835 {
836 enum {
837 rows = 1,
838 cols = 1
839 };
840 };
841
842 template<typename B, int i, int j, typename A>
844 {
845 enum {
846 rows = i,
847 cols = j
848 };
849 };
850
851 template<typename B, typename P, int i, int j, typename A>
852 struct mm_multipliers<Experimental::BCRSMatrix<FieldMatrix<B,i,j>,P,A> >
853 {
854 enum {
855 rows = i,
856 cols = j
857 };
858 };
859
860 template<typename T, typename A, typename D>
862 std::istream& file, std::size_t entries,
863 const MMHeader& mmHeader, const D&)
864 {
866
867 // Number of rows and columns of T, if it is a matrix (1x1 otherwise)
868 constexpr int brows = mm_multipliers<Matrix>::rows;
869 constexpr int bcols = mm_multipliers<Matrix>::cols;
870
871 // First path
872 // store entries together with column index in a separate
873 // data structure
874 std::vector<std::set<IndexData<D> > > rows(matrix.N()*brows);
875
876 auto readloop = [&] (auto symmetryFixup) {
877 for(std::size_t i = 0; i < entries; ++i) {
878 std::size_t row;
879 IndexData<D> data;
880 skipComments(file);
881 file>>row;
882 --row; // Index was 1 based.
883 assert(row/bcols<matrix.N());
884 file>>data;
885 assert(data.index/bcols<matrix.M());
886 rows[row].insert(data);
887 if(row!=data.index)
888 symmetryFixup(row, data);
889 }
890 };
891
892 switch(mmHeader.structure)
893 {
894 case general:
895 readloop([](auto...){});
896 break;
897 case symmetric :
898 readloop([&](auto row, auto data) {
899 IndexData<D> data_sym(data);
900 data_sym.index = row;
901 rows[data.index].insert(data_sym);
902 });
903 break;
904 case skew_symmetric :
905 readloop([&](auto row, auto data) {
906 IndexData<D> data_sym;
907 data_sym.number = -data.number;
908 data_sym.index = row;
909 rows[data.index].insert(data_sym);
910 });
911 break;
912 case hermitian :
913 readloop([&](auto row, auto data) {
914 IndexData<D> data_sym;
915 data_sym.number = conj(data.number);
916 data_sym.index = row;
917 rows[data.index].insert(data_sym);
918 });
919 break;
920 default:
922 "Only general, symmetric, skew-symmetric and hermitian is supported right now!");
923 }
924
925 // Setup the matrix sparsity pattern
926 int nnz=0;
927 for(typename Matrix::CreateIterator iter=matrix.createbegin();
928 iter!= matrix.createend(); ++iter)
929 {
930 for(std::size_t brow=iter.index()*brows, browend=iter.index()*brows+brows;
931 brow<browend; ++brow)
932 {
933 typedef typename std::set<IndexData<D> >::const_iterator Siter;
934 for(Siter siter=rows[brow].begin(), send=rows[brow].end();
935 siter != send; ++siter, ++nnz)
936 iter.insert(siter->index/bcols);
937 }
938 }
939
940 //Set the matrix values
941 matrix=0;
942
944
945 Setter(rows, matrix);
946 }
947
948 template<typename T, typename P, typename A, typename D>
950 std::istream& file, std::size_t entries,
951 const MMHeader& mmHeader, const D&)
952 {
953 DUNE_THROW(Dune::NotImplemented, "Reading of Experimental::BCRSMatrix is not implemented yet!");
954 }
955
957 std::size_t lastdot = filename.find_last_of(".");
958 if(lastdot == std::string::npos)
959 return std::make_tuple(filename, "");
960 else {
961 std::string potentialFileExtension = filename.substr(lastdot);
962 if (potentialFileExtension == ".mm" || potentialFileExtension == ".mtx")
963 return std::make_tuple(filename.substr(0, lastdot), potentialFileExtension);
964 else
965 return std::make_tuple(filename, "");
966 }
967 }
968
969 } // end namespace MatrixMarketImpl
970
973
974
975 inline void mm_read_header(std::size_t& rows, std::size_t& cols,
977 bool isVector)
978 {
979 using namespace MatrixMarketImpl;
980
981 if(!readMatrixMarketBanner(istr, header)) {
982 std::cerr << "First line was not a correct Matrix Market banner. Using default:\n"
983 << "%%MatrixMarket matrix coordinate real general"<<std::endl;
984 // Go to the beginning of the file
985 istr.clear() ;
986 istr.seekg(0, std::ios::beg);
987 if(isVector)
988 header.type=array_type;
989 }
990
991 skipComments(istr);
992
993 if(lineFeed(istr))
995
996 istr >> rows;
997
998 if(lineFeed(istr))
1000 istr >> cols;
1001 }
1002
1003 template<typename T, typename A>
1006 std::istream& istr,
1007 size_t lane)
1008 {
1009 for (int i=0; size>0; ++i, --size)
1010 istr>>Simd::lane(lane,vector[i]);
1011 }
1012
1013 template<typename T, typename A, int entries>
1016 std::istream& istr,
1017 size_t lane)
1018 {
1019 for(int i=0; size>0; ++i, --size) {
1020 Simd::Scalar<T> val;
1021 istr>>val;
1022 Simd::lane(lane, vector[i/entries][i%entries])=val;
1023 }
1024 }
1025
1026
1033 template<typename T, typename A>
1035 std::istream& istr)
1036 {
1037 typedef typename Dune::BlockVector<T,A>::field_type field_type;
1038 using namespace MatrixMarketImpl;
1039
1040 MMHeader header;
1041 std::size_t rows, cols;
1042 mm_read_header(rows,cols,header,istr, true);
1043 if(cols!=Simd::lanes<field_type>()) {
1044 if(Simd::lanes<field_type>() == 1)
1045 DUNE_THROW(MatrixMarketFormatError, "cols!=1, therefore this is no vector!");
1046 else
1047 DUNE_THROW(MatrixMarketFormatError, "cols does not match the number of lanes in the field_type!");
1048 }
1049
1050 if(header.type!=array_type)
1051 DUNE_THROW(MatrixMarketFormatError, "Vectors have to be stored in array format!");
1052
1053
1054 if constexpr (Dune::IsNumber<T>())
1055 vector.resize(rows);
1056 else
1057 {
1058 T dummy;
1059 auto blocksize = dummy.size();
1060 std::size_t size=rows/blocksize;
1061 if(size*blocksize!=rows)
1062 DUNE_THROW(MatrixMarketFormatError, "Block size of vector is not correct!");
1063
1064 vector.resize(size);
1065 }
1066
1068 for(size_t l=0;l<Simd::lanes<field_type>();++l){
1069 mm_read_vector_entries(vector, rows, istr, l);
1070 }
1071 }
1072
1073 namespace Imp {
1074 template<typename Matrix>
1075 void readSparseMatrixMarket(Matrix& matrix,
1076 std::istream& istr)
1077 {
1078 using namespace MatrixMarketImpl;
1079
1080 MMHeader header;
1081 if(!readMatrixMarketBanner(istr, header)) {
1082 std::cerr << "First line was not a correct Matrix Market banner. Using default:\n"
1083 << "%%MatrixMarket matrix coordinate real general"<<std::endl;
1084 // Go to the beginning of the file
1085 istr.clear() ;
1086 istr.seekg(0, std::ios::beg);
1087 }
1088 skipComments(istr);
1089
1090 std::size_t rows, cols, entries;
1091
1092 if(lineFeed(istr))
1093 throw MatrixMarketFormatError();
1094
1095 istr >> rows;
1096
1097 if(lineFeed(istr))
1098 throw MatrixMarketFormatError();
1099 istr >> cols;
1100
1101 if(lineFeed(istr))
1102 throw MatrixMarketFormatError();
1103
1104 istr >>entries;
1105
1106 std::size_t nnz, blockrows, blockcols;
1107
1108 // Number of rows and columns of T, if it is a matrix (1x1 otherwise)
1109 constexpr int brows = mm_multipliers<Matrix>::rows;
1110 constexpr int bcols = mm_multipliers<Matrix>::cols;
1111
1112 std::tie(blockrows, blockcols, nnz) = calculateNNZ<brows, bcols>(rows, cols, entries, header);
1113
1115
1116
1117 matrix.setBuildMode(Matrix::row_wise);
1118 matrix.setSize(blockrows, blockcols, nnz);
1119
1120 if(header.type==array_type)
1121 DUNE_THROW(Dune::NotImplemented, "Array format currently not supported for matrices!");
1122
1123 readSparseEntries(matrix, istr, entries, header, NumericWrapper<typename Matrix::field_type>());
1124 }
1125 }
1126
1133 template<typename T, typename A>
1135 std::istream& istr)
1136 {
1137 Imp::readSparseMatrixMarket(matrix, istr);
1138 }
1139
1146 template<typename T, typename I, typename A>
1148 std::istream& istr)
1149 {
1150 Imp::readSparseMatrixMarket(matrix, istr);
1151 }
1152
1153
1154 // Print a scalar entry
1155 template<typename B>
1156 void mm_print_entry(const B& entry,
1157 std::size_t rowidx,
1158 std::size_t colidx,
1159 std::ostream& ostr)
1160 {
1161 if constexpr (IsNumber<B>())
1162 ostr << rowidx << " " << colidx << " " << entry << std::endl;
1163 else
1164 {
1165 for (auto row=entry.begin(); row != entry.end(); ++row, ++rowidx) {
1166 int coli=colidx;
1167 for (auto col = row->begin(); col != row->end(); ++col, ++coli)
1168 ostr<< rowidx<<" "<<coli<<" "<<*col<<std::endl;
1169 }
1170 }
1171 }
1172
1173 // Write a vector entry
1174 template<typename V>
1175 void mm_print_vector_entry(const V& entry, std::ostream& ostr,
1177 size_t lane)
1178 {
1179 ostr<<Simd::lane(lane,entry)<<std::endl;
1180 }
1181
1182 // Write a vector
1183 template<typename V>
1184 void mm_print_vector_entry(const V& vector, std::ostream& ostr,
1186 size_t lane)
1187 {
1188 using namespace MatrixMarketImpl;
1189
1190 // Is the entry a supported numeric type?
1191 const int isnumeric = mm_numeric_type<Simd::Scalar<typename V::block_type>>::is_numeric;
1192 typedef typename V::const_iterator VIter;
1193
1194 for(VIter i=vector.begin(); i != vector.end(); ++i)
1195
1196 mm_print_vector_entry(*i, ostr,
1198 lane);
1199 }
1200
1201 template<typename T, typename A>
1203 {
1204 return vector.size();
1205 }
1206
1207 template<typename T, typename A, int i>
1209 {
1210 return vector.size()*i;
1211 }
1212
1213 // Version for writing vectors.
1214 template<typename V>
1215 void writeMatrixMarket(const V& vector, std::ostream& ostr,
1217 {
1218 using namespace MatrixMarketImpl;
1219 typedef typename V::field_type field_type;
1220
1221 ostr<<countEntries(vector)<<" "<<Simd::lanes<field_type>()<<std::endl;
1222 const int isnumeric = mm_numeric_type<Simd::Scalar<V>>::is_numeric;
1223 for(size_t l=0;l<Simd::lanes<field_type>(); ++l){
1225 }
1226 }
1227
1228 // Versions for writing matrices
1229 template<typename M>
1230 void writeMatrixMarket(const M& matrix,
1231 std::ostream& ostr,
1233 {
1234 ostr<<matrix.N()*MatrixMarketImpl::mm_multipliers<M>::rows<<" "
1236 <<countNonZeros(matrix)<<std::endl;
1237
1238 typedef typename M::const_iterator riterator;
1239 typedef typename M::ConstColIterator citerator;
1240 for(riterator row=matrix.begin(); row != matrix.end(); ++row)
1241 for(citerator col = row->begin(); col != row->end(); ++col)
1242 // Matrix Market indexing start with 1!
1245 }
1246
1247
1251 template<typename M>
1252 void writeMatrixMarket(const M& matrix,
1253 std::ostream& ostr)
1254 {
1255 using namespace MatrixMarketImpl;
1256
1257 // Write header information
1258 mm_header_printer<M>::print(ostr);
1259 mm_block_structure_header<M>::print(ostr,matrix);
1260 // Choose the correct function for matrix and vector
1262 }
1263
1264 static const int default_precision = -1;
1276 template<typename M>
1277 void storeMatrixMarket(const M& matrix,
1278 std::string filename,
1279 int prec=default_precision)
1280 {
1281 auto [pureFilename, extension] = MatrixMarketImpl::splitFilename(filename);
1282 std::string rfilename;
1283 std::ofstream file;
1284 if (extension != "") {
1285 rfilename = pureFilename + extension;
1286 file.open(rfilename.c_str());
1287 if(!file)
1288 DUNE_THROW(IOError, "Could not open file for storage: " << rfilename.c_str());
1289 }
1290 else {
1291 // only try .mm so we do not ignore potential errors
1292 rfilename = pureFilename + ".mm";
1293 file.open(rfilename.c_str());
1294 if(!file)
1295 DUNE_THROW(IOError, "Could not open file for storage: " << rfilename.c_str());
1296 }
1297
1298 file.setf(std::ios::scientific,std::ios::floatfield);
1299 if(prec>0)
1300 file.precision(prec);
1301 writeMatrixMarket(matrix, file);
1302 file.close();
1303 }
1304
1305#if HAVE_MPI
1320 template<typename M, typename G, typename L>
1321 void storeMatrixMarket(const M& matrix,
1322 std::string filename,
1324 bool storeIndices=true,
1325 int prec=default_precision)
1326 {
1327 // Get our rank
1328 int rank = comm.communicator().rank();
1329 // Write the local matrix
1330 auto [pureFilename, extension] = MatrixMarketImpl::splitFilename(filename);
1331 std::string rfilename;
1332 std::ofstream file;
1333 if (extension != "") {
1334 rfilename = pureFilename + "_" + std::to_string(rank) + extension;
1335 file.open(rfilename.c_str());
1336 dverb<< rfilename <<std::endl;
1337 if(!file)
1338 DUNE_THROW(IOError, "Could not open file for storage: " << rfilename.c_str());
1339 }
1340 else {
1341 // only try .mm so we do not ignore potential errors
1342 rfilename = pureFilename + "_" + std::to_string(rank) + ".mm";
1343 file.open(rfilename.c_str());
1344 dverb<< rfilename <<std::endl;
1345 if(!file)
1346 DUNE_THROW(IOError, "Could not open file for storage: " << rfilename.c_str());
1347 }
1348 file.setf(std::ios::scientific,std::ios::floatfield);
1349 if(prec>0)
1350 file.precision(prec);
1351 writeMatrixMarket(matrix, file);
1352 file.close();
1353
1354 if(!storeIndices)
1355 return;
1356
1357 // Write the global to local index mapping
1358 rfilename = pureFilename + "_" + std::to_string(rank) + ".idx";
1359 file.open(rfilename.c_str());
1360 if(!file)
1361 DUNE_THROW(IOError, "Could not open file for storage: " << rfilename.c_str());
1362 file.setf(std::ios::scientific,std::ios::floatfield);
1364 typedef typename IndexSet::const_iterator Iterator;
1365 for(Iterator iter = comm.indexSet().begin();
1366 iter != comm.indexSet().end(); ++iter) {
1367 file << iter->global()<<" "<<(std::size_t)iter->local()<<" "
1368 <<(int)iter->local().attribute()<<" "<<(int)iter->local().isPublic()<<std::endl;
1369 }
1370 // Store neighbour information for efficient remote indices setup.
1371 file<<"neighbours:";
1372 const std::set<int>& neighbours=comm.remoteIndices().getNeighbours();
1373 typedef std::set<int>::const_iterator SIter;
1374 for(SIter neighbour=neighbours.begin(); neighbour != neighbours.end(); ++neighbour) {
1375 file<<" "<< *neighbour;
1376 }
1377 file.close();
1378 }
1379
1394 template<typename M, typename G, typename L>
1395 void loadMatrixMarket(M& matrix,
1396 const std::string& filename,
1398 bool readIndices=true)
1399 {
1400 using namespace MatrixMarketImpl;
1401
1403 typedef typename LocalIndexT::Attribute Attribute;
1404 // Get our rank
1405 int rank = comm.communicator().rank();
1406 // load local matrix
1407 auto [pureFilename, extension] = MatrixMarketImpl::splitFilename(filename);
1408 std::string rfilename;
1409 std::ifstream file;
1410 if (extension != "") {
1411 rfilename = pureFilename + "_" + std::to_string(rank) + extension;
1412 file.open(rfilename.c_str(), std::ios::in);
1413 dverb<< rfilename <<std::endl;
1414 if(!file)
1415 DUNE_THROW(IOError, "Could not open file: " << rfilename.c_str());
1416 }
1417 else {
1418 // try both .mm and .mtx
1419 rfilename = pureFilename + "_" + std::to_string(rank) + ".mm";
1420 file.open(rfilename.c_str(), std::ios::in);
1421 if(!file) {
1422 rfilename = pureFilename + "_" + std::to_string(rank) + ".mtx";
1423 file.open(rfilename.c_str(), std::ios::in);
1424 dverb<< rfilename <<std::endl;
1425 if(!file)
1426 DUNE_THROW(IOError, "Could not open file: " << rfilename.c_str());
1427 }
1428 }
1429 readMatrixMarket(matrix,file);
1430 file.close();
1431
1432 if(!readIndices)
1433 return;
1434
1435 // read indices
1437 IndexSet& pis=comm.pis;
1438 rfilename = pureFilename + "_" + std::to_string(rank) + ".idx";
1439 file.open(rfilename.c_str());
1440 if(!file)
1441 DUNE_THROW(IOError, "Could not open file: " << rfilename.c_str());
1442 if(pis.size()!=0)
1443 DUNE_THROW(InvalidIndexSetState, "Index set is not empty!");
1444
1445 pis.beginResize();
1446 while(!file.eof() && file.peek()!='n') {
1447 G g;
1448 file >>g;
1449 std::size_t l;
1450 file >>l;
1451 int c;
1452 file >>c;
1453 bool b;
1454 file >> b;
1455 pis.add(g,LocalIndexT(l,Attribute(c),b));
1456 lineFeed(file);
1457 }
1458 pis.endResize();
1459 if(!file.eof()) {
1460 // read neighbours
1461 std::string s;
1462 file>>s;
1463 if(s!="neighbours:")
1464 DUNE_THROW(MatrixMarketFormatError, "was expecting the string: \"neighbours:\"");
1465 std::set<int> nb;
1466 while(!file.eof()) {
1467 int i;
1468 file >> i;
1469 nb.insert(i);
1470 }
1471 file.close();
1472 comm.ri.setNeighbours(nb);
1473 }
1474 comm.ri.template rebuild<false>();
1475 }
1476
1477 #endif
1478
1489 template<typename M>
1490 void loadMatrixMarket(M& matrix,
1491 const std::string& filename)
1492 {
1493 auto [pureFilename, extension] = MatrixMarketImpl::splitFilename(filename);
1494 std::string rfilename;
1495 std::ifstream file;
1496 if (extension != "") {
1497 rfilename = pureFilename + extension;
1498 file.open(rfilename.c_str());
1499 if(!file)
1500 DUNE_THROW(IOError, "Could not open file: " << rfilename.c_str());
1501 }
1502 else {
1503 // try both .mm and .mtx
1504 rfilename = pureFilename + ".mm";
1505 file.open(rfilename.c_str(), std::ios::in);
1506 if(!file) {
1507 rfilename = pureFilename + ".mtx";
1508 file.open(rfilename.c_str(), std::ios::in);
1509 if(!file)
1510 DUNE_THROW(IOError, "Could not open file: " << rfilename.c_str());
1511 }
1512 }
1513 readMatrixMarket(matrix,file);
1514 file.close();
1515 }
1516
1518}
1519#endif
Some handy generic functions for ISTL matrices.
This file implements a vector space as a tensor product of a given vector space. The number of compon...
Implementation of the BCRSMatrix class.
Classes providing communication interfaces for overlapping Schwarz methods.
Col col
Definition matrixmatrix.hh:351
auto countNonZeros(const M &, typename std::enable_if_t< Dune::IsNumber< M >::value > *sfinae=nullptr)
Get the number of nonzero fields in the matrix.
Definition matrixutils.hh:129
void readMatrixMarket(Dune::BlockVector< T, A > &vector, std::istream &istr)
Reads a BlockVector from a matrix market file.
Definition matrixmarket.hh:1034
void storeMatrixMarket(const M &matrix, std::string filename, int prec=default_precision)
Stores a parallel matrix/vector in matrix market format in a file.
Definition matrixmarket.hh:1277
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:1395
std::size_t countEntries(const BlockVector< T, A > &vector)
Definition matrixmarket.hh:1202
void writeMatrixMarket(const V &vector, std::ostream &ostr, const std::integral_constant< int, 0 > &)
Definition matrixmarket.hh:1215
void mm_print_vector_entry(const V &entry, std::ostream &ostr, const std::integral_constant< int, 1 > &, size_t lane)
Definition matrixmarket.hh:1175
static const int default_precision
Definition matrixmarket.hh:1264
void mm_read_vector_entries(Dune::BlockVector< T, A > &vector, std::size_t size, std::istream &istr, size_t lane)
Definition matrixmarket.hh:1004
void mm_read_header(std::size_t &rows, std::size_t &cols, MatrixMarketImpl::MMHeader &header, std::istream &istr, bool isVector)
Definition matrixmarket.hh:975
void mm_print_entry(const B &entry, std::size_t rowidx, std::size_t colidx, std::ostream &ostr)
Definition matrixmarket.hh:1156
STL namespace.
std::tuple< std::size_t, std::size_t, std::size_t > calculateNNZ(std::size_t rows, std::size_t cols, std::size_t entries, const MMHeader &header)
Definition matrixmarket.hh:625
bool operator<(const IndexData< T > &i1, const IndexData< T > &i2)
LessThan operator.
Definition matrixmarket.hh:708
LineType
Definition matrixmarket.hh:374
@ DATA
Definition matrixmarket.hh:374
@ MM_HEADER
Definition matrixmarket.hh:374
@ MM_ISTLSTRUCT
Definition matrixmarket.hh:374
bool readMatrixMarketBanner(std::istream &file, MMHeader &mmHeader)
Definition matrixmarket.hh:431
void readSparseEntries(Dune::BCRSMatrix< T, A > &matrix, std::istream &file, std::size_t entries, const MMHeader &mmHeader, const D &)
Definition matrixmarket.hh:861
MM_TYPE
Definition matrixmarket.hh:377
@ array_type
Definition matrixmarket.hh:377
@ coordinate_type
Definition matrixmarket.hh:377
@ unknown_type
Definition matrixmarket.hh:377
std::istream & operator>>(std::istream &is, NumericWrapper< T > &num)
Definition matrixmarket.hh:692
void skipComments(std::istream &file)
Definition matrixmarket.hh:417
bool lineFeed(std::istream &file)
Definition matrixmarket.hh:393
@ MM_MAX_LINE_LENGTH
Definition matrixmarket.hh:375
MM_STRUCTURE
Definition matrixmarket.hh:381
@ skew_symmetric
Definition matrixmarket.hh:381
@ general
Definition matrixmarket.hh:381
@ hermitian
Definition matrixmarket.hh:381
@ unknown_structure
Definition matrixmarket.hh:381
@ symmetric
Definition matrixmarket.hh:381
MM_CTYPE
Definition matrixmarket.hh:379
@ unknown_ctype
Definition matrixmarket.hh:379
@ pattern
Definition matrixmarket.hh:379
@ complex_type
Definition matrixmarket.hh:379
@ double_type
Definition matrixmarket.hh:379
@ integer_type
Definition matrixmarket.hh:379
std::enable_if_t<!is_complex< T >::value, T > conj(const T &r)
Definition matrixmarket.hh:811
std::tuple< std::string, std::string > splitFilename(const std::string &filename)
Definition matrixmarket.hh:956
int size() const
iterator begin()
static constexpr size_type M()
#define DUNE_THROW(E,...)
int neighbours() const
decltype(auto) lane(std::size_t l, V &&v)
typename Overloads::ScalarType< std::decay_t< V > >::type Scalar
DVerbType dverb
T lane(std::size_t l, const T &v)
A sparse block matrix with compressed row storage.
Definition bcrsmatrix.hh:468
Iterator begin()
Get iterator to first row.
Definition bcrsmatrix.hh:673
Iterator end()
Get iterator to one beyond last row.
Definition bcrsmatrix.hh:679
CreateIterator createend()
get create iterator pointing to one after the last block
Definition bcrsmatrix.hh:1107
size_type M() const
number of columns (counted in blocks)
Definition bcrsmatrix.hh:2014
CreateIterator createbegin()
get initial create iterator
Definition bcrsmatrix.hh:1101
size_type N() const
number of rows (counted in blocks)
Definition bcrsmatrix.hh:2008
A vector of blocks with memory management.
Definition bvector.hh:392
void resize(size_type size)
Resize the vector.
Definition bvector.hh:496
typename Imp::BlockTraits< B >::field_type field_type
export the type representing the field
Definition bvector.hh:398
const std::set< int > & getNeighbours() const
void setNeighbours(const C &neighbours)
Block compressed row storage matrix.
Definition experimental/bcrsmatrix.hh:82
A generic dynamic dense matrix.
Definition matrix.hh:561
Helper metaprogram to get the matrix market string representation of the numeric type.
Definition matrixmarket.hh:78
static std::string str()
Definition matrixmarket.hh:86
@ is_numeric
Whether T is a supported numeric type.
Definition matrixmarket.hh:83
static std::string str()
Definition matrixmarket.hh:102
static std::string str()
Definition matrixmarket.hh:118
static std::string str()
Definition matrixmarket.hh:134
static std::string str()
Definition matrixmarket.hh:186
static std::string str()
Definition matrixmarket.hh:202
Meta program to write the correct Matrix Market header.
Definition matrixmarket.hh:217
static void print(std::ostream &os)
Definition matrixmarket.hh:222
static void print(std::ostream &os)
Definition matrixmarket.hh:232
static void print(std::ostream &os)
Definition matrixmarket.hh:242
static void print(std::ostream &os)
Definition matrixmarket.hh:252
static void print(std::ostream &os)
Definition matrixmarket.hh:262
Metaprogram for writing the ISTL block structure header.
Definition matrixmarket.hh:278
static void print(std::ostream &os, const M &)
Definition matrixmarket.hh:286
BlockVector< T, A > M
Definition matrixmarket.hh:283
BlockVector< FieldVector< T, i >, A > M
Definition matrixmarket.hh:296
static void print(std::ostream &os, const M &)
Definition matrixmarket.hh:298
BCRSMatrix< T, A > M
Definition matrixmarket.hh:308
static void print(std::ostream &os, const M &)
Definition matrixmarket.hh:311
static void print(std::ostream &os, const M &)
Definition matrixmarket.hh:324
Experimental::BCRSMatrix< T, P, A > M
Definition matrixmarket.hh:321
BCRSMatrix< FieldMatrix< T, i, j >, A > M
Definition matrixmarket.hh:334
static void print(std::ostream &os, const M &)
Definition matrixmarket.hh:336
Experimental::BCRSMatrix< FieldMatrix< T, i, j >, P, A > M
Definition matrixmarket.hh:346
FieldMatrix< T, i, j > M
Definition matrixmarket.hh:359
static void print(std::ostream &, const M &)
Definition matrixmarket.hh:361
static void print(std::ostream &, const M &)
Definition matrixmarket.hh:370
FieldVector< T, i > M
Definition matrixmarket.hh:368
Definition matrixmarket.hh:384
MM_STRUCTURE structure
Definition matrixmarket.hh:390
MM_TYPE type
Definition matrixmarket.hh:388
MMHeader()
Definition matrixmarket.hh:385
MM_CTYPE ctype
Definition matrixmarket.hh:389
Definition matrixmarket.hh:656
std::size_t index
Definition matrixmarket.hh:657
a wrapper class of numeric values.
Definition matrixmarket.hh:673
T number
Definition matrixmarket.hh:674
Utility class for marking the pattern type of the MatrixMarket matrices.
Definition matrixmarket.hh:685
Functor to the data values of the matrix.
Definition matrixmarket.hh:755
void operator()(const std::vector< std::set< IndexData< D > > > &rows, BCRSMatrix< T > &matrix)
Sets the matrix values.
Definition matrixmarket.hh:762
void operator()(const std::vector< std::set< IndexData< D > > > &rows, BCRSMatrix< FieldMatrix< T, brows, bcols > > &matrix)
Sets the matrix values.
Definition matrixmarket.hh:780
void operator()(const std::vector< std::set< IndexData< PatternDummy > > > &, M &)
Definition matrixmarket.hh:801
Definition matrixmarket.hh:806
Definition matrixmarket.hh:822
Definition matrixmarket.hh:972
Test whether a type is an ISTL Matrix.
Definition matrixutils.hh:514
T begin(T... args)
T c_str(T... args)
T clear(T... args)
T close(T... args)
T empty(T... args)
T end(T... args)
T endl(T... args)
T eof(T... args)
T find_last_of(T... args)
T get(T... args)
T ignore(T... args)
T insert(T... args)
T make_tuple(T... args)
T open(T... args)
T peek(T... args)
T precision(T... args)
T seekg(T... args)
T setf(T... args)
T size(T... args)
T substr(T... args)
T tie(T... args)
T to_string(T... args)
T transform(T... args)