KratosMultiphysics
KRATOS Multiphysics (Kratos) is a framework for building parallel, multi-disciplinary simulation software, aiming at modularity, extensibility, and high performance. Kratos is written in C++, and counts with an extensive Python interface.
spectra_sym_g_eigs_shift_solver.h
Go to the documentation of this file.
1 /* KRATOS _ _ ____ _
2 // | | (_)_ __ ___ __ _ _ __/ ___| ___ | |_ _____ _ __ ___
3 // | | | | '_ \ / _ \/ _` | '__\___ \ / _ \| \ \ / / _ \ '__/ __|
4 // | |___| | | | | __/ (_| | | ___) | (_) | |\ V / __/ | \__ |
5 // |_____|_|_| |_|\___|\__,_|_| |____/ \___/|_| \_/ \___|_| |___/ Application
6 //
7 // Authors: Armin Geiser
8 */
9 
10 #if !defined(KRATOS_SPECTRA_SYM_G_EIGS_SHIFT_SOLVER_H_INCLUDED)
11 #define KRATOS_SPECTRA_SYM_G_EIGS_SHIFT_SOLVER_H_INCLUDED
12 
13 // External includes
14 #include <Eigen/Core>
15 #include <Spectra/SymGEigsShiftSolver.h>
16 #if defined EIGEN_USE_MKL_ALL
18 #endif // defined EIGEN_USE_MKL_ALL
19 
20 // Project includes
21 #include "includes/define.h"
22 #include "linear_solvers_define.h"
27 
28 namespace Kratos
29 {
30 
31 template<
32  class TSparseSpaceType = UblasSpace<double, CompressedMatrix, Vector>,
33  class TDenseSpaceType = UblasSpace<double, Matrix, Vector>,
34  class TPreconditionerType = Preconditioner<TSparseSpaceType, TDenseSpaceType>,
35  class TReordererType = Reorderer<TSparseSpaceType, TDenseSpaceType>>
37  : public IterativeSolver<TSparseSpaceType, TDenseSpaceType, TPreconditionerType, TReordererType>
38 {
39  Parameters mParam;
40 
41  public:
43 
45 
47 
49 
51 
53  Parameters param
54  ) : mParam(param)
55  {
56  Parameters default_params(R"(
57  {
58  "solver_type": "spectra_sym_g_eigs_shift",
59  "number_of_eigenvalues": 1,
60  "normalize_eigenvectors": false,
61  "max_iteration": 1000,
62  "shift": 0.0,
63  "echo_level": 1
64  })");
65 
66  mParam.ValidateAndAssignDefaults(default_params);
67 
68  BaseType::SetMaxIterationsNumber(mParam["max_iteration"].GetInt());
69  }
70 
72 
76  void Solve(
77  SparseMatrixType& rK,
78  SparseMatrixType& rM,
79  VectorType& rEigenvalues,
80  DenseMatrixType& rEigenvectors) override
81  {
82  using scalar_t = double;
83  using vector_t = Kratos::EigenDynamicVector<scalar_t>;
84  using matrix_t = Kratos::EigenDynamicMatrix<scalar_t>;
85 
86  // --- get settings
87 
88  const int nroot = mParam["number_of_eigenvalues"].GetInt();
89  const int max_iteration = BaseType::GetMaxIterationsNumber();
90  const int echo_level = mParam["echo_level"].GetInt();
91  const double shift = mParam["shift"].GetDouble();
92 
93  // --- wrap ublas matrices
94 
95  UblasWrapper<scalar_t> a_wrapper(rK);
96  UblasWrapper<scalar_t> b_wrapper(rM);
97 
98  const auto& a = a_wrapper.matrix();
99  const auto& b = b_wrapper.matrix();
100 
101  // --- timer
102  const auto timer = BuiltinTimer();
103 
104  KRATOS_INFO_IF("SpectraSymGEigsShiftSolver:", echo_level > 0) << "Start" << std::endl;
105 
106  // --- calculation
107 
108  using OpType = OwnSymShiftInvert<scalar_t>;
109  using BOpType = OwnSparseSymMatProd<scalar_t>;
110 
111  OpType op(a, b);
112  BOpType Bop(b);
113  const int ncv = 3 * nroot; // TODO find a good value
114  Spectra::SymGEigsShiftSolver<OpType, BOpType, Spectra::GEigsMode::ShiftInvert> eigs(op, Bop, nroot, ncv, shift);
115 
116  eigs.init();
117  const int nconv = eigs.compute(Spectra::SortRule::LargestAlge, max_iteration);
118  const int niter = eigs.num_iterations();
119  const int nops = eigs.num_operations();
120 
121  KRATOS_INFO_IF("SpectraSymGEigsShiftSolver:", echo_level > 0) << "nconv = " << nconv << std::endl;
122  KRATOS_INFO_IF("SpectraSymGEigsShiftSolver:", echo_level > 0) << "niter = " << niter << std::endl;
123  KRATOS_INFO_IF("SpectraSymGEigsShiftSolver:", echo_level > 0) << "nops = " << nops << std::endl;
124 
125  KRATOS_ERROR_IF(eigs.info() != Spectra::CompInfo::Successful) << "SpectraSymGEigsShiftSolver: failed" << std::endl;
126 
127  if (static_cast<int>(rEigenvalues.size()) != nroot) {
128  rEigenvalues.resize(nroot);
129  }
130  if (static_cast<int>(rEigenvectors.size1()) != nroot || rEigenvectors.size2() != rK.size1()) {
131  rEigenvectors.resize(nroot, rK.size1());
132  }
133 
134  Eigen::Map<vector_t> eigvals (rEigenvalues.data().begin(), rEigenvalues.size());
135  Eigen::Map<matrix_t> eigvecs (rEigenvectors.data().begin(), rEigenvectors.size1(), rEigenvectors.size2());
136 
137  // Spectra::SortRule::LargestAlge results in values being in descending order
138  eigvals = eigs.eigenvalues().reverse();
139  // conversion back to RowMajor ordering of Kratos and transpose because Spectra returns eigvecs as columns
140  eigvecs = eigs.eigenvectors().transpose().colwise().reverse();
141 
142  // --- normalization
143  // TODO seems to be normalized by Spectra already -> confirm!
144  // Given generalized eigenvalue problem (A - eigenvalue * B) * eigenvector = 0,
145  // eigenvector is normalized such that eigenvector^T * B * eigenvector = 1
146  if(mParam["normalize_eigenvectors"].GetBool())
147  {
148  for (int i = 0; i != nroot; ++i)
149  {
150  const double tmp = eigvecs.row(i) * b_wrapper.matrix() * eigvecs.row(i).transpose();
151  const double factor = 1.0 / std::sqrt(tmp);
152  eigvecs.row(i) *= factor;
153  KRATOS_INFO_IF("SpectraSymGEigsShiftSolver:", echo_level > 0) << "Eigenvector " << i+1 << " is normalized - used factor: " << factor << std::endl;
154  }
155  }
156 
157  // --- output
158  if (echo_level > 0) {
159  Eigen::IOFormat fmt(Eigen::StreamPrecision, Eigen::DontAlignCols, ", ", ", ", "", "", "[ ", " ]");
160 
161  KRATOS_INFO("SpectraSymGEigsShiftSolver:") << "Completed in " << timer << std::endl
162  << " Eigenvalues = " << eigvals.transpose().format(fmt) << std::endl;
163  }
164  }
165 
169  void PrintInfo(std::ostream &rOStream) const override
170  {
171  rOStream << "SpectraSymGEigsShiftSolver";
172  }
173 
177  void PrintData(std::ostream &rOStream) const override
178  {
179  }
180 
181 private:
182 
190  template <typename Scalar_>
191  class OwnSparseSymMatProd
192  {
193  public:
197  using Scalar = Scalar_;
198 
199  private:
200  using Index = Eigen::Index;
202  using MapConstVec = Eigen::Map<const Vector>;
203  using MapVec = Eigen::Map<Vector>;
206  using ConstGenericSparseMatrix = const Eigen::Ref<const SparseMatrix>;
207 
208  ConstGenericSparseMatrix m_mat;
209 
210  public:
218  OwnSparseSymMatProd(ConstGenericSparseMatrix& mat) :
219  m_mat(mat)
220  {}
221 
225  Index rows() const { return m_mat.rows(); }
229  Index cols() const { return m_mat.cols(); }
230 
237  // y_out = A * x_in
238  void perform_op(const Scalar* x_in, Scalar* y_out) const
239  {
240  MapConstVec x(x_in, m_mat.cols());
241  MapVec y(y_out, m_mat.rows());
242  y.noalias() = m_mat * x;
243  }
244 
248  Matrix operator*(const Eigen::Ref<const Matrix>& mat_in) const
249  {
250  return m_mat * mat_in;
251  }
252 
256  Scalar operator()(Index i, Index j) const
257  {
258  return m_mat.coeff(i, j);
259  }
260  };
261 
262 
263 
276  template <typename Scalar_>
277  class OwnSymShiftInvert
278  {
279  public:
283  using Scalar = Scalar_;
284 
285  private:
286  using Index = Eigen::Index;
287 
288  // type of the A matrix
289  using MatrixA = Kratos::EigenSparseMatrix<Scalar>;
290 
291  // type of the B matrix
293 
295  using MapConstVec = Eigen::Map<const Vector>;
296  using MapVec = Eigen::Map<Vector>;
297 
298  using ResType = MatrixA;
299 
300  #if defined EIGEN_USE_MKL_ALL
301  using FacType = Eigen::PardisoLU<ResType>;
302  #else
303  using FacType = Eigen::SparseLU<ResType>;
304  #endif // defined EIGEN_USE_MKL_ALL
305 
306  using ConstGenericMatrixA = const Eigen::Ref<const MatrixA>;
307  using ConstGenericMatrixB = const Eigen::Ref<const MatrixB>;
308 
309  ConstGenericMatrixA m_matA;
310  ConstGenericMatrixB m_matB;
311  const Index m_n;
312  FacType m_solver;
313 
314  public:
324  OwnSymShiftInvert(ConstGenericMatrixA& A, ConstGenericMatrixB& B) :
325  m_matA(A), m_matB(B), m_n(A.rows())
326  {
327  KRATOS_ERROR_IF(m_n != A.cols() || m_n != B.rows() || m_n != B.cols()) << "SymShiftInvert: A and B must be square matrices of the same size" << std::endl;
328  }
329 
333  Index rows() const { return m_n; }
337  Index cols() const { return m_n; }
338 
342  void set_shift(const Scalar& sigma)
343  {
344  if (sigma == 0.0) {
345  m_solver.compute(m_matA);
346  } else {
347  m_solver.compute(m_matA - sigma * m_matB);
348  }
349  const bool success = m_solver.info() == Eigen::Success;
350  KRATOS_ERROR_IF_NOT(success) << "SymShiftInvert: factorization failed with the given shift" << std::endl;
351  }
352 
359  // y_out = inv(A - sigma * B) * x_in
360  void perform_op(const Scalar* x_in, Scalar* y_out) const
361  {
362  MapConstVec x(x_in, m_n);
363  MapVec y(y_out, m_n);
364  y.noalias() = m_solver.solve(x);
365  }
366  };
367 
368 
369 }; // class SpectraSymGEigsShiftSolver
370 
371 
375 template<class TSparseSpaceType, class TDenseSpaceType, class TReordererType>
376 inline std::istream& operator >>(
377  std::istream& rIStream,
378  SpectraSymGEigsShiftSolver<TSparseSpaceType,
379  TDenseSpaceType,
380  TReordererType>& rThis)
381 {
382  return rIStream;
383 }
384 
388 template<class TSparseSpaceType, class TDenseSpaceType, class TReordererType>
389 inline std::ostream& operator <<(
390  std::ostream& rOStream,
392 {
393  rThis.PrintInfo(rOStream);
394  rOStream << std::endl;
395  rThis.PrintData(rOStream);
396 
397  return rOStream;
398 }
399 
400 } // namespace Kratos
401 
402 #endif // defined(KRATOS_SPECTRA_SYM_G_EIGS_SHIFT_SOLVER_H_INCLUDED)
Definition: builtin_timer.h:26
Base class for all the iterative solvers in Kratos.
Definition: iterative_solver.h:68
virtual void SetMaxIterationsNumber(unsigned int NewMaxIterationsNumber)
Definition: iterative_solver.h:285
virtual IndexType GetMaxIterationsNumber()
Definition: iterative_solver.h:290
TSparseSpaceType::MatrixType SparseMatrixType
Definition: linear_solver.h:73
TDenseSpaceType::MatrixType DenseMatrixType
Definition: linear_solver.h:81
TSparseSpaceType::VectorType VectorType
Definition: linear_solver.h:77
This class provides to Kratos a data structure for I/O based on the standard of JSON.
Definition: kratos_parameters.h:59
Definition: spectra_sym_g_eigs_shift_solver.h:38
SpectraSymGEigsShiftSolver(Parameters param)
Definition: spectra_sym_g_eigs_shift_solver.h:52
IterativeSolver< TSparseSpaceType, TDenseSpaceType, TPreconditionerType, TReordererType > BaseType
Definition: spectra_sym_g_eigs_shift_solver.h:44
~SpectraSymGEigsShiftSolver() override
Definition: spectra_sym_g_eigs_shift_solver.h:71
void PrintInfo(std::ostream &rOStream) const override
Definition: spectra_sym_g_eigs_shift_solver.h:169
TDenseSpaceType::MatrixType DenseMatrixType
Definition: spectra_sym_g_eigs_shift_solver.h:50
TSparseSpaceType::VectorType VectorType
Definition: spectra_sym_g_eigs_shift_solver.h:48
void PrintData(std::ostream &rOStream) const override
Definition: spectra_sym_g_eigs_shift_solver.h:177
KRATOS_CLASS_POINTER_DEFINITION(SpectraSymGEigsShiftSolver)
TSparseSpaceType::MatrixType SparseMatrixType
Definition: spectra_sym_g_eigs_shift_solver.h:46
void Solve(SparseMatrixType &rK, SparseMatrixType &rM, VectorType &rEigenvalues, DenseMatrixType &rEigenvectors) override
Definition: spectra_sym_g_eigs_shift_solver.h:76
Definition: ublas_wrapper.h:32
const Eigen::Map< const TEigenSparseMatrix > & matrix() const
Definition: ublas_wrapper.h:53
#define KRATOS_ERROR_IF_NOT(conditional)
Definition: exception.h:163
#define KRATOS_ERROR_IF(conditional)
Definition: exception.h:162
#define KRATOS_INFO(label)
Definition: logger.h:250
#define KRATOS_INFO_IF(label, conditional)
Definition: logger.h:251
Vector VectorType
Definition: geometrical_transformation_utilities.h:56
Matrix MatrixType
Definition: geometrical_transformation_utilities.h:55
REF: G. R. Cowper, GAUSSIAN QUADRATURE FORMULAS FOR TRIANGLES.
Definition: mesh_condition.cpp:21
mapped_matrix< double > SparseMatrix
Definition: ublas_interface.h:84
Expression::Pointer operator*(const Expression::ConstPointer &rpLeft, const double Right)
Internals::Matrix< double, AMatrix::dynamic, 1 > Vector
Definition: amatrix_interface.h:472
Eigen::Matrix< _Scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor > EigenDynamicMatrix
Definition: linear_solvers_define.h:32
Internals::Matrix< double, AMatrix::dynamic, AMatrix::dynamic > Matrix
Definition: amatrix_interface.h:470
Eigen::SparseMatrix< _Scalar, Eigen::RowMajor, int > EigenSparseMatrix
Definition: linear_solvers_define.h:35
std::istream & operator>>(std::istream &rIStream, LinearMasterSlaveConstraint &rThis)
input stream function
TABLE_NUMBER_ANGULAR_VELOCITY TABLE_NUMBER_MOMENT I33 BEAM_INERTIA_ROT_UNIT_LENGHT_Y KRATOS_DEFINE_APPLICATION_VARIABLE(DEM_APPLICATION, double, BEAM_INERTIA_ROT_UNIT_LENGHT_Z) typedef std double
Definition: DEM_application_variables.h:182
std::ostream & operator<<(std::ostream &rOStream, const LinearMasterSlaveConstraint &rThis)
output stream function
Definition: linear_master_slave_constraint.h:432
Eigen::Matrix< _Scalar, Eigen::Dynamic, 1 > EigenDynamicVector
Definition: linear_solvers_define.h:33
y
Other simbols definition.
Definition: generate_axisymmetric_navier_stokes_element.py:54
a
Definition: generate_stokes_twofluid_element.py:77
tuple tmp
Definition: generate_total_lagrangian_mixed_volumetric_strain_element.py:98
b
Definition: generate_total_lagrangian_mixed_volumetric_strain_element.py:31
def Index()
Definition: hdf5_io_tools.py:38
int j
Definition: quadrature.py:648
float sigma
Definition: rotating_cone.py:79
mat
Definition: script_ELASTIC.py:155
echo_level
Definition: script.py:68
A
Definition: sensitivityMatrix.py:70
x
Definition: sensitivityMatrix.py:49
B
Definition: sensitivityMatrix.py:76
def MatrixB(DN)
This method defines the deformation matrix B.
Definition: sympy_fe_utilities.py:202
integer i
Definition: TensorModule.f:17
Definition: timer.py:1
float factor
for node in (self.combined_model_part).Nodes: pold = node.GetSolutionStepValue(PRESSURE,...
Definition: ulf_PGLASS.py:254