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.
strain_energy_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: Baumgaertner Daniel, https://github.com/dbaumgaertner
10 // Geiser Armin, https://github.com/armingeiser
11 //
12 
13 #pragma once
14 
15 // System includes
16 #include <iostream>
17 #include <string>
18 
19 // External includes
20 
21 // Project includes
22 #include "includes/define.h"
24 #include "includes/model_part.h"
28 
29 // ==============================================================================
30 
31 namespace Kratos
32 {
33 
36 
40 
44 
48 
52 
54 
59 {
60 public:
63 
65 
68 
72 
75  : mrModelPart(model_part)
76  {
77  // Set gradient mode
78  std::string gradient_mode = responseSettings["gradient_mode"].GetString();
79 
80  if (gradient_mode.compare("semi_analytic") == 0)
81  {
82  double delta = responseSettings["step_size"].GetDouble();
83  mDelta = delta;
84  }
85  else
86  KRATOS_ERROR << "Specified gradient_mode '" << gradient_mode << "' not recognized. The only option is: semi_analytic" << std::endl;
87 
88  }
89 
92  {
93  }
94 
98 
102 
103  // ==============================================================================
104  void Initialize()
105  {
106  }
107 
108  // --------------------------------------------------------------------------
109  double CalculateValue()
110  {
111  KRATOS_TRY;
112 
113  const ProcessInfo &CurrentProcessInfo = mrModelPart.GetProcessInfo();
114  double strain_energy = 0.0;
115 
116  // Sum all elemental strain energy values calculated as: W_e = u_e^T K_e u_e
117  for (auto& elem_i : mrModelPart.Elements())
118  {
119  const bool element_is_active = elem_i.IsDefined(ACTIVE) ? elem_i.Is(ACTIVE) : true;
120  if(element_is_active)
121  {
122  Matrix LHS;
123  Vector RHS;
124  Vector u;
125 
126  // Get state solution relevant for energy calculation
127  const auto& rConstElemRef = elem_i;
128  rConstElemRef.GetValuesVector(u,0);
129 
130  elem_i.CalculateLocalSystem(LHS,RHS,CurrentProcessInfo);
131 
132  // Compute strain energy
133  strain_energy += 0.5 * inner_prod(u,prod(LHS,u));
134  }
135  }
136 
137  return strain_energy;
138 
139  KRATOS_CATCH("");
140  }
141 
142  // --------------------------------------------------------------------------
144  {
145  KRATOS_TRY;
146 
147  // Formula computed in general notation:
148  // \frac{dF}{dx} = \frac{\partial F}{\partial x}
149  // - \lambda^T \frac{\partial R_S}{\partial x}
150 
151  // Adjoint variable:
152  // \lambda = \frac{1}{2} u^T
153 
154  // Correspondingly in specific notation for given response function
155  // \frac{dF}{dx} = \frac{1}{2} u^T \cdot \frac{\partial f_{ext}}{\partial x}
156  // + \frac{1}{2} u^T \cdot ( \frac{\partial f_{ext}}{\partial x} - \frac{\partial K}{\partial x} )
157 
158  // First gradients are initialized
159  VariableUtils().SetHistoricalVariableToZero(SHAPE_SENSITIVITY, mrModelPart.Nodes());
160 
161 
162  // Gradient calculation
163  // 1st step: Calculate partial derivative of response function w.r.t. node coordinates
164  // 2nd step: Calculate adjoint field
165  // 3rd step: Calculate partial derivative of state equation w.r.t. node coordinates and multiply with adjoint field
166 
167  // Semi analytic sensitivities
171 
172  KRATOS_CATCH("");
173  }
174 
175  // ==============================================================================
176 
180 
184 
188 
190  std::string Info() const
191  {
192  return "StrainEnergyResponseFunctionUtility";
193  }
194 
196  virtual void PrintInfo(std::ostream &rOStream) const
197  {
198  rOStream << "StrainEnergyResponseFunctionUtility";
199  }
200 
202  virtual void PrintData(std::ostream &rOStream) const
203  {
204  }
205 
209 
211 
212 protected:
215 
219 
223 
227 
228  // ==============================================================================
230  {
231  KRATOS_TRY;
232 
233  // Adjoint field may be directly obtained from state solution
234 
235  KRATOS_CATCH("");
236  }
237 
238  // --------------------------------------------------------------------------
240  {
241  KRATOS_TRY;
242 
243  // Working variables
244  const ProcessInfo &CurrentProcessInfo = mrModelPart.GetProcessInfo();
245 
246  // Computation of: \frac{1}{2} u^T \cdot ( - \frac{\partial K}{\partial x} )
247  for (auto& elem_i : mrModelPart.Elements())
248  {
249  const bool element_is_active = elem_i.IsDefined(ACTIVE) ? elem_i.Is(ACTIVE) : true;
250  if(element_is_active)
251  {
252  Vector u;
253  Vector lambda;
254  Vector RHS;
255 
256  // Get state solution
257  const auto& rConstElemRef = elem_i;
258  rConstElemRef.GetValuesVector(u,0);
259 
260  // Get adjoint variables (Corresponds to 1/2*u)
261  lambda = 0.5*u;
262 
263  // Semi-analytic computation of partial derivative of state equation w.r.t. node coordinates
264  elem_i.CalculateRightHandSide(RHS, CurrentProcessInfo);
265  for (auto& node_i : elem_i.GetGeometry())
266  {
267  array_3d gradient_contribution(3, 0.0);
268  Vector derived_RHS = Vector(0);
269 
270  // x-direction
271  FiniteDifferenceUtility::CalculateRightHandSideDerivative(elem_i, RHS, SHAPE_SENSITIVITY_X, node_i, mDelta, derived_RHS, CurrentProcessInfo);
272  gradient_contribution[0] = inner_prod(lambda, derived_RHS);
273 
274  // y-direction
275  FiniteDifferenceUtility::CalculateRightHandSideDerivative(elem_i, RHS, SHAPE_SENSITIVITY_Y, node_i, mDelta, derived_RHS, CurrentProcessInfo);
276  gradient_contribution[1] = inner_prod(lambda, derived_RHS);
277 
278  // z-direction
279  FiniteDifferenceUtility::CalculateRightHandSideDerivative(elem_i, RHS, SHAPE_SENSITIVITY_Z, node_i, mDelta, derived_RHS, CurrentProcessInfo);
280  gradient_contribution[2] = inner_prod(lambda, derived_RHS);
281 
282  // Assemble sensitivity to node
283  noalias(node_i.FastGetSolutionStepValue(SHAPE_SENSITIVITY)) += gradient_contribution;
284  }
285  }
286  }
287 
288  // Computation of \frac{1}{2} u^T \cdot ( \frac{\partial f_{ext}}{\partial x} )
289  for (auto& cond_i : mrModelPart.Conditions())
290  {
291  //detect if the condition is active or not. If the user did not make any choice the element
292  //is active by default
293  const bool condition_is_active = cond_i.IsDefined(ACTIVE) ? cond_i.Is(ACTIVE) : true;
294  if (condition_is_active)
295  {
296  Vector u;
297  Vector lambda;
298  Vector RHS;
299 
300  // Get adjoint variables (Corresponds to 1/2*u)
301  const auto& rConstCondRef = cond_i;
302  rConstCondRef.GetValuesVector(u,0);
303  lambda = 0.5*u;
304 
305  // Semi-analytic computation of partial derivative of force vector w.r.t. node coordinates
306  cond_i.CalculateRightHandSide(RHS, CurrentProcessInfo);
307  for (auto& node_i : cond_i.GetGeometry())
308  {
309  array_3d gradient_contribution(3, 0.0);
310  Vector perturbed_RHS = Vector(0);
311 
312  // Pertubation, gradient analysis and recovery of x
313  node_i.X0() += mDelta;
314  cond_i.CalculateRightHandSide(perturbed_RHS, CurrentProcessInfo);
315  gradient_contribution[0] = inner_prod(lambda, (perturbed_RHS - RHS) / mDelta);
316  node_i.X0() -= mDelta;
317 
318  // Reset pertubed vector
319  perturbed_RHS = Vector(0);
320 
321  // Pertubation, gradient analysis and recovery of y
322  node_i.Y0() += mDelta;
323  cond_i.CalculateRightHandSide(perturbed_RHS, CurrentProcessInfo);
324  gradient_contribution[1] = inner_prod(lambda, (perturbed_RHS - RHS) / mDelta);
325  node_i.Y0() -= mDelta;
326 
327  // Reset pertubed vector
328  perturbed_RHS = Vector(0);
329 
330  // Pertubation, gradient analysis and recovery of z
331  node_i.Z0() += mDelta;
332  cond_i.CalculateRightHandSide(perturbed_RHS, CurrentProcessInfo);
333  gradient_contribution[2] = inner_prod(lambda, (perturbed_RHS - RHS) / mDelta);
334  node_i.Z0() -= mDelta;
335 
336  // Assemble shape gradient to node
337  noalias(node_i.FastGetSolutionStepValue(SHAPE_SENSITIVITY)) += gradient_contribution;
338  }
339  }
340  }
341 
342  KRATOS_CATCH("");
343  }
344 
345  // --------------------------------------------------------------------------
347  {
348  KRATOS_TRY;
349 
350  // Working variables
351  const ProcessInfo &CurrentProcessInfo = mrModelPart.GetProcessInfo();
352 
353  // Computation of \frac{1}{2} u^T \cdot ( \frac{\partial f_{ext}}{\partial x} )
354  for (auto& cond_i : mrModelPart.Conditions())
355  {
356  //detect if the condition is active or not. If the user did not make any choice the element
357  //is active by default
358  const bool condition_is_active = cond_i.IsDefined(ACTIVE) ? cond_i.Is(ACTIVE) : true;
359  if (condition_is_active)
360  {
361  Vector u;
362  Vector RHS;
363 
364  // Get state solution
365  const auto& rConstCondRef = cond_i;
366  rConstCondRef.GetValuesVector(u,0);
367 
368  // Perform finite differencing of RHS vector
369  cond_i.CalculateRightHandSide(RHS, CurrentProcessInfo);
370  for (auto& node_i : cond_i.GetGeometry())
371  {
372  array_3d gradient_contribution(3, 0.0);
373  Vector perturbed_RHS = Vector(0);
374 
375  // Pertubation, gradient analysis and recovery of x
376  node_i.X0() += mDelta;
377  cond_i.CalculateRightHandSide(perturbed_RHS, CurrentProcessInfo);
378  gradient_contribution[0] = inner_prod(0.5*u, (perturbed_RHS - RHS) / mDelta);
379  node_i.X0() -= mDelta;
380 
381  // Reset pertubed vector
382  perturbed_RHS = Vector(0);
383 
384  // Pertubation, gradient analysis and recovery of y
385  node_i.Y0() += mDelta;
386  cond_i.CalculateRightHandSide(perturbed_RHS, CurrentProcessInfo);
387  gradient_contribution[1] = inner_prod(0.5*u, (perturbed_RHS - RHS) / mDelta);
388  node_i.Y0() -= mDelta;
389 
390  // Reset pertubed vector
391  perturbed_RHS = Vector(0);
392 
393  // Pertubation, gradient analysis and recovery of z
394  node_i.Z0() += mDelta;
395  cond_i.CalculateRightHandSide(perturbed_RHS, CurrentProcessInfo);
396  gradient_contribution[2] = inner_prod(0.5*u, (perturbed_RHS - RHS) / mDelta);
397  node_i.Z0() -= mDelta;
398 
399  // Assemble shape gradient to node
400  noalias(node_i.FastGetSolutionStepValue(SHAPE_SENSITIVITY)) += gradient_contribution;
401  }
402  }
403  }
404  KRATOS_CATCH("");
405  }
406 
407  // ==============================================================================
408 
412 
416 
420 
422 
423 private:
426 
430 
431  ModelPart &mrModelPart;
432  double mDelta;
433 
437 
441 
445 
449 
453 
455  // StrainEnergyResponseFunctionUtility& operator=(StrainEnergyResponseFunctionUtility const& rOther);
456 
458  // StrainEnergyResponseFunctionUtility(StrainEnergyResponseFunctionUtility const& rOther);
459 
461 
462 }; // Class StrainEnergyResponseFunctionUtility
463 
465 
468 
472 
474 
475 } // namespace Kratos.
static void CalculateRightHandSideDerivative(Element &rElement, const Vector &rRHS, const Variable< double > &rDesignVariable, const double &rPertubationSize, Matrix &rOutput, const ProcessInfo &rCurrentProcessInfo)
Definition: finite_difference_utility.cpp:22
bool IsDefined(Flags const &rOther) const
Definition: flags.h:279
This class aims to manage meshes for multi-physics simulations.
Definition: model_part.h:77
ConditionsContainerType & Conditions(IndexType ThisIndex=0)
Definition: model_part.h:1381
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
ProcessInfo holds the current value of different solution parameters.
Definition: process_info.h:59
Short class definition.
Definition: strain_energy_response_function_utility.h:59
double CalculateValue()
Definition: strain_energy_response_function_utility.h:109
KRATOS_CLASS_POINTER_DEFINITION(StrainEnergyResponseFunctionUtility)
Pointer definition of StrainEnergyResponseFunctionUtility.
void CalculateGradient()
Definition: strain_energy_response_function_utility.h:143
virtual void PrintInfo(std::ostream &rOStream) const
Print information about this object.
Definition: strain_energy_response_function_utility.h:196
void CalculateStateDerivativePartByFiniteDifferencing()
Definition: strain_energy_response_function_utility.h:239
virtual void PrintData(std::ostream &rOStream) const
Print object's data.
Definition: strain_energy_response_function_utility.h:202
void CalculateResponseDerivativePartByFiniteDifferencing()
Definition: strain_energy_response_function_utility.h:346
std::string Info() const
Turn back information as a string.
Definition: strain_energy_response_function_utility.h:190
void Initialize()
Definition: strain_energy_response_function_utility.h:104
virtual ~StrainEnergyResponseFunctionUtility()
Destructor.
Definition: strain_energy_response_function_utility.h:91
void CalculateAdjointField()
Definition: strain_energy_response_function_utility.h:229
StrainEnergyResponseFunctionUtility(ModelPart &model_part, Parameters responseSettings)
Default constructor.
Definition: strain_energy_response_function_utility.h:74
array_1d< double, 3 > array_3d
Definition: strain_energy_response_function_utility.h:64
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_CATCH(MoreInfo)
Definition: define.h:110
#define KRATOS_TRY
Definition: define.h:109
#define KRATOS_ERROR
Definition: exception.h:161
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
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
model_part
Definition: face_heat.py:14
u
Definition: generate_total_lagrangian_mixed_volumetric_strain_element.py:30
double precision, dimension(3, 3), public delta
Definition: TensorModule.f:16