dune-istl 2.11
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
24#include <dune/common/exceptions.hh>
25#include <dune/common/fmatrix.hh>
26#include <dune/common/fvector.hh>
27#include <dune/common/gmpfield.hh>
28#include <dune/common/hybridutilities.hh>
29#include <dune/common/quadmath.hh>
30#include <dune/common/stdstreams.hh>
31#include <dune/common/simd/simd.hh>
32
34#include <dune/istl/bvector.hh>
35#include <dune/istl/matrixutils.hh> // countNonZeros()
37
38namespace Dune
39{
40
60
67 {
77 template<class T>
79 enum {
84 };
85
86 static std::string str()
87 {
88 return "unknown";
89 }
90 };
91
92 template<>
93 struct mm_numeric_type<int>
94 {
95 enum {
100 };
101
102 static std::string str()
103 {
104 return "integer";
105 }
106 };
107
108 template<>
109 struct mm_numeric_type<double>
110 {
111 enum {
116 };
117
118 static std::string str()
119 {
120 return "real";
121 }
122 };
123
124 template<>
125 struct mm_numeric_type<float>
126 {
127 enum {
132 };
133
134 static std::string str()
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 {
184 };
185
186 static std::string str()
187 {
188 return "complex";
189 }
190 };
191
192 template<>
193 struct mm_numeric_type<std::complex<float> >
194 {
195 enum {
200 };
201
202 static std::string str()
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 B, typename A>
231 {
232 static void print(std::ostream& os)
233 {
234 os<<"%%MatrixMarket matrix array ";
235 os<<mm_numeric_type<Simd::Scalar<typename Imp::BlockTraits<B>::field_type>>::str()<<" general"<<std::endl;
236 }
237 };
238
239 template<typename T, int j>
240 struct mm_header_printer<FieldVector<T,j> >
241 {
242 static void print(std::ostream& os)
243 {
244 os<<"%%MatrixMarket matrix array ";
245 os<<mm_numeric_type<T>::str()<<" general"<<std::endl;
246 }
247 };
248
249 template<typename T, int i, 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
267 template<class M>
269
270 template<typename T, typename A>
272 {
274 static_assert(IsNumber<T>::value, "Only scalar entries are expected here!");
275
276 static void print(std::ostream& os, const M&)
277 {
278 os<<"% ISTL_STRUCT blocked ";
279 os<<"1 1"<<std::endl;
280 }
281 };
282
283 template<typename T, typename A, int i>
284 struct mm_block_structure_header<BlockVector<FieldVector<T,i>,A> >
285 {
287
288 static void print(std::ostream& os, const M&)
289 {
290 os<<"% ISTL_STRUCT blocked ";
291 os<<i<<" "<<1<<std::endl;
292 }
293 };
294
295 template<typename T, typename A>
297 {
299 static_assert(IsNumber<T>::value, "Only scalar entries are expected here!");
300
301 static void print(std::ostream& os, const M&)
302 {
303 os<<"% ISTL_STRUCT blocked ";
304 os<<"1 1"<<std::endl;
305 }
306 };
307
308 template<typename T, typename A, int i, int j>
310 {
312
313 static void print(std::ostream& os, const M&)
314 {
315 os<<"% ISTL_STRUCT blocked ";
316 os<<i<<" "<<j<<std::endl;
317 }
318 };
319
320
321 template<typename T, int i, int j>
323 {
325
326 static void print(std::ostream& /*os*/, const M& /*m*/)
327 {}
328 };
329
330 template<typename T, int i>
331 struct mm_block_structure_header<FieldVector<T,i> >
332 {
333 typedef FieldVector<T,i> M;
334
335 static void print(std::ostream& /*os*/, const M& /*m*/)
336 {}
337 };
338
340 enum { MM_MAX_LINE_LENGTH=1025 };
341
343
345
347
357
358 inline bool lineFeed(std::istream& file)
359 {
360 char c;
361 if(!file.eof())
362 c=file.peek();
363 else
364 return false;
365 // ignore whitespace
366 while(c==' ')
367 {
368 file.get();
369 if(file.eof())
370 return false;
371 c=file.peek();
372 }
373
374 if(c=='\n') {
375 /* eat the line feed */
376 file.get();
377 return true;
378 }
379 return false;
380 }
381
382 inline void skipComments(std::istream& file)
383 {
384 lineFeed(file);
385 char c=file.peek();
386 // ignore comment lines
387 while(c=='%')
388 {
389 /* discard the rest of the line */
390 file.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
391 c=file.peek();
392 }
393 }
394
395
396 inline bool readMatrixMarketBanner(std::istream& file, MMHeader& mmHeader)
397 {
398 std::string buffer;
399 char c;
400 file >> buffer;
401 c=buffer[0];
402 mmHeader=MMHeader();
403 if(c!='%')
404 return false;
405 dverb<<buffer<<std::endl;
406 /* read the banner */
407 if(buffer!="%%MatrixMarket") {
408 /* discard the rest of the line */
409 file.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
410 return false;
411 }
412
413 if(lineFeed(file))
414 /* premature end of line */
415 return false;
416
417 /* read the matrix_type */
418 file >> buffer;
419
420 if(buffer != "matrix")
421 {
422 /* discard the rest of the line */
423 file.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
424 return false;
425 }
426
427 if(lineFeed(file))
428 /* premature end of line */
429 return false;
430
431 /* The type of the matrix */
432 file >> buffer;
433
434 if(buffer.empty())
435 return false;
436
437 std::transform(buffer.begin(), buffer.end(), buffer.begin(),
438 ::tolower);
439
440 switch(buffer[0])
441 {
442 case 'a' :
443 /* sanity check */
444 if(buffer != "array")
445 {
446 file.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
447 return false;
448 }
449 mmHeader.type=array_type;
450 break;
451 case 'c' :
452 /* sanity check */
453 if(buffer != "coordinate")
454 {
455 file.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
456 return false;
457 }
458 mmHeader.type=coordinate_type;
459 break;
460 default :
461 file.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
462 return false;
463 }
464
465 if(lineFeed(file))
466 /* premature end of line */
467 return false;
468
469 /* The numeric type used. */
470 file >> buffer;
471
472 if(buffer.empty())
473 return false;
474
475 std::transform(buffer.begin(), buffer.end(), buffer.begin(),
476 ::tolower);
477 switch(buffer[0])
478 {
479 case 'i' :
480 /* sanity check */
481 if(buffer != "integer")
482 {
483 file.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
484 return false;
485 }
486 mmHeader.ctype=integer_type;
487 break;
488 case 'r' :
489 /* sanity check */
490 if(buffer != "real")
491 {
492 file.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
493 return false;
494 }
495 mmHeader.ctype=double_type;
496 break;
497 case 'c' :
498 /* sanity check */
499 if(buffer != "complex")
500 {
501 file.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
502 return false;
503 }
504 mmHeader.ctype=complex_type;
505 break;
506 case 'p' :
507 /* sanity check */
508 if(buffer != "pattern")
509 {
510 file.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
511 return false;
512 }
513 mmHeader.ctype=pattern;
514 break;
515 default :
516 file.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
517 return false;
518 }
519
520 if(lineFeed(file))
521 return false;
522
523 file >> buffer;
524
525 std::transform(buffer.begin(), buffer.end(), buffer.begin(),
526 ::tolower);
527 switch(buffer[0])
528 {
529 case 'g' :
530 /* sanity check */
531 if(buffer != "general")
532 {
533 file.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
534 return false;
535 }
536 mmHeader.structure=general;
537 break;
538 case 'h' :
539 /* sanity check */
540 if(buffer != "hermitian")
541 {
542 file.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
543 return false;
544 }
545 mmHeader.structure=hermitian;
546 break;
547 case 's' :
548 if(buffer.size()==1) {
549 file.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
550 return false;
551 }
552
553 switch(buffer[1])
554 {
555 case 'y' :
556 /* sanity check */
557 if(buffer != "symmetric")
558 {
559 file.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
560 return false;
561 }
562 mmHeader.structure=symmetric;
563 break;
564 case 'k' :
565 /* sanity check */
566 if(buffer != "skew-symmetric")
567 {
568 file.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
569 return false;
570 }
571 mmHeader.structure=skew_symmetric;
572 break;
573 default :
574 file.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
575 return false;
576 }
577 break;
578 default :
579 file.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
580 return false;
581 }
582 file.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
583 c=file.peek();
584 return true;
585
586 }
587
588 template<std::size_t brows, std::size_t bcols>
589 std::tuple<std::size_t, std::size_t, std::size_t>
590 calculateNNZ(std::size_t rows, std::size_t cols, std::size_t entries, const MMHeader& header)
591 {
592 std::size_t blockrows=rows/brows;
593 std::size_t blockcols=cols/bcols;
594 std::size_t blocksize=brows*bcols;
595 std::size_t blockentries=0;
596
597 switch(header.structure)
598 {
599 case general :
600 blockentries = entries/blocksize; break;
601 case skew_symmetric :
602 blockentries = 2*entries/blocksize; break;
603 case symmetric :
604 blockentries = (2*entries-rows)/blocksize; break;
605 case hermitian :
606 blockentries = (2*entries-rows)/blocksize; break;
607 default :
608 throw Dune::NotImplemented();
609 }
610 return std::make_tuple(blockrows, blockcols, blockentries);
611 }
612
613 /*
614 * @brief Storage class for the column index and the numeric value.
615 *
616 * \tparam T Either a NumericWrapper of the numeric type or PatternDummy
617 * for MatrixMarket pattern case.
618 */
619 template<typename T>
620 struct IndexData : public T
621 {
622 std::size_t index = {};
623 };
624
625
636 template<typename T>
638 {
639 T number = {};
640 operator T&()
641 {
642 return number;
643 }
644 };
645
650 {};
651
652 template<>
655
656 template<typename T>
657 std::istream& operator>>(std::istream& is, NumericWrapper<T>& num)
658 {
659 return is>>num.number;
660 }
661
662 inline std::istream& operator>>(std::istream& is, [[maybe_unused]] NumericWrapper<PatternDummy>& num)
663 {
664 return is;
665 }
666
672 template<typename T>
673 bool operator<(const IndexData<T>& i1, const IndexData<T>& i2)
674 {
675 return i1.index<i2.index;
676 }
677
683 template<typename T>
684 std::istream& operator>>(std::istream& is, IndexData<T>& data)
685 {
686 is>>data.index;
687 /* MatrixMarket indices are one based. Decrement for C++ */
688 --data.index;
689 return is>>data.number;
690 }
691
697 template<typename T>
698 std::istream& operator>>(std::istream& is, IndexData<NumericWrapper<std::complex<T>>>& data)
699 {
700 is>>data.index;
701 /* MatrixMarket indices are one based. Decrement for C++ */
702 --data.index;
703 // real and imaginary part needs to be read separately as
704 // complex numbers are not provided in pair form. (x,y)
705 NumericWrapper<T> real, imag;
706 is>>real;
707 is>>imag;
708 data.number = {real.number, imag.number};
709 return is;
710 }
711
718 template<typename D, int brows, int bcols>
720 {
726 template<typename T>
727 void operator()(const std::vector<std::set<IndexData<D> > >& rows,
728 BCRSMatrix<T>& matrix)
729 {
730 static_assert(IsNumber<T>::value && brows==1 && bcols==1, "Only scalar entries are expected here!");
731 for (auto iter=matrix.begin(); iter!= matrix.end(); ++iter)
732 {
733 auto brow=iter.index();
734 for (auto siter=rows[brow].begin(); siter != rows[brow].end(); ++siter)
735 (*iter)[siter->index] = siter->number;
736 }
737 }
738
744 template<typename T>
745 void operator()(const std::vector<std::set<IndexData<D> > >& rows,
747 {
748 for (auto iter=matrix.begin(); iter!= matrix.end(); ++iter)
749 {
750 for (auto brow=iter.index()*brows,
751 browend=iter.index()*brows+brows;
752 brow<browend; ++brow)
753 {
754 for (auto siter=rows[brow].begin(), send=rows[brow].end();
755 siter != send; ++siter)
756 (*iter)[siter->index/bcols][brow%brows][siter->index%bcols]=siter->number;
757 }
758 }
759 }
760 };
761
762 template<int brows, int bcols>
764 {
765 template<typename M>
766 void operator()(const std::vector<std::set<IndexData<PatternDummy> > >& /*rows*/,
767 M& /*matrix*/)
768 {}
769 };
770
771 template<class T> struct is_complex : std::false_type {};
772 template<class T> struct is_complex<std::complex<T>> : std::true_type {};
773
774 // wrapper for std::conj. Returns T if T is not complex.
775 template<class T>
776 std::enable_if_t<!is_complex<T>::value, T> conj(const T& r){
777 return r;
778 }
779
780 template<class T>
781 std::enable_if_t<is_complex<T>::value, T> conj(const T& r){
782 return std::conj(r);
783 }
784
785 template<typename M>
787 {};
788
789 template<typename B, typename A>
791 {
792 enum {
793 rows = 1,
795 };
796 };
797
798 template<typename B, int i, int j, typename A>
800 {
801 enum {
802 rows = i,
804 };
805 };
806
807 template<typename T, typename A, typename D>
809 std::istream& file, std::size_t entries,
810 const MMHeader& mmHeader, const D&)
811 {
813
814 // Number of rows and columns of T, if it is a matrix (1x1 otherwise)
815 constexpr int brows = mm_multipliers<Matrix>::rows;
816 constexpr int bcols = mm_multipliers<Matrix>::cols;
817
818 // First path
819 // store entries together with column index in a separate
820 // data structure
821 std::vector<std::set<IndexData<D> > > rows(matrix.N()*brows);
822
823 auto readloop = [&] (auto symmetryFixup) {
824 for(std::size_t i = 0; i < entries; ++i) {
825 std::size_t row;
826 IndexData<D> data;
827 skipComments(file);
828 file>>row;
829 --row; // Index was 1 based.
830 assert(row/bcols<matrix.N());
831 file>>data;
832 assert(data.index/bcols<matrix.M());
833 rows[row].insert(data);
834 if(row!=data.index)
835 symmetryFixup(row, data);
836 }
837 };
838
839 switch(mmHeader.structure)
840 {
841 case general:
842 readloop([](auto...){});
843 break;
844 case symmetric :
845 readloop([&](auto row, auto data) {
846 IndexData<D> data_sym(data);
847 data_sym.index = row;
848 rows[data.index].insert(data_sym);
849 });
850 break;
851 case skew_symmetric :
852 readloop([&](auto row, auto data) {
853 IndexData<D> data_sym;
854 data_sym.number = -data.number;
855 data_sym.index = row;
856 rows[data.index].insert(data_sym);
857 });
858 break;
859 case hermitian :
860 readloop([&](auto row, auto data) {
861 IndexData<D> data_sym;
862 data_sym.number = conj(data.number);
863 data_sym.index = row;
864 rows[data.index].insert(data_sym);
865 });
866 break;
867 default:
868 DUNE_THROW(Dune::NotImplemented,
869 "Only general, symmetric, skew-symmetric and hermitian is supported right now!");
870 }
871
872 // Setup the matrix sparsity pattern
873 int nnz=0;
874 for(typename Matrix::CreateIterator iter=matrix.createbegin();
875 iter!= matrix.createend(); ++iter)
876 {
877 for(std::size_t brow=iter.index()*brows, browend=iter.index()*brows+brows;
878 brow<browend; ++brow)
879 {
880 typedef typename std::set<IndexData<D> >::const_iterator Siter;
881 for(Siter siter=rows[brow].begin(), send=rows[brow].end();
882 siter != send; ++siter, ++nnz)
883 iter.insert(siter->index/bcols);
884 }
885 }
886
887 //Set the matrix values
888 matrix=0;
889
891
892 Setter(rows, matrix);
893 }
894
895 inline std::tuple<std::string, std::string> splitFilename(const std::string& filename) {
896 std::size_t lastdot = filename.find_last_of(".");
897 if(lastdot == std::string::npos)
898 return std::make_tuple(filename, "");
899 else {
900 std::string potentialFileExtension = filename.substr(lastdot);
901 if (potentialFileExtension == ".mm" || potentialFileExtension == ".mtx")
902 return std::make_tuple(filename.substr(0, lastdot), potentialFileExtension);
903 else
904 return std::make_tuple(filename, "");
905 }
906 }
907
908 } // end namespace MatrixMarketImpl
909
910 class MatrixMarketFormatError : public Dune::Exception
911 {};
912
913
914 inline void mm_read_header(std::size_t& rows, std::size_t& cols,
915 MatrixMarketImpl::MMHeader& header, std::istream& istr,
916 bool isVector)
917 {
918 using namespace MatrixMarketImpl;
919
920 if(!readMatrixMarketBanner(istr, header)) {
921 std::cerr << "First line was not a correct Matrix Market banner. Using default:\n"
922 << "%%MatrixMarket matrix coordinate real general"<<std::endl;
923 // Go to the beginning of the file
924 istr.clear() ;
925 istr.seekg(0, std::ios::beg);
926 if(isVector)
927 header.type=array_type;
928 }
929
930 skipComments(istr);
931
932 if(lineFeed(istr))
934
935 istr >> rows;
936
937 if(lineFeed(istr))
939 istr >> cols;
940 }
941
942 template<typename T, typename A>
944 std::size_t size,
945 std::istream& istr,
946 size_t lane)
947 {
948 for (int i=0; size>0; ++i, --size)
949 istr>>Simd::lane(lane,vector[i]);
950 }
951
952 template<typename T, typename A, int entries>
953 void mm_read_vector_entries(Dune::BlockVector<Dune::FieldVector<T,entries>,A>& vector,
954 std::size_t size,
955 std::istream& istr,
956 size_t lane)
957 {
958 for(int i=0; size>0; ++i, --size) {
959 Simd::Scalar<T> val;
960 istr>>val;
961 Simd::lane(lane, vector[i/entries][i%entries])=val;
962 }
963 }
964
965
972 template<typename T, typename A>
974 std::istream& istr)
975 {
976 typedef typename Dune::BlockVector<T,A>::field_type field_type;
977 using namespace MatrixMarketImpl;
978
979 MMHeader header;
980 std::size_t rows, cols;
981 mm_read_header(rows,cols,header,istr, true);
982 if(cols!=Simd::lanes<field_type>()) {
983 if(Simd::lanes<field_type>() == 1)
984 DUNE_THROW(MatrixMarketFormatError, "cols!=1, therefore this is no vector!");
985 else
986 DUNE_THROW(MatrixMarketFormatError, "cols does not match the number of lanes in the field_type!");
987 }
988
989 if(header.type!=array_type)
990 DUNE_THROW(MatrixMarketFormatError, "Vectors have to be stored in array format!");
991
992
993 if constexpr (Dune::IsNumber<T>())
994 vector.resize(rows);
995 else
996 {
997 T dummy;
998 auto blocksize = dummy.size();
999 std::size_t size=rows/blocksize;
1000 if(size*blocksize!=rows)
1001 DUNE_THROW(MatrixMarketFormatError, "Block size of vector is not correct!");
1002
1003 vector.resize(size);
1004 }
1005
1006 istr.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
1007 for(size_t l=0;l<Simd::lanes<field_type>();++l){
1008 mm_read_vector_entries(vector, rows, istr, l);
1009 }
1010 }
1011
1018 template<typename T, typename A>
1020 std::istream& istr)
1021 {
1022 using namespace MatrixMarketImpl;
1024
1025 MMHeader header;
1026 if(!readMatrixMarketBanner(istr, header)) {
1027 std::cerr << "First line was not a correct Matrix Market banner. Using default:\n"
1028 << "%%MatrixMarket matrix coordinate real general"<<std::endl;
1029 // Go to the beginning of the file
1030 istr.clear() ;
1031 istr.seekg(0, std::ios::beg);
1032 }
1033 skipComments(istr);
1034
1035 std::size_t rows, cols, entries;
1036
1037 if(lineFeed(istr))
1039
1040 istr >> rows;
1041
1042 if(lineFeed(istr))
1044 istr >> cols;
1045
1046 if(lineFeed(istr))
1048
1049 istr >>entries;
1050
1051 std::size_t nnz, blockrows, blockcols;
1052
1053 // Number of rows and columns of T, if it is a matrix (1x1 otherwise)
1054 constexpr int brows = mm_multipliers<Matrix>::rows;
1055 constexpr int bcols = mm_multipliers<Matrix>::cols;
1056
1057 std::tie(blockrows, blockcols, nnz) = calculateNNZ<brows, bcols>(rows, cols, entries, header);
1058
1059 istr.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
1060
1061
1062 matrix.setSize(blockrows, blockcols, nnz);
1064
1065 if(header.type==array_type)
1066 DUNE_THROW(Dune::NotImplemented, "Array format currently not supported for matrices!");
1067
1068 readSparseEntries(matrix, istr, entries, header, NumericWrapper<typename Matrix::field_type>());
1069 }
1070
1071 // Print a scalar entry
1072 template<typename B>
1073 void mm_print_entry(const B& entry,
1074 std::size_t rowidx,
1075 std::size_t colidx,
1076 std::ostream& ostr)
1077 {
1078 if constexpr (IsNumber<B>())
1079 ostr << rowidx << " " << colidx << " " << entry << std::endl;
1080 else
1081 {
1082 for (auto row=entry.begin(); row != entry.end(); ++row, ++rowidx) {
1083 int coli=colidx;
1084 for (auto col = row->begin(); col != row->end(); ++col, ++coli)
1085 ostr<< rowidx<<" "<<coli<<" "<<*col<<std::endl;
1086 }
1087 }
1088 }
1089
1090 // Write a vector entry
1091 template<typename V>
1092 void mm_print_vector_entry(const V& entry, std::ostream& ostr,
1093 const std::integral_constant<int,1>&,
1094 size_t lane)
1095 {
1096 ostr<<Simd::lane(lane,entry)<<std::endl;
1097 }
1098
1099 // Write a vector
1100 template<typename V>
1101 void mm_print_vector_entry(const V& vector, std::ostream& ostr,
1102 const std::integral_constant<int,0>&,
1103 size_t lane)
1104 {
1105 using namespace MatrixMarketImpl;
1106
1107 // Is the entry a supported numeric type?
1108 const int isnumeric = mm_numeric_type<Simd::Scalar<typename V::block_type>>::is_numeric;
1109 typedef typename V::const_iterator VIter;
1110
1111 for(VIter i=vector.begin(); i != vector.end(); ++i)
1112
1113 mm_print_vector_entry(*i, ostr,
1114 std::integral_constant<int,isnumeric>(),
1115 lane);
1116 }
1117
1118 template<typename T, typename A>
1119 std::size_t countEntries(const BlockVector<T,A>& vector)
1120 {
1121 return vector.size();
1122 }
1123
1124 template<typename T, typename A, int i>
1125 std::size_t countEntries(const BlockVector<FieldVector<T,i>,A>& vector)
1126 {
1127 return vector.size()*i;
1128 }
1129
1130 // Version for writing vectors.
1131 template<typename V>
1132 void writeMatrixMarket(const V& vector, std::ostream& ostr,
1133 const std::integral_constant<int,0>&)
1134 {
1135 using namespace MatrixMarketImpl;
1136 typedef typename V::field_type field_type;
1137
1138 ostr<<countEntries(vector)<<" "<<Simd::lanes<field_type>()<<std::endl;
1139 const int isnumeric = mm_numeric_type<Simd::Scalar<V>>::is_numeric;
1140 for(size_t l=0;l<Simd::lanes<field_type>(); ++l){
1141 mm_print_vector_entry(vector,ostr, std::integral_constant<int,isnumeric>(), l);
1142 }
1143 }
1144
1145 // Versions for writing matrices
1146 template<typename M>
1147 void writeMatrixMarket(const M& matrix,
1148 std::ostream& ostr,
1149 const std::integral_constant<int,1>&)
1150 {
1151 ostr<<matrix.N()*MatrixMarketImpl::mm_multipliers<M>::rows<<" "
1153 <<countNonZeros(matrix)<<std::endl;
1154
1155 typedef typename M::const_iterator riterator;
1156 typedef typename M::ConstColIterator citerator;
1157 for(riterator row=matrix.begin(); row != matrix.end(); ++row)
1158 for(citerator col = row->begin(); col != row->end(); ++col)
1159 // Matrix Market indexing start with 1!
1162 }
1163
1164
1168 template<typename M>
1169 void writeMatrixMarket(const M& matrix,
1170 std::ostream& ostr)
1171 {
1172 using namespace MatrixMarketImpl;
1173
1174 // Write header information
1175 mm_header_printer<M>::print(ostr);
1176 mm_block_structure_header<M>::print(ostr,matrix);
1177 // Choose the correct function for matrix and vector
1178 writeMatrixMarket(matrix,ostr,std::integral_constant<int,IsMatrix<M>::value>());
1179 }
1180
1181 static const int default_precision = -1;
1193 template<typename M>
1194 void storeMatrixMarket(const M& matrix,
1195 std::string filename,
1196 int prec=default_precision)
1197 {
1198 auto [pureFilename, extension] = MatrixMarketImpl::splitFilename(filename);
1199 std::string rfilename;
1200 std::ofstream file;
1201 if (extension != "") {
1202 rfilename = pureFilename + extension;
1203 file.open(rfilename.c_str());
1204 if(!file)
1205 DUNE_THROW(IOError, "Could not open file for storage: " << rfilename.c_str());
1206 }
1207 else {
1208 // only try .mm so we do not ignore potential errors
1209 rfilename = pureFilename + ".mm";
1210 file.open(rfilename.c_str());
1211 if(!file)
1212 DUNE_THROW(IOError, "Could not open file for storage: " << rfilename.c_str());
1213 }
1214
1215 file.setf(std::ios::scientific,std::ios::floatfield);
1216 if(prec>0)
1217 file.precision(prec);
1218 writeMatrixMarket(matrix, file);
1219 file.close();
1220 }
1221
1222#if HAVE_MPI
1237 template<typename M, typename G, typename L>
1238 void storeMatrixMarket(const M& matrix,
1239 std::string filename,
1241 bool storeIndices=true,
1242 int prec=default_precision)
1243 {
1244 // Get our rank
1245 int rank = comm.communicator().rank();
1246 // Write the local matrix
1247 auto [pureFilename, extension] = MatrixMarketImpl::splitFilename(filename);
1248 std::string rfilename;
1249 std::ofstream file;
1250 if (extension != "") {
1251 rfilename = pureFilename + "_" + std::to_string(rank) + extension;
1252 file.open(rfilename.c_str());
1253 dverb<< rfilename <<std::endl;
1254 if(!file)
1255 DUNE_THROW(IOError, "Could not open file for storage: " << rfilename.c_str());
1256 }
1257 else {
1258 // only try .mm so we do not ignore potential errors
1259 rfilename = pureFilename + "_" + std::to_string(rank) + ".mm";
1260 file.open(rfilename.c_str());
1261 dverb<< rfilename <<std::endl;
1262 if(!file)
1263 DUNE_THROW(IOError, "Could not open file for storage: " << rfilename.c_str());
1264 }
1265 file.setf(std::ios::scientific,std::ios::floatfield);
1266 if(prec>0)
1267 file.precision(prec);
1268 writeMatrixMarket(matrix, file);
1269 file.close();
1270
1271 if(!storeIndices)
1272 return;
1273
1274 // Write the global to local index mapping
1275 rfilename = pureFilename + "_" + std::to_string(rank) + ".idx";
1276 file.open(rfilename.c_str());
1277 if(!file)
1278 DUNE_THROW(IOError, "Could not open file for storage: " << rfilename.c_str());
1279 file.setf(std::ios::scientific,std::ios::floatfield);
1281 typedef typename IndexSet::const_iterator Iterator;
1282 for(Iterator iter = comm.indexSet().begin();
1283 iter != comm.indexSet().end(); ++iter) {
1284 file << iter->global()<<" "<<(std::size_t)iter->local()<<" "
1285 <<(int)iter->local().attribute()<<" "<<(int)iter->local().isPublic()<<std::endl;
1286 }
1287 // Store neighbour information for efficient remote indices setup.
1288 file<<"neighbours:";
1289 const std::set<int>& neighbours=comm.remoteIndices().getNeighbours();
1290 typedef std::set<int>::const_iterator SIter;
1291 for(SIter neighbour=neighbours.begin(); neighbour != neighbours.end(); ++neighbour) {
1292 file<<" "<< *neighbour;
1293 }
1294 file.close();
1295 }
1296
1311 template<typename M, typename G, typename L>
1312 void loadMatrixMarket(M& matrix,
1313 const std::string& filename,
1315 bool readIndices=true)
1316 {
1317 using namespace MatrixMarketImpl;
1318
1320 typedef typename LocalIndexT::Attribute Attribute;
1321 // Get our rank
1322 int rank = comm.communicator().rank();
1323 // load local matrix
1324 auto [pureFilename, extension] = MatrixMarketImpl::splitFilename(filename);
1325 std::string rfilename;
1326 std::ifstream file;
1327 if (extension != "") {
1328 rfilename = pureFilename + "_" + std::to_string(rank) + extension;
1329 file.open(rfilename.c_str(), std::ios::in);
1330 dverb<< rfilename <<std::endl;
1331 if(!file)
1332 DUNE_THROW(IOError, "Could not open file: " << rfilename.c_str());
1333 }
1334 else {
1335 // try both .mm and .mtx
1336 rfilename = pureFilename + "_" + std::to_string(rank) + ".mm";
1337 file.open(rfilename.c_str(), std::ios::in);
1338 if(!file) {
1339 rfilename = pureFilename + "_" + std::to_string(rank) + ".mtx";
1340 file.open(rfilename.c_str(), std::ios::in);
1341 dverb<< rfilename <<std::endl;
1342 if(!file)
1343 DUNE_THROW(IOError, "Could not open file: " << rfilename.c_str());
1344 }
1345 }
1346 readMatrixMarket(matrix,file);
1347 file.close();
1348
1349 if(!readIndices)
1350 return;
1351
1352 // read indices
1354 IndexSet& pis=comm.pis;
1355 rfilename = pureFilename + "_" + std::to_string(rank) + ".idx";
1356 file.open(rfilename.c_str());
1357 if(!file)
1358 DUNE_THROW(IOError, "Could not open file: " << rfilename.c_str());
1359 if(pis.size()!=0)
1360 DUNE_THROW(InvalidIndexSetState, "Index set is not empty!");
1361
1362 pis.beginResize();
1363 while(!file.eof() && file.peek()!='n') {
1364 G g;
1365 file >>g;
1366 std::size_t l;
1367 file >>l;
1368 int c;
1369 file >>c;
1370 bool b;
1371 file >> b;
1372 pis.add(g,LocalIndexT(l,Attribute(c),b));
1373 lineFeed(file);
1374 }
1375 pis.endResize();
1376 if(!file.eof()) {
1377 // read neighbours
1378 std::string s;
1379 file>>s;
1380 if(s!="neighbours:")
1381 DUNE_THROW(MatrixMarketFormatError, "was expecting the string: \"neighbours:\"");
1382 std::set<int> nb;
1383 while(!file.eof()) {
1384 int i;
1385 file >> i;
1386 nb.insert(i);
1387 }
1388 file.close();
1389 comm.ri.setNeighbours(nb);
1390 }
1391 comm.ri.template rebuild<false>();
1392 }
1393
1394 #endif
1395
1406 template<typename M>
1407 void loadMatrixMarket(M& matrix,
1408 const std::string& filename)
1409 {
1410 auto [pureFilename, extension] = MatrixMarketImpl::splitFilename(filename);
1411 std::string rfilename;
1412 std::ifstream file;
1413 if (extension != "") {
1414 rfilename = pureFilename + extension;
1415 file.open(rfilename.c_str());
1416 if(!file)
1417 DUNE_THROW(IOError, "Could not open file: " << rfilename.c_str());
1418 }
1419 else {
1420 // try both .mm and .mtx
1421 rfilename = pureFilename + ".mm";
1422 file.open(rfilename.c_str(), std::ios::in);
1423 if(!file) {
1424 rfilename = pureFilename + ".mtx";
1425 file.open(rfilename.c_str(), std::ios::in);
1426 if(!file)
1427 DUNE_THROW(IOError, "Could not open file: " << rfilename.c_str());
1428 }
1429 }
1430 readMatrixMarket(matrix,file);
1431 file.close();
1432 }
1433
1435}
1436#endif
Implementation of the BCRSMatrix class.
Some handy generic functions for ISTL matrices.
Classes providing communication interfaces for overlapping Schwarz methods.
This file implements a vector space as a tensor product of a given vector space. The number of compon...
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:119
void readMatrixMarket(Dune::BlockVector< T, A > &vector, std::istream &istr)
Reads a BlockVector from a matrix market file.
Definition matrixmarket.hh:973
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:1194
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:1312
std::size_t countEntries(const BlockVector< T, A > &vector)
Definition matrixmarket.hh:1119
void writeMatrixMarket(const V &vector, std::ostream &ostr, const std::integral_constant< int, 0 > &)
Definition matrixmarket.hh:1132
void mm_print_vector_entry(const V &entry, std::ostream &ostr, const std::integral_constant< int, 1 > &, size_t lane)
Definition matrixmarket.hh:1092
static const int default_precision
Definition matrixmarket.hh:1181
void mm_read_vector_entries(Dune::BlockVector< T, A > &vector, std::size_t size, std::istream &istr, size_t lane)
Definition matrixmarket.hh:943
void mm_read_header(std::size_t &rows, std::size_t &cols, MatrixMarketImpl::MMHeader &header, std::istream &istr, bool isVector)
Definition matrixmarket.hh:914
void mm_print_entry(const B &entry, std::size_t rowidx, std::size_t colidx, std::ostream &ostr)
Definition matrixmarket.hh:1073
STL namespace.
Definition allocator.hh:11
MatrixSparsityPatternGatherScatter< M, I >::ColIter MatrixSparsityPatternGatherScatter< M, I >::col
Definition matrixredistribute.hh:591
Definition matrixmarket.hh:67
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:590
bool operator<(const IndexData< T > &i1, const IndexData< T > &i2)
LessThan operator.
Definition matrixmarket.hh:673
LineType
Definition matrixmarket.hh:339
@ DATA
Definition matrixmarket.hh:339
@ MM_HEADER
Definition matrixmarket.hh:339
@ MM_ISTLSTRUCT
Definition matrixmarket.hh:339
bool readMatrixMarketBanner(std::istream &file, MMHeader &mmHeader)
Definition matrixmarket.hh:396
void readSparseEntries(Dune::BCRSMatrix< T, A > &matrix, std::istream &file, std::size_t entries, const MMHeader &mmHeader, const D &)
Definition matrixmarket.hh:808
MM_TYPE
Definition matrixmarket.hh:342
@ array_type
Definition matrixmarket.hh:342
@ coordinate_type
Definition matrixmarket.hh:342
@ unknown_type
Definition matrixmarket.hh:342
std::istream & operator>>(std::istream &is, NumericWrapper< T > &num)
Definition matrixmarket.hh:657
void skipComments(std::istream &file)
Definition matrixmarket.hh:382
bool lineFeed(std::istream &file)
Definition matrixmarket.hh:358
@ MM_MAX_LINE_LENGTH
Definition matrixmarket.hh:340
MM_STRUCTURE
Definition matrixmarket.hh:346
@ skew_symmetric
Definition matrixmarket.hh:346
@ general
Definition matrixmarket.hh:346
@ hermitian
Definition matrixmarket.hh:346
@ unknown_structure
Definition matrixmarket.hh:346
@ symmetric
Definition matrixmarket.hh:346
MM_CTYPE
Definition matrixmarket.hh:344
@ unknown_ctype
Definition matrixmarket.hh:344
@ pattern
Definition matrixmarket.hh:344
@ complex_type
Definition matrixmarket.hh:344
@ double_type
Definition matrixmarket.hh:344
@ integer_type
Definition matrixmarket.hh:344
std::enable_if_t<!is_complex< T >::value, T > conj(const T &r)
Definition matrixmarket.hh:776
std::tuple< std::string, std::string > splitFilename(const std::string &filename)
Definition matrixmarket.hh:895
A sparse block matrix with compressed row storage.
Definition bcrsmatrix.hh:467
Iterator begin()
Get iterator to first row.
Definition bcrsmatrix.hh:672
@ row_wise
Build in a row-wise manner.
Definition bcrsmatrix.hh:518
Iterator end()
Get iterator to one beyond last row.
Definition bcrsmatrix.hh:678
CreateIterator createend()
get create iterator pointing to one after the last block
Definition bcrsmatrix.hh:1103
size_type M() const
number of columns (counted in blocks)
Definition bcrsmatrix.hh:2010
CreateIterator createbegin()
get initial create iterator
Definition bcrsmatrix.hh:1097
size_type N() const
number of rows (counted in blocks)
Definition bcrsmatrix.hh:2004
void setBuildMode(BuildMode bm)
Sets the build mode of the matrix.
Definition bcrsmatrix.hh:831
void setSize(size_type rows, size_type columns, size_type nnz=0)
Set the size of the matrix.
Definition bcrsmatrix.hh:859
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
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
@ is_numeric
Whether T is a supported numeric type.
Definition matrixmarket.hh:99
@ is_numeric
Whether T is a supported numeric type.
Definition matrixmarket.hh:115
static std::string str()
Definition matrixmarket.hh:118
@ is_numeric
Whether T is a supported numeric type.
Definition matrixmarket.hh:131
static std::string str()
Definition matrixmarket.hh:134
@ is_numeric
Whether T is a supported numeric type.
Definition matrixmarket.hh:183
static std::string str()
Definition matrixmarket.hh:186
static std::string str()
Definition matrixmarket.hh:202
@ is_numeric
Whether T is a supported numeric type.
Definition matrixmarket.hh:199
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
Metaprogram for writing the ISTL block structure header.
Definition matrixmarket.hh:268
static void print(std::ostream &os, const M &)
Definition matrixmarket.hh:276
BlockVector< T, A > M
Definition matrixmarket.hh:273
BlockVector< FieldVector< T, i >, A > M
Definition matrixmarket.hh:286
static void print(std::ostream &os, const M &)
Definition matrixmarket.hh:288
BCRSMatrix< T, A > M
Definition matrixmarket.hh:298
static void print(std::ostream &os, const M &)
Definition matrixmarket.hh:301
BCRSMatrix< FieldMatrix< T, i, j >, A > M
Definition matrixmarket.hh:311
static void print(std::ostream &os, const M &)
Definition matrixmarket.hh:313
FieldMatrix< T, i, j > M
Definition matrixmarket.hh:324
static void print(std::ostream &, const M &)
Definition matrixmarket.hh:326
static void print(std::ostream &, const M &)
Definition matrixmarket.hh:335
FieldVector< T, i > M
Definition matrixmarket.hh:333
Definition matrixmarket.hh:349
MM_STRUCTURE structure
Definition matrixmarket.hh:355
MM_TYPE type
Definition matrixmarket.hh:353
MMHeader()
Definition matrixmarket.hh:350
MM_CTYPE ctype
Definition matrixmarket.hh:354
Definition matrixmarket.hh:621
std::size_t index
Definition matrixmarket.hh:622
a wrapper class of numeric values.
Definition matrixmarket.hh:638
T number
Definition matrixmarket.hh:639
Utility class for marking the pattern type of the MatrixMarket matrices.
Definition matrixmarket.hh:650
Functor to the data values of the matrix.
Definition matrixmarket.hh:720
void operator()(const std::vector< std::set< IndexData< D > > > &rows, BCRSMatrix< T > &matrix)
Sets the matrix values.
Definition matrixmarket.hh:727
void operator()(const std::vector< std::set< IndexData< D > > > &rows, BCRSMatrix< FieldMatrix< T, brows, bcols > > &matrix)
Sets the matrix values.
Definition matrixmarket.hh:745
void operator()(const std::vector< std::set< IndexData< PatternDummy > > > &, M &)
Definition matrixmarket.hh:766
Definition matrixmarket.hh:771
Definition matrixmarket.hh:787
Definition matrixmarket.hh:911
Definition matrixutils.hh:27
@ value
True if T is an ISTL matrix.
Definition matrixutils.hh:509
A class setting up standard communication for a two-valued attribute set with owner/overlap/copy sema...
Definition owneroverlapcopy.hh:174
const ParallelIndexSet & indexSet() const
Get the underlying parallel index set.
Definition owneroverlapcopy.hh:462
OwnerOverlapCopyCommunication(MPI_Comm comm_, SolverCategory::Category cat_=SolverCategory::overlapping, bool freecomm_=false)
Definition owneroverlapcopy.hh:554
const Communication< MPI_Comm > & communicator() const
Definition owneroverlapcopy.hh:299
const RemoteIndices & remoteIndices() const
Get the underlying remote indices.
Definition owneroverlapcopy.hh:471
Dune::ParallelIndexSet< GlobalIdType, LI, 512 > ParallelIndexSet
The type of the parallel index set.
Definition owneroverlapcopy.hh:449