deal.II version 9.7.1
\(\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: LGPL-2.1-or-later
4// Copyright (C) 2001 - 2025 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Part of the source code is dual licensed under Apache-2.0 WITH
9// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
10// governing the source code and code contributions can be found in
11// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
12//
13// ------------------------------------------------------------------------
14
15#ifndef dealii_matrix_out_h
16# define dealii_matrix_out_h
17
18# include <deal.II/base/config.h>
19
21
24
25# ifdef DEAL_II_WITH_TRILINOS
28# endif
29
30
32
73class MatrixOut : public DataOutInterface<2, 2>
74{
75public:
80
85 struct Options
86 {
96
106 unsigned int block_size;
107
122
147
152 Options(const bool show_absolute_values = false,
153 const unsigned int block_size = 1,
154 const bool discontinuous = false,
155 const bool create_sparse_plot = true);
156 };
157
161 virtual ~MatrixOut() override = default;
162
181 template <class Matrix>
182 void
183 build_patches(const Matrix &matrix,
184 const std::string &name,
185 const Options options = Options());
186
187private:
193
199 std::vector<Patch> patches;
200
204 std::string name;
205
210 virtual const std::vector<Patch> &
211 get_patches() const override;
212
217 virtual std::vector<std::string>
218 get_dataset_names() const override;
219
227 template <class Matrix>
228 static double
229 get_gridpoint_value(const Matrix &matrix,
230 const size_type i,
231 const size_type j,
232 const Options &options);
233};
234
235
236/* ---------------------- Template and inline functions ------------- */
237
238
239namespace internal
240{
242 {
246 template <typename number>
247 double
248 get_element(const ::SparseMatrix<number> &matrix,
251 {
252 return matrix.el(i, j);
253 }
254
255
256
260 template <typename number>
261 double
262 get_element(const ::BlockSparseMatrix<number> &matrix,
265 {
266 return matrix.el(i, j);
267 }
268
269
270# ifdef DEAL_II_WITH_TRILINOS
274 inline double
278 {
279 return matrix.el(i, j);
280 }
281
282
283
288 inline double
292 {
293 return matrix.el(i, j);
294 }
295# endif
296
297
298# ifdef DEAL_II_WITH_PETSC
299 // no need to do anything: PETSc matrix objects do not distinguish
300 // between operator() and el(i,j), so we can safely access elements
301 // through the generic function below
302# endif
303
304
310 template <class Matrix>
311 double
312 get_element(const Matrix &matrix,
315 {
316 return matrix(i, j);
317 }
318 } // namespace MatrixOutImplementation
319} // namespace internal
320
321
322
323template <class Matrix>
324inline double
326 const size_type i,
327 const size_type j,
328 const Options &options)
329{
330 // special case if block size is
331 // one since we then don't need all
332 // that loop overhead
333 if (options.block_size == 1)
334 {
335 if (options.show_absolute_values == true)
336 return std::fabs(
338 else
340 }
341
342 // if blocksize greater than one,
343 // then compute average of elements
344 double average = 0;
345 size_type n_elements = 0;
346 for (size_type row = i * options.block_size;
347 row <
348 std::min(size_type(matrix.m()), size_type((i + 1) * options.block_size));
349 ++row)
350 for (size_type col = j * options.block_size;
351 col < std::min(size_type(matrix.m()),
352 size_type((j + 1) * options.block_size));
353 ++col, ++n_elements)
354 if (options.show_absolute_values == true)
355 average += std::fabs(
357 else
358 average +=
360 average /= n_elements;
361 return average;
362}
363
364
365
366template <class Matrix>
367void
368MatrixOut::build_patches(const Matrix &matrix,
369 const std::string &name,
370 const Options options)
371{
372 size_type n_patches_x = (matrix.n() / options.block_size +
373 (matrix.n() % options.block_size != 0 ? 1 : 0)),
374 n_patches_y = (matrix.m() / options.block_size +
375 (matrix.m() % options.block_size != 0 ? 1 : 0));
376
377 // If continuous, the number of
378 // plotted patches is matrix size-1
379 if (!options.discontinuous)
380 {
381 --n_patches_x;
382 --n_patches_y;
383 }
384
385 const size_type n_patches =
386 (options.create_sparse_plot ?
387 [&]() {
388 size_type count = 0;
389 for (size_type i = 0; i < n_patches_y; ++i)
390 {
391 for (size_type j = 0; j < n_patches_x; ++j)
392 // Use the same logic as below to determine whether we
393 // need to output a patch, and count if we do:
394 if ((((options.discontinuous == true) &&
395 (get_gridpoint_value(matrix, i, j, options) != 0)) ||
396 ((options.discontinuous == false) &&
397 ((get_gridpoint_value(matrix, i, j, options) != 0) ||
398 (get_gridpoint_value(matrix, i + 1, j, options) != 0) ||
399 (get_gridpoint_value(matrix, i, j + 1, options) != 0) ||
400 (get_gridpoint_value(matrix, i + 1, j + 1, options) !=
401 0)))))
402 ++count;
403 }
404 return count;
405 }() :
406 n_patches_x * n_patches_y);
407
408 // first clear old data and re-set the object to a correctly sized state:
409 patches.clear();
410 try
411 {
412 patches.resize(n_patches);
413 }
414 catch (const std::bad_alloc &)
415 {
416 AssertThrow(false,
417 ExcMessage("You are trying to create a graphical "
418 "representation of a matrix that would "
419 "requiring outputting " +
420 (options.create_sparse_plot ?
421 std::to_string(n_patches) :
422 std::to_string(n_patches_x) + "x" +
423 std::to_string(n_patches_y)) +
424 " patches. There is not enough memory to output " +
425 "this many patches."));
426 }
427
428 // now build the patches
429 size_type index = 0;
430 for (size_type i = 0; i < n_patches_y; ++i)
431 for (size_type j = 0; j < n_patches_x; ++j)
432 {
433 // If we are creating a sparse plot, check whether this patch
434 // would have any nonzero values. If not, we can skip the
435 // patch:
436 if (options.create_sparse_plot &&
437 (((options.discontinuous == true) &&
438 (get_gridpoint_value(matrix, i, j, options) == 0)) ||
439 ((options.discontinuous == false) &&
440 (get_gridpoint_value(matrix, i, j, options) == 0) &&
441 (get_gridpoint_value(matrix, i + 1, j, options) == 0) &&
442 (get_gridpoint_value(matrix, i, j + 1, options) == 0) &&
443 (get_gridpoint_value(matrix, i + 1, j + 1, options) == 0))))
444 continue;
445
446 patches[index].n_subdivisions = 1;
447 patches[index].reference_cell = ReferenceCells::Quadrilateral;
448
449 // within each patch, order the points in such a way that if some
450 // graphical output program (such as gnuplot) plots the quadrilaterals
451 // as two triangles, then the diagonal of the quadrilateral which cuts
452 // it into the two printed triangles is parallel to the diagonal of the
453 // matrix, rather than perpendicular to it. this has the advantage that,
454 // for example, the unit matrix is plotted as a straight ridge, rather
455 // than as a series of bumps and valleys along the diagonal
456 patches[index].vertices[0][0] = j;
457 patches[index].vertices[0][1] = -static_cast<signed int>(i);
458 patches[index].vertices[1][0] = j;
459 patches[index].vertices[1][1] = -static_cast<signed int>(i + 1);
460 patches[index].vertices[2][0] = j + 1;
461 patches[index].vertices[2][1] = -static_cast<signed int>(i);
462 patches[index].vertices[3][0] = j + 1;
463 patches[index].vertices[3][1] = -static_cast<signed int>(i + 1);
464 // next scale all the patch
465 // coordinates by the block
466 // size, to get original
467 // coordinates
468 for (auto &vertex : patches[index].vertices)
469 vertex *= options.block_size;
470
471 patches[index].n_subdivisions = 1;
472
473 patches[index].data.reinit(1, 4);
474 if (options.discontinuous)
475 {
476 patches[index].data(0, 0) =
477 get_gridpoint_value(matrix, i, j, options);
478 patches[index].data(0, 1) =
479 get_gridpoint_value(matrix, i, j, options);
480 patches[index].data(0, 2) =
481 get_gridpoint_value(matrix, i, j, options);
482 patches[index].data(0, 3) =
483 get_gridpoint_value(matrix, i, j, options);
484 }
485 else
486 {
487 patches[index].data(0, 0) =
488 get_gridpoint_value(matrix, i, j, options);
489 patches[index].data(0, 1) =
490 get_gridpoint_value(matrix, i + 1, j, options);
491 patches[index].data(0, 2) =
492 get_gridpoint_value(matrix, i, j + 1, options);
493 patches[index].data(0, 3) =
494 get_gridpoint_value(matrix, i + 1, j + 1, options);
495 }
496
497 ++index;
498 }
499
500 // finally set the name
501 this->name = name;
502}
503
504
505
506/*---------------------------- matrix_out.h ---------------------------*/
507
509
510#endif
511/*---------------------------- 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:368
static double get_gridpoint_value(const Matrix &matrix, const size_type i, const size_type j, const Options &options)
Definition matrix_out.h:325
std::vector< Patch > patches
Definition matrix_out.h:199
types::global_dof_index size_type
Definition matrix_out.h:79
virtual ~MatrixOut() override=default
std::string name
Definition matrix_out.h:204
virtual std::vector< std::string > get_dataset_names() const override
Definition matrix_out.cc:45
DataOutBase::Patch< 2, 2 > Patch
Definition matrix_out.h:192
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:40
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:41
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
constexpr ReferenceCell Quadrilateral
double get_element(const ::SparseMatrix< number > &matrix, const types::global_dof_index i, const types::global_dof_index j)
Definition matrix_out.h:248
::VectorizedArray< Number, width > min(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
unsigned int global_dof_index
Definition types.h:94
Options(const bool show_absolute_values=false, const unsigned int block_size=1, const bool discontinuous=false, const bool create_sparse_plot=true)
Definition matrix_out.cc:24
unsigned int block_size
Definition matrix_out.h:106