https://mooseframework.inl.gov
MatrixEigenvalueCheck.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://mooseframework.inl.gov
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
10 #include "MatrixEigenvalueCheck.h"
11 
12 #include <petscmat.h>
13 #include <slepceps.h>
14 
15 registerMooseObject("NavierStokesApp", MatrixEigenvalueCheck);
16 
19 {
21  params.addClassDescription("Report the number of zero eigenvalues of a matrix.");
22  params.addRequiredParam<std::string>("mat", "The petsc binary mat file containing the matrix");
23  params.addParam<Real>("zero_tol", 1e-8, "The tolerance for determining zero values");
24  params.addParam<bool>("print", false, "Whether to print the eigensolves to the console");
25  return params;
26 }
27 
29  : GeneralPostprocessor(parameters),
30  _zero_tol(getParam<Real>("zero_tol")),
31  _mat_name(getParam<std::string>("mat")),
32  _print(getParam<bool>("print"))
33 {
34 }
35 
36 void
38 {
39  PetscViewer matviewer;
40 
41  LibmeshPetscCallA(_communicator.get(), MatCreate(_communicator.get(), &_petsc_mat));
42  LibmeshPetscCallA(
44  PetscViewerBinaryOpen(_communicator.get(), _mat_name.c_str(), FILE_MODE_READ, &matviewer));
45  LibmeshPetscCallA(_communicator.get(), MatLoad(_petsc_mat, matviewer));
46  LibmeshPetscCallA(_communicator.get(), PetscViewerDestroy(&matviewer));
47 
49 }
50 
51 void
53 {
54  if (_print)
55  _console << std::endl << "Conducting eigen-solve for " << _mat_name << std::endl;
56 
57  PetscScalar kr, ki;
58  PetscReal error, re, im;
59  PetscInt nconv, nev, i;
60  EPS eps;
61 
62  LibmeshPetscCallA(_communicator.get(), EPSCreate(_communicator.get(), &eps));
63  LibmeshPetscCallA(_communicator.get(), EPSSetOperators(eps, _petsc_mat, nullptr));
64  LibmeshPetscCallA(_communicator.get(), EPSSetType(eps, EPSLAPACK));
65  LibmeshPetscCallA(_communicator.get(), EPSSolve(eps));
66  LibmeshPetscCallA(_communicator.get(), EPSGetDimensions(eps, &nev, nullptr, nullptr));
67  if (_print)
68  {
69  LibmeshPetscCallA(_communicator.get(),
70  PetscPrintf(_communicator.get(),
71  " Number of requested eigenvalues: %" PetscInt_FMT "\n",
72  nev));
73  }
74 
75  LibmeshPetscCallA(_communicator.get(), EPSGetConverged(eps, &nconv));
76  if (_print)
77  {
78  LibmeshPetscCallA(_communicator.get(),
79  PetscPrintf(_communicator.get(),
80  " Number of converged eigenpairs: %" PetscInt_FMT "\n\n",
81  nconv));
82  }
83 
84  if (nconv > 0)
85  {
86  if (_print)
87  {
88  /*
89  Display eigenvalues and relative errors
90  */
91  LibmeshPetscCallA(_communicator.get(),
92  PetscPrintf(_communicator.get(),
93  " k ||Ax-kx||/||kx||\n"
94  " ----------------- ------------------\n"));
95  }
96 
97  for (i = 0; i < nconv; i++)
98  {
99  /*
100  Get converged eigenpairs: i-th eigenvalue is stored in kr (real part) and
101  ki (imaginary part)
102  */
103  LibmeshPetscCallA(_communicator.get(), EPSGetEigenpair(eps, i, &kr, &ki, nullptr, nullptr));
104  /*
105  Compute the relative error associated to each eigenpair
106  */
107  LibmeshPetscCallA(_communicator.get(), EPSComputeError(eps, i, EPS_ERROR_RELATIVE, &error));
108 
109 #if defined(PETSC_USE_COMPLEX)
110  re = PetscRealPart(kr);
111  im = PetscImaginaryPart(kr);
112 #else
113  re = kr;
114  im = ki;
115 #endif
116  const bool zero_im = std::abs(im) < _zero_tol;
117  const bool zero_re = std::abs(re) < _zero_tol;
118  if (_print)
119  {
120  if (!zero_im)
121  LibmeshPetscCallA(
122  _communicator.get(),
123  PetscPrintf(
124  PETSC_COMM_WORLD, " %9f+%9fi %12g\n", (double)re, (double)im, (double)error));
125  else
126  LibmeshPetscCallA(
127  _communicator.get(),
128  PetscPrintf(_communicator.get(), " %12f %12g\n", (double)re, (double)error));
129  }
130  if (zero_im && zero_re)
132  }
133 
134  if (_print)
135  {
136  LibmeshPetscCallA(_communicator.get(), PetscPrintf(_communicator.get(), "\n"));
137  }
138  }
139 }
140 
141 void
143 {
144 }
145 
146 Real
148 {
149  return _num_zero_eigenvalues;
150 }
const std::string & _mat_name
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
const Real eps
registerMooseObject("NavierStokesApp", MatrixEigenvalueCheck)
virtual void execute() override
static InputParameters validParams()
const Parallel::Communicator & _communicator
void addRequiredParam(const std::string &name, const std::string &doc_string)
virtual Real getValue() const override
static InputParameters validParams()
MatrixEigenvalueCheck(const InputParameters &parameters)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Returns the number of zero eigenvalues in a PETSc matrix.
void addClassDescription(const std::string &doc_string)
const ConsoleStream _console
virtual void finalize() override
virtual void initialize() override