https://mooseframework.inl.gov
Loading...
Searching...
No Matches
GeneralizedPlaneStrainAction.C
Go to the documentation of this file.
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
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
20registerMooseAction("SolidMechanicsApp", GeneralizedPlaneStrainAction, "add_scalar_kernel");
21
22registerMooseAction("SolidMechanicsApp", GeneralizedPlaneStrainAction, "add_kernel");
23
24registerMooseAction("SolidMechanicsApp", GeneralizedPlaneStrainAction, "add_user_object");
25
26registerMooseAction("SolidMechanicsApp", GeneralizedPlaneStrainAction, "add_variables_physics");
27
30{
32 params.addClassDescription("Set up the GeneralizedPlaneStrain environment");
33 params.addRequiredParam<std::vector<VariableName>>("displacements", "The displacement variables");
34 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 params.addParam<std::vector<VariableName>>("temperature", "The temperature variable");
39 MooseEnum outOfPlaneDirection("x y z", "z");
40 params.addParam<MooseEnum>(
41 "out_of_plane_direction", outOfPlaneDirection, "The direction of the out-of-plane strain.");
42 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 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 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 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 params.addParam<Real>(
60 "pressure_factor",
61 "Scale factor applied to prescribed out-of-plane pressure (both material and function)");
62 params.addParam<bool>("use_displaced_mesh", false, "Whether to use displaced mesh");
63 params.addParam<std::string>("base_name", "Material property base name");
64 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 params.addParam<std::vector<TagName>>(
69 "extra_vector_tags",
70 "The tag names for extra vectors that residual data should be saved into");
71 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 params.addParam<bool>("use_automatic_differentiation",
75 false,
76 "Use automatic differentiation to assemble the generalized plane strain "
77 "equation and its coupling terms");
78
79 return params;
80}
81
83 : Action(params),
84 _displacements(getParam<std::vector<VariableName>>("displacements")),
85 _ndisp(_displacements.size()),
86 _out_of_plane_direction(getParam<MooseEnum>("out_of_plane_direction")),
87 _use_ad(getParam<bool>("use_automatic_differentiation"))
88{
89}
90
91unsigned int
93{
94 for (unsigned int i = 0; i < _ndisp; ++i)
96 return i;
97
98 paramError("displacements", "No acceptable in-plane displacement found");
99}
100
101void
103{
104 // user object name
105 const std::string uo_name = _name + "_GeneralizedPlaneStrainUserObject";
106
107 if (_current_task == "add_variables_physics")
108 {
109 std::set<SubdomainID> block_ids;
110 if (isParamValid("block"))
111 for (const auto & block : getParam<std::vector<SubdomainName>>("block"))
112 {
113 const auto id = _mesh->getSubdomainID(block);
114 if (id == Moose::INVALID_BLOCK_ID)
115 paramError("block", "Subdomain '", block, "' was not found in the mesh");
116 block_ids.insert(id);
117 }
118
119 const auto & subdomains = block_ids.empty() ? _problem->mesh().meshSubdomains() : block_ids;
120 if (subdomains.empty())
121 mooseError("No subdomains found for the generalized plane strain action");
122
123 const auto coord_system = _problem->getCoordSystem(*subdomains.begin());
124 for (const auto subdomain : subdomains)
125 if (_problem->getCoordSystem(subdomain) != coord_system)
126 paramError("block",
127 "Generalized plane strain requires all selected subdomains to use the same "
128 "coordinate system");
129
130 if (coord_system == Moose::COORD_RZ)
131 {
132 if (_ndisp != 1)
133 paramError("displacements",
134 "One radial displacement is required for 1D axisymmetric generalized plane "
135 "strain");
136 }
137 else if (coord_system == Moose::COORD_XYZ)
138 {
139 const unsigned int required_displacements = _out_of_plane_direction == 2 ? 2 : 3;
140 if (_ndisp != required_displacements)
141 paramError("displacements",
142 required_displacements,
143 " displacement variables are required when the out-of-plane direction is ",
144 getParam<MooseEnum>("out_of_plane_direction"));
145 }
146 else
147 paramError("out_of_plane_direction",
148 "Generalized plane strain supports only Cartesian and axisymmetric coordinate "
149 "systems");
150
151 const auto first_in_plane_disp = firstInPlaneDisplacementIndex();
152 const auto & first_in_plane_variable = _problem->getVariable(
153 0, _displacements[first_in_plane_disp], Moose::VarKindType::VAR_SOLVER);
154 const auto solver_sys_num = first_in_plane_variable.sys().number();
155 if (!_problem->isSolverSystemNonlinear(solver_sys_num))
156 paramError("displacements", "The in-plane displacements must be nonlinear variables");
157
158 for (unsigned int i = 0; i < _ndisp; ++i)
159 if (i != _out_of_plane_direction &&
160 _problem->getVariable(0, _displacements[i], Moose::VarKindType::VAR_SOLVER)
161 .sys()
162 .number() != solver_sys_num)
163 paramError("displacements",
164 "All in-plane displacements must belong to the same nonlinear system");
165
166 auto & nonlinear_system = _problem->getNonlinearSystemBase(solver_sys_num);
167 const auto & scalar_variable = getParam<VariableName>("scalar_out_of_plane_strain");
168 if (nonlinear_system.hasScalarVariable(scalar_variable))
169 return;
170 if (_problem->hasScalarVariable(scalar_variable))
171 paramError("scalar_out_of_plane_strain",
172 "Variable '",
173 scalar_variable,
174 "' already exists but is not a nonlinear scalar variable in system '",
175 nonlinear_system.name(),
176 "'");
177 if (_problem->hasVariable(scalar_variable))
178 paramError("scalar_out_of_plane_strain",
179 "Variable '",
180 scalar_variable,
181 "' already exists as a field variable; a scalar variable is required");
182
183 InputParameters params = _factory.getValidParams("MooseVariableScalar");
184 params.set<MooseEnum>("family") = "SCALAR";
185 params.set<MooseEnum>("order") = "FIRST";
186 params.set<SolverSystemName>("solver_sys") = nonlinear_system.name();
187 _problem->addVariable("MooseVariableScalar", scalar_variable, params);
188 }
189
190 //
191 // Add the scalar equation kernel (AD) or the off diagonal Jacobian kernels (non-AD)
192 //
193 else if (_current_task == "add_kernel")
194 {
195 if (_use_ad)
196 {
197 const std::string k_type = "ADGeneralizedPlaneStrain";
198 InputParameters params = _factory.getValidParams(k_type);
199
200 params.applyParameters(parameters(), {"scalar_out_of_plane_strain"});
201 params.set<std::vector<VariableName>>("scalar_out_of_plane_strain") = {
202 getParam<VariableName>("scalar_out_of_plane_strain")};
203
204 // The kernel only carries the current parameter variants, so map the action's deprecated
205 // parameters onto them
206 if (parameters().isParamSetByUser("out_of_plane_pressure"))
207 {
208 if (parameters().isParamSetByUser("out_of_plane_pressure_function"))
209 paramError("out_of_plane_pressure_function",
210 "Cannot specify both 'out_of_plane_pressure_function' and "
211 "'out_of_plane_pressure'");
212 params.set<FunctionName>("out_of_plane_pressure_function") =
213 getParam<FunctionName>("out_of_plane_pressure");
214 }
215 if (parameters().isParamSetByUser("factor"))
216 {
217 if (parameters().isParamSetByUser("pressure_factor"))
218 paramError("pressure_factor", "Cannot specify both 'pressure_factor' and 'factor'");
219 params.set<Real>("pressure_factor") = getParam<Real>("factor");
220 }
221
222 const auto first_in_plane_disp = firstInPlaneDisplacementIndex();
223 params.set<NonlinearVariableName>("variable") = _displacements[first_in_plane_disp];
224 _problem->addKernel(k_type, _name + "_ADGeneralizedPlaneStrain", params);
225 }
226 else
227 {
228 std::string k_type = "GeneralizedPlaneStrainOffDiag";
229 InputParameters params = _factory.getValidParams(k_type);
230
231 params.applyParameters(parameters(), {"scalar_out_of_plane_strain"});
232 params.set<std::vector<VariableName>>("scalar_out_of_plane_strain") = {
233 getParam<VariableName>("scalar_out_of_plane_strain")};
234
235 // add off-diagonal jacobian kernels for the displacements
236 for (unsigned int i = 0; i < _ndisp; ++i)
237 {
239 continue;
240
241 std::string k_name = _name + "GeneralizedPlaneStrainOffDiag_disp" + Moose::stringify(i);
242 params.set<NonlinearVariableName>("variable") = _displacements[i];
243
244 _problem->addKernel(k_type, k_name, params);
245 }
246
247 // add temperature kernel only if temperature is a nonlinear variable (and not an auxvariable)
248 if (isParamValid("temperature"))
249 {
250 auto temp = getParam<std::vector<VariableName>>("temperature");
251 if (temp.size() > 1)
252 mooseError("Only one variable may be specified in 'temperature'");
253 if (_problem->getNonlinearSystemBase(/*nl_sys_num=*/0).hasVariable(temp[0]))
254 {
255 std::string k_name = _name + "_GeneralizedPlaneStrainOffDiag_temp";
256 params.set<NonlinearVariableName>("variable") = temp[0];
257
258 _problem->addKernel(k_type, k_name, params);
259 }
260 }
261 }
262 }
263
264 //
265 // Add user object
266 //
267 else if (_current_task == "add_user_object")
268 {
269 // ADKernelScalarBase assembles both the elemental resultant and the scalar equation, so the
270 // UserObject is not needed in AD mode
271 if (!_use_ad)
272 {
273 std::string uo_type = "GeneralizedPlaneStrainUserObject";
274 InputParameters params = _factory.getValidParams(uo_type);
275
276 // Skipping selected parameters in applyParameters() and then manually setting them only if
277 // they are set by the user is just to prevent both the current and deprecated variants of
278 // these parameters from both getting passed to the UserObject. Once we get rid of the
279 // deprecated versions, we can just set them all with applyParameters().
280 params.applyParameters(
281 parameters(),
282 {"out_of_plane_pressure", "out_of_plane_pressure_function", "factor", "pressure_factor"});
283 if (parameters().isParamSetByUser("out_of_plane_pressure"))
284 params.set<FunctionName>("out_of_plane_pressure") =
285 getParam<FunctionName>("out_of_plane_pressure");
286 if (parameters().isParamSetByUser("out_of_plane_pressure_function"))
287 params.set<FunctionName>("out_of_plane_pressure_function") =
288 getParam<FunctionName>("out_of_plane_pressure_function");
289 if (parameters().isParamSetByUser("factor"))
290 params.set<Real>("factor") = getParam<Real>("factor");
291 if (parameters().isParamSetByUser("pressure_factor"))
292 params.set<Real>("pressure_factor") = getParam<Real>("pressure_factor");
293
294 _problem->addUserObject(uo_type, uo_name, params);
295 }
296 }
297
298 //
299 // Add scalar kernel
300 //
301 else if (_current_task == "add_scalar_kernel")
302 {
303 // ADKernelScalarBase assembles the scalar equation directly, so the ScalarKernel is not
304 // needed in AD mode
305 if (!_use_ad)
306 {
307 std::string sk_type = "GeneralizedPlaneStrain";
308 InputParameters params = _factory.getValidParams(sk_type);
309
310 params.set<NonlinearVariableName>("variable") =
311 getParam<VariableName>("scalar_out_of_plane_strain");
312
313 // set the UserObjectName from previously added UserObject
314 params.set<UserObjectName>("generalized_plane_strain") = uo_name;
315
316 if (isParamValid("extra_vector_tags"))
317 params.set<std::vector<TagName>>("extra_vector_tags") =
318 getParam<std::vector<TagName>>("extra_vector_tags");
319 if (isParamValid("absolute_value_vector_tags"))
320 params.set<std::vector<TagName>>("absolute_value_vector_tags") =
321 getParam<std::vector<TagName>>("absolute_value_vector_tags");
322
323 _problem->addScalarKernel(sk_type, _name + "_GeneralizedPlaneStrain", params);
324 }
325 }
326}
registerMooseAction("SolidMechanicsApp", GeneralizedPlaneStrainAction, "add_scalar_kernel")
std::shared_ptr< MooseMesh > & _mesh
static InputParameters validParams()
std::shared_ptr< FEProblemBase > & _problem
const std::string & _current_task
InputParameters getValidParams(const std::string &name) const
std::vector< VariableName > _displacements
GeneralizedPlaneStrainAction(const InputParameters &params)
unsigned int _ndisp
Number of displacement variables.
unsigned int firstInPlaneDisplacementIndex() const
Return the first displacement component in the plane.
bool isParamSetByUser(const std::string &name) const
void addRequiredParam(const std::string &name, const std::string &doc_string)
void addDeprecatedParam(const std::string &name, const T &value, const std::string &doc_string, const std::string &deprecation_message)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
T & set(const std::string &name, bool quiet_mode=false)
void applyParameters(const InputParameters &common, const std::vector< std::string > &exclude={}, const bool allow_private=false)
const InputParameters & parameters() const
void paramError(const std::string &param, Args... args) const
bool isParamSetByUser(const std::string &name) const
void mooseError(Args &&... args) const
const std::string & _name
bool isParamValid(const std::string &name) const
Factory & _factory
std::string stringify(const T &t)
const SubdomainID INVALID_BLOCK_ID