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.
eigenfrequency_response_function_utility.h
Go to the documentation of this file.
1 // KRATOS ___| | | |
2 // \___ \ __| __| | | __| __| | | __| _` | |
3 // | | | | | ( | | | | ( | |
4 // _____/ \__|_| \__,_|\___|\__|\__,_|_| \__,_|_| MECHANICS
5 //
6 // License: BSD License
7 // license: StructuralMechanicsApplication/license.txt
8 //
9 // Main authors: Fusseder Martin, Armin Geiser, Daniel Baumgaertner
10 //
11 
12 #pragma once
13 
14 // System includes
15 #include <iostream>
16 #include <string>
17 
18 // External includes
19 
20 // Project includes
21 #include "includes/define.h"
23 #include "includes/model_part.h"
26 
27 // ==============================================================================
28 
29 namespace Kratos
30 {
31 
34 
38 
42 
46 
50 
52 
56 //template<class TDenseSpace>
57 
59 {
60 public:
63 
66 
70 
73  : mrModelPart(model_part)
74  {
75  CheckSettingsForGradientAnalysis(response_settings);
76  DetermineTracedEigenfrequencies(response_settings);
78  {
79  KRATOS_ERROR_IF_NOT(response_settings.Has("weighting_method")) << "Several eigenfrequencies are traced but no weighting method specified in the parameters!" << std::endl;
80  if(response_settings["weighting_method"].GetString() == "linear_scaling")
81  CalculateLinearWeights(response_settings);
82  else
83  KRATOS_ERROR << "Specified weighting method for eigenfrequencies is not implemented! Available weighting methods are: 'linear_scaling'." << std::endl;
84  }
85  else
87  }
88 
91  {
92  }
93 
97 
101 
102  // ==============================================================================
103  void Initialize()
104  {
105  //not needed because only semi-analytical sensitivity analysis is implemented yet
106  }
107 
108  // --------------------------------------------------------------------------
109  double CalculateValue()
110  {
112 
113  double resp_function_value = 0.0;
114  KRATOS_INFO("EigenfrequencyResponseFunctionUtility") << "CalculateValue:" << std::endl
115  << " # Eigenfrequency [Hz] weighting factor" <<std::endl;
116  for(std::size_t i = 0; i < mTracedEigenfrequencyIds.size(); i++)
117  {
118  const double eigenfrequency = std::sqrt(GetEigenvalue(mTracedEigenfrequencyIds[i])) / (2*Globals::Pi);
119  resp_function_value += mWeightingFactors[i] * eigenfrequency;
120  std::stringstream msg;
121  msg << std::setw(5) << mTracedEigenfrequencyIds[i]
122  << std::setw(23) << eigenfrequency
123  << std::setw(20) << mWeightingFactors[i]<< std::endl;
124  KRATOS_INFO("") << msg.str();
125  }
126 
127  return resp_function_value;
128  }
129 
130  // --------------------------------------------------------------------------
132  {
134  VariableUtils().SetHistoricalVariableToZero(SHAPE_SENSITIVITY, mrModelPart.Nodes());
136  }
137 
138  // ==============================================================================
139 
143 
147 
151 
153  std::string Info() const
154  {
155  return "EigenfrequencyResponseFunctionUtility";
156  }
157 
159  virtual void PrintInfo(std::ostream &rOStream) const
160  {
161  rOStream << "EigenfrequencyResponseFunctionUtility";
162  }
163 
165  virtual void PrintData(std::ostream &rOStream) const
166  {
167  }
168 
172 
174 
175 protected:
178 
182 
186 
190 
191  // ==============================================================================
193  {
194  const std::string gradient_mode = rResponseSettings["gradient_mode"].GetString();
195 
196  if (gradient_mode == "semi_analytic")
197  mDelta = rResponseSettings["step_size"].GetDouble();
198  else
199  KRATOS_ERROR << "Specified gradient_mode '" << gradient_mode << "' not recognized. The only option is: semi_analytic" << std::endl;
200  }
201 
202  // --------------------------------------------------------------------------
204  {
205  mTracedEigenfrequencyIds.resize(rResponseSettings["traced_eigenfrequencies"].size(),false);
206  for(std::size_t i = 0; i < mTracedEigenfrequencyIds.size(); i++)
207  mTracedEigenfrequencyIds[i] = rResponseSettings["traced_eigenfrequencies"][i].GetInt();
208  }
209 
210  // --------------------------------------------------------------------------
212  {
213  return (mTracedEigenfrequencyIds.size()>1);
214  }
215 
216  // --------------------------------------------------------------------------
217  void CalculateLinearWeights(Parameters rResponseSettings)
218  {
219  KRATOS_ERROR_IF_NOT(rResponseSettings.Has("weighting_factors")) << "No weighting factors defined for given eigenfrequency response!" << std::endl;
220  KRATOS_ERROR_IF_NOT(rResponseSettings["weighting_factors"].size() == mTracedEigenfrequencyIds.size()) << "The number of chosen eigenvalues does not fit to the number of weighting factors!" << std::endl;
221 
222  mWeightingFactors.resize(rResponseSettings["weighting_factors"].size(),false);
223 
224  // Read weighting factors and sum them up
225  double test_sum_weight_facs = 0.0;
226  for(std::size_t i = 0; i < mWeightingFactors.size(); i++)
227  {
228  mWeightingFactors[i] = rResponseSettings["weighting_factors"][i].GetDouble();
229  test_sum_weight_facs += mWeightingFactors[i];
230  }
231 
232  // Check the weighting factors and modify them for the case that their sum is unequal to one
233  if(std::abs(test_sum_weight_facs - 1.0) > 1e-12)
234  {
235  for(std::size_t i = 0; i < mWeightingFactors.size(); i++)
236  mWeightingFactors[i] /= test_sum_weight_facs;
237 
238  KRATOS_INFO("\n> EigenfrequencyResponseFunctionUtility") << "The sum of the chosen weighting factors is unequal one. A corresponding scaling process was exected!" << std::endl;
239  }
240  }
241 
242  // --------------------------------------------------------------------------
244  {
245  mWeightingFactors.resize(1,false);
246  mWeightingFactors[0] = 1.0;
247  }
248 
249  // --------------------------------------------------------------------------
251  {
252  const int num_of_computed_eigenvalues = (mrModelPart.GetProcessInfo()[EIGENVALUE_VECTOR]).size();
253  const int max_required_eigenvalue = *(std::max_element(mTracedEigenfrequencyIds.begin(), mTracedEigenfrequencyIds.end()));
254  KRATOS_ERROR_IF(max_required_eigenvalue > num_of_computed_eigenvalues) << "The following Eigenfrequency shall be traced but their corresponding eigenvalue was not computed by the eigenvalue analysies: " << max_required_eigenvalue << std::endl;
255  }
256 
257  // --------------------------------------------------------------------------
259  {
260  const ProcessInfo &CurrentProcessInfo = mrModelPart.GetProcessInfo();
261 
262  // Predetermine all necessary eigenvalues and prefactors for gradient calculation
263  const std::size_t num_of_traced_eigenfrequencies = mTracedEigenfrequencyIds.size();
264  Vector traced_eigenvalues(num_of_traced_eigenfrequencies,0.0);
265  Vector gradient_prefactors(num_of_traced_eigenfrequencies,0.0);
266  for(std::size_t i = 0; i < num_of_traced_eigenfrequencies; i++)
267  {
268  traced_eigenvalues[i] = GetEigenvalue(mTracedEigenfrequencyIds[i]);
269  gradient_prefactors[i] = 1.0 / (4.0 * Globals::Pi * std::sqrt(traced_eigenvalues[i]));
270  }
271 
272  // Element-wise computation of gradients
273  for (auto& elem_i : mrModelPart.Elements())
274  {
275  Matrix LHS;
276  Matrix mass_matrix;
277  elem_i.CalculateLeftHandSide(LHS, CurrentProcessInfo);
278  elem_i.CalculateMassMatrix(mass_matrix, CurrentProcessInfo);
279 
280  const std::size_t num_dofs_element = mass_matrix.size1();
281  const std::size_t domain_size = CurrentProcessInfo.GetValue(DOMAIN_SIZE);
282 
283  Matrix aux_matrix = Matrix(num_dofs_element,num_dofs_element);
284  Vector aux_vector = Vector(num_dofs_element);
285 
286  // Predetermine the necessary eigenvectors
287  std::vector<Vector> eigenvectors_of_element(num_of_traced_eigenfrequencies,Vector(0));
288  for(std::size_t i = 0; i < num_of_traced_eigenfrequencies; i++)
289  DetermineEigenvectorOfElement(elem_i, mTracedEigenfrequencyIds[i], eigenvectors_of_element[i], CurrentProcessInfo);
290 
291  const std::vector<const FiniteDifferenceUtility::array_1d_component_type*> coord_directions = {&SHAPE_SENSITIVITY_X, &SHAPE_SENSITIVITY_Y, &SHAPE_SENSITIVITY_Z};
292 
293  // Computation of derivative of state equation w.r.t. node coordinates
294  for(auto& node_i : elem_i.GetGeometry())
295  {
296  Vector gradient_contribution(3, 0.0);
297  Matrix derived_LHS = Matrix(num_dofs_element,num_dofs_element);
298  Matrix derived_mass_matrix = Matrix(num_dofs_element,num_dofs_element);
299 
300  for(std::size_t coord_dir_i = 0; coord_dir_i < domain_size; coord_dir_i++)
301  {
302  FiniteDifferenceUtility::CalculateLeftHandSideDerivative(elem_i, LHS, *coord_directions[coord_dir_i], node_i, mDelta, derived_LHS, CurrentProcessInfo);
303  FiniteDifferenceUtility::CalculateMassMatrixDerivative(elem_i, mass_matrix, *coord_directions[coord_dir_i], node_i, mDelta, derived_mass_matrix, CurrentProcessInfo);
304 
305  for(std::size_t i = 0; i < num_of_traced_eigenfrequencies; i++)
306  {
307  aux_matrix.clear();
308  aux_vector.clear();
309 
310  noalias(aux_matrix) = derived_LHS - derived_mass_matrix * traced_eigenvalues[i];
311  noalias(aux_vector) = prod(aux_matrix , eigenvectors_of_element[i]);
312 
313  gradient_contribution[coord_dir_i] += gradient_prefactors[i] * inner_prod(eigenvectors_of_element[i] , aux_vector) * mWeightingFactors[i];
314  }
315  }
316  noalias(node_i.FastGetSolutionStepValue(SHAPE_SENSITIVITY)) += gradient_contribution;
317  }
318  }
319  }
320 
321  // --------------------------------------------------------------------------
322  double GetEigenvalue(const int eigenfrequency_id)
323  {
324  return (mrModelPart.GetProcessInfo()[EIGENVALUE_VECTOR])[eigenfrequency_id-1];
325  }
326 
327  // --------------------------------------------------------------------------
328  void DetermineEigenvectorOfElement(ModelPart::ElementType& rElement, const int eigenfrequency_id, Vector& rEigenvectorOfElement, const ProcessInfo& CurrentProcessInfo)
329  {
330  std::vector<std::size_t> eq_ids;
331  rElement.EquationIdVector(eq_ids, CurrentProcessInfo);
332 
333  if (rEigenvectorOfElement.size() != eq_ids.size())
334  {
335  rEigenvectorOfElement.resize(eq_ids.size(), false);
336  }
337 
338  // sort the values of the eigenvector into the rEigenvectorOfElement according to the dof ordering at the element
339  for (auto& r_node_i : rElement.GetGeometry())
340  {
341  const auto& r_node_dofs = r_node_i.GetDofs();
342 
343  const Matrix& rNodeEigenvectors = r_node_i.GetValue(EIGENVECTOR_MATRIX);
344  for (std::size_t dof_index = 0; dof_index < r_node_dofs.size(); dof_index++)
345  {
346  const auto& current_dof = *(std::begin(r_node_dofs) + dof_index);
347  const std::size_t dof_index_at_element = std::distance(eq_ids.begin(), std::find(eq_ids.begin(), eq_ids.end(), current_dof->EquationId()));
348  rEigenvectorOfElement(dof_index_at_element) = rNodeEigenvectors((eigenfrequency_id-1), dof_index);
349  }
350  }
351  }
352 
353  // ==============================================================================
354 
358 
362 
366 
368 
369 private:
372 
376 
377  ModelPart &mrModelPart;
378  double mDelta;
379  std::vector<int> mTracedEigenfrequencyIds;
380  std::vector<double> mWeightingFactors;
381 
385 
389 
393 
397 
401 
403  // EigenfrequencyResponseFunctionUtility& operator=(EigenfrequencyResponseFunctionUtility const& rOther);
404 
406  // EigenfrequencyResponseFunctionUtility(EigenfrequencyResponseFunctionUtility const& rOther);
407 
409 
410 }; // Class EigenfrequencyResponseFunctionUtility
411 
413 
416 
420 
422 
423 } // namespace Kratos.
TDataType & GetValue(const Variable< TDataType > &rThisVariable)
Gets the value associated with a given variable.
Definition: data_value_container.h:268
Short class definition.
Definition: eigenfrequency_response_function_utility.h:59
double GetEigenvalue(const int eigenfrequency_id)
Definition: eigenfrequency_response_function_utility.h:322
EigenfrequencyResponseFunctionUtility(ModelPart &model_part, Parameters response_settings)
Default constructor.
Definition: eigenfrequency_response_function_utility.h:72
void CheckIfAllNecessaryEigenvaluesAreComputed()
Definition: eigenfrequency_response_function_utility.h:250
double CalculateValue()
Definition: eigenfrequency_response_function_utility.h:109
void CalculateLinearWeights(Parameters rResponseSettings)
Definition: eigenfrequency_response_function_utility.h:217
void PerformSemiAnalyticSensitivityAnalysis()
Definition: eigenfrequency_response_function_utility.h:258
void Initialize()
Definition: eigenfrequency_response_function_utility.h:103
void CheckSettingsForGradientAnalysis(Parameters rResponseSettings)
Definition: eigenfrequency_response_function_utility.h:192
virtual void PrintData(std::ostream &rOStream) const
Print object's data.
Definition: eigenfrequency_response_function_utility.h:165
std::string Info() const
Turn back information as a string.
Definition: eigenfrequency_response_function_utility.h:153
virtual void PrintInfo(std::ostream &rOStream) const
Print information about this object.
Definition: eigenfrequency_response_function_utility.h:159
void CalculateGradient()
Definition: eigenfrequency_response_function_utility.h:131
void DetermineTracedEigenfrequencies(Parameters rResponseSettings)
Definition: eigenfrequency_response_function_utility.h:203
void UseDefaultWeight()
Definition: eigenfrequency_response_function_utility.h:243
bool AreSeveralEigenfrequenciesTraced()
Definition: eigenfrequency_response_function_utility.h:211
virtual ~EigenfrequencyResponseFunctionUtility()
Destructor.
Definition: eigenfrequency_response_function_utility.h:90
void DetermineEigenvectorOfElement(ModelPart::ElementType &rElement, const int eigenfrequency_id, Vector &rEigenvectorOfElement, const ProcessInfo &CurrentProcessInfo)
Definition: eigenfrequency_response_function_utility.h:328
KRATOS_CLASS_POINTER_DEFINITION(EigenfrequencyResponseFunctionUtility)
Pointer definition of EigenfrequencyResponseFunctionUtility.
Base class for all Elements.
Definition: element.h:60
virtual void EquationIdVector(EquationIdVectorType &rResult, const ProcessInfo &rCurrentProcessInfo) const
Definition: element.h:258
static void CalculateLeftHandSideDerivative(Element &rElement, const Matrix &rLHS, const array_1d_component_type &rDesignVariable, Node &rNode, const double &rPertubationSize, Matrix &rOutput, const ProcessInfo &rCurrentProcessInfo)
Definition: finite_difference_utility.cpp:68
static void CalculateMassMatrixDerivative(Element &rElement, const Matrix &rMassMatrix, const array_1d_component_type &rDesignVariable, Node &rNode, const double &rPertubationSize, Matrix &rOutput, const ProcessInfo &rCurrentProcessInfo)
Definition: finite_difference_utility.cpp:119
GeometryType & GetGeometry()
Returns the reference of the geometry.
Definition: geometrical_object.h:158
void resize(std::size_t NewSize1, std::size_t NewSize2, bool preserve=0)
Definition: amatrix_interface.h:224
void clear()
Definition: amatrix_interface.h:284
This class aims to manage meshes for multi-physics simulations.
Definition: model_part.h:77
ProcessInfo & GetProcessInfo()
Definition: model_part.h:1746
ElementsContainerType & Elements(IndexType ThisIndex=0)
Definition: model_part.h:1189
NodesContainerType & Nodes(IndexType ThisIndex=0)
Definition: model_part.h:507
This class provides to Kratos a data structure for I/O based on the standard of JSON.
Definition: kratos_parameters.h:59
double GetDouble() const
This method returns the double contained in the current Parameter.
Definition: kratos_parameters.cpp:657
std::string GetString() const
This method returns the string contained in the current Parameter.
Definition: kratos_parameters.cpp:684
bool Has(const std::string &rEntry) const
This method checks if the Parameter contains a certain entry.
Definition: kratos_parameters.cpp:520
ProcessInfo holds the current value of different solution parameters.
Definition: process_info.h:59
This class implements a set of auxiliar, already parallelized, methods to perform some common tasks r...
Definition: variable_utils.h:63
void SetHistoricalVariableToZero(const Variable< TType > &rVariable, NodesContainerType &rNodes)
Sets the nodal value of any variable to zero.
Definition: variable_utils.h:757
#define KRATOS_ERROR
Definition: exception.h:161
#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
constexpr double Pi
Definition: global_variables.h:25
REF: G. R. Cowper, GAUSSIAN QUADRATURE FORMULAS FOR TRIANGLES.
Definition: mesh_condition.cpp:21
Internals::Matrix< double, AMatrix::dynamic, 1 > Vector
Definition: amatrix_interface.h:472
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
TExpression1Type::data_type inner_prod(AMatrix::MatrixExpression< TExpression1Type, TCategory1 > const &First, AMatrix::MatrixExpression< TExpression2Type, TCategory2 > const &Second)
Definition: amatrix_interface.h:592
T & noalias(T &TheMatrix)
Definition: amatrix_interface.h:484
int domain_size
Definition: face_heat.py:4
model_part
Definition: face_heat.py:14
integer i
Definition: TensorModule.f:17
e
Definition: run_cpp_mpi_tests.py:31