deal.II version 9.7.0
\(\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
180 template <class Matrix>
181 void
182 build_patches(const Matrix &matrix,
183 const std::string &name,
184 const Options options = Options(false, 1, false, false));
185
186private:
192
198 std::vector<Patch> patches;
199
203 std::string name;
204
209 virtual const std::vector<Patch> &
210 get_patches() const override;
211
216 virtual std::vector<std::string>
217 get_dataset_names() const override;
218
226 template <class Matrix>
227 static double
228 get_gridpoint_value(const Matrix &matrix,
229 const size_type i,
230 const size_type j,
231 const Options &options);
232};
233
234
235/* ---------------------- Template and inline functions ------------- */
236
237
238namespace internal
239{
241 {
245 template <typename number>
246 double
247 get_element(const ::SparseMatrix<number> &matrix,
250 {
251 return matrix.el(i, j);
252 }
253
254
255
259 template <typename number>
260 double
261 get_element(const ::BlockSparseMatrix<number> &matrix,
264 {
265 return matrix.el(i, j);
266 }
267
268
269# ifdef DEAL_II_WITH_TRILINOS
273 inline double
277 {
278 return matrix.el(i, j);
279 }
280
281
282
287 inline double
291 {
292 return matrix.el(i, j);
293 }
294# endif
295
296
297# ifdef DEAL_II_WITH_PETSC
298 // no need to do anything: PETSc matrix objects do not distinguish
299 // between operator() and el(i,j), so we can safely access elements
300 // through the generic function below
301# endif
302
303
309 template <class Matrix>
310 double
311 get_element(const Matrix &matrix,
314 {
315 return matrix(i, j);
316 }
317 } // namespace MatrixOutImplementation
318} // namespace internal
319
320
321
322template <class Matrix>
323inline double
325 const size_type i,
326 const size_type j,
327 const Options &options)
328{
329 // special case if block size is
330 // one since we then don't need all
331 // that loop overhead
332 if (options.block_size == 1)
333 {
334 if (options.show_absolute_values == true)
335 return std::fabs(
337 else
339 }
340
341 // if blocksize greater than one,
342 // then compute average of elements
343 double average = 0;
344 size_type n_elements = 0;
345 for (size_type row = i * options.block_size;
346 row <
347 std::min(size_type(matrix.m()), size_type((i + 1) * options.block_size));
348 ++row)
349 for (size_type col = j * options.block_size;
350 col < std::min(size_type(matrix.m()),
351 size_type((j + 1) * options.block_size));
352 ++col, ++n_elements)
353 if (options.show_absolute_values == true)
354 average += std::fabs(
356 else
357 average +=
359 average /= n_elements;
360 return average;
361}
362
363
364
365template <class Matrix>
366void
367MatrixOut::build_patches(const Matrix &matrix,
368 const std::string &name,
369 const Options options)
370{
371 size_type n_patches_x = (matrix.n() / options.block_size +
372 (matrix.n() % options.block_size != 0 ? 1 : 0)),
373 n_patches_y = (matrix.m() / options.block_size +
374 (matrix.m() % options.block_size != 0 ? 1 : 0));
375
376 // If continuous, the number of
377 // plotted patches is matrix size-1
378 if (!options.discontinuous)
379 {
380 --n_patches_x;
381 --n_patches_y;
382 }
383
384 const size_type n_patches =
385 (options.create_sparse_plot ?
386 [&]() {
387 size_type count = 0;
388 for (size_type i = 0; i < n_patches_y; ++i)
389 {
390 for (size_type j = 0; j < n_patches_x; ++j)
391 // Use the same logic as below to determine whether we
392 // need to output a patch, and count if we do:
393 if ((((options.discontinuous == true) &&
394 (get_gridpoint_value(matrix, i, j, options) != 0)) ||
395 ((options.discontinuous == false) &&
396 ((get_gridpoint_value(matrix, i, j, options) != 0) ||
397 (get_gridpoint_value(matrix, i + 1, j, options) != 0) ||
398 (get_gridpoint_value(matrix, i, j + 1, options) != 0) ||
399 (get_gridpoint_value(matrix, i + 1, j + 1, options) !=
400 0)))))
401 ++count;
402 }
403 return count;
404 }() :
405 n_patches_x * n_patches_y);
406
407 // first clear old data and re-set the object to a correctly sized state:
408 patches.clear();
409 try
410 {
411 patches.resize(n_patches);
412 }
413 catch (const std::bad_alloc &)
414 {
415 AssertThrow(false,
416 ExcMessage("You are trying to create a graphical "
417 "representation of a matrix that would "
418 "requiring outputting " +
419 (options.create_sparse_plot ?
420 std::to_string(n_patches) :
421 std::to_string(n_patches_x) + "x" +
422 std::to_string(n_patches_y)) +
423 " patches. There is not enough memory to output " +
424 "this many patches."));
425 }
426
427 // now build the patches
428 size_type index = 0;
429 for (size_type i = 0; i < n_patches_y; ++i)
430 for (size_type j = 0; j < n_patches_x; ++j)
431 {
432 // If we are creating a sparse plot, check whether this patch
433 // would have any nonzero values. If not, we can skip the
434 // patch:
435 if (options.create_sparse_plot &&
436 (((options.discontinuous == true) &&
437 (get_gridpoint_value(matrix, i, j, options) == 0)) ||
438 ((options.discontinuous == false) &&
439 (get_gridpoint_value(matrix, i, j, options) == 0) &&
440 (get_gridpoint_value(matrix, i + 1, j, options) == 0) &&
441 (get_gridpoint_value(matrix, i, j + 1, options) == 0) &&
442 (get_gridpoint_value(matrix, i + 1, j + 1, options) == 0))))
443 continue;
444
445 patches[index].n_subdivisions = 1;
446 patches[index].reference_cell = ReferenceCells::Quadrilateral;
447
448 // within each patch, order the points in such a way that if some
449 // graphical output program (such as gnuplot) plots the quadrilaterals
450 // as two triangles, then the diagonal of the quadrilateral which cuts
451 // it into the two printed triangles is parallel to the diagonal of the
452 // matrix, rather than perpendicular to it. this has the advantage that,
453 // for example, the unit matrix is plotted as a straight ridge, rather
454 // than as a series of bumps and valleys along the diagonal
455 patches[index].vertices[0][0] = j;
456 patches[index].vertices[0][1] = -static_cast<signed int>(i);
457 patches[index].vertices[1][0] = j;
458 patches[index].vertices[1][1] = -static_cast<signed int>(i + 1);
459 patches[index].vertices[2][0] = j + 1;
460 patches[index].vertices[2][1] = -static_cast<signed int>(i);
461 patches[index].vertices[3][0] = j + 1;
462 patches[index].vertices[3][1] = -static_cast<signed int>(i + 1);
463 // next scale all the patch
464 // coordinates by the block
465 // size, to get original
466 // coordinates
467 for (auto &vertex : patches[index].vertices)
468 vertex *= options.block_size;
469
470 patches[index].n_subdivisions = 1;
471
472 patches[index].data.reinit(1, 4);
473 if (options.discontinuous)
474 {
475 patches[index].data(0, 0) =
476 get_gridpoint_value(matrix, i, j, options);
477 patches[index].data(0, 1) =
478 get_gridpoint_value(matrix, i, j, options);
479 patches[index].data(0, 2) =
480 get_gridpoint_value(matrix, i, j, options);
481 patches[index].data(0, 3) =
482 get_gridpoint_value(matrix, i, j, options);
483 }
484 else
485 {
486 patches[index].data(0, 0) =
487 get_gridpoint_value(matrix, i, j, options);
488 patches[index].data(0, 1) =
489 get_gridpoint_value(matrix, i + 1, j, options);
490 patches[index].data(0, 2) =
491 get_gridpoint_value(matrix, i, j + 1, options);
492 patches[index].data(0, 3) =
493 get_gridpoint_value(matrix, i + 1, j + 1, options);
494 }
495
496 ++index;
497 }
498
499 // finally set the name
500 this->name = name;
501}
502
503
504
505/*---------------------------- matrix_out.h ---------------------------*/
506
508
509#endif
510/*---------------------------- 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(false, 1, false, false))
Definition matrix_out.h:367
static double get_gridpoint_value(const Matrix &matrix, const size_type i, const size_type j, const Options &options)
Definition matrix_out.h:324
std::vector< Patch > patches
Definition matrix_out.h:198
types::global_dof_index size_type
Definition matrix_out.h:79
virtual ~MatrixOut() override=default
std::string name
Definition matrix_out.h:203
virtual std::vector< std::string > get_dataset_names() const override
Definition matrix_out.cc:45
DataOutBase::Patch< 2, 2 > Patch
Definition matrix_out.h:191
#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:247
::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