LCOV - code coverage report
Current view: top level - src/actions - GeneralizedPlaneStrainAction.C (source / functions) Hit Total Coverage
Test: idaholab/moose solid_mechanics: #33416 (b10b36) with base 9fbd27 Lines: 139 158 88.0 %
Date: 2026-07-23 16:20:48 Functions: 4 4 100.0 %
Legend: Lines: hit not hit

          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             : #include "GeneralizedPlaneStrainAction.h"
      11             : 
      12             : #include "Conversion.h"
      13             : #include "FEProblem.h"
      14             : #include "MooseMesh.h"
      15             : #include "MooseVariableFE.h"
      16             : #include "NonlinearSystemBase.h"
      17             : 
      18             : #include <set>
      19             : 
      20             : registerMooseAction("SolidMechanicsApp", GeneralizedPlaneStrainAction, "add_scalar_kernel");
      21             : 
      22             : registerMooseAction("SolidMechanicsApp", GeneralizedPlaneStrainAction, "add_kernel");
      23             : 
      24             : registerMooseAction("SolidMechanicsApp", GeneralizedPlaneStrainAction, "add_user_object");
      25             : 
      26             : registerMooseAction("SolidMechanicsApp", GeneralizedPlaneStrainAction, "add_variables_physics");
      27             : 
      28             : InputParameters
      29         264 : GeneralizedPlaneStrainAction::validParams()
      30             : {
      31         264 :   InputParameters params = Action::validParams();
      32         264 :   params.addClassDescription("Set up the GeneralizedPlaneStrain environment");
      33         528 :   params.addRequiredParam<std::vector<VariableName>>("displacements", "The displacement variables");
      34         528 :   params.addRequiredParam<VariableName>("scalar_out_of_plane_strain",
      35             :                                         "Scalar variable for the out-of-plane strain (in "
      36             :                                         "y direction for 1D Axisymmetric or in z "
      37             :                                         "direction for 2D Cartesian problems)");
      38         528 :   params.addParam<std::vector<VariableName>>("temperature", "The temperature variable");
      39         528 :   MooseEnum outOfPlaneDirection("x y z", "z");
      40         528 :   params.addParam<MooseEnum>(
      41             :       "out_of_plane_direction", outOfPlaneDirection, "The direction of the out-of-plane strain.");
      42         528 :   params.addParam<FunctionName>(
      43             :       "out_of_plane_pressure_function",
      44             :       "Function used to prescribe pressure (applied toward the body) in the out-of-plane direction "
      45             :       "(y for 1D Axisymmetric or z for 2D Cartesian problems)");
      46         528 :   params.addDeprecatedParam<FunctionName>(
      47             :       "out_of_plane_pressure",
      48             :       "Function used to prescribe pressure (applied toward the body) in the out-of-plane direction "
      49             :       "(y for 1D Axisymmetric or z for 2D Cartesian problems)",
      50             :       "This has been replaced by 'out_of_plane_pressure_function'");
      51         528 :   params.addParam<MaterialPropertyName>("out_of_plane_pressure_material",
      52             :                                         "0",
      53             :                                         "Material used to prescribe pressure (applied toward the "
      54             :                                         "body) in the out-of-plane direction");
      55         528 :   params.addDeprecatedParam<Real>(
      56             :       "factor",
      57             :       "Scale factor applied to prescribed out-of-plane pressure (both material and function)",
      58             :       "This has been replaced by 'pressure_factor'");
      59         528 :   params.addParam<Real>(
      60             :       "pressure_factor",
      61             :       "Scale factor applied to prescribed out-of-plane pressure (both material and function)");
      62         528 :   params.addParam<bool>("use_displaced_mesh", false, "Whether to use displaced mesh");
      63         528 :   params.addParam<std::string>("base_name", "Material property base name");
      64         528 :   params.addParam<std::vector<SubdomainName>>("block",
      65             :                                               "The list of ids of the blocks (subdomain) "
      66             :                                               "that the GeneralizedPlaneStrain kernels "
      67             :                                               "will be applied to");
      68         528 :   params.addParam<std::vector<TagName>>(
      69             :       "extra_vector_tags",
      70             :       "The tag names for extra vectors that residual data should be saved into");
      71         528 :   params.addParam<std::vector<TagName>>("absolute_value_vector_tags",
      72             :                                         "The tag names for extra vectors that the absolute value "
      73             :                                         "of the residual should be accumulated into");
      74         528 :   params.addParam<bool>("use_automatic_differentiation",
      75         528 :                         false,
      76             :                         "Use automatic differentiation to assemble the generalized plane strain "
      77             :                         "equation and its coupling terms");
      78             : 
      79         264 :   return params;
      80         264 : }
      81             : 
      82         264 : GeneralizedPlaneStrainAction::GeneralizedPlaneStrainAction(const InputParameters & params)
      83             :   : Action(params),
      84         528 :     _displacements(getParam<std::vector<VariableName>>("displacements")),
      85         264 :     _ndisp(_displacements.size()),
      86         528 :     _out_of_plane_direction(getParam<MooseEnum>("out_of_plane_direction")),
      87         792 :     _use_ad(getParam<bool>("use_automatic_differentiation"))
      88             : {
      89         264 : }
      90             : 
      91             : unsigned int
      92         384 : GeneralizedPlaneStrainAction::inPlaneDisplacementIndex() const
      93             : {
      94         425 :   for (unsigned int i = 0; i < _ndisp; ++i)
      95         425 :     if (i != _out_of_plane_direction)
      96         384 :       return i;
      97             : 
      98           0 :   paramError("displacements", "No in-plane displacement is available to anchor the action");
      99             : }
     100             : 
     101             : void
     102        1056 : GeneralizedPlaneStrainAction::act()
     103             : {
     104             :   // user object name
     105        1056 :   const std::string uo_name = _name + "_GeneralizedPlaneStrainUserObject";
     106             : 
     107        1056 :   if (_current_task == "add_variables_physics")
     108             :   {
     109         264 :     if (_use_ad)
     110             :     {
     111             :       std::set<SubdomainID> block_ids;
     112         240 :       if (isParamValid("block"))
     113         279 :         for (const auto & block : getParam<std::vector<SubdomainName>>("block"))
     114             :         {
     115          69 :           const auto id = _mesh->getSubdomainID(block);
     116          69 :           if (id == Moose::INVALID_BLOCK_ID)
     117           0 :             paramError("block", "Subdomain '", block, "' was not found in the mesh");
     118          69 :           block_ids.insert(id);
     119             :         }
     120             : 
     121         120 :       const auto & subdomains = block_ids.empty() ? _problem->mesh().meshSubdomains() : block_ids;
     122         120 :       if (subdomains.empty())
     123           0 :         mooseError("No subdomains found for the generalized plane strain action");
     124             : 
     125         120 :       const auto coord_system = _problem->getCoordSystem(*subdomains.begin());
     126         240 :       for (const auto subdomain : subdomains)
     127         120 :         if (_problem->getCoordSystem(subdomain) != coord_system)
     128           0 :           paramError("block",
     129             :                      "Generalized plane strain requires all selected subdomains to use the same "
     130             :                      "coordinate system");
     131             : 
     132         120 :       if (coord_system == Moose::COORD_RZ)
     133             :       {
     134          21 :         if (_ndisp != 1)
     135           0 :           paramError("displacements",
     136             :                      "One radial displacement is required for 1D axisymmetric generalized plane "
     137             :                      "strain");
     138             :       }
     139          99 :       else if (coord_system == Moose::COORD_XYZ)
     140             :       {
     141          99 :         const unsigned int required_displacements = _out_of_plane_direction == 2 ? 2 : 3;
     142          99 :         if (_ndisp != required_displacements)
     143           0 :           paramError("displacements",
     144             :                      required_displacements,
     145             :                      " displacement variables are required when the out-of-plane direction is ",
     146             :                      getParam<MooseEnum>("out_of_plane_direction"));
     147             :       }
     148             :       else
     149           0 :         paramError("out_of_plane_direction",
     150             :                    "Generalized plane strain supports only Cartesian and axisymmetric coordinate "
     151             :                    "systems");
     152             :     }
     153             : 
     154         264 :     const auto anchor_displacement = inPlaneDisplacementIndex();
     155         264 :     const auto & anchor_variable = _problem->getVariable(
     156         264 :         0, _displacements[anchor_displacement], Moose::VarKindType::VAR_SOLVER);
     157         264 :     const auto solver_sys_num = anchor_variable.sys().number();
     158         264 :     if (!_problem->isSolverSystemNonlinear(solver_sys_num))
     159           0 :       paramError("displacements", "The in-plane displacements must be nonlinear variables");
     160             : 
     161         802 :     for (unsigned int i = 0; i < _ndisp; ++i)
     162        1020 :       if (i != _out_of_plane_direction &&
     163         482 :           _problem->getVariable(0, _displacements[i], Moose::VarKindType::VAR_SOLVER)
     164             :                   .sys()
     165         482 :                   .number() != solver_sys_num)
     166           0 :         paramError("displacements",
     167             :                    "All in-plane displacements must belong to the same nonlinear system");
     168             : 
     169         264 :     auto & nonlinear_system = _problem->getNonlinearSystemBase(solver_sys_num);
     170         264 :     const auto & scalar_variable = getParam<VariableName>("scalar_out_of_plane_strain");
     171         264 :     if (nonlinear_system.hasScalarVariable(scalar_variable))
     172         247 :       return;
     173          17 :     if (_problem->hasScalarVariable(scalar_variable))
     174           0 :       paramError("scalar_out_of_plane_strain",
     175             :                  "Variable '",
     176             :                  scalar_variable,
     177             :                  "' already exists but is not a nonlinear scalar variable in system '",
     178           0 :                  nonlinear_system.name(),
     179             :                  "'");
     180          17 :     if (_problem->hasVariable(scalar_variable))
     181           0 :       paramError("scalar_out_of_plane_strain",
     182             :                  "Variable '",
     183             :                  scalar_variable,
     184             :                  "' already exists as a field variable; a scalar variable is required");
     185             : 
     186          17 :     InputParameters params = _factory.getValidParams("MooseVariableScalar");
     187          34 :     params.set<MooseEnum>("family") = "SCALAR";
     188          34 :     params.set<MooseEnum>("order") = "FIRST";
     189          51 :     params.set<SolverSystemName>("solver_sys") = nonlinear_system.name();
     190          17 :     _problem->addVariable("MooseVariableScalar", scalar_variable, params);
     191          17 :   }
     192             : 
     193             :   //
     194             :   // Add off diagonal Jacobian kernels
     195             :   //
     196         792 :   else if (_current_task == "add_kernel" && _use_ad)
     197             :   {
     198         120 :     const std::string k_type = "ADGeneralizedPlaneStrain";
     199         120 :     InputParameters params = _factory.getValidParams(k_type);
     200             : 
     201         120 :     params.applyParameters(parameters(),
     202             :                            {"scalar_out_of_plane_strain",
     203             :                             "out_of_plane_pressure",
     204             :                             "out_of_plane_pressure_function",
     205             :                             "factor",
     206             :                             "pressure_factor"});
     207         240 :     params.set<std::vector<VariableName>>("scalar_out_of_plane_strain") = {
     208         480 :         getParam<VariableName>("scalar_out_of_plane_strain")};
     209             : 
     210         240 :     if (parameters().isParamSetByUser("out_of_plane_pressure"))
     211           0 :       params.set<FunctionName>("out_of_plane_pressure") =
     212           0 :           getParam<FunctionName>("out_of_plane_pressure");
     213         240 :     if (parameters().isParamSetByUser("out_of_plane_pressure_function"))
     214          30 :       params.set<FunctionName>("out_of_plane_pressure_function") =
     215          30 :           getParam<FunctionName>("out_of_plane_pressure_function");
     216         240 :     if (parameters().isParamSetByUser("factor"))
     217           0 :       params.set<Real>("factor") = getParam<Real>("factor");
     218         240 :     if (parameters().isParamSetByUser("pressure_factor"))
     219          30 :       params.set<Real>("pressure_factor") = getParam<Real>("pressure_factor");
     220             : 
     221         120 :     const auto anchor_displacement = inPlaneDisplacementIndex();
     222         240 :     params.set<NonlinearVariableName>("variable") = _displacements[anchor_displacement];
     223         120 :     _problem->addKernel(k_type, _name + "_ADGeneralizedPlaneStrain", params);
     224         120 :   }
     225         672 :   else if (_use_ad && (_current_task == "add_user_object" || _current_task == "add_scalar_kernel"))
     226             :   {
     227             :     // ADKernelScalarBase assembles both the elemental resultant and the scalar equation, so the
     228             :     // legacy UserObject and ScalarKernel are intentionally unnecessary in AD mode.
     229             :   }
     230         432 :   else if (_current_task == "add_kernel")
     231             :   {
     232         144 :     std::string k_type = "GeneralizedPlaneStrainOffDiag";
     233         144 :     InputParameters params = _factory.getValidParams(k_type);
     234             : 
     235         144 :     params.applyParameters(parameters(), {"scalar_out_of_plane_strain"});
     236         288 :     params.set<std::vector<VariableName>>("scalar_out_of_plane_strain") = {
     237         576 :         getParam<VariableName>("scalar_out_of_plane_strain")};
     238             : 
     239             :     // add off-diagonal jacobian kernels for the displacements
     240         437 :     for (unsigned int i = 0; i < _ndisp; ++i)
     241             :     {
     242         293 :       if (_out_of_plane_direction == i)
     243          30 :         continue;
     244             : 
     245         526 :       std::string k_name = _name + "GeneralizedPlaneStrainOffDiag_disp" + Moose::stringify(i);
     246         526 :       params.set<NonlinearVariableName>("variable") = _displacements[i];
     247             : 
     248         263 :       _problem->addKernel(k_type, k_name, params);
     249             :     }
     250             : 
     251             :     // add temperature kernel only if temperature is a nonlinear variable (and not an auxvariable)
     252         288 :     if (isParamValid("temperature"))
     253             :     {
     254          96 :       auto temp = getParam<std::vector<VariableName>>("temperature");
     255          32 :       if (temp.size() > 1)
     256           0 :         mooseError("Only one variable may be specified in 'temperature'");
     257          32 :       if (_problem->getNonlinearSystemBase(/*nl_sys_num=*/0).hasVariable(temp[0]))
     258             :       {
     259          12 :         std::string k_name = _name + "_GeneralizedPlaneStrainOffDiag_temp";
     260          24 :         params.set<NonlinearVariableName>("variable") = temp[0];
     261             : 
     262          12 :         _problem->addKernel(k_type, k_name, params);
     263             :       }
     264          32 :     }
     265         144 :   }
     266             : 
     267             :   //
     268             :   // Add user object
     269             :   //
     270         288 :   else if (_current_task == "add_user_object")
     271             :   {
     272         144 :     std::string uo_type = "GeneralizedPlaneStrainUserObject";
     273         144 :     InputParameters params = _factory.getValidParams(uo_type);
     274             : 
     275             :     // Skipping selected parameters in applyParameters() and then manually setting them only if they
     276             :     // are set by the user is just to prevent both the current and deprecated variants of these
     277             :     // parameters from both getting passed to the UserObject. Once we get rid of the deprecated
     278             :     // versions, we can just set them all with applyParameters().
     279         144 :     params.applyParameters(
     280             :         parameters(),
     281             :         {"out_of_plane_pressure", "out_of_plane_pressure_function", "factor", "pressure_factor"});
     282         288 :     if (parameters().isParamSetByUser("out_of_plane_pressure"))
     283           0 :       params.set<FunctionName>("out_of_plane_pressure") =
     284           0 :           getParam<FunctionName>("out_of_plane_pressure");
     285         288 :     if (parameters().isParamSetByUser("out_of_plane_pressure_function"))
     286          24 :       params.set<FunctionName>("out_of_plane_pressure_function") =
     287          24 :           getParam<FunctionName>("out_of_plane_pressure_function");
     288         288 :     if (parameters().isParamSetByUser("factor"))
     289           0 :       params.set<Real>("factor") = getParam<Real>("factor");
     290         288 :     if (parameters().isParamSetByUser("pressure_factor"))
     291          24 :       params.set<Real>("pressure_factor") = getParam<Real>("pressure_factor");
     292             : 
     293         144 :     _problem->addUserObject(uo_type, uo_name, params);
     294         144 :   }
     295             : 
     296             :   //
     297             :   // Add scalar kernel
     298             :   //
     299         144 :   else if (_current_task == "add_scalar_kernel")
     300             :   {
     301         144 :     std::string sk_type = "GeneralizedPlaneStrain";
     302         144 :     InputParameters params = _factory.getValidParams(sk_type);
     303             : 
     304         288 :     params.set<NonlinearVariableName>("variable") =
     305         432 :         getParam<VariableName>("scalar_out_of_plane_strain");
     306             : 
     307             :     // set the UserObjectName from previously added UserObject
     308         288 :     params.set<UserObjectName>("generalized_plane_strain") = uo_name;
     309             : 
     310         288 :     if (isParamValid("extra_vector_tags"))
     311           8 :       params.set<std::vector<TagName>>("extra_vector_tags") =
     312          12 :           getParam<std::vector<TagName>>("extra_vector_tags");
     313         288 :     if (isParamValid("absolute_value_vector_tags"))
     314          16 :       params.set<std::vector<TagName>>("absolute_value_vector_tags") =
     315          24 :           getParam<std::vector<TagName>>("absolute_value_vector_tags");
     316             : 
     317         144 :     _problem->addScalarKernel(sk_type, _name + "_GeneralizedPlaneStrain", params);
     318         144 :   }
     319         528 : }

Generated by: LCOV version 1.14