From 731da5be9f8ee2d26cff4911152da27ed3fa808b Mon Sep 17 00:00:00 2001 From: Lynn Munday Date: Wed, 27 Nov 2024 16:48:00 -0700 Subject: [PATCH 1/5] Eigendecomposition material and example input. --- .../include/materials/EigenDecompMaterial.h | 45 ++++++ .../src/materials/EigenDecompMaterial.C | 65 +++++++++ .../eigen_decomp_material/prescribed_strain.i | 136 ++++++++++++++++++ 3 files changed, 246 insertions(+) create mode 100644 modules/solid_mechanics/include/materials/EigenDecompMaterial.h create mode 100644 modules/solid_mechanics/src/materials/EigenDecompMaterial.C create mode 100644 modules/solid_mechanics/test/tests/eigen_decomp_material/prescribed_strain.i diff --git a/modules/solid_mechanics/include/materials/EigenDecompMaterial.h b/modules/solid_mechanics/include/materials/EigenDecompMaterial.h new file mode 100644 index 000000000000..a5e519947065 --- /dev/null +++ b/modules/solid_mechanics/include/materials/EigenDecompMaterial.h @@ -0,0 +1,45 @@ +//* This file is part of the MOOSE framework +//* https://www.mooseframework.org +//* +//* All rights reserved, see COPYRIGHT for full restrictions +//* https://github.com/idaholab/moose/blob/master/COPYRIGHT +//* +//* Licensed under LGPL 2.1, please see LICENSE for details +//* https://www.gnu.org/licenses/lgpl-2.1.html + +#pragma once + +#include "Material.h" +#include "RankTwoTensorForward.h" +/** + * Decomp + */ +template +class EigenDecompMaterialTempl : public Material +{ +public: + static InputParameters validParams(); + + EigenDecompMaterialTempl(const InputParameters & parameters); + + virtual void computeQpProperties() override; + +protected: + /// Base name to allow multiple tensors to be decomposed + const std::string _base_name; + /// Rank two tensor for eigen decomposition + const GenericMaterialProperty & _tensor; + + /// eigen vectors + GenericMaterialProperty & _max_eigen_vector; + GenericMaterialProperty & _mid_eigen_vector; + GenericMaterialProperty & _min_eigen_vector; + + /// eigen values + GenericMaterialProperty & _max_eigen_value; + GenericMaterialProperty & _mid_eigen_value; + GenericMaterialProperty & _min_eigen_value; +}; + +typedef EigenDecompMaterialTempl EigenDecompMaterial; +typedef EigenDecompMaterialTempl ADEigenDecompMaterial; diff --git a/modules/solid_mechanics/src/materials/EigenDecompMaterial.C b/modules/solid_mechanics/src/materials/EigenDecompMaterial.C new file mode 100644 index 000000000000..c997e9b899e3 --- /dev/null +++ b/modules/solid_mechanics/src/materials/EigenDecompMaterial.C @@ -0,0 +1,65 @@ +//* This file is part of the MOOSE framework +//* https://www.mooseframework.org +//* +//* All rights reserved, see COPYRIGHT for full restrictions +//* https://github.com/idaholab/moose/blob/master/COPYRIGHT +//* +//* Licensed under LGPL 2.1, please see LICENSE for details +//* https://www.gnu.org/licenses/lgpl-2.1.html + +#include "EigenDecompMaterial.h" +#include "RankTwoTensor.h" + +registerMooseObject("SolidMechanicsApp", EigenDecompMaterial); +registerMooseObject("SolidMechanicsApp", ADEigenDecompMaterial); + +template +InputParameters +EigenDecompMaterialTempl::validParams() +{ + InputParameters params = Material::validParams(); + params.addClassDescription( + "Creates material with eigenvalues and eigenvectors of a symmetric rank two tensor."); + params.addRequiredParam( + "rank_two_tensor", + "The name of the symmetric rank two tensor to used in eigen decomposition."); + params.addParam( + "base_name", + "Optional parameter to allow multiple tensors to be decomposed on the same block."); + return params; +} + +template +EigenDecompMaterialTempl::EigenDecompMaterialTempl(const InputParameters & parameters) + : Material(parameters), + _base_name(isParamValid("base_name") ? getParam("base_name") + "_" : ""), + _tensor(getGenericMaterialProperty("rank_two_tensor")), + _max_eigen_vector( + declareGenericProperty(_base_name + "max_eigen_vector")), + _mid_eigen_vector( + declareGenericProperty(_base_name + "mid_eigen_vector")), + _min_eigen_vector( + declareGenericProperty(_base_name + "min_eigen_vector")), + _max_eigen_value(declareGenericProperty(_base_name + "max_eigen_value")), + _mid_eigen_value(declareGenericProperty(_base_name + "mid_eigen_value")), + _min_eigen_value(declareGenericProperty(_base_name + "min_eigen_value")) +{ +} + +template +void +EigenDecompMaterialTempl::computeQpProperties() +{ + std::vector> eigval(3, 0.0); + GenericRankTwoTensor eigvec; + + _tensor[_qp].symmetricEigenvaluesEigenvectors(eigval, eigvec); + + _max_eigen_vector[_qp] = eigvec.column(2); + _mid_eigen_vector[_qp] = eigvec.column(1); + _min_eigen_vector[_qp] = eigvec.column(0); + + _max_eigen_value[_qp] = eigval[2]; + _mid_eigen_value[_qp] = eigval[1]; + _min_eigen_value[_qp] = eigval[0]; +} diff --git a/modules/solid_mechanics/test/tests/eigen_decomp_material/prescribed_strain.i b/modules/solid_mechanics/test/tests/eigen_decomp_material/prescribed_strain.i new file mode 100644 index 000000000000..6fd0097da181 --- /dev/null +++ b/modules/solid_mechanics/test/tests/eigen_decomp_material/prescribed_strain.i @@ -0,0 +1,136 @@ +[Problem] + kernel_coverage_check = false + solve = false +[] + +[Mesh] + type = GeneratedMesh + dim = 3 + nx = 1 + ny = 1 + nz = 1 + displacements = 'disp_x disp_y disp_z' +[] + +[AuxVariables] + [disp_y] + initial_condition = 0 + [] + [disp_x] + initial_condition = 0 + [] + [disp_z] + initial_condition = 0 + [] +[] + +[AuxKernels] + [disp_x] + execute_on = 'TIMESTEP_BEGIN' + type = ParsedAux + variable = disp_x + use_xyzt = true + expression = "4e-1*x*t" + [] + [disp_y] + execute_on = 'TIMESTEP_BEGIN' + type = ParsedAux + variable = disp_y + use_xyzt = true + expression = "3e-1*y*t^2" + [] + [disp_z] + execute_on = 'TIMESTEP_BEGIN' + type = ParsedAux + variable = disp_z + use_xyzt = true + expression = "1e-1*z*t^3" + [] +[] + +[Materials] + [strain] + type = ADComputeFiniteStrain + displacements = 'disp_x disp_y disp_z' + [] + [nonAD_strain] + type = RankTwoTensorMaterialADConverter + ad_props_in = mechanical_strain + reg_props_out = nonAD_mechanical_strain + [] + [eig_decomp] + type = ADEigenDecompMaterial + rank_two_tensor = mechanical_strain + outputs = exodus + output_properties = "max_eigen_vector mid_eigen_vector min_eigen_vector max_eigen_value " + "mid_eigen_value min_eigen_value" + [] + [nonADeig_decomp] + type = EigenDecompMaterial + rank_two_tensor = nonAD_mechanical_strain + base_name = nonAD + outputs = exodus + output_properties = "nonAD_max_eigen_vector nonAD_mid_eigen_vector nonAD_min_eigen_vector " + "nonAD_max_eigen_value nonAD_mid_eigen_value nonAD_min_eigen_value" + [] +[] + +[BCs] +[] + +[Executioner] + type = Transient + solve_type = LINEAR + dt = 1 + end_time = 5 +[] + +[Postprocessors] + [sxx] + type = ADMaterialTensorAverage + rank_two_tensor = mechanical_strain + index_i = 0 + index_j = 0 + execute_on = 'TIMESTEP_END' + [] + [syy] + type = ADMaterialTensorAverage + rank_two_tensor = mechanical_strain + index_i = 1 + index_j = 1 + [] + [szz] + type = ADMaterialTensorAverage + rank_two_tensor = mechanical_strain + index_i = 2 + index_j = 2 + [] + [AD_eigval_max] + type = ADElementAverageMaterialProperty + mat_prop = max_eigen_value + [] + [AD_eigval_mid] + type = ADElementAverageMaterialProperty + mat_prop = mid_eigen_value + [] + [AD_eigval_min] + type = ADElementAverageMaterialProperty + mat_prop = min_eigen_value + [] + [nonAD_eigval_max] + type = ElementAverageMaterialProperty + mat_prop = nonAD_max_eigen_value + [] + [nonAD_eigval_mid] + type = ElementAverageMaterialProperty + mat_prop = nonAD_mid_eigen_value + [] + [nonAD_eigval_min] + type = ElementAverageMaterialProperty + mat_prop = nonAD_min_eigen_value + [] +[] + +[Outputs] + exodus = true +[] From b23c6d2202bfbbfd5ad34e869e2a1461755c468c Mon Sep 17 00:00:00 2001 From: Lynn Munday Date: Mon, 2 Dec 2024 16:05:23 -0700 Subject: [PATCH 2/5] cleaning up code and adding documentation and tests. closes #29179 --- .../source/materials/EigenDecompMaterial.md | 17 +++ .../include/materials/EigenDecompMaterial.h | 2 +- .../eigen_decomp_material/gold/pipe_2d_out.e | Bin 0 -> 76912 bytes .../gold/prescribed_strain_3D_out.e | Bin 0 -> 100580 bytes .../tests/eigen_decomp_material/pipe_2d.i | 126 ++++++++++++++++++ ...cribed_strain.i => prescribed_strain_3D.i} | 13 +- .../test/tests/eigen_decomp_material/tests | 17 +++ 7 files changed, 171 insertions(+), 4 deletions(-) create mode 100644 modules/solid_mechanics/doc/content/source/materials/EigenDecompMaterial.md create mode 100644 modules/solid_mechanics/test/tests/eigen_decomp_material/gold/pipe_2d_out.e create mode 100644 modules/solid_mechanics/test/tests/eigen_decomp_material/gold/prescribed_strain_3D_out.e create mode 100644 modules/solid_mechanics/test/tests/eigen_decomp_material/pipe_2d.i rename modules/solid_mechanics/test/tests/eigen_decomp_material/{prescribed_strain.i => prescribed_strain_3D.i} (90%) create mode 100644 modules/solid_mechanics/test/tests/eigen_decomp_material/tests diff --git a/modules/solid_mechanics/doc/content/source/materials/EigenDecompMaterial.md b/modules/solid_mechanics/doc/content/source/materials/EigenDecompMaterial.md new file mode 100644 index 000000000000..c00595dd2dcb --- /dev/null +++ b/modules/solid_mechanics/doc/content/source/materials/EigenDecompMaterial.md @@ -0,0 +1,17 @@ +# EigenDecompMaterial + +!syntax description /Materials/EigenDecompMaterial + +## Description + +This class reads in a Rank two tensor material given by [!param](/Materials/EigenDecompMaterial/rank_two_tensor) and performs an eigendecomposition on it. The results of the decomposition are scalar materials named `max_eigen_value`, `mid_eigen_value`, and `min_eigen_value` and the corresponding vector material properties named `max_eigen_vector`, `mid_eigen_vector`, and `min_eigen_vector`. These names can be preceeded by the [!param](/Materials/EigenDecompMaterial/base_name) to allow for more than one `EigenDecompMaterial` per block. These material properties can be output using the Material Outputs system with the [!param](/Materials/EigenDecompMaterial/output_properties) as shown in the below example. This material is useful for visualizing the elemental maximum principal stress and direction as a vector. + +## Example Input File Syntax + +!listing modules/solid_mechanics/test/tests/eigen_decomp_material/prescribed_strain_3D.i block=Materials/nonADeig_decomp + +!syntax parameters /Materials/EigenDecompMaterial + +!syntax inputs /Materials/EigenDecompMaterial + +!syntax children /Materials/EigenDecompMaterial diff --git a/modules/solid_mechanics/include/materials/EigenDecompMaterial.h b/modules/solid_mechanics/include/materials/EigenDecompMaterial.h index a5e519947065..2ee9f5bd4ee3 100644 --- a/modules/solid_mechanics/include/materials/EigenDecompMaterial.h +++ b/modules/solid_mechanics/include/materials/EigenDecompMaterial.h @@ -12,7 +12,7 @@ #include "Material.h" #include "RankTwoTensorForward.h" /** - * Decomp + * Perform eigen decomposition on Rank two tensor */ template class EigenDecompMaterialTempl : public Material diff --git a/modules/solid_mechanics/test/tests/eigen_decomp_material/gold/pipe_2d_out.e b/modules/solid_mechanics/test/tests/eigen_decomp_material/gold/pipe_2d_out.e new file mode 100644 index 0000000000000000000000000000000000000000..59ddffe1781e4232c760707f25ea458a25e51777 GIT binary patch literal 76912 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 DpXg=h literal 0 HcmV?d00001 diff --git a/modules/solid_mechanics/test/tests/eigen_decomp_material/pipe_2d.i b/modules/solid_mechanics/test/tests/eigen_decomp_material/pipe_2d.i new file mode 100644 index 000000000000..4198437acfbc --- /dev/null +++ b/modules/solid_mechanics/test/tests/eigen_decomp_material/pipe_2d.i @@ -0,0 +1,126 @@ +# units in MPa, meters +[GlobalParams] + order = SECOND + family = LAGRANGE + displacements = 'disp_x disp_y' +[] + +[Mesh] + coord_type = RZ + [pipe] + type = GeneratedMeshGenerator + dim = 2 + xmin = 0.2799334 #12"-0.979" + xmax = .3048 #12" + ymin = 0 + ymax = 0.00497 #0.979"/5 + nx = 5 + ny = 1 + elem_type = quad9 + [] +[] + +[Variables] + [disp_x] + [] + [disp_y] + [] +[] + +[Physics] + [SolidMechanics] + [QuasiStatic] + [all] + strain = SMALL + add_variables = true + new_system = true + formulation = TOTAL + volumetric_locking_correction = false + # generate_output = "cauchy_stress_xx cauchy_stress_yy cauchy_stress_zz cauchy_stress_xy " + # "cauchy_stress_xz cauchy_stress_yz strain_xx strain_yy strain_zz strain_xy " + # "strain_xz strain_yz vonmises_cauchy_stress" + [] + [] + [] +[] + +[Functions] + [inner_pressure] + type = ConstantFunction + value = 3 + [] + [big_pipe] + type = ParsedFunction + expression = -(p*11.021*11.021)/(12*12-11.021*11.021) + symbol_names = 'p' + symbol_values = 3 + [] +[] + +[BCs] + [fixBottom] + type = DirichletBC + variable = disp_y + boundary = bottom + value = 0.0 + preset = true + [] + [Pressure] + [inside] + boundary = left + function = inner_pressure + [] + [axial] + boundary = top + function = big_pipe + [] + [] +[] + +[Constraints] + [top] + type = EqualValueBoundaryConstraint + variable = disp_y + secondary = top #sideset on top boundary + penalty = 1e+14 + formulation = penalty + [] +[] + +[Materials] + [elastic_tensor] + type = ComputeIsotropicElasticityTensor + youngs_modulus = 168000 + poissons_ratio = 0.31 + [] + [compute_stress] + type = ComputeLagrangianLinearElasticStress + [] + [nonADeig_decomp] + type = EigenDecompMaterial + rank_two_tensor = cauchy_stress + outputs = exodus + output_properties = "max_eigen_vector mid_eigen_vector min_eigen_vector " + "max_eigen_valuemid_eigen_value min_eigen_value" + [] +[] + +[Executioner] + type = Steady + solve_type = 'NEWTON' + petsc_options_iname = '-pc_type -pc_factor_mat_solver_package' + petsc_options_value = 'lu superlu_dist' + nl_rel_tol = 5e-8 +[] + +[Postprocessors] + [eigval_max] + type = ElementAverageMaterialProperty + mat_prop = max_eigen_value + [] +[] + +[Outputs] + exodus = on + console = true +[] diff --git a/modules/solid_mechanics/test/tests/eigen_decomp_material/prescribed_strain.i b/modules/solid_mechanics/test/tests/eigen_decomp_material/prescribed_strain_3D.i similarity index 90% rename from modules/solid_mechanics/test/tests/eigen_decomp_material/prescribed_strain.i rename to modules/solid_mechanics/test/tests/eigen_decomp_material/prescribed_strain_3D.i index 6fd0097da181..ce915d0717e3 100644 --- a/modules/solid_mechanics/test/tests/eigen_decomp_material/prescribed_strain.i +++ b/modules/solid_mechanics/test/tests/eigen_decomp_material/prescribed_strain_3D.i @@ -30,21 +30,21 @@ type = ParsedAux variable = disp_x use_xyzt = true - expression = "4e-1*x*t" + expression = "if(t<4.1,4e-1*x*t,x)" [] [disp_y] execute_on = 'TIMESTEP_BEGIN' type = ParsedAux variable = disp_y use_xyzt = true - expression = "3e-1*y*t^2" + expression = "if(t<4.1,3e-1*y*t^2,1e-1*y*t+1e-1*x*t)" [] [disp_z] execute_on = 'TIMESTEP_BEGIN' type = ParsedAux variable = disp_z use_xyzt = true - expression = "1e-1*z*t^3" + expression = "if(t<4.1,1e-1*z*t^3,z)" [] [] @@ -93,6 +93,13 @@ index_j = 0 execute_on = 'TIMESTEP_END' [] + [sxy] + type = ADMaterialTensorAverage + rank_two_tensor = mechanical_strain + index_i = 0 + index_j = 1 + execute_on = 'TIMESTEP_END' + [] [syy] type = ADMaterialTensorAverage rank_two_tensor = mechanical_strain diff --git a/modules/solid_mechanics/test/tests/eigen_decomp_material/tests b/modules/solid_mechanics/test/tests/eigen_decomp_material/tests new file mode 100644 index 000000000000..8c7021a65196 --- /dev/null +++ b/modules/solid_mechanics/test/tests/eigen_decomp_material/tests @@ -0,0 +1,17 @@ +[Tests] + design = 'source/materials/EigenDecompMaterial.md' + issues = '#29179' + requirement = 'The system shall output eigen decompositions of tensors in ' + [3D] + type = Exodiff + input = prescribed_strain_3D.i + exodiff = prescribed_strain_3D_out.e + detail = 'a 3D simulation with an evolving rank two tensor.' + [] + [2Drz] + type = Exodiff + input = pipe_2d.i + exodiff =pipe_2d_out.e + detail = 'a 2D radial symmetry simulation of a pressurized pipe.' + [] +[] From fb72d578880394fef9c55fddd35f789517faecde Mon Sep 17 00:00:00 2001 From: Lynn Munday Date: Wed, 4 Dec 2024 10:48:22 -0700 Subject: [PATCH 3/5] rename files and classes --- .../source/materials/EigenDecompMaterial.md | 17 ----------------- .../materials/EigenDecompositionMaterial.md | 17 +++++++++++++++++ ...pMaterial.h => EigenDecompositionMaterial.h} | 8 ++++---- ...pMaterial.C => EigenDecompositionMaterial.C} | 12 ++++++------ .../test/tests/eigen_decomp_material/pipe_2d.i | 2 +- .../prescribed_strain_3D.i | 4 ++-- 6 files changed, 30 insertions(+), 30 deletions(-) delete mode 100644 modules/solid_mechanics/doc/content/source/materials/EigenDecompMaterial.md create mode 100644 modules/solid_mechanics/doc/content/source/materials/EigenDecompositionMaterial.md rename modules/solid_mechanics/include/materials/{EigenDecompMaterial.h => EigenDecompositionMaterial.h} (81%) rename modules/solid_mechanics/src/materials/{EigenDecompMaterial.C => EigenDecompositionMaterial.C} (84%) diff --git a/modules/solid_mechanics/doc/content/source/materials/EigenDecompMaterial.md b/modules/solid_mechanics/doc/content/source/materials/EigenDecompMaterial.md deleted file mode 100644 index c00595dd2dcb..000000000000 --- a/modules/solid_mechanics/doc/content/source/materials/EigenDecompMaterial.md +++ /dev/null @@ -1,17 +0,0 @@ -# EigenDecompMaterial - -!syntax description /Materials/EigenDecompMaterial - -## Description - -This class reads in a Rank two tensor material given by [!param](/Materials/EigenDecompMaterial/rank_two_tensor) and performs an eigendecomposition on it. The results of the decomposition are scalar materials named `max_eigen_value`, `mid_eigen_value`, and `min_eigen_value` and the corresponding vector material properties named `max_eigen_vector`, `mid_eigen_vector`, and `min_eigen_vector`. These names can be preceeded by the [!param](/Materials/EigenDecompMaterial/base_name) to allow for more than one `EigenDecompMaterial` per block. These material properties can be output using the Material Outputs system with the [!param](/Materials/EigenDecompMaterial/output_properties) as shown in the below example. This material is useful for visualizing the elemental maximum principal stress and direction as a vector. - -## Example Input File Syntax - -!listing modules/solid_mechanics/test/tests/eigen_decomp_material/prescribed_strain_3D.i block=Materials/nonADeig_decomp - -!syntax parameters /Materials/EigenDecompMaterial - -!syntax inputs /Materials/EigenDecompMaterial - -!syntax children /Materials/EigenDecompMaterial diff --git a/modules/solid_mechanics/doc/content/source/materials/EigenDecompositionMaterial.md b/modules/solid_mechanics/doc/content/source/materials/EigenDecompositionMaterial.md new file mode 100644 index 000000000000..0f55b87d9d95 --- /dev/null +++ b/modules/solid_mechanics/doc/content/source/materials/EigenDecompositionMaterial.md @@ -0,0 +1,17 @@ +# EigenDecompositionMaterial + +!syntax description /Materials/EigenDecompositionMaterial + +## Description + +This class reads in a Rank two tensor material given by [!param](/Materials/EigenDecompositionMaterial/rank_two_tensor) and performs an eigendecomposition on it. The results of the decomposition are scalar materials named `max_eigen_value`, `mid_eigen_value`, and `min_eigen_value` and the corresponding vector material properties named `max_eigen_vector`, `mid_eigen_vector`, and `min_eigen_vector`. These names can be preceeded by the [!param](/Materials/EigenDecompositionMaterial/base_name) to allow for more than one `EigenDecompositionMaterial` per block. These material properties can be output using the Material Outputs system with the [!param](/Materials/EigenDecompositionMaterial/output_properties) as shown in the below example. This material is useful for visualizing the elemental maximum principal stress and direction as a vector. + +## Example Input File Syntax + +!listing modules/solid_mechanics/test/tests/eigen_decomp_material/prescribed_strain_3D.i block=Materials/nonADeig_decomp + +!syntax parameters /Materials/EigenDecompositionMaterial + +!syntax inputs /Materials/EigenDecompositionMaterial + +!syntax children /Materials/EigenDecompositionMaterial diff --git a/modules/solid_mechanics/include/materials/EigenDecompMaterial.h b/modules/solid_mechanics/include/materials/EigenDecompositionMaterial.h similarity index 81% rename from modules/solid_mechanics/include/materials/EigenDecompMaterial.h rename to modules/solid_mechanics/include/materials/EigenDecompositionMaterial.h index 2ee9f5bd4ee3..9910f6bd5c20 100644 --- a/modules/solid_mechanics/include/materials/EigenDecompMaterial.h +++ b/modules/solid_mechanics/include/materials/EigenDecompositionMaterial.h @@ -15,12 +15,12 @@ * Perform eigen decomposition on Rank two tensor */ template -class EigenDecompMaterialTempl : public Material +class EigenDecompositionMaterialTempl : public Material { public: static InputParameters validParams(); - EigenDecompMaterialTempl(const InputParameters & parameters); + EigenDecompositionMaterialTempl(const InputParameters & parameters); virtual void computeQpProperties() override; @@ -41,5 +41,5 @@ class EigenDecompMaterialTempl : public Material GenericMaterialProperty & _min_eigen_value; }; -typedef EigenDecompMaterialTempl EigenDecompMaterial; -typedef EigenDecompMaterialTempl ADEigenDecompMaterial; +typedef EigenDecompositionMaterialTempl EigenDecompositionMaterial; +typedef EigenDecompositionMaterialTempl ADEigenDecompositionMaterial; diff --git a/modules/solid_mechanics/src/materials/EigenDecompMaterial.C b/modules/solid_mechanics/src/materials/EigenDecompositionMaterial.C similarity index 84% rename from modules/solid_mechanics/src/materials/EigenDecompMaterial.C rename to modules/solid_mechanics/src/materials/EigenDecompositionMaterial.C index c997e9b899e3..8e5aad551dd9 100644 --- a/modules/solid_mechanics/src/materials/EigenDecompMaterial.C +++ b/modules/solid_mechanics/src/materials/EigenDecompositionMaterial.C @@ -7,15 +7,15 @@ //* Licensed under LGPL 2.1, please see LICENSE for details //* https://www.gnu.org/licenses/lgpl-2.1.html -#include "EigenDecompMaterial.h" +#include "EigenDecompositionMaterial.h" #include "RankTwoTensor.h" -registerMooseObject("SolidMechanicsApp", EigenDecompMaterial); -registerMooseObject("SolidMechanicsApp", ADEigenDecompMaterial); +registerMooseObject("SolidMechanicsApp", EigenDecompositionMaterial); +registerMooseObject("SolidMechanicsApp", ADEigenDecompositionMaterial); template InputParameters -EigenDecompMaterialTempl::validParams() +EigenDecompositionMaterialTempl::validParams() { InputParameters params = Material::validParams(); params.addClassDescription( @@ -30,7 +30,7 @@ EigenDecompMaterialTempl::validParams() } template -EigenDecompMaterialTempl::EigenDecompMaterialTempl(const InputParameters & parameters) +EigenDecompositionMaterialTempl::EigenDecompositionMaterialTempl(const InputParameters & parameters) : Material(parameters), _base_name(isParamValid("base_name") ? getParam("base_name") + "_" : ""), _tensor(getGenericMaterialProperty("rank_two_tensor")), @@ -48,7 +48,7 @@ EigenDecompMaterialTempl::EigenDecompMaterialTempl(const InputParameters template void -EigenDecompMaterialTempl::computeQpProperties() +EigenDecompositionMaterialTempl::computeQpProperties() { std::vector> eigval(3, 0.0); GenericRankTwoTensor eigvec; diff --git a/modules/solid_mechanics/test/tests/eigen_decomp_material/pipe_2d.i b/modules/solid_mechanics/test/tests/eigen_decomp_material/pipe_2d.i index 4198437acfbc..96ef061df9ab 100644 --- a/modules/solid_mechanics/test/tests/eigen_decomp_material/pipe_2d.i +++ b/modules/solid_mechanics/test/tests/eigen_decomp_material/pipe_2d.i @@ -97,7 +97,7 @@ type = ComputeLagrangianLinearElasticStress [] [nonADeig_decomp] - type = EigenDecompMaterial + type = EigenDecompositionMaterial rank_two_tensor = cauchy_stress outputs = exodus output_properties = "max_eigen_vector mid_eigen_vector min_eigen_vector " diff --git a/modules/solid_mechanics/test/tests/eigen_decomp_material/prescribed_strain_3D.i b/modules/solid_mechanics/test/tests/eigen_decomp_material/prescribed_strain_3D.i index ce915d0717e3..280edfeda5d6 100644 --- a/modules/solid_mechanics/test/tests/eigen_decomp_material/prescribed_strain_3D.i +++ b/modules/solid_mechanics/test/tests/eigen_decomp_material/prescribed_strain_3D.i @@ -59,14 +59,14 @@ reg_props_out = nonAD_mechanical_strain [] [eig_decomp] - type = ADEigenDecompMaterial + type = ADEigenDecompositionMaterial rank_two_tensor = mechanical_strain outputs = exodus output_properties = "max_eigen_vector mid_eigen_vector min_eigen_vector max_eigen_value " "mid_eigen_value min_eigen_value" [] [nonADeig_decomp] - type = EigenDecompMaterial + type = EigenDecompositionMaterial rank_two_tensor = nonAD_mechanical_strain base_name = nonAD outputs = exodus From 379a4ae9727325791a5e998f11fcd28bb9bed2dd Mon Sep 17 00:00:00 2001 From: Lynn Munday Date: Wed, 4 Dec 2024 13:37:20 -0700 Subject: [PATCH 4/5] address review comments. closes #29179 --- .../materials/EigenDecompositionMaterial.md | 2 +- .../materials/EigenDecompositionMaterial.h | 5 +-- .../materials/EigenDecompositionMaterial.C | 13 ++++-- .../gold/prescribed_strain_3D_out.e | Bin 100580 -> 102280 bytes .../tests/eigen_decomp_material/pipe_2d.i | 7 ++-- .../prescribed_strain_3D.i | 37 ++++++++++++------ .../test/tests/eigen_decomp_material/tests | 15 +++++-- 7 files changed, 52 insertions(+), 27 deletions(-) diff --git a/modules/solid_mechanics/doc/content/source/materials/EigenDecompositionMaterial.md b/modules/solid_mechanics/doc/content/source/materials/EigenDecompositionMaterial.md index 0f55b87d9d95..abc0b210ab69 100644 --- a/modules/solid_mechanics/doc/content/source/materials/EigenDecompositionMaterial.md +++ b/modules/solid_mechanics/doc/content/source/materials/EigenDecompositionMaterial.md @@ -4,7 +4,7 @@ ## Description -This class reads in a Rank two tensor material given by [!param](/Materials/EigenDecompositionMaterial/rank_two_tensor) and performs an eigendecomposition on it. The results of the decomposition are scalar materials named `max_eigen_value`, `mid_eigen_value`, and `min_eigen_value` and the corresponding vector material properties named `max_eigen_vector`, `mid_eigen_vector`, and `min_eigen_vector`. These names can be preceeded by the [!param](/Materials/EigenDecompositionMaterial/base_name) to allow for more than one `EigenDecompositionMaterial` per block. These material properties can be output using the Material Outputs system with the [!param](/Materials/EigenDecompositionMaterial/output_properties) as shown in the below example. This material is useful for visualizing the elemental maximum principal stress and direction as a vector. +This class reads in a symmetric `RankTwoTensor` material given by [!param](/Materials/EigenDecompositionMaterial/rank_two_tensor) and performs an eigendecomposition on it. The results of the decomposition are scalar materials named `max_eigen_value`, `mid_eigen_value`, and `min_eigen_value` and the corresponding vector material properties named `max_eigen_vector`, `mid_eigen_vector`, and `min_eigen_vector`. These names can be preceeded by the [!param](/Materials/EigenDecompositionMaterial/base_name) to allow for more than one `EigenDecompositionMaterial` per block. These material properties can be output using the Material Outputs system with the [!param](/Materials/EigenDecompositionMaterial/output_properties) as shown in the below example. This material is useful for visualizing the elemental maximum principal stress and direction as a vector. An error will be produced if an unsymmetric `RankTwoTensor` is decomposed which can happen for the deformation gradient. ## Example Input File Syntax diff --git a/modules/solid_mechanics/include/materials/EigenDecompositionMaterial.h b/modules/solid_mechanics/include/materials/EigenDecompositionMaterial.h index 9910f6bd5c20..abe33fc2948e 100644 --- a/modules/solid_mechanics/include/materials/EigenDecompositionMaterial.h +++ b/modules/solid_mechanics/include/materials/EigenDecompositionMaterial.h @@ -12,7 +12,7 @@ #include "Material.h" #include "RankTwoTensorForward.h" /** - * Perform eigen decomposition on Rank two tensor + * Perform eigendecomposition on a RankTwoTensor material property */ template class EigenDecompositionMaterialTempl : public Material @@ -22,9 +22,8 @@ class EigenDecompositionMaterialTempl : public Material EigenDecompositionMaterialTempl(const InputParameters & parameters); - virtual void computeQpProperties() override; - protected: + virtual void computeQpProperties() override; /// Base name to allow multiple tensors to be decomposed const std::string _base_name; /// Rank two tensor for eigen decomposition diff --git a/modules/solid_mechanics/src/materials/EigenDecompositionMaterial.C b/modules/solid_mechanics/src/materials/EigenDecompositionMaterial.C index 8e5aad551dd9..ded508bbfec3 100644 --- a/modules/solid_mechanics/src/materials/EigenDecompositionMaterial.C +++ b/modules/solid_mechanics/src/materials/EigenDecompositionMaterial.C @@ -18,8 +18,8 @@ InputParameters EigenDecompositionMaterialTempl::validParams() { InputParameters params = Material::validParams(); - params.addClassDescription( - "Creates material with eigenvalues and eigenvectors of a symmetric rank two tensor."); + params.addClassDescription("Emits material properties for the eigenvalues and eigenvectors of a " + "symmetric rank two tensor."); params.addRequiredParam( "rank_two_tensor", "The name of the symmetric rank two tensor to used in eigen decomposition."); @@ -30,7 +30,8 @@ EigenDecompositionMaterialTempl::validParams() } template -EigenDecompositionMaterialTempl::EigenDecompositionMaterialTempl(const InputParameters & parameters) +EigenDecompositionMaterialTempl::EigenDecompositionMaterialTempl( + const InputParameters & parameters) : Material(parameters), _base_name(isParamValid("base_name") ? getParam("base_name") + "_" : ""), _tensor(getGenericMaterialProperty("rank_two_tensor")), @@ -44,12 +45,18 @@ EigenDecompositionMaterialTempl::EigenDecompositionMaterialTempl(const In _mid_eigen_value(declareGenericProperty(_base_name + "mid_eigen_value")), _min_eigen_value(declareGenericProperty(_base_name + "min_eigen_value")) { + if (LIBMESH_DIM != 3) + mooseError("EigenDecompositionMaterial is only defined for LIBMESH_DIM=3"); } template void EigenDecompositionMaterialTempl::computeQpProperties() { + + if (!_tensor[_qp].isSymmetric()) + mooseError("EigenDecompositionMaterial will only operate on symmetric rank two tensors."); + std::vector> eigval(3, 0.0); GenericRankTwoTensor eigvec; diff --git a/modules/solid_mechanics/test/tests/eigen_decomp_material/gold/prescribed_strain_3D_out.e b/modules/solid_mechanics/test/tests/eigen_decomp_material/gold/prescribed_strain_3D_out.e index c0ccfe328799020940439ef6f4921ae62ecf4f36..b646464ffc5bcc617510112f07543eebb438f111 100644 GIT binary patch delta 2185 zcma)4e{2(F7~Xe`l}Jb1f!p}GnlYoYLfZ`(8*nU)$QXkn0U>VQZtb`BLfh-EEmr=} z4K`&22=J=62!x@;%^%?KkTQmLB!FPh3?YUnkV+af#=t5GAPL}o*E<4Z1~1n>ec$JK zpYQqJG_gHnq1BnaDZ7a!z!pDPzUV z8wLm*fkJ}}ec&N*8uk(Bhd6ls1#exNa7c{i+Yvr1AVY%Vu>O;KX^jKVYE$75$XCR!PpKo4?h2YewQ`10KRRqR@ zNl;o9&S|KhX?IPZSyEDB=KW^7)n06|*)3MsTb(Uks;Wh!U&StS1$LUv#b#SksclxN zZ6@rlE`Y}Bv4c5#X|Yw>U43@$@CsZXc0-b@5*Z)Le|9+zg#${j+!^9{ze-;o54BsK zgSur_IIv|Ibl=k%0s`;E!64(}eJtk>f@$xZ;Vy;^N1*ZYIB^?=Y&jnO4Te>07#9v; zzYF`F91g!w5JS5;$cL*rR1*6beVMGfW~eyx_tD zl)p7cuMiDkzf)c!Z2x_CwAZr2!#3mR z1)qH0`7$H%eUt*zsk!iF;$w;1{FixzllKL}A~nKZf!t?Vtf(Gh<@9E?oiO(YZo7|D3APzI_l9TDmr2X`U(vtjLO1a zsc5ohD82*R3BM)%iAkAx?1&v0sWMIn)+yST0Kvk zxE|$+`$pYCrj~uku^t0bbFb*rV(R?vJa74*;h-`OkLKT-Dh6j3J; zEmcLd>O!jq^w9lImG9KzXmeUE>fc4DU!W7$_rJXBm-+M!+l5Q_rsUIS+ol~goSLAi zVmFtx@7#3vn4CX%VeFqtg)O$q4KY=u4QXP{ET)=iI*otSETEdL*F^tmrY6u1e|X5_ d{q^*3*wX&lgG~C$b>)fOUhVzj$ZOZM`d?*zbIbq$ delta 1734 zcma)&e@qi+9LDz^g>HaI5v90}p4JgJDE3N$(4bc$5*HvX@?#iTSm`=xD7{(=aYS&A zs6@AA+m~@BBZDmd!Im*`hgPQvWkRQ&TQxS@{veSq;1Wkn7fpuAe%)K%V(jMN{JlJr#1 zX_&+K9Oz^bVmmnbktm zTAC@)YYOyC5!|bK9=@*1d~BAlXA1QNI^kZ`^&LVAEYO1PvKPU(-zgxR77t@x@xtu6 zc?7BZ5_nTRst`=xal{WDK%WS+{v0ISyz+PCRST3)2{)#-g68~(kLI_p3-=lw zy|&Y}<~Qt|Yu7=i+0iZh*j zOo0-?c&GwLzL3syM-jt2k0QAkF2@g==$nZ*9Yfcow|bws+qu^V&a_NvpmY8Q*=;9p zIF2%<7q+}r`SF(&42y%+m`udPk`$H%uq)_Kkt=r3z)$ueCBM55eJY**>`$L0l(wq*5=8yxnWrz;i|!FWKlTo~y4CQ~#@4!rAtf6+ zmNT*-RZZOW*)Mc$AB=7pN-q@$KH9g351&9A%S$>K|H}`fo(ZzE>|M&rit6nDWjSzG wL;MO^%INv*ou#u$->k>=hIqra4VyCR&<1benVU2HwmpW@(cs*#{^F?bALC!Q@&Et; diff --git a/modules/solid_mechanics/test/tests/eigen_decomp_material/pipe_2d.i b/modules/solid_mechanics/test/tests/eigen_decomp_material/pipe_2d.i index 96ef061df9ab..49af09f8fd22 100644 --- a/modules/solid_mechanics/test/tests/eigen_decomp_material/pipe_2d.i +++ b/modules/solid_mechanics/test/tests/eigen_decomp_material/pipe_2d.i @@ -1,3 +1,5 @@ + +# pipe with outer diameter = 24", wall thickness 0.979" # units in MPa, meters [GlobalParams] order = SECOND @@ -36,9 +38,6 @@ new_system = true formulation = TOTAL volumetric_locking_correction = false - # generate_output = "cauchy_stress_xx cauchy_stress_yy cauchy_stress_zz cauchy_stress_xy " - # "cauchy_stress_xz cauchy_stress_yz strain_xx strain_yy strain_zz strain_xy " - # "strain_xz strain_yz vonmises_cauchy_stress" [] [] [] @@ -81,7 +80,7 @@ [top] type = EqualValueBoundaryConstraint variable = disp_y - secondary = top #sideset on top boundary + secondary = top penalty = 1e+14 formulation = penalty [] diff --git a/modules/solid_mechanics/test/tests/eigen_decomp_material/prescribed_strain_3D.i b/modules/solid_mechanics/test/tests/eigen_decomp_material/prescribed_strain_3D.i index 280edfeda5d6..cc3d406baa51 100644 --- a/modules/solid_mechanics/test/tests/eigen_decomp_material/prescribed_strain_3D.i +++ b/modules/solid_mechanics/test/tests/eigen_decomp_material/prescribed_strain_3D.i @@ -1,3 +1,7 @@ +[Debug] + show_material_props = true +[] + [Problem] kernel_coverage_check = false solve = false @@ -25,6 +29,8 @@ [] [AuxKernels] + # The applied displacements will cause the max eigenvector to change directions. + # At t=5, the body undergoes simple shear, producing a nonsymmetric deformation gradient. [disp_x] execute_on = 'TIMESTEP_BEGIN' type = ParsedAux @@ -49,30 +55,37 @@ [] [Materials] - [strain] - type = ADComputeFiniteStrain + [compute_strain] + type = ComputeLagrangianStrain displacements = 'disp_x disp_y disp_z' + large_kinematics = true [] [nonAD_strain] type = RankTwoTensorMaterialADConverter - ad_props_in = mechanical_strain - reg_props_out = nonAD_mechanical_strain + reg_props_in = mechanical_strain + ad_props_out = AD_mechanical_strain [] [eig_decomp] type = ADEigenDecompositionMaterial - rank_two_tensor = mechanical_strain + rank_two_tensor = AD_mechanical_strain outputs = exodus output_properties = "max_eigen_vector mid_eigen_vector min_eigen_vector max_eigen_value " "mid_eigen_value min_eigen_value" [] [nonADeig_decomp] type = EigenDecompositionMaterial - rank_two_tensor = nonAD_mechanical_strain + rank_two_tensor = mechanical_strain base_name = nonAD outputs = exodus output_properties = "nonAD_max_eigen_vector nonAD_mid_eigen_vector nonAD_min_eigen_vector " "nonAD_max_eigen_value nonAD_mid_eigen_value nonAD_min_eigen_value" [] + + [non_symmetric_eig_decomp_error] + type = EigenDecompositionMaterial + rank_two_tensor = deformation_gradient + base_name = nonSym + [] [] [BCs] @@ -87,30 +100,30 @@ [Postprocessors] [sxx] - type = ADMaterialTensorAverage + type = MaterialTensorAverage rank_two_tensor = mechanical_strain index_i = 0 index_j = 0 execute_on = 'TIMESTEP_END' [] [sxy] - type = ADMaterialTensorAverage + type = MaterialTensorAverage rank_two_tensor = mechanical_strain index_i = 0 index_j = 1 execute_on = 'TIMESTEP_END' [] [syy] - type = ADMaterialTensorAverage + type = MaterialTensorAverage rank_two_tensor = mechanical_strain index_i = 1 index_j = 1 [] [szz] - type = ADMaterialTensorAverage + type = MaterialTensorAverage rank_two_tensor = mechanical_strain - index_i = 2 - index_j = 2 + index_i = 1 + index_j = 0 [] [AD_eigval_max] type = ADElementAverageMaterialProperty diff --git a/modules/solid_mechanics/test/tests/eigen_decomp_material/tests b/modules/solid_mechanics/test/tests/eigen_decomp_material/tests index 8c7021a65196..a4e5067db1b0 100644 --- a/modules/solid_mechanics/test/tests/eigen_decomp_material/tests +++ b/modules/solid_mechanics/test/tests/eigen_decomp_material/tests @@ -1,17 +1,24 @@ [Tests] - design = 'source/materials/EigenDecompMaterial.md' + design = 'source/materials/EigenDecompositionMaterial.md' issues = '#29179' - requirement = 'The system shall output eigen decompositions of tensors in ' + requirement = 'The system shall output an eigen decomposition of a symmetric rank two tensor ' [3D] type = Exodiff input = prescribed_strain_3D.i exodiff = prescribed_strain_3D_out.e - detail = 'a 3D simulation with an evolving rank two tensor.' + cli_args = 'Materials/inactive=non_symmetric_eig_decomp_error' + detail = 'in a 3D simulation with an evolving strain field.' + [] + [nonSymmetricError] + type = RunException + input = 'prescribed_strain_3D.i' + expect_err = 'EigenDecompositionMaterial will only operate on symmetric rank two tensors.' + requirement = 'The system shall produce an error if the rank two tensor is unsymmetric.' [] [2Drz] type = Exodiff input = pipe_2d.i exodiff =pipe_2d_out.e - detail = 'a 2D radial symmetry simulation of a pressurized pipe.' + detail = 'in a 2D radial symmetry simulation of a pressurized pipe.' [] [] From fcf45b1109e17c446546d619caee87d1e1a7bdfc Mon Sep 17 00:00:00 2001 From: Lynn Munday Date: Wed, 4 Dec 2024 21:41:30 -0700 Subject: [PATCH 5/5] fixing sqa failure --- .../solid_mechanics/test/tests/eigen_decomp_material/tests | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/modules/solid_mechanics/test/tests/eigen_decomp_material/tests b/modules/solid_mechanics/test/tests/eigen_decomp_material/tests index a4e5067db1b0..57c61578bfa7 100644 --- a/modules/solid_mechanics/test/tests/eigen_decomp_material/tests +++ b/modules/solid_mechanics/test/tests/eigen_decomp_material/tests @@ -1,13 +1,12 @@ [Tests] design = 'source/materials/EigenDecompositionMaterial.md' issues = '#29179' - requirement = 'The system shall output an eigen decomposition of a symmetric rank two tensor ' [3D] type = Exodiff input = prescribed_strain_3D.i exodiff = prescribed_strain_3D_out.e cli_args = 'Materials/inactive=non_symmetric_eig_decomp_error' - detail = 'in a 3D simulation with an evolving strain field.' + requirement = 'The system shall output an eigen decomposition of a symmetric rank two tensor in a 3D simulation with an evolving strain field.' [] [nonSymmetricError] type = RunException @@ -19,6 +18,6 @@ type = Exodiff input = pipe_2d.i exodiff =pipe_2d_out.e - detail = 'in a 2D radial symmetry simulation of a pressurized pipe.' + requirement = 'The system shall output an eigen decomposition of a symmetric rank two tensor in a 2D radial symmetry simulation of a pressurized pipe.' [] []