www.mooseframework.org
RankTwoScalarTools.h
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
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 #pragma once
11 
12 // MOOSE includes
13 #include "MooseEnum.h"
14 #include "MooseTypes.h"
15 #include "libmesh/point.h"
16 #include "RankTwoTensor.h"
17 #include "MooseError.h"
18 
20 {
21 /*
22  * Return the scalar_type MooseEnum
23  */
24 MooseEnum scalarOptions();
25 
26 /*
27  * Extracts the value of the tensor component at the specified indices
28  */
29 template <typename T>
30 T
31 component(const RankTwoTensorTempl<T> & r2tensor, unsigned int i, unsigned int j)
32 {
33  return r2tensor(i, j);
34 }
35 
36 /*
37  * Extracts the value of the tensor component at the specified indices and
38  * updates the unit direction vector.
39  */
40 template <typename T>
41 T
42 component(const RankTwoTensorTempl<T> & r2tensor, unsigned int i, unsigned int j, Point & direction)
43 {
44  direction.zero();
45  if (i == j)
46  direction(i) = 1.0;
47  else
48  {
49  direction(i) = std::sqrt(0.5);
50  direction(j) = std::sqrt(0.5);
51  }
52 
53  return r2tensor(i, j);
54 }
55 
56 /*
57  * The von Mises Stress is calculated in the deviatoric stress space:
58  * \sigma_{vm} = \sqrt{\frac{3}{2}S_{ij}S_{ij}}
59  * This scalar quanitity is often used to determine the onset of plasticity by
60  * comparing the von Mises stress to the yield stress in J2 plasticity models.
61  */
62 template <typename T>
63 T
65 {
66  RankTwoTensorTempl<T> dev_stress = stress.deviatoric();
67 
68  return std::sqrt(1.5 * dev_stress.doubleContraction(dev_stress));
69 }
70 
71 /*
72  * The effective strain is calculated as
73  * \epsilon_{eff} = \sqrt{\frac{2}{3}\epsilon_{ij} \epsilon_{ij}}
74  */
75 template <typename T>
76 T
78 {
79  return std::sqrt(2.0 / 3.0 * strain.doubleContraction(strain));
80 }
81 
82 /*
83  * The hydrostatic scalar of a tensor is computed as the sum of the diagonal
84  * terms divided by 3.
85  */
86 template <typename T>
87 T
89 {
90  return r2tensor.trace() / 3.0;
91 }
92 
93 /*
94  * Computes the L2 normal of a rank two tensor
95  */
96 template <typename T>
97 T
98 L2norm(const RankTwoTensorTempl<T> & r2tensor)
99 {
100  return r2tensor.L2norm();
101 }
102 
103 /*
104  * The volumentric strain is the change in volume over the original volume. In
105  * this method the squared and cubic terms are included so that the calculation
106  * is valid for both small and finite strains.
107  * Since the strains are logarithmic strains, which are by definition log(L/L0),
108  * exp(log_strain) = L/L0
109  * The ratio of the volume change of a strained cube to the original volume
110  * (delta V / V) is thus:
111  * exp(log_strain_11) * exp(log_strain_22) * exp(log_strain_33) - 1
112  *
113  * Since eng_strain = exp(log_strain) - 1, the equivalent calculation using
114  * engineering strains would be:
115  * (1 + eng_strain_11) * (1 + eng_strain_22) + (1 + eng_strain_33) - 1
116  * If strains are small, the resulting terms that involve squared and cubed
117  * strains are negligible, resulting in the following approximate form:
118  * strain_11 + strain_22 + strain_33
119  * There is not currently an option to compute this small-strain form of the
120  * volumetric strain, but at small strains, it is approximately equal to the
121  * finite strain form that is computed.
122  *
123  * @param strain Total logarithmic strain
124  * @return volumetric strain (delta V / V)
125  */
126 template <typename T>
127 T
129 {
130  return std::exp(strain(0, 0)) * std::exp(strain(1, 1)) * std::exp(strain(2, 2)) - 1.0;
131 }
132 
133 /*
134  * The first invariant of a tensor is the sum of the diagonal component; defined
135  * in L. Malvern, Introduction to the Mechanics of a Continuous Mediam (1969) pg 89.
136  */
137 template <typename T>
138 T
140 {
141  return r2tensor.trace();
142 }
143 
144 /*
145  * The second invariant is calculated using the formula from K. Hjelmstad,
146  * Fundamentals of Structural Mechanics (1997) pg. 24.
147  * Note that the Hjelmstad version of the second invariant is the negative of
148  * the second invariant given in L. Malvern, Introduction to the Mechanics of a
149  * Continuous Medium (1969) pg 89.
150  */
151 template <typename T>
152 T
154 {
155  T val = 0.0;
156  for (unsigned int i = 0; i < 2; ++i)
157  for (unsigned int j = i + 1; j < 3; ++j)
158  {
159  val += r2tensor(i, i) * r2tensor(j, j);
160  val -= (r2tensor(i, j) * r2tensor(i, j) + r2tensor(j, i) * r2tensor(j, i)) * 0.5;
161  }
162 
163  return val;
164 }
165 
166 /*
167  * The third invariant of a rank 2 tensor is the determinate of the tensor; defined
168  * in L. Malvern, Introduction to the Mechanics of a Continuous Mediam (1969) pg 89.
169  */
170 template <typename T>
171 T
173 {
174  T val = 0.0;
175  val = r2tensor(0, 0) * r2tensor(1, 1) * r2tensor(2, 2) -
176  r2tensor(0, 0) * r2tensor(1, 2) * r2tensor(2, 1) +
177  r2tensor(0, 1) * r2tensor(1, 2) * r2tensor(2, 0) -
178  r2tensor(0, 1) * r2tensor(1, 0) * r2tensor(2, 2) +
179  r2tensor(0, 2) * r2tensor(1, 0) * r2tensor(2, 1) -
180  r2tensor(0, 2) * r2tensor(1, 1) * r2tensor(2, 0);
181 
182  return val;
183 }
184 
185 /*
186  * This method is called by the *Principal methods to calculate the eigenvalues
187  * and eigenvectors of a symmetric tensor and return the desired value based on
188  * vector position.
189  * param r2tensor The RankTwoTensor from which to extract eigenvalues/vectors
190  * param index The index of the principal value
191  * param direction The eigenvector corresponding to the computed eigenvalue
192  */
193 template <typename T>
194 T
196  unsigned int index,
197  Point & eigenvec)
198 {
199  std::vector<T> eigenval(LIBMESH_DIM);
200  RankTwoTensorTempl<T> eigvecs;
201  r2tensor.symmetricEigenvaluesEigenvectors(eigenval, eigvecs);
202 
203  T val = eigenval[index];
204  eigenvec = eigvecs.column(index);
205 
206  return val;
207 }
208 
209 /*
210  * The max Principal method returns the largest principal value for a symmetric
211  * tensor, using the calcEigenValues method.
212  * param r2tensor RankTwoTensor from which to extract the principal value
213  * param direction Direction corresponding to the principal value
214  */
215 template <typename T>
216 T
217 maxPrincipal(const RankTwoTensorTempl<T> & r2tensor, Point & direction)
218 {
219  return calcEigenValuesEigenVectors(r2tensor, (LIBMESH_DIM - 1), direction);
220 }
221 
222 /*
223  * The mid Principal method calculates the second largest principal value for a
224  * tensor.
225  * param r2tensor RankTwoTensor from which to extract the principal value
226  * param direction Direction corresponding to the principal value
227  */
228 template <typename T>
229 T
230 midPrincipal(const RankTwoTensorTempl<T> & r2tensor, Point & direction)
231 {
232  return calcEigenValuesEigenVectors(r2tensor, 1, direction);
233 }
234 
235 /*
236  * The min Principal stress returns the smallest principal value from a symmetric
237  * tensor.
238  * param r2tensor RankTwoTensor from which to extract the principal value
239  * param direction Direction corresponding to the principal value
240  */
241 template <typename T>
242 T
243 minPrincipal(const RankTwoTensorTempl<T> & r2tensor, Point & direction)
244 {
245  return calcEigenValuesEigenVectors(r2tensor, 0, direction);
246 }
247 
248 /*
249  * The axial stress is the scalar component of the stress tensor in an user-defined
250  * direction; the axis direction is specified by inputing two points.
251  * axial-stress = axis^T_i * \sigma_{ij} * axis_j
252  * @param point1 The starting point of the rotation axis for a cylinderical system
253  * @param point2 The end point of the rotation axis
254  * @param direction The direction vector in which the scalar stress value is calculated.
255  */
256 template <typename T>
257 T
259  const Point & point1,
260  const Point & point2,
261  Point & direction)
262 {
263  Point axis = point2 - point1;
264  axis /= axis.norm();
265 
266  // Calculate the stress in the direction of the axis specifed by the user
267  T axial_stress = 0.0;
268  for (unsigned int i = 0; i < 3; ++i)
269  for (unsigned int j = 0; j < 3; ++j)
270  axial_stress += axis(j) * stress(j, i) * axis(i);
271 
272  direction = axis;
273 
274  return axial_stress;
275 }
276 
277 /*
278  * This method is a helper method for the hoopStress and radialStress methods to
279  * calculate the unit position vector which is normal to the user supplied axis
280  * of rotation; the rotation axis direction is specified by inputing two points.
281  * @param point1 The starting point of the rotation axis for a cylinderical system
282  * @param point2 The end point of the rotation axis
283  * @param curr_point The point corresponding to the stress (pass in & _q_point[_qp])
284  * @param normalPosition The vector from the current point that is normal to the rotation axis
285  */
286 void normalPositionVector(const Point & point1,
287  const Point & point2,
288  const Point & curr_point,
289  Point & normalPosition);
290 
291 /*
292  * The hoop stress is calculated as
293  * hoop-stress = z^T_i * \sigma_{ij} * z_j
294  * where z is defined as the cross of the user-defined (via input points) axis
295  * of rotation and the normal from the current position to the axis of rotation.
296  * @param point1 The starting point of the rotation axis for a cylinderical system
297  * @param point2 The end point of the rotation axis
298  * @param curr_point The point corresponding to the stress (pass in & _q_point[_qp])
299  * @param direction The direction vector in which the scalar stress value is calculated.
300  */
301 template <typename T>
302 T
304  const Point & point1,
305  const Point & point2,
306  const Point & curr_point,
307  Point & direction)
308 {
309  // Calculate the cross of the normal to the axis of rotation from the current
310  // location and the axis of rotation
311  Point xp;
312  normalPositionVector(point1, point2, curr_point, xp);
313  Point axis_rotation = point2 - point1;
314  Point yp = axis_rotation / axis_rotation.norm();
315  Point zp = xp.cross(yp);
316 
317  // Calculate the scalar value of the hoop stress
318  T hoop_stress = 0.0;
319  for (unsigned int i = 0; i < 3; ++i)
320  for (unsigned int j = 0; j < 3; ++j)
321  hoop_stress += zp(j) * stress(j, i) * zp(i);
322 
323  direction = zp;
324 
325  return hoop_stress;
326 }
327 
328 /* The radial stress is calculated as
329  * radial_stress = normal^T_i * \sigma_{ij} * normal_j
330  * where normal is the position vector of the current point that is normal to
331  * the user-defined axis of rotation; the axis direction is specified with two points.
332  * @param point1 The starting point of the rotation axis for a cylinderical system
333  * @param point2 The end point of the rotation axis
334  * @param curr_point The point corresponding to the stress (pass in & _q_point[_qp])
335  * @param direction The direction vector in which the scalar stress value is calculated.
336  */
337 template <typename T>
338 T
340  const Point & point1,
341  const Point & point2,
342  const Point & curr_point,
343  Point & direction)
344 {
345  Point radial_norm;
346  normalPositionVector(point1, point2, curr_point, radial_norm);
347 
348  // Compute the scalar stress component in the direction of the normal vector from the
349  // user-defined axis of rotation.
350  T radial_stress = 0.0;
351  for (unsigned int i = 0; i < 3; ++i)
352  for (unsigned int j = 0; j < 3; ++j)
353  radial_stress += radial_norm(j) * stress(j, i) * radial_norm(i);
354 
355  direction = radial_norm;
356 
357  return radial_stress;
358 }
359 
360 /*
361  * This method calculates the scalar value of the supplied rank-2 tensor in the
362  * direction specified by the user.
363  */
364 template <typename T>
365 T
366 directionValueTensor(const RankTwoTensorTempl<T> & r2tensor, Point & direction)
367 {
368  T tensor_value_in_direction = 0.0;
369  for (unsigned int i = 0; i < 3; ++i)
370  for (unsigned int j = 0; j < 3; ++j)
371  tensor_value_in_direction += direction(j) * r2tensor(j, i) * direction(i);
372 
373  return tensor_value_in_direction;
374 }
375 
376 /*
377  * Triaxiality is the ratio of the hydrostatic stress to the von Mises stress.
378  */
379 template <typename T>
380 T
382 {
383  return hydrostatic(stress) / vonMisesStress(stress);
384 }
385 
386 /*
387  * maxShear is the maximum shear stress defined as the maximum principal
388  * stress minus the minimum principal stress.
389  */
390 template <typename T>
391 T
393 {
394  Point dummy;
395  return (maxPrincipal(stress, dummy) - minPrincipal(stress, dummy)) / 2.;
396 }
397 /*
398  * stressIntensity is defined as two times the maximum shear stress.
399  */
400 template <typename T>
401 T
403 {
404  return 2. * maxShear(stress);
405 }
406 
407 /*
408  * Return scalar quantity of a rank two tensor based on the user specified scalar_type
409  * @param point1 The starting point of the rotation axis for a cylinderical system
410  * @param point2 The end point of the rotation axis
411  * @param curr_point The point corresponding to the stress (pass in & _q_point[_qp])
412  * @param direction The direction vector in which the scalar stress value is calculated
413  * point1 and point2 are required only for the cases of axialStress, hoopStress and radialStress
414  * curr_point is required only for the cases of hoopStress and radialStress
415  * direction is required only for directionValueTensor
416  * for all other cases, these parameters will take the default values
417  */
418 template <typename T>
419 T
421  const MooseEnum & scalar_type,
422  const Point & point1,
423  const Point & point2,
424  const Point & curr_point,
425  Point & direction)
426 {
427  switch (scalar_type)
428  {
429  case 0:
430  return vonMisesStress(tensor);
431  case 1:
432  return effectiveStrain(tensor);
433  case 2:
434  return hydrostatic(tensor);
435  case 3:
436  return L2norm(tensor);
437  case 4:
438  return maxPrincipal(tensor, direction);
439  case 5:
440  return midPrincipal(tensor, direction);
441  case 6:
442  return minPrincipal(tensor, direction);
443  case 7:
444  return volumetricStrain(tensor);
445  case 8:
446  return firstInvariant(tensor);
447  case 9:
448  return secondInvariant(tensor);
449  case 10:
450  return thirdInvariant(tensor);
451  case 11:
452  return axialStress(tensor, point1, point2, direction);
453  case 12:
454  return hoopStress(tensor, point1, point2, curr_point, direction);
455  case 13:
456  return radialStress(tensor, point1, point2, curr_point, direction);
457  case 14:
458  return triaxialityStress(tensor);
459  case 15:
460  return directionValueTensor(tensor, direction);
461  case 16:
462  return maxShear(tensor);
463  case 17:
464  return stressIntensity(tensor);
465  default:
466  mooseError("RankTwoScalarAux Error: Pass valid scalar type - " +
467  scalarOptions().getRawNames());
468  }
469 }
470 }
RankTwoScalarTools::firstInvariant
T firstInvariant(const RankTwoTensorTempl< T > &r2tensor)
Definition: RankTwoScalarTools.h:139
RankTwoScalarTools::hydrostatic
T hydrostatic(const RankTwoTensorTempl< T > &r2tensor)
Definition: RankTwoScalarTools.h:88
RankTwoScalarTools::triaxialityStress
T triaxialityStress(const RankTwoTensorTempl< T > &stress)
Definition: RankTwoScalarTools.h:381
RankTwoScalarTools::effectiveStrain
T effectiveStrain(const RankTwoTensorTempl< T > &strain)
Definition: RankTwoScalarTools.h:77
RankTwoScalarTools
Definition: RankTwoScalarTools.h:19
RankTwoScalarTools::maxShear
T maxShear(const RankTwoTensorTempl< T > &stress)
Definition: RankTwoScalarTools.h:392
RankTwoScalarTools::radialStress
T radialStress(const RankTwoTensorTempl< T > &stress, const Point &point1, const Point &point2, const Point &curr_point, Point &direction)
Definition: RankTwoScalarTools.h:339
RankTwoScalarTools::axialStress
T axialStress(const RankTwoTensorTempl< T > &stress, const Point &point1, const Point &point2, Point &direction)
Definition: RankTwoScalarTools.h:258
RankTwoScalarTools::secondInvariant
T secondInvariant(const RankTwoTensorTempl< T > &r2tensor)
Definition: RankTwoScalarTools.h:153
RankTwoScalarTools::normalPositionVector
void normalPositionVector(const Point &point1, const Point &point2, const Point &curr_point, Point &normalPosition)
Definition: RankTwoScalarTools.C:25
RankTwoScalarTools::getQuantity
T getQuantity(const RankTwoTensorTempl< T > &tensor, const MooseEnum &scalar_type, const Point &point1, const Point &point2, const Point &curr_point, Point &direction)
Definition: RankTwoScalarTools.h:420
RankTwoScalarTools::midPrincipal
T midPrincipal(const RankTwoTensorTempl< T > &r2tensor, Point &direction)
Definition: RankTwoScalarTools.h:230
RankTwoScalarTools::hoopStress
T hoopStress(const RankTwoTensorTempl< T > &stress, const Point &point1, const Point &point2, const Point &curr_point, Point &direction)
Definition: RankTwoScalarTools.h:303
RankTwoScalarTools::directionValueTensor
T directionValueTensor(const RankTwoTensorTempl< T > &r2tensor, Point &direction)
Definition: RankTwoScalarTools.h:366
RankTwoScalarTools::component
T component(const RankTwoTensorTempl< T > &r2tensor, unsigned int i, unsigned int j)
Definition: RankTwoScalarTools.h:31
RankTwoScalarTools::maxPrincipal
T maxPrincipal(const RankTwoTensorTempl< T > &r2tensor, Point &direction)
Definition: RankTwoScalarTools.h:217
RankTwoScalarTools::thirdInvariant
T thirdInvariant(const RankTwoTensorTempl< T > &r2tensor)
Definition: RankTwoScalarTools.h:172
RankTwoScalarTools::calcEigenValuesEigenVectors
T calcEigenValuesEigenVectors(const RankTwoTensorTempl< T > &r2tensor, unsigned int index, Point &eigenvec)
Definition: RankTwoScalarTools.h:195
RankTwoScalarTools::stressIntensity
T stressIntensity(const RankTwoTensorTempl< T > &stress)
Definition: RankTwoScalarTools.h:402
RankTwoScalarTools::volumetricStrain
T volumetricStrain(const RankTwoTensorTempl< T > &strain)
Definition: RankTwoScalarTools.h:128
RankTwoScalarTools::vonMisesStress
T vonMisesStress(const RankTwoTensorTempl< T > &stress)
Definition: RankTwoScalarTools.h:64
RankTwoTensorTempl
Definition: ACGrGrElasticDrivingForce.h:17
RankTwoScalarTools::scalarOptions
MooseEnum scalarOptions()
Definition: RankTwoScalarTools.C:16
RankTwoScalarTools::L2norm
T L2norm(const RankTwoTensorTempl< T > &r2tensor)
Definition: RankTwoScalarTools.h:98
RankTwoScalarTools::minPrincipal
T minPrincipal(const RankTwoTensorTempl< T > &r2tensor, Point &direction)
Definition: RankTwoScalarTools.h:243