deal.II version GIT relicensing-6842-g793a97d2aa 2026-10-02 14:00:01+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
matrix_out.h
Go to the documentation of this file.
1// -----------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception OR LGPL-2.1-or-later
4// Copyright (C) 2001 - 2026 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Detailed license information governing the source code and contributions
9// can be found in LICENSE.md and CONTRIBUTING.md at the top level directory.
10//
11// -----------------------------------------------------------------------------
12
13#ifndef dealii_matrix_out_h
14# define dealii_matrix_out_h
15
16# include <deal.II/base/config.h>
17
21# include <deal.II/base/point.h>
22# include <deal.II/base/table.h>
23# include <deal.II/base/tensor.h>
24# include <deal.II/base/types.h>
25
27
30
31# include <algorithm>
32# include <array>
33# include <cmath>
34# include <new>
35# include <string>
36# include <vector>
37
38# ifdef DEAL_II_WITH_TRILINOS
41# endif
42
43
45
86class MatrixOut : public DataOutInterface<2, 2>
87{
88public:
93
98 struct Options
99 {
109
119 unsigned int block_size;
120
135
160
165 Options(const bool show_absolute_values = false,
166 const unsigned int block_size = 1,
167 const bool discontinuous = false,
168 const bool create_sparse_plot = true);
169 };
170
174 virtual ~MatrixOut() override = default;
175
194 template <class Matrix>
195 void
196 build_patches(const Matrix &matrix,
197 const std::string &name,
198 const Options options = Options());
199
200private:
206
212 std::vector<Patch> patches;
213
217 std::string name;
218
223 virtual const std::vector<Patch> &
224 get_patches() const override;
225
230 virtual std::vector<std::string>
231 get_dataset_names() const override;
232
240 template <class Matrix>
241 static double
242 get_gridpoint_value(const Matrix &matrix,
243 const size_type i,
244 const size_type j,
245 const Options &options);
246};
247
248
249/* ---------------------- Template and inline functions ------------- */
250
251
252namespace internal
253{
254 namespace MatrixOutImplementation
255 {
259 template <typename number>
260 double
261 get_element(const ::SparseMatrix<number> &matrix,
264 {
265 return matrix.el(i, j);
266 }
267
268
269
273 template <typename number>
274 double
275 get_element(const ::BlockSparseMatrix<number> &matrix,
278 {
279 return matrix.el(i, j);
280 }
281
282
283# ifdef DEAL_II_TRILINOS_WITH_EPETRA
287 inline double
291 {
292 return matrix.el(i, j);
293 }
294
295
296
301 inline double
305 {
306 return matrix.el(i, j);
307 }
308# endif
309
310
311# ifdef DEAL_II_WITH_PETSC
312 // no need to do anything: PETSc matrix objects do not distinguish
313 // between operator() and el(i,j), so we can safely access elements
314 // through the generic function below
315# endif
316
317
323 template <class Matrix>
324 double
325 get_element(const Matrix &matrix,
328 {
329 return matrix(i, j);
330 }
331 } // namespace MatrixOutImplementation
332} // namespace internal
333
334
335
336template <class Matrix>
337inline double
339 const size_type i,
340 const size_type j,
341 const Options &options)
342{
343 // special case if block size is
344 // one since we then don't need all
345 // that loop overhead
346 if (options.block_size == 1)
347 {
348 if (options.show_absolute_values == true)
349 return std::fabs(
351 else
353 }
354
355 // if blocksize greater than one,
356 // then compute average of elements
357 double average = 0;
358 size_type n_elements = 0;
359 for (size_type row = i * options.block_size;
360 row <
361 std::min(size_type(matrix.m()), size_type((i + 1) * options.block_size));
362 ++row)
363 for (size_type col = j * options.block_size;
364 col < std::min(size_type(matrix.m()),
365 size_type((j + 1) * options.block_size));
366 ++col, ++n_elements)
367 if (options.show_absolute_values == true)
368 average += std::fabs(
370 else
371 average +=
373 average /= n_elements;
374 return average;
375}
376
377
378
379template <class Matrix>
380void
381MatrixOut::build_patches(const Matrix &matrix,
382 const std::string &name,
383 const Options options)
384{
385 size_type n_patches_x = (matrix.n() / options.block_size +
386 (matrix.n() % options.block_size != 0 ? 1 : 0)),
387 n_patches_y = (matrix.m() / options.block_size +
388 (matrix.m() % options.block_size != 0 ? 1 : 0));
389
390 // If continuous, the number of
391 // plotted patches is matrix size-1
392 if (!options.discontinuous)
393 {
394 --n_patches_x;
395 --n_patches_y;
396 }
397
398 const size_type n_patches =
399 (options.create_sparse_plot ?
400 [&]() {
401 size_type count = 0;
402 for (size_type i = 0; i < n_patches_y; ++i)
403 {
404 for (size_type j = 0; j < n_patches_x; ++j)
405 // Use the same logic as below to determine whether we
406 // need to output a patch, and count if we do:
407 if ((((options.discontinuous == true) &&
408 (get_gridpoint_value(matrix, i, j, options) != 0)) ||
409 ((options.discontinuous == false) &&
410 ((get_gridpoint_value(matrix, i, j, options) != 0) ||
411 (get_gridpoint_value(matrix, i + 1, j, options) != 0) ||
412 (get_gridpoint_value(matrix, i, j + 1, options) != 0) ||
413 (get_gridpoint_value(matrix, i + 1, j + 1, options) !=
414 0)))))
415 ++count;
416 }
417 return count;
418 }() :
419 n_patches_x * n_patches_y);
420
421 // first clear old data and re-set the object to a correctly sized state:
422 patches.clear();
423 try
424 {
425 patches.resize(n_patches);
426 }
427 catch (const std::bad_alloc &)
428 {
429 AssertThrow(false,
430 ExcMessage("You are trying to create a graphical "
431 "representation of a matrix that would "
432 "requiring outputting " +
433 (options.create_sparse_plot ?
434 std::to_string(n_patches) :
435 std::to_string(n_patches_x) + "x" +
436 std::to_string(n_patches_y)) +
437 " patches. There is not enough memory to output " +
438 "this many patches."));
439 }
440
441 // now build the patches
442 size_type index = 0;
443 for (size_type i = 0; i < n_patches_y; ++i)
444 for (size_type j = 0; j < n_patches_x; ++j)
445 {
446 // If we are creating a sparse plot, check whether this patch
447 // would have any nonzero values. If not, we can skip the
448 // patch:
449 if (options.create_sparse_plot &&
450 (((options.discontinuous == true) &&
451 (get_gridpoint_value(matrix, i, j, options) == 0)) ||
452 ((options.discontinuous == false) &&
453 (get_gridpoint_value(matrix, i, j, options) == 0) &&
454 (get_gridpoint_value(matrix, i + 1, j, options) == 0) &&
455 (get_gridpoint_value(matrix, i, j + 1, options) == 0) &&
456 (get_gridpoint_value(matrix, i + 1, j + 1, options) == 0))))
457 continue;
458
459 patches[index].n_subdivisions = 1;
460 patches[index].reference_cell = ReferenceCells::Quadrilateral;
461
462 // within each patch, order the points in such a way that if some
463 // graphical output program (such as gnuplot) plots the quadrilaterals
464 // as two triangles, then the diagonal of the quadrilateral which cuts
465 // it into the two printed triangles is parallel to the diagonal of the
466 // matrix, rather than perpendicular to it. this has the advantage that,
467 // for example, the unit matrix is plotted as a straight ridge, rather
468 // than as a series of bumps and valleys along the diagonal
469 patches[index].vertices[0][0] = j;
470 patches[index].vertices[0][1] = -static_cast<signed int>(i);
471 patches[index].vertices[1][0] = j;
472 patches[index].vertices[1][1] = -static_cast<signed int>(i + 1);
473 patches[index].vertices[2][0] = j + 1;
474 patches[index].vertices[2][1] = -static_cast<signed int>(i);
475 patches[index].vertices[3][0] = j + 1;
476 patches[index].vertices[3][1] = -static_cast<signed int>(i + 1);
477 // next scale all the patch
478 // coordinates by the block
479 // size, to get original
480 // coordinates
481 for (auto &vertex : patches[index].vertices)
482 vertex *= options.block_size;
483
484 patches[index].n_subdivisions = 1;
485
486 patches[index].data.reinit(1, 4);
487 if (options.discontinuous)
488 {
489 patches[index].data(0, 0) =
490 get_gridpoint_value(matrix, i, j, options);
491 patches[index].data(0, 1) =
492 get_gridpoint_value(matrix, i, j, options);
493 patches[index].data(0, 2) =
494 get_gridpoint_value(matrix, i, j, options);
495 patches[index].data(0, 3) =
496 get_gridpoint_value(matrix, i, j, options);
497 }
498 else
499 {
500 patches[index].data(0, 0) =
501 get_gridpoint_value(matrix, i, j, options);
502 patches[index].data(0, 1) =
503 get_gridpoint_value(matrix, i + 1, j, options);
504 patches[index].data(0, 2) =
505 get_gridpoint_value(matrix, i, j + 1, options);
506 patches[index].data(0, 3) =
507 get_gridpoint_value(matrix, i + 1, j + 1, options);
508 }
509
510 ++index;
511 }
512
513 // finally set the name
514 this->name = name;
515}
516
517
518
519/*---------------------------- matrix_out.h ---------------------------*/
520
522
523#endif
524/*---------------------------- matrix_out.h ---------------------------*/
virtual const std::vector< Patch > & get_patches() const override
Definition matrix_out.cc:37
void build_patches(const Matrix &matrix, const std::string &name, const Options options=Options())
Definition matrix_out.h:381
static double get_gridpoint_value(const Matrix &matrix, const size_type i, const size_type j, const Options &options)
Definition matrix_out.h:338
std::vector< Patch > patches
Definition matrix_out.h:212
types::global_dof_index size_type
Definition matrix_out.h:92
virtual ~MatrixOut() override=default
std::string name
Definition matrix_out.h:217
virtual std::vector< std::string > get_dataset_names() const override
Definition matrix_out.cc:45
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
constexpr ReferenceCell< 2 > Quadrilateral
double get_element(const ::SparseMatrix< number > &matrix, const types::global_dof_index i, const types::global_dof_index j)
Definition matrix_out.h:261
::VectorizedArray< Number, width > min(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
unsigned int global_dof_index
Definition types.h:92
unsigned int block_size
Definition matrix_out.h:119