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.
eigensolver_strategy.hpp
Go to the documentation of this file.
1 //
2 // Project Name: KratosSolidMechanicsApplication $
3 // Created by: $Author: michael.andre@tum.de $
4 // Last modified by: $Co-Author: $
5 // Date: $Date: September 2016 $
6 // Revision: $Revision: March 2018 $
7 //
8 //
9 
10 #if !defined(KRATOS_EIGENSOLVER_STRATEGY_H_INCLUDED)
11 #define KRATOS_EIGENSOLVER_STRATEGY_H_INCLUDED
12 
13 // System includes
14 
15 // External includes
16 
17 // Project includes
19 
20 // Application includes
22 
23 namespace Kratos
24 {
25 
28 
32 
36 
40 
44 
46 template<class TSparseSpace,
47  class TDenseSpace,
48  class TLinearSolver
49  >
51  : public SolutionStrategy<TSparseSpace, TDenseSpace, TLinearSolver>
52 {
53  public:
56 
58 
60 
62 
64 
65  typedef typename BaseType::SchemeType SchemeType;
66 
68 
70 
71  typedef TSparseSpace SparseSpaceType;
72 
73  typedef typename TSparseSpace::VectorPointerType SparseVectorPointerType;
74 
75  typedef typename TSparseSpace::MatrixPointerType SparseMatrixPointerType;
76 
78 
80 
84 
87  typename SchemeType::Pointer pScheme,
88  typename BuilderAndSolverType::Pointer pBuilderAndSolver,
89  Flags & rOptions,
90  bool ComputeModalContribution = false)
91  : SolutionStrategy<TSparseSpace, TDenseSpace, TLinearSolver>(rModelPart, rOptions)
92  {
94 
95  mpScheme = pScheme;
96 
97  mpBuilderAndSolver = pBuilderAndSolver;
98 
99  // set if modal contribution is computed
100  mComputeModalContribution = ComputeModalContribution;
101 
102  mpMassMatrix = Kratos::make_shared<SparseMatrixType>(0,0);
103  mpStiffnessMatrix = Kratos::make_shared<SparseMatrixType>(0,0);
104 
105  mpBuilderAndSolver->SetEchoLevel(this->mEchoLevel);
106 
107  KRATOS_CATCH("")
108  }
109 
111  EigensolverStrategy(const EigensolverStrategy& Other) = delete;
112 
115  {
116  // Clear() controls order of deallocation to avoid invalid memory access in some special cases.
117  // warning: BaseType::GetModelPart() may be invalid here.
118  this->Clear();
119  }
120 
124 
128 
134  void InitializeSolutionStep() override
135  {
136  KRATOS_TRY
137 
138  if(this->IsNot(LocalFlagType::INITIALIZED))
139  this->Initialize();
140 
141  SparseVectorPointerType pDx = SparseSpaceType::CreateEmptyVectorPointer(); //dummy
143 
144  //set up the system
145  this->SetSystemDofs();
146 
147  //set system sizes
148  this->SetSystemMatrices(pDx,pb);
149 
150  //initial operations ... things that are constant over the Solution Step
151  mpBuilderAndSolver->InitializeSolutionStep(mpScheme, BaseType::GetModelPart(), mpStiffnessMatrix, pDx, pb);
152 
153  //initial operations ... things that are constant over the Solution Step
154  mpScheme->InitializeSolutionStep(BaseType::GetModelPart());
155 
156 
157  KRATOS_CATCH("")
158  }
159 
163  bool SolveSolutionStep() override
164  {
165  KRATOS_TRY
166 
167  // Initialize dummy rhs vector
169  SparseSpaceType::Resize((*pb),SparseSpaceType::Size1((*mpMassMatrix)));
170  SparseSpaceType::Set((*pb),0.0);
171 
172  // Generate lhs matrix. the factor 1 is chosen to preserve
173  // SPD property
174  this->GetModelPart().GetProcessInfo()[BUILD_LEVEL] = 1;
175  TSparseSpace::SetToZero((*mpMassMatrix));
176  mpBuilderAndSolver->Build(mpScheme,this->GetModelPart(),(*mpMassMatrix),(*pb));
177  this->ApplyDirichletConditions((*mpMassMatrix), 1.0);
178 
179  // Generate rhs matrix. the factor -1 is chosen to make
180  // Eigenvalues corresponding to fixed dofs negative
181  this->GetModelPart().GetProcessInfo()[BUILD_LEVEL] = 2;
182  TSparseSpace::SetToZero((*mpStiffnessMatrix));
183  mpBuilderAndSolver->Build(mpScheme,this->GetModelPart(),(*mpStiffnessMatrix),(*pb));
184  ApplyDirichletConditions((*mpStiffnessMatrix), -1.0);
185 
186  // Eigenvector matrix and eigenvalue vector are initialized by the solver
187  DenseVectorType Eigenvalues;
188  DenseMatrixType Eigenvectors;
189 
190  // Solve for eigenvalues and eigenvectors
191  mpBuilderAndSolver->GetLinearSystemSolver()->Solve((*mpStiffnessMatrix),
192  (*mpMassMatrix),
193  Eigenvalues,
194  Eigenvectors);
195 
196  this->AssignVariables(Eigenvalues,Eigenvectors);
197 
198  if( mComputeModalContribution == true )
199  this->ComputeModalContribution((*mpMassMatrix),Eigenvalues,Eigenvectors);
200 
201  return true;
202 
203  KRATOS_CATCH("")
204  }
205 
209  void Clear() override
210  {
211  KRATOS_TRY
212 
213  // if the preconditioner is saved between solves, it should be cleared here
214  mpBuilderAndSolver->GetLinearSystemSolver()->Clear();
215 
216  if(this->pGetMassMatrix() != nullptr)
217  {
218  this->pGetMassMatrix() = nullptr;
219  }
220 
221  if(this->pGetStiffnessMatrix() != nullptr)
222  {
223  this->pGetStiffnessMatrix() = nullptr;
224  }
225 
226  mpBuilderAndSolver->Clear();
227 
228  mpScheme->Clear();
229 
230  KRATOS_CATCH("")
231  }
232 
237  int Check() override
238  {
239  KRATOS_TRY
240 
241  //check the model part
242  BaseType::Check();
243 
244  //check the scheme
245  mpScheme->Check(this->GetModelPart());
246 
247  //check the builder and solver
248  mpBuilderAndSolver->Check(this->GetModelPart());
249 
250  return 0;
251 
252  KRATOS_CATCH("")
253  }
254 
258 
259  /* @brief This sets the level of echo for the solving strategy
260  * @param Level of echo for the solving strategy
261  * @details
262  * {
263  * 0 -> Mute... no echo at all
264  * 1 -> Printing time and basic informations
265  * 2 -> Printing linear solver data
266  * 3 -> Print of debug informations: Echo of stiffness matrix, Dx, b...
267  * }
268  */
269  void SetEchoLevel(const int Level) override
270  {
271  BaseType::SetEchoLevel(Level);
272  mpBuilderAndSolver->SetEchoLevel(Level);
273  }
274 
275 
276  void SetScheme(typename SchemeType::Pointer pScheme)
277  {
278  mpScheme = pScheme;
279  };
280 
281  typename SchemeType::Pointer& pGetScheme()
282  {
283  return mpScheme;
284  };
285 
286  void SetBuilderAndSolver(typename BuilderAndSolverType::Pointer pBuilderAndSolver)
287  {
288  mpBuilderAndSolver = pBuilderAndSolver;
289  };
290 
291  typename BuilderAndSolverType::Pointer& pGetBuilderAndSolver()
292  {
293  return mpBuilderAndSolver;
294  };
295 
297  {
298  return *mpMassMatrix;
299  }
300 
302  {
303  return *mpStiffnessMatrix;
304  }
305 
307  {
308  return mpMassMatrix;
309  }
310 
312  {
313  return mpStiffnessMatrix;
314  }
315 
319 
323 
325 
326  protected:
329 
333 
337 
341 
345  void Initialize() override
346  {
347  KRATOS_TRY
348 
349  //Initialize The Scheme - OPERATIONS TO BE DONE ONCE
350  if(mpScheme->IsNot(LocalFlagType::INITIALIZED))
351  mpScheme->Initialize(this->GetModelPart());
352 
353  //set up the system
354  this->SetSystemDofs();
355 
356  this->Set(LocalFlagType::INITIALIZED,true);
357 
358  KRATOS_CATCH("")
359  }
360 
364 
368 
372 
374 
375  private:
378 
382 
383  typename SchemeType::Pointer mpScheme;
384 
385  typename BuilderAndSolverType::Pointer mpBuilderAndSolver;
386 
387  SparseMatrixPointerType mpMassMatrix;
388 
389  SparseMatrixPointerType mpStiffnessMatrix;
390 
391  bool mComputeModalContribution;
392 
396 
400 
404  void SetSystemMatrices(SparseVectorPointerType& pDx, SparseVectorPointerType& pb)
405  {
406  KRATOS_TRY
407 
408  // Mass matrix
409  mpBuilderAndSolver->SetUpSystemMatrices(mpScheme, this->GetModelPart(), mpMassMatrix, pDx, pb);
410 
411  // Stiffness matrix
412  mpBuilderAndSolver->SetUpSystemMatrices(mpScheme, this->GetModelPart(), mpStiffnessMatrix, pDx, pb);
413 
414  KRATOS_CATCH("")
415  }
416 
420  void SetSystemDofs()
421  {
422  KRATOS_TRY
423 
424  if (this->mEchoLevel >= 2)
425  KRATOS_INFO(" Reform Dofs ") << " Flag = " <<this->mOptions.Is(LocalFlagType::REFORM_DOFS) << std::endl;
426 
427  //set up the system, operation performed just once unless it is required to reform the dof set at each iteration
428 
429  //setting up the list of the DOFs to be solved
430  // double begin_time = OpenMPUtils::GetCurrentTime();
431  mpBuilderAndSolver->SetUpDofSet(mpScheme, this->GetModelPart());
432  // double end_time = OpenMPUtils::GetCurrentTime();
433  // if (this->mEchoLevel >= 2)
434  // KRATOS_INFO("setup_dofs_time") << "setup_dofs_time : " << end_time - begin_time << "\n" << LoggerMessage::Category::STATISTICS;
435 
436  //shaping correctly the system
437  // begin_time = OpenMPUtils::GetCurrentTime();
438  mpBuilderAndSolver->SetUpSystem();
439  // end_time = OpenMPUtils::GetCurrentTime();
440  // if (this->mEchoLevel >= 2)
441  // KRATOS_INFO("setup_system_time") << ": setup_system_time : " << end_time - begin_time << "\n" << LoggerMessage::Category::STATISTICS;
442 
443  KRATOS_CATCH("")
444  }
445 
447 
452  void ApplyDirichletConditions(SparseMatrixType& rA, double Factor)
453  {
454  KRATOS_TRY
455 
456  const std::size_t SystemSize = rA.size1();
457  std::vector<double> ScalingFactors(SystemSize);
458  auto& rDofSet = this->pGetBuilderAndSolver()->GetDofSet();
459  const int NumDofs = static_cast<int>(rDofSet.size());
460 
461  // NOTE: dofs are assumed to be numbered consecutively
462 #pragma omp parallel for firstprivate(NumDofs)
463  for(int k = 0; k<NumDofs; k++)
464  {
465  auto dof_iterator = std::begin(rDofSet) + k;
466  ScalingFactors[k] = (dof_iterator->IsFixed()) ? 0.0 : 1.0;
467  }
468 
469  double* AValues = std::begin(rA.value_data());
470  std::size_t* ARowIndices = std::begin(rA.index1_data());
471  std::size_t* AColIndices = std::begin(rA.index2_data());
472 
473  // if there is a line of all zeros, put one on the diagonal
474  // #pragma omp parallel for firstprivate(SystemSize)
475  // for(int k = 0; k < static_cast<int>(SystemSize); ++k)
476  // {
477  // std::size_t ColBegin = ARowIndices[k];
478  // std::size_t ColEnd = ARowIndices[k+1];
479  // bool empty = true;
480  // for (auto j = ColBegin; j < ColEnd; ++j)
481  // if(AValues[j] != 0.0)
482  // {
483  // empty = false;
484  // break;
485  // }
486  // if(empty == true)
487  // rA(k,k) = 1.0;
488  // }
489 
490 #pragma omp parallel for
491  for (int k = 0; k < static_cast<int>(SystemSize); ++k)
492  {
493  std::size_t ColBegin = ARowIndices[k];
494  std::size_t ColEnd = ARowIndices[k+1];
495  if(ScalingFactors[k] == 0.0)
496  {
497  // row dof is fixed. zero off-diagonal columns and factor diagonal
498  for (std::size_t j = ColBegin; j < ColEnd; ++j)
499  {
500  if(static_cast<int>(AColIndices[j]) != k)
501  {
502  AValues[j] = 0.0;
503  }
504  else
505  {
506  AValues[j] *= Factor;
507  }
508  }
509  }
510  else
511  {
512  // row dof is not fixed. zero columns associated with fixed dofs
513  for (std::size_t j = ColBegin; j < ColEnd; ++j)
514  {
515  AValues[j] *= ScalingFactors[AColIndices[j]];
516  }
517  }
518  }
519 
520  KRATOS_CATCH("")
521  }
522 
524  void AssignVariables(DenseVectorType& rEigenvalues, DenseMatrixType& rEigenvectors)
525  {
526  KRATOS_TRY
527 
528  const std::size_t NumEigenvalues = rEigenvalues.size();
529 
530  // store eigenvalues in process info
531  this->GetModelPart().GetProcessInfo()[EIGENVALUE_VECTOR] = rEigenvalues;
532 
533  for (ModelPart::NodeIterator itNode = this->GetModelPart().NodesBegin(); itNode!= this->GetModelPart().NodesEnd(); itNode++)
534  {
535  ModelPart::NodeType::DofsContainerType& NodeDofs = itNode->GetDofs();
536  const std::size_t NumNodeDofs = NodeDofs.size();
537  Matrix& rNodeEigenvectors = itNode->GetValue(EIGENVECTOR_MATRIX);
538  if(rNodeEigenvectors.size1() != NumEigenvalues || rNodeEigenvectors.size2() != NumNodeDofs)
539  {
540  rNodeEigenvectors.resize(NumEigenvalues,NumNodeDofs,false);
541  }
542 
543  // the jth column index of EIGENVECTOR_MATRIX corresponds to the jth nodal dof. therefore,
544  // the dof ordering must not change.
545  // if(NodeDofs.IsSorted() == false)
546  // {
547  // NodeDofs.Sort();
548  // }
549 
550  // fill the EIGENVECTOR_MATRIX
551  for (std::size_t i = 0; i < NumEigenvalues; i++)
552  for (std::size_t j = 0; j < NumNodeDofs; j++)
553  {
554  auto itDof = std::begin(NodeDofs) + j;
555  rNodeEigenvectors(i,j) = rEigenvectors(i,(*itDof)->EquationId());
556  }
557  }
558 
559  KRATOS_CATCH("")
560  }
561 
563  void ComputeModalContribution(SparseMatrixType& rMassMatrix, DenseVectorType& rEigenValues, DenseMatrixType& rEigenVectors)
564  {
565  KRATOS_TRY
566 
567  //Computing modal contribution
568  const auto num_eigen_values = rEigenValues.size();
569  const auto system_size = rMassMatrix.size1();
570  Matrix mass(num_eigen_values,num_eigen_values);
571  noalias(mass) = ZeroMatrix(num_eigen_values,num_eigen_values);
572  Vector mode_contribution(num_eigen_values);
573  noalias(mode_contribution)= ZeroVector(num_eigen_values);
574  Vector ratio_mass_mode_contribution(num_eigen_values);
575  noalias(ratio_mass_mode_contribution) = ZeroVector(num_eigen_values);
576  Matrix eigen_contribution(num_eigen_values, system_size);
577  noalias(eigen_contribution)= ZeroMatrix(num_eigen_values, system_size);
578 
579  double total_mass= 0.0;
580  for (std::size_t i = 0; i < system_size; i++)
581  {
582  for (std::size_t j = 0; j < system_size; j++)
583  {
584  total_mass += rMassMatrix(i,j);
585  }
586  }
587 
588  noalias(eigen_contribution) = prod(rEigenVectors,rMassMatrix);
589  noalias(mass) = prod(eigen_contribution,trans(rEigenVectors));
590  double total_mass_contribution =0.0;
591 
592  for (std::size_t i = 0; i < num_eigen_values; i++)
593  {
594  for (std::size_t j = 0; j < system_size; j++)
595  {
596  mode_contribution[i] += eigen_contribution(i,j);
597  }
598 
599  ratio_mass_mode_contribution[i] = (mode_contribution[i]*mode_contribution[i])/(mass(i,i)*total_mass)*100.0;
600  total_mass_contribution += ratio_mass_mode_contribution[i];
601  }
602 
603  if (this->mEchoLevel >= 1){
604  KRATOS_INFO(" eigen_ratio") << " ::EIGEN_CONTRIBUTION:: (Mode/Mass) RATIO [" <<ratio_mass_mode_contribution << "]\n" << LoggerMessage::Category::STATUS;
605  KRATOS_INFO(" eigen_total") << " ::EIGEN_CONTRIBUTION:: (Mode/Mass) TOTAL [" << total_mass_contribution<< "]\n" << LoggerMessage::Category::STATUS;
606  }
607 
608  KRATOS_CATCH("")
609  }
610 
611 
615 
619 
621 
622 };
623 
625 
632 
634 
635 } // namespace Kratos.
636 
637 #endif // KRATOS_EIGENSOLVER_STRATEGY_H_INCLUDED defined
Strategy for solving generalized eigenvalue problems.
Definition: eigensolver_strategy.hpp:52
BaseType::LocalFlagType LocalFlagType
Definition: eigensolver_strategy.hpp:61
SparseMatrixPointerType & pGetMassMatrix()
Definition: eigensolver_strategy.hpp:306
BuilderAndSolverType::Pointer & pGetBuilderAndSolver()
Definition: eigensolver_strategy.hpp:291
SparseMatrixType & GetStiffnessMatrix()
Definition: eigensolver_strategy.hpp:301
TDenseSpace::VectorType DenseVectorType
Definition: eigensolver_strategy.hpp:67
int Check() override
Definition: eigensolver_strategy.hpp:237
TSparseSpace::MatrixPointerType SparseMatrixPointerType
Definition: eigensolver_strategy.hpp:75
void Clear() override
Definition: eigensolver_strategy.hpp:209
bool SolveSolutionStep() override
Solves the current step. This function returns true if a solution has been found, false otherwise.
Definition: eigensolver_strategy.hpp:163
TSparseSpace SparseSpaceType
Definition: eigensolver_strategy.hpp:71
SparseMatrixPointerType & pGetStiffnessMatrix()
Definition: eigensolver_strategy.hpp:311
BaseType::SchemeType SchemeType
Definition: eigensolver_strategy.hpp:65
void InitializeSolutionStep() override
Definition: eigensolver_strategy.hpp:134
void Initialize() override
Definition: eigensolver_strategy.hpp:345
TSparseSpace::VectorType SparseVectorType
Definition: eigensolver_strategy.hpp:79
SchemeType::Pointer & pGetScheme()
Definition: eigensolver_strategy.hpp:281
void SetEchoLevel(const int Level) override
This sets the level of echo for the solution strategy.
Definition: eigensolver_strategy.hpp:269
void SetBuilderAndSolver(typename BuilderAndSolverType::Pointer pBuilderAndSolver)
Definition: eigensolver_strategy.hpp:286
EigensolverStrategy(const EigensolverStrategy &Other)=delete
Deleted copy constructor.
SolutionStrategy< TSparseSpace, TDenseSpace, TLinearSolver > BaseType
Definition: eigensolver_strategy.hpp:59
TDenseSpace::MatrixType DenseMatrixType
Definition: eigensolver_strategy.hpp:69
void SetScheme(typename SchemeType::Pointer pScheme)
Definition: eigensolver_strategy.hpp:276
TSparseSpace::VectorPointerType SparseVectorPointerType
Definition: eigensolver_strategy.hpp:73
SparseMatrixType & GetMassMatrix()
Definition: eigensolver_strategy.hpp:296
BaseType::BuilderAndSolverType BuilderAndSolverType
Definition: eigensolver_strategy.hpp:63
EigensolverStrategy(ModelPart &rModelPart, typename SchemeType::Pointer pScheme, typename BuilderAndSolverType::Pointer pBuilderAndSolver, Flags &rOptions, bool ComputeModalContribution=false)
Constructor.
Definition: eigensolver_strategy.hpp:86
~EigensolverStrategy() override
Destructor.
Definition: eigensolver_strategy.hpp:114
TSparseSpace::MatrixType SparseMatrixType
Definition: eigensolver_strategy.hpp:77
KRATOS_CLASS_POINTER_DEFINITION(EigensolverStrategy)
Definition: flags.h:58
void Set(const Flags ThisFlag)
Definition: flags.cpp:33
bool Is(Flags const &rOther) const
Definition: flags.h:274
bool IsNot(Flags const &rOther) const
Definition: flags.h:291
void resize(std::size_t NewSize1, std::size_t NewSize2, bool preserve=0)
Definition: amatrix_interface.h:224
This class aims to manage meshes for multi-physics simulations.
Definition: model_part.h:77
ProcessInfo & GetProcessInfo()
Definition: model_part.h:1746
MeshType::NodeIterator NodeIterator
Definition: model_part.h:134
NodeIterator NodesEnd(IndexType ThisIndex=0)
Definition: model_part.h:497
std::vector< std::unique_ptr< Dof< double > >> DofsContainerType
The DoF container type definition.
Definition: node.h:92
Solution strategy base class.
Definition: solution_strategy.hpp:52
SolverLocalFlags LocalFlagType
Definition: solution_strategy.hpp:57
SolutionScheme< TSparseSpace, TDenseSpace > SchemeType
Definition: solution_strategy.hpp:65
ModelPart & GetModelPart()
Operations to get the pointer to the model.
Definition: solution_strategy.hpp:243
Flags mOptions
Definition: solution_strategy.hpp:267
virtual int Check()
Function to perform expensive checks.
Definition: solution_strategy.hpp:154
SolutionBuilderAndSolver< TSparseSpace, TDenseSpace, TLinearSolver > BuilderAndSolverType
Definition: solution_strategy.hpp:66
virtual void SetEchoLevel(const int Level)
This sets the level of echo for the solution strategy.
Definition: solution_strategy.hpp:190
int mEchoLevel
Definition: solution_strategy.hpp:270
static void Set(VectorType &rX, TDataType A)
rX = A
Definition: ublas_space.h:553
static void Resize(MatrixType &rA, SizeType m, SizeType n)
Definition: ublas_space.h:558
static IndexType Size1(MatrixType const &rM)
return number of rows of rM
Definition: ublas_space.h:197
static VectorPointerType CreateEmptyVectorPointer()
Definition: ublas_space.h:183
#define KRATOS_CATCH(MoreInfo)
Definition: define.h:110
#define KRATOS_TRY
Definition: define.h:109
#define KRATOS_INFO(label)
Definition: logger.h:250
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
KratosZeroVector< double > ZeroVector
Definition: amatrix_interface.h:561
Internals::Matrix< double, AMatrix::dynamic, 1 > Vector
Definition: amatrix_interface.h:472
KratosZeroMatrix< double > ZeroMatrix
Definition: amatrix_interface.h:559
Internals::Matrix< double, AMatrix::dynamic, AMatrix::dynamic > Matrix
Definition: amatrix_interface.h:470
AMatrix::MatrixProductExpression< TExpression1Type, TExpression2Type > prod(AMatrix::MatrixExpression< TExpression1Type, TCategory1 > const &First, AMatrix::MatrixExpression< TExpression2Type, TCategory2 > const &Second)
Definition: amatrix_interface.h:568
T & noalias(T &TheMatrix)
Definition: amatrix_interface.h:484
AMatrix::TransposeMatrix< const T > trans(const T &TheMatrix)
Definition: amatrix_interface.h:486
int k
Definition: quadrature.py:595
int j
Definition: quadrature.py:648
integer i
Definition: TensorModule.f:17