dune-istl  2.3beta2
matrixmarket.hh
Go to the documentation of this file.
1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=4 sw=2 sts=2:
3 #ifndef DUNE_MATRIXMARKET_HH
4 #define DUNE_MATRIXMARKET_HH
5 
6 #include <ostream>
7 #include <istream>
8 #include <fstream>
9 #include <sstream>
10 #include <limits>
11 #include <ios>
12 #include "matrixutils.hh"
13 #include "bcrsmatrix.hh"
14 #include "owneroverlapcopy.hh"
15 #include <dune/common/fmatrix.hh>
16 #include <dune/common/tuples.hh>
17 #include <dune/common/unused.hh>
18 
19 namespace Dune
20 {
21 
47  namespace
48  {
58  template<class T>
59  struct mm_numeric_type {
60  enum {
64  is_numeric=false
65  };
66  };
67 
68  template<>
69  struct mm_numeric_type<int>
70  {
71  enum {
75  is_numeric=true
76  };
77 
78  static std::string str()
79  {
80  return "integer";
81  }
82  };
83 
84  template<>
85  struct mm_numeric_type<double>
86  {
87  enum {
91  is_numeric=true
92  };
93 
94  static std::string str()
95  {
96  return "real";
97  }
98  };
99 
100  template<>
101  struct mm_numeric_type<float>
102  {
103  enum {
107  is_numeric=true
108  };
109 
110  static std::string str()
111  {
112  return "real";
113  }
114  };
115 
116  template<>
117  struct mm_numeric_type<std::complex<double> >
118  {
119  enum {
123  is_numeric=true
124  };
125 
126  static std::string str()
127  {
128  return "complex";
129  }
130  };
131 
132  template<>
133  struct mm_numeric_type<std::complex<float> >
134  {
135  enum {
139  is_numeric=true
140  };
141 
142  static std::string str()
143  {
144  return "complex";
145  }
146  };
147 
156  template<class M>
157  struct mm_header_printer;
158 
159  template<typename T, typename A, int i, int j>
160  struct mm_header_printer<BCRSMatrix<FieldMatrix<T,i,j>,A> >
161  {
162  static void print(std::ostream& os)
163  {
164  os<<"%%MatrixMarket matrix coordinate ";
165  os<<mm_numeric_type<T>::str()<<" general"<<std::endl;
166  }
167  };
168 
169  template<typename B, typename A>
170  struct mm_header_printer<BlockVector<B,A> >
171  {
172  static void print(std::ostream& os)
173  {
174  os<<"%%MatrixMarket matrix array ";
175  os<<mm_numeric_type<typename B::field_type>::str()<<" general"<<std::endl;
176  }
177  };
178 
179  template<typename T, int j>
180  struct mm_header_printer<FieldVector<T,j> >
181  {
182  static void print(std::ostream& os)
183  {
184  os<<"%%MatrixMarket matrix array ";
185  os<<mm_numeric_type<T>::str()<<" general"<<std::endl;
186  }
187  };
188 
189  template<typename T, int i, int j>
190  struct mm_header_printer<FieldMatrix<T,i,j> >
191  {
192  static void print(std::ostream& os)
193  {
194  os<<"%%MatrixMarket matrix array ";
195  os<<mm_numeric_type<T>::str()<<" general"<<std::endl;
196  }
197  };
198 
207  template<class M>
208  struct mm_block_structure_header;
209 
210  template<typename T, typename A, int i>
211  struct mm_block_structure_header<BlockVector<FieldVector<T,i>,A> >
212  {
213  typedef BlockVector<FieldVector<T,i>,A> M;
214 
215  static void print(std::ostream& os, const M& m)
216  {
217  os<<"% ISTL_STRUCT blocked ";
218  os<<i<<" "<<1<<std::endl;
219  }
220  };
221 
222  template<typename T, typename A, int i, int j>
223  struct mm_block_structure_header<BCRSMatrix<FieldMatrix<T,i,j>,A> >
224  {
225  typedef BCRSMatrix<FieldMatrix<T,i,j>,A> M;
226 
227  static void print(std::ostream& os, const M& m)
228  {
229  os<<"% ISTL_STRUCT blocked ";
230  os<<i<<" "<<j<<std::endl;
231  }
232  };
233 
234 
235  template<typename T, int i, int j>
236  struct mm_block_structure_header<FieldMatrix<T,i,j> >
237  {
238  typedef FieldMatrix<T,i,j> M;
239 
240  static void print(std::ostream& os, const M& m)
241  {}
242  };
243 
244  template<typename T, int i>
245  struct mm_block_structure_header<FieldVector<T,i> >
246  {
247  typedef FieldVector<T,i> M;
248 
249  static void print(std::ostream& os, const M& m)
250  {}
251  };
252 
253  enum LineType { MM_HEADER, MM_ISTLSTRUCT, DATA };
254  enum { MM_MAX_LINE_LENGTH=1025 };
255 
256  enum MM_TYPE { coordinate_type, array_type, unknown_type };
257 
258  enum MM_CTYPE { integer_type, double_type, complex_type, pattern, unknown_ctype };
259 
260  enum MM_STRUCTURE { general, symmetric, skew_symmetric, hermitian, unknown_structure };
261 
262  struct MMHeader
263  {
264  MMHeader()
265  : type(coordinate_type), ctype(double_type), structure(general)
266  {}
267  MM_TYPE type;
268  MM_CTYPE ctype;
269  MM_STRUCTURE structure;
270  };
271 
272  bool lineFeed(std::istream& file)
273  {
274  char c;
275  if(!file.eof())
276  c=file.peek();
277  else
278  return false;
279  // ignore whitespace
280  while(c==' ')
281  {
282  file.get();
283  if(file.eof())
284  return false;
285  c=file.peek();
286  }
287 
288  if(c=='\n') {
289  /* eat the line feed */
290  file.get();
291  return true;
292  }
293  return false;
294  }
295 
296  void skipComments(std::istream& file)
297  {
298  lineFeed(file);
299  char c=file.peek();
300  // ignore comment lines
301  while(c=='%')
302  {
303  /* disgard the rest of the line */
304  file.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
305  c=file.peek();
306  }
307  }
308 
309 
310  bool readMatrixMarketBanner(std::istream& file, MMHeader& mmHeader)
311  {
312  std::string buffer;
313  char c;
314  file >> buffer;
315  c=buffer[0];
316  mmHeader=MMHeader();
317  if(c!='%')
318  return false;
319  std::cout<<buffer<<std::endl;
320  /* read the banner */
321  if(buffer!="%%MatrixMarket") {
322  /* disgard the rest of the line */
323  file.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
324  return false;
325  }
326 
327  if(lineFeed(file))
328  /* premature end of line */
329  return false;
330 
331  /* read the matrix_type */
332  file >> buffer;
333 
334  if(buffer != "matrix")
335  {
336  /* disgard the rest of the line */
337  file.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
338  return false;
339  }
340 
341  if(lineFeed(file))
342  /* premature end of line */
343  return false;
344 
345  /* The type of the matrix */
346  file >> buffer;
347 
348  if(buffer.empty())
349  return false;
350 
351  std::transform(buffer.begin(), buffer.end(), buffer.begin(),
352  tolower);
353 
354  switch(buffer[0])
355  {
356  case 'a' :
357  /* sanity check */
358  if(buffer != "array")
359  {
360  file.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
361  return false;
362  }
363  mmHeader.type=array_type;
364  break;
365  case 'c' :
366  /* sanity check */
367  if(buffer != "coordinate")
368  {
369  file.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
370  return false;
371  }
372  mmHeader.type=coordinate_type;
373  break;
374  default :
375  file.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
376  return false;
377  }
378 
379  if(lineFeed(file))
380  /* premature end of line */
381  return false;
382 
383  /* The numeric type used. */
384  file >> buffer;
385 
386  if(buffer.empty())
387  return false;
388 
389  std::transform(buffer.begin(), buffer.end(), buffer.begin(),
390  tolower);
391  switch(buffer[0])
392  {
393  case 'i' :
394  /* sanity check */
395  if(buffer != "integer")
396  {
397  file.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
398  return false;
399  }
400  mmHeader.ctype=integer_type;
401  break;
402  case 'r' :
403  /* sanity check */
404  if(buffer != "real")
405  {
406  file.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
407  return false;
408  }
409  mmHeader.ctype=double_type;
410  break;
411  case 'c' :
412  /* sanity check */
413  if(buffer != "complex")
414  {
415  file.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
416  return false;
417  }
418  mmHeader.ctype=complex_type;
419  break;
420  case 'p' :
421  /* sanity check */
422  if(buffer != "pattern")
423  {
424  file.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
425  return false;
426  }
427  mmHeader.ctype=pattern;
428  break;
429  default :
430  file.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
431  return false;
432  }
433 
434  if(lineFeed(file))
435  return false;
436 
437  file >> buffer;
438 
439  std::transform(buffer.begin(), buffer.end(), buffer.begin(),
440  tolower);
441  switch(buffer[0])
442  {
443  case 'g' :
444  /* sanity check */
445  if(buffer != "general")
446  {
447  file.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
448  return false;
449  }
450  mmHeader.structure=general;
451  break;
452  case 'h' :
453  /* sanity check */
454  if(buffer != "hermitian")
455  {
456  file.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
457  return false;
458  }
459  mmHeader.structure=hermitian;
460  break;
461  case 's' :
462  if(buffer.size()==1) {
463  file.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
464  return false;
465  }
466 
467  switch(buffer[1])
468  {
469  case 'y' :
470  /* sanity check */
471  if(buffer != "symmetric")
472  {
473  file.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
474  return false;
475  }
476  mmHeader.structure=symmetric;
477  break;
478  case 'k' :
479  /* sanity check */
480  if(buffer != "skew-symmetric")
481  {
482  file.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
483  return false;
484  }
485  mmHeader.structure=skew_symmetric;
486  break;
487  default :
488  file.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
489  return false;
490  }
491  default :
492  file.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
493  return false;
494  }
495  file.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
496  c=file.peek();
497  return true;
498 
499  }
500 
501  void readNextLine(std::istream& file, std::ostringstream&, LineType& type)
502  {
503  DUNE_UNUSED_PARAMETER(type);
504  char c;
505  std::size_t index=0;
506 
507  //empty lines will be disgarded and we will simply read the next line
508  while(index==0&&!file.eof())
509  {
510  // strip spaces
511  while(!file.eof() && (c=file.get())==' ') ;
512 
513  //read the rest of the line until comment
514  while(!file.eof() && (c=file.get())=='\n') {
515  switch(c)
516  {
517  case '%' :
518  /* disgard the rest of the line */
519  file.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
520  }
521  }
522  }
523 
524  // buffer[index]='\0';
525  }
526 
527  template<std::size_t brows, std::size_t bcols>
528  Dune::tuple<std::size_t, std::size_t, std::size_t>
529  calculateNNZ(std::size_t rows, std::size_t cols, std::size_t entries, const MMHeader& header)
530  {
531  std::size_t blockrows=rows/brows;
532  std::size_t blockcols=cols/bcols;
533  std::size_t blocksize=brows*bcols;
534  std::size_t blockentries=0;
535 
536  switch(header.structure)
537  {
538  case general :
539  blockentries = entries/blocksize; break;
540  case skew_symmetric :
541  blockentries = 2*entries/blocksize; break;
542  case symmetric :
543  blockentries = (2*entries-rows)/blocksize; break;
544  case hermitian :
545  blockentries = (2*entries-rows)/blocksize; break;
546  default :
547  throw Dune::NotImplemented();
548  }
549  return Dune::make_tuple(blockrows, blockcols, blockentries);
550  }
551 
552  /*
553  * @brief Storage class for the column index and the numeric value.
554  *
555  * \tparam T Either a NumericWrapper of the numeric type or PatternDummy
556  * for MatrixMarket pattern case.
557  */
558  template<typename T>
559  struct IndexData : public T
560  {
561  std::size_t index;
562  };
563 
564 
575  template<typename T>
576  struct NumericWrapper
577  {
579  operator T&()
580  {
581  return number;
582  }
583  };
584 
588  struct PatternDummy
589  {};
590 
591  template<>
592  struct NumericWrapper<PatternDummy>
593  {};
594 
595  template<typename T>
596  std::istream& operator>>(std::istream& is, NumericWrapper<T>& num)
597  {
598  return is>>num.number;
599  }
600 
601  std::istream& operator>>(std::istream& is, NumericWrapper<PatternDummy>& num)
602  {
603  DUNE_UNUSED_PARAMETER(num);
604  return is;
605  }
606 
612  template<typename T>
613  bool operator<(const IndexData<T>& i1, const IndexData<T>& i2)
614  {
615  return i1.index<i2.index;
616  }
617 
623  template<typename T>
624  std::istream& operator>>(std::istream& is, IndexData<T>& data)
625  {
626  is>>data.index;
627  /* MatrixMarket indices are one based. Decrement for C++ */
628  --data.index;
629  return is>>data.number;
630  }
631 
638  template<typename D, int brows, int bcols>
639  struct MatrixValuesSetter
640  {
646  template<typename M>
647  void operator()(const std::vector<std::set<IndexData<D> > >& rows,
648  M& matrix)
649  {
650  for(typename M::RowIterator iter=matrix.begin();
651  iter!= matrix.end(); ++iter)
652  {
653  for(typename M::size_type brow=iter.index()*brows,
654  browend=iter.index()*brows+brows;
655  brow<browend; ++brow)
656  {
657  typedef typename std::set<IndexData<D> >::const_iterator Siter;
658  for(Siter siter=rows[brow].begin(), send=rows[brow].end();
659  siter != send; ++siter)
660  (*iter)[siter->index/bcols][brow%brows][siter->index%bcols]=siter->number;
661  }
662  }
663  }
664  };
665 
666  template<int brows, int bcols>
667  struct MatrixValuesSetter<PatternDummy,brows,bcols>
668  {
669  template<typename M>
670  void operator()(const std::vector<std::set<IndexData<PatternDummy> > >& rows,
671  M& matrix)
672  {}
673  };
674 
675  template<typename T, typename A, int brows, int bcols, typename D>
676  void readSparseEntries(Dune::BCRSMatrix<Dune::FieldMatrix<T,brows,bcols>,A>& matrix,
677  std::istream& file, std::size_t entries,
678  const MMHeader& mmHeader, const D&)
679  {
681  // First path
682  // store entries together with column index in a speparate
683  // data structure
684  std::vector<std::set<IndexData<D> > > rows(matrix.N()*brows);
685 
686  for(; entries>0; --entries) {
687  std::size_t row;
688  IndexData<D> data;
689  skipComments(file);
690  file>>row;
691  --row; // Index was 1 based.
692  assert(row/bcols<matrix.N());
693  file>>data;
694  assert(data.index/bcols<matrix.M());
695  rows[row].insert(data);
696  }
697 
698  // TODO extend to capture the nongeneral cases.
699  if(mmHeader.structure!= general)
700  DUNE_THROW(Dune::NotImplemented, "Only general is supported right now!");
701 
702  // Setup the matrix sparsity pattern
703  int nnz=0;
704  for(typename Matrix::CreateIterator iter=matrix.createbegin();
705  iter!= matrix.createend(); ++iter)
706  {
707  for(std::size_t brow=iter.index()*brows, browend=iter.index()*brows+brows;
708  brow<browend; ++brow)
709  {
710  typedef typename std::set<IndexData<D> >::const_iterator Siter;
711  for(Siter siter=rows[brow].begin(), send=rows[brow].end();
712  siter != send; ++siter, ++nnz)
713  iter.insert(siter->index/bcols);
714  }
715  }
716 
717  //Set the matrix values
718  matrix=0;
719 
720  MatrixValuesSetter<D,brows,bcols> Setter;
721 
722  Setter(rows, matrix);
723  }
724  } // end anonymous namespace
725 
726  class MatrixMarketFormatError : public Dune::Exception
727  {};
728 
729 
730  void mm_read_header(std::size_t& rows, std::size_t& cols, MMHeader& header, std::istream& istr,
731  bool isVector)
732  {
733  if(!readMatrixMarketBanner(istr, header)) {
734  std::cerr << "First line was not a correct Matrix Market banner. Using default:\n"
735  << "%%MatrixMarket matrix coordinate real general"<<std::endl;
736  // Go to the beginning of the file
737  istr.clear() ;
738  istr.seekg(0, std::ios::beg);
739  if(isVector)
740  header.type=array_type;
741  }
742 
743  skipComments(istr);
744 
745  if(lineFeed(istr))
746  throw MatrixMarketFormatError();
747 
748  istr >> rows;
749 
750  if(lineFeed(istr))
751  throw MatrixMarketFormatError();
752  istr >> cols;
753  }
754 
755  template<typename T, typename A, int entries>
756  void mm_read_vector_entries(Dune::BlockVector<Dune::FieldVector<T,entries>,A>& vector,
757  std::size_t size,
758  std::istream& istr)
759  {
760  for(int i=0; size>0; ++i, --size) {
761  T val;
762  istr>>val;
763  vector[i/entries][i%entries]=val;
764  }
765  }
766 
767 
774  template<typename T, typename A, int entries>
775  void readMatrixMarket(Dune::BlockVector<Dune::FieldVector<T,entries>,A>& vector,
776  std::istream& istr)
777  {
778  MMHeader header;
779  std::size_t rows, cols;
780  mm_read_header(rows,cols,header,istr, true);
781  if(cols!=1)
782  DUNE_THROW(MatrixMarketFormatError, "cols!=1, therefore this is no vector!");
783 
784  if(header.type!=array_type)
785  DUNE_THROW(MatrixMarketFormatError, "Vectors have to be stored in array format!");
786 
787  std::size_t size=rows/entries;
788  if(size*entries!=rows)
789  DUNE_THROW(MatrixMarketFormatError, "Block size of vector is not correct1");
790 
791  vector.resize(size);
792 
793  istr.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
794 
795  mm_read_vector_entries(vector, rows, istr);
796  }
797 
798 
805  template<typename T, typename A, int brows, int bcols>
806  void readMatrixMarket(Dune::BCRSMatrix<Dune::FieldMatrix<T,brows,bcols>,A>& matrix,
807  std::istream& istr)
808  {
809  MMHeader header;
810  if(!readMatrixMarketBanner(istr, header)) {
811  std::cerr << "First line was not a correct Matrix Market banner. Using default:\n"
812  << "%%MatrixMarket matrix coordinate real general"<<std::endl;
813  // Go to the beginning of the file
814  istr.clear() ;
815  istr.seekg(0, std::ios::beg);
816  }
817  skipComments(istr);
818 
819  std::size_t rows, cols, entries;
820 
821  if(lineFeed(istr))
822  throw MatrixMarketFormatError();
823 
824  istr >> rows;
825 
826  if(lineFeed(istr))
827  throw MatrixMarketFormatError();
828  istr >> cols;
829 
830  if(lineFeed(istr))
831  throw MatrixMarketFormatError();
832 
833  istr >>entries;
834 
835  std::size_t nnz, blockrows, blockcols;
836 
837  Dune::tie(blockrows, blockcols, nnz) = calculateNNZ<brows, bcols>(rows, cols, entries, header);
838 
839  istr.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
840 
841 
842  matrix.setSize(blockrows, blockcols);
843  matrix.setBuildMode(Dune::BCRSMatrix<Dune::FieldMatrix<T,brows,bcols>,A>::row_wise);
844 
845  if(header.type==array_type)
846  DUNE_THROW(Dune::NotImplemented, "Array format currently not supported for matrices!");
847 
848  readSparseEntries(matrix, istr, entries, header, NumericWrapper<T>());
849  }
850 
851  template<typename M>
853  {};
854 
855  template<typename B, int i, int j, typename A>
856  struct mm_multipliers<BCRSMatrix<FieldMatrix<B,i,j>,A> >
857  {
858  enum {
859  rows = i,
860  cols = j
861  };
862  };
863 
864  template<typename B, int i, int j>
865  void mm_print_entry(const FieldMatrix<B,i,j>& entry,
866  typename FieldMatrix<B,i,j>::size_type rowidx,
867  typename FieldMatrix<B,i,j>::size_type colidx,
868  std::ostream& ostr)
869  {
870  typedef typename FieldMatrix<B,i,j>::const_iterator riterator;
871  typedef typename FieldMatrix<B,i,j>::ConstColIterator citerator;
872  for(riterator row=entry.begin(); row != entry.end(); ++row, ++rowidx) {
873  int coli=colidx;
874  for(citerator col = row->begin(); col != row->end(); ++col, ++coli)
875  ostr<< rowidx<<" "<<coli<<" "<<*col<<std::endl;
876  }
877  }
878 
879  // Write a vector entry
880  template<typename V>
881  void mm_print_vector_entry(const V& entry, std::ostream& ostr,
882  const integral_constant<int,1>&)
883  {
884  ostr<<entry<<std::endl;
885  }
886 
887  // Write a vector
888  template<typename V>
889  void mm_print_vector_entry(const V& vector, std::ostream& ostr,
890  const integral_constant<int,0>&)
891  {
892  // Is the entry a supported numeric type?
893  const int isnumeric = mm_numeric_type<typename V::block_type>::is_numeric;
894  typedef typename V::const_iterator VIter;
895 
896  for(VIter i=vector.begin(); i != vector.end(); ++i)
897 
898  mm_print_vector_entry(*i, ostr,
899  integral_constant<int,isnumeric>());
900  }
901 
902  template<typename T, typename A, int i>
903  std::size_t countEntries(const BlockVector<FieldVector<T,i>,A>& vector)
904  {
905  return vector.size()*i;
906  }
907 
908  // Version for writing vectors.
909  template<typename V>
910  void writeMatrixMarket(const V& vector, std::ostream& ostr,
911  const integral_constant<int,0>&)
912  {
913  ostr<<countEntries(vector)<<" "<<1<<std::endl;
914  const int isnumeric = mm_numeric_type<typename V::block_type>::is_numeric;
915  mm_print_vector_entry(vector,ostr, integral_constant<int,isnumeric>());
916  }
917 
918  // Versions for writing matrices
919  template<typename M>
920  void writeMatrixMarket(const M& matrix,
921  std::ostream& ostr,
922  const integral_constant<int,1>&)
923  {
924  ostr<<matrix.M()*mm_multipliers<M>::rows<<" "
925  <<matrix.N()*mm_multipliers<M>::cols<<" "
926  <<countNonZeros(matrix)<<std::endl;
927 
928  typedef typename M::const_iterator riterator;
929  typedef typename M::ConstColIterator citerator;
930  for(riterator row=matrix.begin(); row != matrix.end(); ++row)
931  for(citerator col = row->begin(); col != row->end(); ++col)
932  // Matrix Market indexing start with 1!
934  col.index()*mm_multipliers<M>::cols+1, ostr);
935  }
936 
937 
941  template<typename M>
942  void writeMatrixMarket(const M& matrix,
943  std::ostream& ostr)
944  {
945  // Write header information
946  mm_header_printer<M>::print(ostr);
947  mm_block_structure_header<M>::print(ostr,matrix);
948  // Choose the correct function for matrix and vector
949  writeMatrixMarket(matrix,ostr,integral_constant<int,IsMatrix<M>::value>());
950  }
951 
952 
963  template<typename M>
964  void storeMatrixMarket(const M& matrix,
965  std::string filename)
966  {
967  std::ofstream file(filename.c_str());
968  file.setf(std::ios::scientific,std::ios::floatfield);
969  writeMatrixMarket(matrix, file);
970  file.close();
971  }
972 
973 #if HAVE_MPI
974 
987  template<typename M, typename G, typename L>
988  void storeMatrixMarket(const M& matrix,
989  std::string filename,
991  bool storeIndices=true)
992  {
993  // Get our rank
994  int rank = comm.communicator().rank();
995  // Write the local matrix
996  std::ostringstream rfilename;
997  rfilename<<filename <<"_"<<rank<<".mm";
998  std::cout<< rfilename.str()<<std::endl;
999  std::ofstream file(rfilename.str().c_str());
1000  file.setf(std::ios::scientific,std::ios::floatfield);
1001  writeMatrixMarket(matrix, file);
1002  file.close();
1003 
1004  if(!storeIndices)
1005  return;
1006 
1007  // Write the global to local index mapping
1008  rfilename.str("");
1009  rfilename<<filename<<"_"<<rank<<".idx";
1010  file.open(rfilename.str().c_str());
1011  file.setf(std::ios::scientific,std::ios::floatfield);
1012  typedef typename OwnerOverlapCopyCommunication<G,L>::ParallelIndexSet IndexSet;
1013  typedef typename IndexSet::const_iterator Iterator;
1014  for(Iterator iter = comm.indexSet().begin();
1015  iter != comm.indexSet().end(); ++iter) {
1016  file << iter->global()<<" "<<(std::size_t)iter->local()<<" "
1017  <<(int)iter->local().attribute()<<" "<<(int)iter->local().isPublic()<<std::endl;
1018  }
1019  // Store neighbour information for efficient remote indices setup.
1020  file<<"neighbours:";
1021  const std::set<int>& neighbours=comm.remoteIndices().getNeighbours();
1022  typedef std::set<int>::const_iterator SIter;
1023  for(SIter neighbour=neighbours.begin(); neighbour != neighbours.end(); ++neighbour) {
1024  file<<" "<< *neighbour;
1025  }
1026  file.close();
1027  }
1028 
1043  template<typename M, typename G, typename L>
1044  void loadMatrixMarket(M& matrix,
1045  const std::string& filename,
1047  bool readIndices=true)
1048  {
1050  typedef typename LocalIndex::Attribute Attribute;
1051  // Get our rank
1052  int rank = comm.communicator().rank();
1053  // load local matrix
1054  std::ostringstream rfilename;
1055  rfilename<<filename <<"_"<<rank<<".mm";
1056  std::ifstream file;
1057  file.open(rfilename.str().c_str(), std::ios::in);
1058  if(!file)
1059  DUNE_THROW(IOError, "Could not open file" << rfilename.str().c_str());
1060  //if(!file.is_open())
1061  //
1062  readMatrixMarket(matrix,file);
1063  file.close();
1064 
1065  if(!readIndices)
1066  return;
1067 
1068  // read indices
1069  typedef typename OwnerOverlapCopyCommunication<G,L>::ParallelIndexSet IndexSet;
1070  IndexSet& pis=comm.pis;
1071  rfilename.str("");
1072  rfilename<<filename<<"_"<<rank<<".idx";
1073  file.open(rfilename.str().c_str());
1074  if(pis.size()!=0)
1075  DUNE_THROW(InvalidIndexSetState, "Index set is not empty!");
1076 
1077  pis.beginResize();
1078  while(!file.eof() && file.peek()!='n') {
1079  G g;
1080  file >>g;
1081  std::size_t l;
1082  file >>l;
1083  int c;
1084  file >>c;
1085  bool b;
1086  file >> b;
1087  pis.add(g,LocalIndex(l,Attribute(c),b));
1088  lineFeed(file);
1089  }
1090  pis.endResize();
1091  if(!file.eof()) {
1092  // read neighbours
1093  std::string s;
1094  file>>s;
1095  if(s!="neighbours:")
1096  DUNE_THROW(MatrixMarketFormatError, "was exspecting the string: \"neighbours:\"");
1097  std::set<int> nb;
1098  while(!file.eof()) {
1099  int i;
1100  file >> i;
1101  nb.insert(i);
1102  }
1103  file.close();
1104  comm.ri.setNeighbours(nb);
1105  }
1106  comm.ri.template rebuild<false>();
1107  }
1108 
1109  #endif
1110 
1121  template<typename M>
1122  void loadMatrixMarket(M& matrix,
1123  const std::string& filename)
1124  {
1125  std::ifstream file;
1126  file.open(filename.c_str(), std::ios::in);
1127  if(!file)
1128  DUNE_THROW(IOError, "Could not open file" << filename);
1129  readMatrixMarket(matrix,file);
1130  file.close();
1131  }
1132 
1134 }
1135 #endif