Line data Source code
1 : //* This file is part of the MOOSE framework
2 : //* https://mooseframework.inl.gov
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 : #include "MooseUtils.h"
19 :
20 : namespace RankTwoScalarTools
21 : {
22 : /*
23 : * Return the scalar_type MooseEnum
24 : */
25 : MooseEnum scalarOptions();
26 :
27 : MooseEnum invariantOptions();
28 : MooseEnum cylindricalOptions();
29 : MooseEnum sphericalOptions();
30 :
31 : enum class InvariantType
32 : {
33 : VonMisesStress,
34 : EffectiveStrain,
35 : Hydrostatic,
36 : L2norm,
37 : VolumetricStrain,
38 : FirstInvariant,
39 : SecondInvariant,
40 : ThirdInvariant,
41 : TriaxialityStress,
42 : MaxShear,
43 : StressIntensity,
44 : MaxPrincipal,
45 : MidPrincipal,
46 : MinPrincipal
47 : };
48 :
49 : enum class CylindricalComponent
50 : {
51 : AxialStress,
52 : HoopStress,
53 : RadialStress
54 : };
55 :
56 : enum class SphericalComponent
57 : {
58 : HoopStress,
59 : RadialStress
60 : };
61 :
62 : /*
63 : * Extracts the value of the tensor component at the specified indices
64 : */
65 : template <typename T>
66 : T
67 : component(const RankTwoTensorTempl<T> & r2tensor, unsigned int i, unsigned int j)
68 : {
69 315211944 : return r2tensor(i, j);
70 : }
71 :
72 : /*
73 : * Extracts the value of the tensor component at the specified indices and
74 : * updates the unit direction vector.
75 : */
76 : template <typename T>
77 : T
78 : component(const RankTwoTensorTempl<T> & r2tensor, unsigned int i, unsigned int j, Point & direction)
79 : {
80 : direction.zero();
81 : if (i == j)
82 : direction(i) = 1.0;
83 : else
84 : {
85 : direction(i) = std::sqrt(0.5);
86 : direction(j) = std::sqrt(0.5);
87 : }
88 :
89 : return r2tensor(i, j);
90 : }
91 :
92 : /*
93 : * The von Mises Stress is calculated in the deviatoric stress space:
94 : * \sigma_{vm} = \sqrt{\frac{3}{2}S_{ij}S_{ij}}
95 : * This scalar quanitity is often used to determine the onset of plasticity by
96 : * comparing the von Mises stress to the yield stress in J2 plasticity models.
97 : */
98 : template <typename T>
99 : T
100 34927146 : vonMisesStress(const RankTwoTensorTempl<T> & stress)
101 : {
102 34927146 : RankTwoTensorTempl<T> dev_stress = stress.deviatoric();
103 :
104 34927146 : return std::sqrt(1.5 * dev_stress.doubleContraction(dev_stress));
105 : }
106 :
107 : /*
108 : * The effective strain increment (or equivalent von Mises strain) is calculated as
109 : * \epsilon_{eff} = \sqrt{\frac{2}{3}\epsilon_{ij} \epsilon_{ij}}
110 : */
111 : template <typename T>
112 : T
113 768 : effectiveStrain(const RankTwoTensorTempl<T> & strain)
114 : {
115 768 : return std::sqrt(2.0 / 3.0 * strain.doubleContraction(strain));
116 : }
117 :
118 : /*
119 : * The hydrostatic scalar of a tensor is computed as the sum of the diagonal
120 : * terms divided by 3.
121 : */
122 : template <typename T>
123 : T
124 : hydrostatic(const RankTwoTensorTempl<T> & r2tensor)
125 : {
126 12755726 : return r2tensor.trace() / 3.0;
127 : }
128 :
129 : /*
130 : * Computes the L2 normal of a rank two tensor
131 : */
132 : template <typename T>
133 : T
134 : L2norm(const RankTwoTensorTempl<T> & r2tensor)
135 : {
136 3520 : return r2tensor.L2norm();
137 : }
138 :
139 : /*
140 : * The volumentric strain is the change in volume over the original volume. In
141 : * this method the squared and cubic terms are included so that the calculation
142 : * is valid for both small and finite strains.
143 : * Since the strains are logarithmic strains, which are by definition log(L/L0),
144 : * exp(log_strain) = L/L0
145 : * The ratio of the volume change of a strained cube to the original volume
146 : * (delta V / V) is thus:
147 : * exp(log_strain_11) * exp(log_strain_22) * exp(log_strain_33) - 1
148 : *
149 : * Since eng_strain = exp(log_strain) - 1, the equivalent calculation using
150 : * engineering strains would be:
151 : * (1 + eng_strain_11) * (1 + eng_strain_22) + (1 + eng_strain_33) - 1
152 : * If strains are small, the resulting terms that involve squared and cubed
153 : * strains are negligible, resulting in the following approximate form:
154 : * strain_11 + strain_22 + strain_33
155 : * There is not currently an option to compute this small-strain form of the
156 : * volumetric strain, but at small strains, it is approximately equal to the
157 : * finite strain form that is computed.
158 : *
159 : * @param strain Total logarithmic strain
160 : * @return volumetric strain (delta V / V)
161 : */
162 : template <typename T>
163 : T
164 2304 : volumetricStrain(const RankTwoTensorTempl<T> & strain)
165 : {
166 2304 : return std::exp(strain(0, 0)) * std::exp(strain(1, 1)) * std::exp(strain(2, 2)) - 1.0;
167 : }
168 :
169 : /*
170 : * The first invariant of a tensor is the sum of the diagonal component; defined
171 : * in L. Malvern, Introduction to the Mechanics of a Continuous Mediam (1969) pg 89.
172 : */
173 : template <typename T>
174 : T
175 : firstInvariant(const RankTwoTensorTempl<T> & r2tensor)
176 : {
177 64022 : return r2tensor.trace();
178 : }
179 :
180 : /*
181 : * The second invariant is calculated using the formula from K. Hjelmstad,
182 : * Fundamentals of Structural Mechanics (1997) pg. 24.
183 : * Note that the Hjelmstad version of the second invariant is the negative of
184 : * the second invariant given in L. Malvern, Introduction to the Mechanics of a
185 : * Continuous Medium (1969) pg 89.
186 : */
187 : template <typename T>
188 : T
189 64022 : secondInvariant(const RankTwoTensorTempl<T> & r2tensor)
190 : {
191 : T val = 0.0;
192 192066 : for (unsigned int i = 0; i < 2; ++i)
193 320110 : for (unsigned int j = i + 1; j < 3; ++j)
194 : {
195 192066 : val += r2tensor(i, i) * r2tensor(j, j);
196 192066 : val -= (r2tensor(i, j) * r2tensor(i, j) + r2tensor(j, i) * r2tensor(j, i)) * 0.5;
197 : }
198 :
199 64022 : return val;
200 : }
201 :
202 : /*
203 : * The third invariant of a rank 2 tensor is the determinate of the tensor; defined
204 : * in L. Malvern, Introduction to the Mechanics of a Continuous Mediam (1969) pg 89.
205 : */
206 : template <typename T>
207 : T
208 86678 : thirdInvariant(const RankTwoTensorTempl<T> & r2tensor)
209 : {
210 : T val = 0.0;
211 86678 : val = r2tensor(0, 0) * r2tensor(1, 1) * r2tensor(2, 2) -
212 86678 : r2tensor(0, 0) * r2tensor(1, 2) * r2tensor(2, 1) +
213 86678 : r2tensor(0, 1) * r2tensor(1, 2) * r2tensor(2, 0) -
214 86678 : r2tensor(0, 1) * r2tensor(1, 0) * r2tensor(2, 2) +
215 86678 : r2tensor(0, 2) * r2tensor(1, 0) * r2tensor(2, 1) -
216 86678 : r2tensor(0, 2) * r2tensor(1, 1) * r2tensor(2, 0);
217 :
218 86678 : return val;
219 : }
220 :
221 : /*
222 : * This method is called by the *Principal methods to calculate the eigenvalues
223 : * and eigenvectors of a symmetric tensor and return the desired value based on
224 : * vector position.
225 : * param r2tensor The RankTwoTensor from which to extract eigenvalues/vectors
226 : * param index The index of the principal value
227 : * param direction The eigenvector corresponding to the computed eigenvalue
228 : */
229 : template <typename T>
230 : T
231 1087953 : calcEigenValuesEigenVectors(const RankTwoTensorTempl<T> & r2tensor,
232 : unsigned int index,
233 : Point & eigenvec)
234 : {
235 1087953 : std::vector<T> eigenval(LIBMESH_DIM);
236 1087953 : RankTwoTensorTempl<T> eigvecs;
237 1087953 : r2tensor.symmetricEigenvaluesEigenvectors(eigenval, eigvecs);
238 :
239 1087952 : T val = eigenval[index];
240 1087953 : eigenvec = eigvecs.column(index);
241 :
242 1087952 : return val;
243 : }
244 :
245 : /*
246 : * The max Principal method returns the largest principal value for a symmetric
247 : * tensor, using the calcEigenValues method.
248 : * param r2tensor RankTwoTensor from which to extract the principal value
249 : * param direction Direction corresponding to the principal value
250 : */
251 : template <typename T>
252 : T
253 : maxPrincipal(const RankTwoTensorTempl<T> & r2tensor, Point & direction)
254 : {
255 862864 : return calcEigenValuesEigenVectors(r2tensor, (LIBMESH_DIM - 1), direction);
256 : }
257 :
258 : /*
259 : * The mid Principal method calculates the second largest principal value for a
260 : * tensor.
261 : * param r2tensor RankTwoTensor from which to extract the principal value
262 : * param direction Direction corresponding to the principal value
263 : */
264 : template <typename T>
265 : T
266 : midPrincipal(const RankTwoTensorTempl<T> & r2tensor, Point & direction)
267 : {
268 75024 : return calcEigenValuesEigenVectors(r2tensor, 1, direction);
269 : }
270 :
271 : /*
272 : * The min Principal stress returns the smallest principal value from a symmetric
273 : * tensor.
274 : * param r2tensor RankTwoTensor from which to extract the principal value
275 : * param direction Direction corresponding to the principal value
276 : */
277 : template <typename T>
278 : T
279 : minPrincipal(const RankTwoTensorTempl<T> & r2tensor, Point & direction)
280 : {
281 150064 : return calcEigenValuesEigenVectors(r2tensor, 0, direction);
282 : }
283 :
284 : /*
285 : * The axial stress is the scalar component of the stress tensor in an user-defined
286 : * direction; the axis direction is specified by inputing two points.
287 : * axial-stress = axis^T_i * \sigma_{ij} * axis_j
288 : * @param point1 The starting point of the rotation axis for a cylinderical system
289 : * @param point2 The end point of the rotation axis
290 : * @param direction The direction vector in which the scalar stress value is calculated.
291 : */
292 : template <typename T>
293 : T
294 0 : axialStress(const RankTwoTensorTempl<T> & stress,
295 : const Point & point1,
296 : const Point & point2,
297 : Point & direction)
298 : {
299 : Point axis = point2 - point1;
300 0 : axis /= axis.norm();
301 :
302 : // Calculate the stress in the direction of the axis specifed by the user
303 0 : T axial_stress = axis * (stress * axis);
304 :
305 0 : direction = axis;
306 :
307 0 : return axial_stress;
308 : }
309 :
310 : /*
311 : * This method is a helper method for the hoopStress and radialStress methods to
312 : * calculate the unit position vector which is normal to the user supplied axis
313 : * of rotation; the rotation axis direction is specified by inputing two points.
314 : * @param point1 The starting point of the rotation axis for a cylinderical system
315 : * @param point2 The end point of the rotation axis
316 : * @param curr_point The point corresponding to the stress (pass in & _q_point[_qp])
317 : * @param normalPosition The vector from the current point that is normal to the rotation axis
318 : */
319 : void normalPositionVector(const Point & point1,
320 : const Point & point2,
321 : const Point & curr_point,
322 : Point & normalPosition);
323 :
324 : /*
325 : * The hoop stress is calculated as
326 : * hoop-stress = z^T_i * \sigma_{ij} * z_j
327 : * where z is defined as the cross of the user-defined (via input points) axis
328 : * of rotation and the normal from the current position to the axis of rotation.
329 : * @param point1 The starting point of the rotation axis for a cylinderical system
330 : * @param point2 The end point of the rotation axis
331 : * @param curr_point The point corresponding to the stress (pass in & _q_point[_qp])
332 : * @param direction The direction vector in which the scalar stress value is calculated.
333 : */
334 : template <typename T>
335 : T
336 98880 : hoopStress(const RankTwoTensorTempl<T> & stress,
337 : const Point & point1,
338 : const Point & point2,
339 : const Point & curr_point,
340 : Point & direction)
341 : {
342 : // Calculate the cross of the normal to the axis of rotation from the current
343 : // location and the axis of rotation
344 : Point xp;
345 98880 : normalPositionVector(point1, point2, curr_point, xp);
346 : Point axis_rotation = point2 - point1;
347 98880 : Point yp = axis_rotation / axis_rotation.norm();
348 98880 : Point zp = xp.cross(yp);
349 :
350 : // Calculate the scalar value of the hoop stress
351 98880 : T hoop_stress = zp * (stress * zp);
352 :
353 98880 : direction = zp;
354 :
355 98880 : return hoop_stress;
356 : }
357 :
358 : /* The radial stress is calculated as
359 : * radial_stress = normal^T_i * \sigma_{ij} * normal_j
360 : * where normal is the position vector of the current point that is normal to
361 : * the user-defined axis of rotation; the axis direction is specified with two points.
362 : * @param point1 The starting point of the rotation axis for a cylinderical system
363 : * @param point2 The end point of the rotation axis
364 : * @param curr_point The point corresponding to the stress (pass in & _q_point[_qp])
365 : * @param direction The direction vector in which the scalar stress value is calculated.
366 : */
367 : template <typename T>
368 : T
369 0 : radialStress(const RankTwoTensorTempl<T> & stress,
370 : const Point & point1,
371 : const Point & point2,
372 : const Point & curr_point,
373 : Point & direction)
374 : {
375 : Point radial_norm;
376 0 : normalPositionVector(point1, point2, curr_point, radial_norm);
377 :
378 : // Compute the scalar stress component in the direction of the normal vector from the
379 : // user-defined axis of rotation.
380 0 : T radial_stress = radial_norm * (stress * radial_norm);
381 :
382 0 : direction = radial_norm;
383 :
384 0 : return radial_stress;
385 : }
386 :
387 : /* The radial stress is calculated as
388 : * radial_stress = radial^T_i * \sigma_{ij} * radial_j
389 : * where normal is the position vector of the current point that is normal to
390 : * the user-defined axis of rotation;
391 : * @param center The center point of the spherical system
392 : * @param curr_point The point corresponding to the stress (pass in & _q_point[_qp])
393 : * @param direction The direction vector in which the scalar stress value is calculated.
394 : */
395 : template <typename T>
396 : T
397 4320 : radialStress(const RankTwoTensorTempl<T> & stress,
398 : const Point & center,
399 : const Point & curr_point,
400 : Point & direction)
401 : {
402 : Point radial = curr_point - center;
403 4320 : radial /= radial.norm();
404 :
405 : // Compute the scalar stress component in the radial direction
406 4320 : T radial_stress = radial * (stress * radial);
407 :
408 4320 : direction = radial;
409 :
410 4320 : return radial_stress;
411 : }
412 :
413 : /* The hoop stress is calculated as
414 : * hoop_stress = tangential^T_i * \sigma_{ij} * tangential_j
415 : * where tangential is tangential direction at the current point in the spherical system;
416 : * @param center The center point of the spherical system
417 : * @param curr_point The point corresponding to the stress (pass in & _q_point[_qp])
418 : * @param direction The direction vector in which the scalar stress value is calculated.
419 : */
420 : template <typename T>
421 : T
422 1968 : hoopStress(const RankTwoTensorTempl<T> & stress,
423 : const Point & center,
424 : const Point & curr_point,
425 : Point & direction)
426 : {
427 : Point radial = curr_point - center;
428 1968 : Real r = radial.norm();
429 : radial /= r;
430 :
431 : // Given normal vector N=(n1,n2,n3) and current point C(c1,c2,c3), the tangential plane is then
432 : // defined as n1(x-c1) + n2(y-c2) + n3(z-c3)=0. Let us assume n1!=0, the arbitrary point P on this
433 : // plane can be taken as P(x,c2+r,c3+r) where r is the radius. The x can be solved as x =
434 : // -r(n2+n3)/n1 + c1. The tangential vector PC is given as P-C.
435 :
436 : Point tangential;
437 :
438 1968 : if (!MooseUtils::absoluteFuzzyEqual(radial(0), 0.0))
439 : {
440 1968 : Real x = curr_point(0) - (radial(1) + radial(2)) * r / radial(0);
441 1968 : tangential = Point(x, curr_point(1) + r, curr_point(2) + r) - curr_point;
442 : }
443 0 : else if (!MooseUtils::absoluteFuzzyEqual(radial(1), 0.0))
444 : {
445 0 : Real y = curr_point(1) - (radial(0) + radial(2)) * r / radial(1);
446 0 : tangential = Point(curr_point(0) + r, y, curr_point(2) + r) - curr_point;
447 : }
448 0 : else if (!MooseUtils::absoluteFuzzyEqual(radial(1), 0.0))
449 : {
450 0 : Real z = curr_point(2) - (radial(0) + radial(1)) * r / radial(2);
451 0 : tangential = Point(curr_point(0) + r, curr_point(1) + r, z) - curr_point;
452 : }
453 : else
454 0 : mooseError("In Hoop stress calculation for spherical geometry, the current (quadracture) point "
455 : "is likely to be at the center. ");
456 :
457 1968 : tangential /= tangential.norm();
458 :
459 : // Compute the scalar stress component in the hoop direction
460 : T hoop_stress = 0.0;
461 7872 : for (unsigned int i = 0; i < 3; ++i)
462 23616 : for (unsigned int j = 0; j < 3; ++j)
463 17712 : hoop_stress += tangential(j) * stress(j, i) * tangential(i);
464 :
465 1968 : direction = tangential;
466 :
467 1968 : return hoop_stress;
468 : }
469 :
470 : /*
471 : * This method calculates the scalar value of the supplied rank-2 tensor in the
472 : * direction specified by the user.
473 : */
474 : template <typename T>
475 : T
476 38180 : directionValueTensor(const RankTwoTensorTempl<T> & r2tensor, const Point & direction)
477 : {
478 38180 : T tensor_value_in_direction = direction * (r2tensor * direction);
479 :
480 38180 : return tensor_value_in_direction;
481 : }
482 :
483 : /*
484 : * Triaxiality is the ratio of the hydrostatic stress to the von Mises stress.
485 : */
486 : template <typename T>
487 : T
488 0 : triaxialityStress(const RankTwoTensorTempl<T> & stress)
489 : {
490 0 : return hydrostatic(stress) / vonMisesStress(stress);
491 : }
492 :
493 : /*
494 : * maxShear is the maximum shear stress defined as the maximum principal
495 : * stress minus the minimum principal stress.
496 : */
497 : template <typename T>
498 : T
499 75040 : maxShear(const RankTwoTensorTempl<T> & stress)
500 : {
501 : Point dummy;
502 75040 : return (maxPrincipal(stress, dummy) - minPrincipal(stress, dummy)) / 2.;
503 : }
504 : /*
505 : * stressIntensity is defined as two times the maximum shear stress.
506 : */
507 : template <typename T>
508 : T
509 : stressIntensity(const RankTwoTensorTempl<T> & stress)
510 : {
511 37520 : return 2. * maxShear(stress);
512 : }
513 :
514 : /*
515 : * Return scalar quantity of a rank two tensor based on the user specified scalar_type
516 : * @param point1 The starting point of the rotation axis for a cylinderical system
517 : * @param point2 The end point of the rotation axis
518 : * @param curr_point The point corresponding to the stress (pass in & _q_point[_qp])
519 : * @param direction The direction vector in which the scalar stress value is calculated
520 : * point1 and point2 are required only for the cases of axialStress, hoopStress and radialStress
521 : * curr_point is required only for the cases of hoopStress and radialStress
522 : * direction is required only for directionValueTensor
523 : * for all other cases, these parameters will take the default values
524 : */
525 : template <typename T>
526 : T
527 13589870 : getQuantity(const RankTwoTensorTempl<T> & tensor,
528 : const MooseEnum & scalar_type,
529 : const Point & point1,
530 : const Point & point2,
531 : const Point & curr_point,
532 : Point & direction)
533 : {
534 13589870 : switch (scalar_type)
535 : {
536 1196342 : case 0:
537 1196342 : return vonMisesStress(tensor);
538 0 : case 1:
539 0 : mooseError("To compute an effective inelastic strain use "
540 : "RankTwoScalarTools::effectiveStrain()");
541 : case 2:
542 11235734 : return hydrostatic(tensor);
543 : case 3:
544 3520 : return L2norm(tensor);
545 : case 4:
546 758832 : return maxPrincipal(tensor, direction);
547 : case 5:
548 46032 : return midPrincipal(tensor, direction);
549 : case 6:
550 46032 : return minPrincipal(tensor, direction);
551 2304 : case 7:
552 2304 : return volumetricStrain(tensor);
553 : case 8:
554 55286 : return firstInvariant(tensor);
555 55286 : case 9:
556 55286 : return secondInvariant(tensor);
557 77942 : case 10:
558 77942 : return thirdInvariant(tensor);
559 0 : case 11:
560 0 : return axialStress(tensor, point1, point2, direction);
561 0 : case 12:
562 0 : return hoopStress(tensor, point1, point2, curr_point, direction);
563 0 : case 13:
564 0 : return radialStress(tensor, point1, point2, curr_point, direction);
565 0 : case 14:
566 0 : return triaxialityStress(tensor);
567 37520 : case 15:
568 37520 : return directionValueTensor(tensor, direction);
569 37520 : case 16:
570 37520 : return maxShear(tensor);
571 : case 17:
572 37520 : return stressIntensity(tensor);
573 0 : default:
574 0 : mooseError("RankTwoScalarTools Error: invalid scalar type");
575 : }
576 : }
577 :
578 : template <typename T>
579 : T
580 98880 : getCylindricalComponent(const RankTwoTensorTempl<T> & tensor,
581 : const CylindricalComponent & scalar_type,
582 : const Point & point1,
583 : const Point & point2,
584 : const Point & curr_point,
585 : Point & direction)
586 : {
587 98880 : switch (scalar_type)
588 : {
589 0 : case CylindricalComponent::AxialStress:
590 0 : return axialStress(tensor, point1, point2, direction);
591 98880 : case CylindricalComponent::HoopStress:
592 98880 : return hoopStress(tensor, point1, point2, curr_point, direction);
593 0 : case CylindricalComponent::RadialStress:
594 0 : return radialStress(tensor, point1, point2, curr_point, direction);
595 0 : default:
596 0 : mooseError("RankTwoCylindricalComponent Error: scalar type invalid");
597 : }
598 : }
599 :
600 : template <typename T>
601 : T
602 6288 : getSphericalComponent(const RankTwoTensorTempl<T> & tensor,
603 : const SphericalComponent & scalar_type,
604 : const Point & center,
605 : const Point & curr_point,
606 : Point & direction)
607 : {
608 6288 : switch (scalar_type)
609 : {
610 1968 : case SphericalComponent::HoopStress:
611 1968 : return hoopStress(tensor, center, curr_point, direction);
612 4320 : case SphericalComponent::RadialStress:
613 4320 : return radialStress(tensor, center, curr_point, direction);
614 0 : default:
615 0 : mooseError("RankTwoSphericalComponent Error: scalar type invalid");
616 : }
617 : }
618 :
619 : template <typename T>
620 : T
621 86976 : getPrincipalComponent(const RankTwoTensorTempl<T> & tensor,
622 : const InvariantType & scalar_type,
623 : Point & direction)
624 : {
625 86976 : switch (scalar_type)
626 : {
627 : case InvariantType::MaxPrincipal:
628 28992 : return maxPrincipal(tensor, direction);
629 : case InvariantType::MidPrincipal:
630 28992 : return midPrincipal(tensor, direction);
631 : case InvariantType::MinPrincipal:
632 28992 : return minPrincipal(tensor, direction);
633 0 : default:
634 0 : mooseError("RankTwoInvariant Error: valid invariant");
635 : }
636 : }
637 :
638 : template <typename T>
639 : T
640 : getDirectionalComponent(const RankTwoTensorTempl<T> & tensor, const Point & direction)
641 : {
642 0 : return directionValueTensor(tensor, direction);
643 : }
644 :
645 : template <typename T>
646 : T
647 35277004 : getInvariant(const RankTwoTensorTempl<T> & tensor, const InvariantType & scalar_type)
648 : {
649 35277004 : switch (scalar_type)
650 : {
651 33730804 : case InvariantType::VonMisesStress:
652 33730804 : return vonMisesStress(tensor);
653 0 : case InvariantType::EffectiveStrain:
654 0 : mooseError("To compute an effective inelastic strain use "
655 : "RankTwoScalarTools::effectiveStrain()");
656 : case InvariantType::Hydrostatic:
657 1519992 : return hydrostatic(tensor);
658 : case InvariantType::L2norm:
659 0 : return L2norm(tensor);
660 0 : case InvariantType::VolumetricStrain:
661 0 : return volumetricStrain(tensor);
662 : case InvariantType::FirstInvariant:
663 8736 : return firstInvariant(tensor);
664 8736 : case InvariantType::SecondInvariant:
665 8736 : return secondInvariant(tensor);
666 8736 : case InvariantType::ThirdInvariant:
667 8736 : return thirdInvariant(tensor);
668 0 : case InvariantType::TriaxialityStress:
669 0 : return triaxialityStress(tensor);
670 0 : case InvariantType::MaxShear:
671 0 : return maxShear(tensor);
672 : case InvariantType::StressIntensity:
673 0 : return stressIntensity(tensor);
674 0 : default:
675 0 : mooseError("RankTwoCartesianComponent Error: Pass valid invariant - " +
676 : invariantOptions().getRawNames());
677 : }
678 : }
679 :
680 : void setRotationMatrix(const RealVectorValue & outwardnormal,
681 : const RealVectorValue & axialVector,
682 : RankTwoTensor & rotationMatrix,
683 : const bool transpose);
684 :
685 : template <bool is_ad>
686 : void
687 230048 : RankTwoTensorToVoigtVector(const GenericRankTwoTensor<is_ad> & tensor,
688 : GenericDenseVector<is_ad> & voigt_vector)
689 : {
690 230048 : voigt_vector(0) = tensor(0, 0);
691 230048 : voigt_vector(1) = tensor(1, 1);
692 230048 : voigt_vector(2) = tensor(2, 2);
693 230048 : voigt_vector(3) = tensor(0, 1);
694 230048 : voigt_vector(4) = tensor(1, 2);
695 230048 : voigt_vector(5) = tensor(0, 2);
696 230048 : }
697 :
698 : template <bool is_ad>
699 : void
700 187760 : VoigtVectorToRankTwoTensor(const GenericDenseVector<is_ad> & voigt_vector,
701 : GenericRankTwoTensor<is_ad> & tensor)
702 : {
703 187760 : tensor(0, 0) = voigt_vector(0);
704 187760 : tensor(1, 1) = voigt_vector(1);
705 187760 : tensor(2, 2) = voigt_vector(2);
706 187760 : tensor(0, 1) = tensor(1, 0) = voigt_vector(3);
707 187760 : tensor(1, 2) = tensor(2, 1) = voigt_vector(4);
708 187760 : tensor(0, 2) = tensor(2, 0) = voigt_vector(5);
709 187760 : }
710 : }
|