Dune Core Modules (2.9.0)

io.hh
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright (C) 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_IO_HH
6 #define DUNE_ISTL_IO_HH
7 
8 #include <cmath>
9 #include <complex>
10 #include <limits>
11 #include <ios>
12 #include <iomanip>
13 #include <fstream>
14 #include <string>
15 
16 #include "matrixutils.hh"
17 #include "istlexception.hh"
18 #include <dune/common/fvector.hh>
19 #include <dune/common/fmatrix.hh>
20 #include <dune/common/hybridutilities.hh>
22 
23 #include <dune/istl/bcrsmatrix.hh>
24 #include <dune/istl/blocklevel.hh>
25 
26 namespace Dune {
27 
40  //
41  // pretty printing of vectors
42  //
43 
51  template<class V>
52  void recursive_printvector (std::ostream& s, const V& v, std::string rowtext,
53  int& counter, int columns, int width)
54  {
55  if constexpr (IsNumber<V>())
56  {
57  // Print one number
58  if (counter%columns==0)
59  {
60  s << rowtext; // start a new row
61  s << " "; // space in front of each entry
62  s.width(4); // set width for counter
63  s << counter; // number of first entry in a line
64  }
65  s << " "; // space in front of each entry
66  s.width(width); // set width for each entry anew
67  s << v; // yeah, the number !
68  counter++; // increment the counter
69  if (counter%columns==0)
70  s << std::endl; // start a new line
71  }
72  else
73  {
74  // Recursively print a vector
75  for (const auto& entry : v)
76  recursive_printvector(s,entry,rowtext,counter,columns,width);
77  }
78  }
79 
80 
88  template<class V>
89  void printvector (std::ostream& s, const V& v, std::string title,
90  std::string rowtext, int columns=1, int width=10,
91  int precision=2)
92  {
93  // count the numbers printed to make columns
94  int counter=0;
95 
96  // remember old flags
97  std::ios_base::fmtflags oldflags = s.flags();
98 
99  // set the output format
100  s.setf(std::ios_base::scientific, std::ios_base::floatfield);
101  int oldprec = s.precision();
102  s.precision(precision);
103 
104  // print title
105  s << title << " [blocks=" << v.N() << ",dimension=" << v.dim() << "]"
106  << std::endl;
107 
108  // print data from all blocks
109  recursive_printvector(s,v,rowtext,counter,columns,width);
110 
111  // check if new line is required
112  if (counter%columns!=0)
113  s << std::endl;
114 
115  // reset the output format
116  s.flags(oldflags);
117  s.precision(oldprec);
118  }
119 
120 
122  //
123  // pretty printing of matrices
124  //
125 
133  inline void fill_row (std::ostream& s, int m, int width, [[maybe_unused]] int precision)
134  {
135  for (int j=0; j<m; j++)
136  {
137  s << " "; // space in front of each entry
138  s.width(width); // set width for each entry anew
139  s << "."; // yeah, the number !
140  }
141  }
142 
150  template<class K>
151  void print_row (std::ostream& s, const K& value,
152  [[maybe_unused]] typename FieldMatrix<K,1,1>::size_type I,
153  [[maybe_unused]] typename FieldMatrix<K,1,1>::size_type J,
154  [[maybe_unused]] typename FieldMatrix<K,1,1>::size_type therow,
155  int width,
156  [[maybe_unused]] int precision,
157  typename std::enable_if_t<Dune::IsNumber<K>::value>* sfinae = nullptr)
158  {
159  s << " "; // space in front of each entry
160  s.width(width); // set width for each entry anew
161  s << value;
162  }
163 
171  template<class M>
172  void print_row (std::ostream& s, const M& A, typename M::size_type I,
173  typename M::size_type J, typename M::size_type therow,
174  int width, int precision,
175  typename std::enable_if_t<!Dune::IsNumber<M>::value>* sfinae = nullptr)
176  {
177  typename M::size_type i0=I;
178  for (typename M::size_type i=0; i<A.N(); i++)
179  {
180  if (therow>=i0 && therow<i0+MatrixDimension<M>::rowdim(A,i))
181  {
182  // the row is in this block row !
183  typename M::size_type j0=J;
184  for (typename M::size_type j=0; j<A.M(); j++)
185  {
186  // find this block
187  typename M::ConstColIterator it = A[i].find(j);
188 
189  // print row or filler
190  if (it!=A[i].end())
191  print_row(s,*it,i0,j0,therow,width,precision);
192  else
193  fill_row(s,MatrixDimension<M>::coldim(A,j),width,precision);
194 
195  // advance columns
196  j0 += MatrixDimension<M>::coldim(A,j);
197  }
198  }
199  // advance rows
200  i0 += MatrixDimension<M>::rowdim(A,i);
201  }
202  }
203 
212  template<class M>
213  void printmatrix (std::ostream& s, const M& A, std::string title,
214  std::string rowtext, int width=10, int precision=2)
215  {
216 
217  // remember old flags
218  std::ios_base::fmtflags oldflags = s.flags();
219 
220  // set the output format
221  s.setf(std::ios_base::scientific, std::ios_base::floatfield);
222  int oldprec = s.precision();
223  s.precision(precision);
224 
225  // print title
226  s << title
227  << " [n=" << A.N()
228  << ",m=" << A.M()
229  << ",rowdim=" << MatrixDimension<M>::rowdim(A)
230  << ",coldim=" << MatrixDimension<M>::coldim(A)
231  << "]" << std::endl;
232 
233  // print all rows
234  for (typename M::size_type i=0; i<MatrixDimension<M>::rowdim(A); i++)
235  {
236  s << rowtext; // start a new row
237  s << " "; // space in front of each entry
238  s.width(4); // set width for counter
239  s << i; // number of first entry in a line
240  print_row(s,A,0,0,i,width,precision); // generic print
241  s << std::endl; // start a new line
242  }
243 
244  // reset the output format
245  s.flags(oldflags);
246  s.precision(oldprec);
247  }
248 
270  template<class B, int n, int m, class A>
271  void printSparseMatrix(std::ostream& s,
272  const BCRSMatrix<FieldMatrix<B,n,m>,A>& mat,
273  std::string title, std::string rowtext,
274  int width=3, int precision=2)
275  {
277  // remember old flags
278  std::ios_base::fmtflags oldflags = s.flags();
279  // set the output format
280  s.setf(std::ios_base::scientific, std::ios_base::floatfield);
281  int oldprec = s.precision();
282  s.precision(precision);
283  // print title
284  s << title
285  << " [n=" << mat.N()
286  << ",m=" << mat.M()
287  << ",rowdim=" << MatrixDimension<Matrix>::rowdim(mat)
288  << ",coldim=" << MatrixDimension<Matrix>::coldim(mat)
289  << "]" << std::endl;
290 
291  typedef typename Matrix::ConstRowIterator Row;
292 
293  for(Row row=mat.begin(); row != mat.end(); ++row) {
294  int skipcols=0;
295  bool reachedEnd=false;
296 
297  while(!reachedEnd) {
298  for(int innerrow=0; innerrow<n; ++innerrow) {
299  int count=0;
300  typedef typename Matrix::ConstColIterator Col;
301  Col col=row->begin();
302  for(; col != row->end(); ++col,++count) {
303  if(count<skipcols)
304  continue;
305  if(count>=skipcols+width)
306  break;
307  if(innerrow==0) {
308  if(count==skipcols) {
309  s << rowtext; // start a new row
310  s << " "; // space in front of each entry
311  s.width(4); // set width for counter
312  s << row.index()<<": "; // number of first entry in a line
313  }
314  s.width(4);
315  s<<col.index()<<": |";
316  } else {
317  if(count==skipcols) {
318  for(typename std::string::size_type i=0; i < rowtext.length(); i++)
319  s<<" ";
320  s<<" ";
321  }
322  s<<" |";
323  }
324  for(int innercol=0; innercol < m; ++innercol) {
325  s.width(9);
326  s<<(*col)[innerrow][innercol]<<" ";
327  }
328 
329  s<<"|";
330  }
331  if(innerrow==n-1 && col==row->end())
332  reachedEnd = true;
333  else
334  s << std::endl;
335  }
336  skipcols += width;
337  s << std::endl;
338  }
339  s << std::endl;
340  }
341 
342  // reset the output format
343  s.flags(oldflags);
344  s.precision(oldprec);
345  }
346 
347  namespace
348  {
349  template<typename T>
350  struct MatlabPODWriter
351  {
352  static std::ostream& write(const T& t, std::ostream& s)
353  {
354  s << t;
355  return s;
356  }
357  };
358  template<typename T>
359  struct MatlabPODWriter<std::complex<T> >
360  {
361  static std::ostream& write(const std::complex<T>& t, std::ostream& s)
362  {
363  s << t.real() << " " << t.imag();
364  return s;
365  }
366  };
367  } // anonymous namespace
368 
378  template <class FieldType>
379  void writeMatrixToMatlabHelper(const FieldType& value,
380  int rowOffset, int colOffset,
381  std::ostream& s,
382  typename std::enable_if_t<Dune::IsNumber<FieldType>::value>* sfinae = nullptr)
383  {
384  //+1 for Matlab numbering
385  s << rowOffset + 1 << " " << colOffset + 1 << " ";
386  MatlabPODWriter<FieldType>::write(value, s)<< std::endl;
387  }
388 
396  template <class MatrixType>
397  void writeMatrixToMatlabHelper(const MatrixType& matrix,
398  int externalRowOffset, int externalColOffset,
399  std::ostream& s,
400  typename std::enable_if_t<!Dune::IsNumber<MatrixType>::value>* sfinae = nullptr)
401  {
402  // Precompute the accumulated sizes of the columns
403  std::vector<typename MatrixType::size_type> colOffset(matrix.M());
404  if (colOffset.size() > 0)
405  colOffset[0] = 0;
406 
407  for (typename MatrixType::size_type i=0; i<matrix.M()-1; i++)
408  colOffset[i+1] = colOffset[i] +
409  MatrixDimension<MatrixType>::coldim(matrix,i);
410 
411  typename MatrixType::size_type rowOffset = 0;
412 
413  // Loop over all matrix rows
414  for (typename MatrixType::size_type rowIdx=0; rowIdx<matrix.N(); rowIdx++)
415  {
416  auto cIt = matrix[rowIdx].begin();
417  auto cEndIt = matrix[rowIdx].end();
418 
419  // Loop over all columns in this row
420  for (; cIt!=cEndIt; ++cIt)
422  externalRowOffset+rowOffset,
423  externalColOffset + colOffset[cIt.index()],
424  s);
425 
426  rowOffset += MatrixDimension<MatrixType>::rowdim(matrix, rowIdx);
427  }
428 
429  }
430 
450  template <class MatrixType>
451  void writeMatrixToMatlab(const MatrixType& matrix,
452  const std::string& filename, int outputPrecision = 18)
453  {
454  std::ofstream outStream(filename.c_str());
455  int oldPrecision = outStream.precision();
456  outStream.precision(outputPrecision);
457 
458  writeMatrixToMatlabHelper(matrix, 0, 0, outStream);
459  outStream.precision(oldPrecision);
460  }
461 
462  // Recursively write vector entries to a stream
463  template<class V>
464  void writeVectorToMatlabHelper (const V& v, std::ostream& stream)
465  {
466  if constexpr (IsNumber<V>()) {
467  stream << v << std::endl;
468  } else {
469  for (const auto& entry : v)
470  writeVectorToMatlabHelper(entry, stream);
471  }
472  }
473 
491  template <class VectorType>
492  void writeVectorToMatlab(const VectorType& vector,
493  const std::string& filename, int outputPrecision = 18)
494  {
495  std::ofstream outStream(filename.c_str());
496  int oldPrecision = outStream.precision();
497  outStream.precision(outputPrecision);
498 
499  writeVectorToMatlabHelper(vector, outStream);
500  outStream.precision(oldPrecision);
501  }
502 
503  namespace Impl {
504 
506  struct NullStream {
507  template <class Any>
508  friend NullStream &operator<<(NullStream &dev0, Any &&) {
509  return dev0;
510  }
511  };
512 
514  // svg shall be closed with a group and an svg. i.e. "</g></svg>"
515  template <class Stream, class SVGMatrixOptions>
516  void writeSVGMatrixHeader(Stream &out, const SVGMatrixOptions &opts,
517  std::pair<std::size_t, size_t> offsets) {
518  auto [col_offset, row_offset] = offsets;
519  double width = opts.width;
520  double height = opts.height;
521  // if empty, we try to figure out a sensible value of width and height
522  if (opts.width == 0 and opts.height == 0)
523  width = height = 500;
524  if (opts.width == 0)
525  width = opts.height * (double(col_offset) / row_offset);
526  if (opts.height == 0)
527  height = opts.width * (double(row_offset) / col_offset);
528 
529  // scale group w.r.t final offsets
530  double scale_width = width / col_offset;
531  double scale_height = height / row_offset;
532 
533  // write the header text
534  out << "<svg xmlns='http://www.w3.org/2000/svg' width='" << std::ceil(width)
535  << "' height='" << std::ceil(height) << "' version='1.1'>\n"
536  << "<style>\n"
537  << opts.style << "</style>\n"
538  << "<g transform='scale(" << scale_width << " " << scale_height
539  << ")'>\n";
540  }
541 
543  template <class Mat, class Stream, class SVGMatrixOptions,
544  class RowPrefix, class ColPrefix>
545  std::pair<std::size_t, size_t>
546  writeSVGMatrix(const Mat &mat, Stream &out, SVGMatrixOptions opts,
547  RowPrefix row_prefix, ColPrefix col_prefix) {
548  // get values to fill the offests
549  const auto& block_size = opts.block_size;
550  const auto& interspace = opts.interspace;
551 
552  const std::size_t rows = mat.N();
553  const std::size_t cols = mat.M();
554 
555  // disable header write for recursive calls
556  const bool write_header = opts.write_header;
557  opts.write_header = false;
558 
559  // counter of offsets for every block
560  std::size_t row_offset = interspace;
561  std::size_t col_offset = interspace;
562 
563  // lambda helper: for-each value
564  auto for_each_entry = [&mat](const auto &call_back) {
565  for (auto row_it = mat.begin(); row_it != mat.end(); ++row_it) {
566  for (auto col_it = row_it->begin(); col_it != row_it->end(); ++col_it) {
567  call_back(row_it.index(), col_it.index(), *col_it);
568  }
569  }
570  };
571 
572  // accumulate content in another stream so that we write in correct order
573  std::stringstream ss;
574 
575  // we need to append current row and col values to the prefixes
576  row_prefix.push_back(0);
577  col_prefix.push_back(0);
578 
579  // do we need to write nested matrix blocks?
580  if constexpr (Dune::blockLevel<typename Mat::block_type>() == 0) {
581  // simple case: write svg block content to stream for each value
582  for_each_entry([&](const auto &row, const auto &col, const auto &val) {
583  std::size_t x_off = interspace + col * (interspace + block_size);
584  std::size_t y_off = interspace + row * (interspace + block_size);
585  row_prefix.back() = row;
586  col_prefix.back() = col;
587  opts.writeSVGBlock(ss, row_prefix, col_prefix, val,
588  {x_off, y_off, block_size, block_size});
589  });
590  col_offset += cols * (block_size + interspace);
591  row_offset += rows * (block_size + interspace);
592  } else {
593  // before we write anything, we need to calculate the
594  // offset for every {row,col} index
595  const auto null_offset = std::numeric_limits<std::size_t>::max();
596  std::vector<std::size_t> col_offsets(cols + 1, null_offset);
597  std::vector<std::size_t> row_offsets(rows + 1, null_offset);
598  for_each_entry([&](const auto &row, const auto &col, const auto &val) {
599  NullStream dev0;
600  // get size of sub-block
601  auto sub_size =
602  writeSVGMatrix(val, dev0, opts, row_prefix, col_prefix);
603 
604  // if we didn't see col size before
605  if (col_offsets[col + 1] == null_offset) // write it in the offset vector
606  col_offsets[col + 1] = sub_size.first;
607 
608  // repeat proces for row sizes
609  if (row_offsets[row + 1] == null_offset)
610  row_offsets[row + 1] = sub_size.second;
611  });
612 
613  // if some rows/cols were not visited, make an educated guess with the minimum offset
614  auto min_row_offset = *std::min_element(begin(row_offsets), end(row_offsets));
615  std::replace(begin(row_offsets), end(row_offsets), null_offset, min_row_offset);
616  auto min_col_offset = *std::min_element(begin(col_offsets), end(col_offsets));
617  std::replace(begin(col_offsets), end(col_offsets), null_offset, min_col_offset);
618 
619  // we have sizes for every block: to get offsets we make a partial sum
620  col_offsets[0] = interspace;
621  row_offsets[0] = interspace;
622  for (std::size_t i = 1; i < col_offsets.size(); i++)
623  col_offsets[i] += col_offsets[i - 1] + interspace;
624  for (std::size_t i = 1; i < row_offsets.size(); i++)
625  row_offsets[i] += row_offsets[i - 1] + interspace;
626 
627  for_each_entry([&](const auto &row, const auto &col, const auto &val) {
628  // calculate svg view from offsets
629  std::size_t width =
630  col_offsets[col + 1] - col_offsets[col] - interspace;
631  std::size_t height =
632  row_offsets[row + 1] - row_offsets[row] - interspace;
633  row_prefix.back() = row;
634  col_prefix.back() = col;
635  // content of the sub-block has origin at {0,0}: shift it to the correct place
636  ss << "<svg x='" << col_offsets[col] << "' y='" << row_offsets[row]
637  << "' width='" << width << "' height='" << height << "'>\n";
638  // write a nested svg with the contents of the sub-block
639  writeSVGMatrix(val, ss, opts, row_prefix, col_prefix);
640  ss << "</svg>\n";
641  });
642  col_offset = col_offsets.back();
643  row_offset = row_offsets.back();
644  }
645 
646  // write content in order!
647  // (i) if required, first header
648  if (write_header)
649  writeSVGMatrixHeader(out, opts, {col_offset, row_offset});
650 
651  col_prefix.pop_back();
652  row_prefix.pop_back();
653  // (ii) an svg block for this level
654  opts.writeSVGBlock(out, row_prefix, col_prefix, mat,
655  {0, 0, col_offset, row_offset});
656  // (iii) the content of the matrix
657  out << ss.str();
658  // (iv) if required, close the header
659  if (write_header)
660  out << "</g>\n</svg>\n";
661 
662  // return the total required for this block
663  return {col_offset, row_offset};
664  }
665  } // namespace Impl
666 
667 
676  std::size_t block_size = 10;
678  std::size_t interspace = 5;
680  std::size_t width = 500;
682  std::size_t height = 0;
684  bool write_header = true;
686  std::string style = " .matrix-block {\n"
687  " fill: cornflowerblue;\n"
688  " fill-opacity: 0.4;\n"
689  " stroke-width: 2;\n"
690  " stroke: black;\n"
691  " stroke-opacity: 0.5;\n"
692  " }\n"
693  " .matrix-block:hover {\n"
694  " fill: lightcoral;\n"
695  " fill-opacity: 0.4;\n"
696  " stroke-opacity: 1;\n"
697  " }\n";
698 
710  std::function<std::string(const double&)> color_fill;
711 
717  template <class RowPrefix, class ColPrefix>
718  std::string blockStyleClass(const RowPrefix &row_prefix,
719  const ColPrefix &col_prefix) const {
720  // here, you can potentially give a different style to each block
721  return "matrix-block";
722  }
723 
725  bool write_block_title = true;
726 
732  template <class Stream, class RowPrefix, class ColPrefix, class Block>
733  void writeBlockTitle(Stream& out, const RowPrefix &row_prefix,
734  const ColPrefix &col_prefix,
735  const Block &block) const {
736  if (this->write_block_title) {
737  out << "<title>";
738  assert(row_prefix.size() == col_prefix.size());
739  for (std::size_t i = 0; i < row_prefix.size(); ++i)
740  out << "[" << row_prefix[i] << ", "<< col_prefix[i] << "]";
741  if constexpr (Dune::blockLevel<Block>() == 0)
742  out << ": " << block;
743  out << "</title>\n";
744  }
745  }
746 
768  template <class Stream, class RowPrefix, class ColPrefix, class Block>
769  void writeSVGBlock(Stream &out,
770  const RowPrefix &row_prefix,
771  const ColPrefix &col_prefix, const Block block,
772  const std::array<std::size_t, 4> &svg_box) const {
773  // get bounding box values
774  auto &[x_off, y_off, width, height] = svg_box;
775  // get style class
776  std::string block_class = this->blockStyleClass(row_prefix, col_prefix);
777  // write a rectangle on the bounding box
778  out << "<rect class='" << block_class << "' x='" << x_off << "' y='"
779  << y_off << "' width='" << width << "' height='" << height << "'";
780  if constexpr (Dune::blockLevel<Block>() == 0 and std::is_convertible<Block,double>{})
781  if (color_fill)
782  out << " style='fill-opacity: 1;fill:" << color_fill(double(block)) << "'";
783 
784  out << ">\n";
785  // give the rectangle a title (in html this shows info about the block)
786  this->writeBlockTitle(out,row_prefix, col_prefix, block);
787  // close rectangle
788  out << "</rect>\n";
789  }
790  };
791 
806  template <class Mat, class SVGOptions = DefaultSVGMatrixOptions>
807  void writeSVGMatrix(const Mat &mat, std::ostream &out,
808  SVGOptions opts = {}) {
809  // We need a vector that can fit all the multi-indices for rows and colums
811  // Call overload for Mat type
812  Impl::writeSVGMatrix(mat, out, opts, IndexPrefix{}, IndexPrefix{});
813  }
814 
817 } // namespace Dune
818 
819 #endif
Implementation of the BCRSMatrix class.
Helper functions for determining the vector/matrix block level.
A sparse block matrix with compressed row storage.
Definition: bcrsmatrix.hh:466
A dense n x m matrix.
Definition: fmatrix.hh:117
ConstIterator class for sequential access.
Definition: matrix.hh:404
A generic dynamic dense matrix.
Definition: matrix.hh:561
RowIterator end()
Get iterator to one beyond last row.
Definition: matrix.hh:620
RowIterator begin()
Get iterator to first row.
Definition: matrix.hh:614
row_type::const_iterator ConstColIterator
Const iterator for the entries of each row.
Definition: matrix.hh:589
size_type M() const
Return the number of columns.
Definition: matrix.hh:700
size_type N() const
Return the number of rows.
Definition: matrix.hh:695
A Vector class with statically reserved memory.
Definition: reservedvector.hh:47
Implements a matrix constructed from a given type representing a field and compile-time given number ...
Implements a vector constructed from a given type representing a field and a compile-time given size.
void writeSVGMatrix(const Mat &mat, std::ostream &out, SVGOptions opts={})
Writes the visualization of matrix in the SVG format.
Definition: io.hh:807
void fill_row(std::ostream &s, int m, int width, [[maybe_unused]] int precision)
Print a row of zeros for a non-existing block.
Definition: io.hh:133
void writeMatrixToMatlab(const MatrixType &matrix, const std::string &filename, int outputPrecision=18)
Writes sparse matrix in a Matlab-readable format.
Definition: io.hh:451
void print_row(std::ostream &s, const K &value, [[maybe_unused]] typename FieldMatrix< K, 1, 1 >::size_type I, [[maybe_unused]] typename FieldMatrix< K, 1, 1 >::size_type J, [[maybe_unused]] typename FieldMatrix< K, 1, 1 >::size_type therow, int width, [[maybe_unused]] int precision, typename std::enable_if_t< Dune::IsNumber< K >::value > *sfinae=nullptr)
Print one row of a matrix, specialization for number types.
Definition: io.hh:151
void printmatrix(std::ostream &s, const M &A, std::string title, std::string rowtext, int width=10, int precision=2)
Print a generic block matrix.
Definition: io.hh:213
void printvector(std::ostream &s, const V &v, std::string title, std::string rowtext, int columns=1, int width=10, int precision=2)
Print an ISTL vector.
Definition: io.hh:89
void writeMatrixToMatlabHelper(const FieldType &value, int rowOffset, int colOffset, std::ostream &s, typename std::enable_if_t< Dune::IsNumber< FieldType >::value > *sfinae=nullptr)
Helper method for the writeMatrixToMatlab routine.
Definition: io.hh:379
void writeVectorToMatlab(const VectorType &vector, const std::string &filename, int outputPrecision=18)
Writes vectors in a Matlab-readable format.
Definition: io.hh:492
void recursive_printvector(std::ostream &s, const V &v, std::string rowtext, int &counter, int columns, int width)
Recursively print a vector.
Definition: io.hh:52
void printSparseMatrix(std::ostream &s, const BCRSMatrix< FieldMatrix< B, n, m >, A > &mat, std::string title, std::string rowtext, int width=3, int precision=2)
Prints a BCRSMatrix with fixed sized blocks.
Definition: io.hh:271
auto max(ADLTag< 0 >, const V &v1, const V &v2)
implements binary Simd::max()
Definition: defaults.hh:81
Some handy generic functions for ISTL matrices.
Dune namespace.
Definition: alignedallocator.hh:13
An stl-compliant random-access container which stores everything on the stack.
Default options class to write SVG matrices.
Definition: io.hh:674
std::string style
CSS style block to write in header.
Definition: io.hh:686
std::size_t width
Final width size (pixels) of the SVG header. If 0, size is automatic.
Definition: io.hh:680
std::function< std::string(const double &)> color_fill
Color fill for default options.
Definition: io.hh:710
std::size_t block_size
size (pixels) of the deepst block/value of the matrix
Definition: io.hh:676
void writeSVGBlock(Stream &out, const RowPrefix &row_prefix, const ColPrefix &col_prefix, const Block block, const std::array< std::size_t, 4 > &svg_box) const
Write an SVG object for a given block/value in the matrix.
Definition: io.hh:769
void writeBlockTitle(Stream &out, const RowPrefix &row_prefix, const ColPrefix &col_prefix, const Block &block) const
Helper function writes a title for a given block and prefix.
Definition: io.hh:733
std::size_t interspace
size (pixels) of the interspace between blocks
Definition: io.hh:678
bool write_block_title
(Helper) Whether to write a title on the rectangle value
Definition: io.hh:725
std::size_t height
Final height size (pixels) of the SVG header. If 0, size is automatic.
Definition: io.hh:682
bool write_header
Whether to write the SVG header.
Definition: io.hh:684
std::string blockStyleClass(const RowPrefix &row_prefix, const ColPrefix &col_prefix) const
Helper function that returns an style class for a given prefix.
Definition: io.hh:718
Whether this type acts as a scalar in the context of (hierarchically blocked) containers.
Definition: typetraits.hh:194
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (May 2, 22:35, 2024)