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 : }
|