www.mooseframework.org
TensorMechanicsAction.C
Go to the documentation of this file.
1 /****************************************************************/
2 /* MOOSE - Multiphysics Object Oriented Simulation Environment */
3 /* */
4 /* All contents are licensed under LGPL V2.1 */
5 /* See LICENSE for full restrictions */
6 /****************************************************************/
7 #include "Conversion.h"
8 #include "FEProblem.h"
9 #include "Factory.h"
10 #include "MooseMesh.h"
11 #include "MooseObjectAction.h"
12 #include "TensorMechanicsAction.h"
13 
14 #include "libmesh/string_to_enum.h"
15 #include <algorithm>
16 
17 template <>
18 InputParameters
20 {
21  InputParameters params = validParams<TensorMechanicsActionBase>();
22  params.addClassDescription("Set up stress divergence kernels with coordinate system aware logic");
23 
24  // parameters specified here only appear in the input file sub-blocks of the
25  // Master action, not in the common parameters area
26  params.addParam<std::vector<SubdomainName>>("block",
27  "The list of ids of the blocks (subdomain) "
28  "that the stress divergence kernels will be "
29  "applied to");
30  params.addParamNamesToGroup("block", "Advanced");
31 
32  params.addParam<MultiMooseEnum>("additional_generate_output",
34  "Add scalar quantity output for stress and/or strain (will be "
35  "appended to the list in `generate_output`)");
36  params.addParamNamesToGroup("additional_generate_output", "Output");
37 
38  return params;
39 }
40 
41 TensorMechanicsAction::TensorMechanicsAction(const InputParameters & params)
42  : TensorMechanicsActionBase(params),
43  _displacements(getParam<std::vector<NonlinearVariableName>>("displacements")),
44  _ndisp(_displacements.size()),
45  _coupled_displacements(_ndisp),
46  _save_in(getParam<std::vector<AuxVariableName>>("save_in")),
47  _diag_save_in(getParam<std::vector<AuxVariableName>>("diag_save_in")),
48  _subdomain_names(getParam<std::vector<SubdomainName>>("block")),
49  _subdomain_ids(),
50  _strain(getParam<MooseEnum>("strain").getEnum<Strain>()),
51  _planar_formulation(getParam<MooseEnum>("planar_formulation").getEnum<PlanarFormulation>())
52 {
53  // determine if incremental strains are to be used
54  if (isParamValid("incremental"))
55  {
56  const bool incremental = getParam<bool>("incremental");
57  if (!incremental && _strain == Strain::Small)
59  else if (!incremental && _strain == Strain::Finite)
61  else if (incremental && _strain == Strain::Small)
63  else if (incremental && _strain == Strain::Finite)
65  else
66  mooseError("Internal error");
67  }
68  else
69  {
70  if (_strain == Strain::Small)
72  else if (_strain == Strain::Finite)
74  else
75  mooseError("Internal error");
76  }
77 
78  // determine if displaced mesh is to be used
80  if (params.isParamSetByUser("use_displaced_mesh"))
81  {
82  bool use_displaced_mesh_param = getParam<bool>("use_displaced_mesh");
83  if (use_displaced_mesh_param != _use_displaced_mesh && params.isParamSetByUser("strain"))
84  mooseError("Wrong combination of use displaced mesh and strain model");
85  _use_displaced_mesh = use_displaced_mesh_param;
86  }
87 
88  // convert vector of NonlinearVariableName to vector of VariableName
89  for (unsigned int i = 0; i < _ndisp; ++i)
91 
92  if (_save_in.size() != 0 && _save_in.size() != _ndisp)
93  mooseError("Number of save_in variables should equal to the number of displacement variables ",
94  _ndisp);
95 
96  if (_diag_save_in.size() != 0 && _diag_save_in.size() != _ndisp)
97  mooseError(
98  "Number of diag_save_in variables should equal to the number of displacement variables ",
99  _ndisp);
100 
101  // plane strain consistency check
102  if (_planar_formulation != PlanarFormulation::None && _ndisp != 2)
103  mooseError("Plane strain only works in 2 dimensions");
104 
105  // convert output variable names to lower case
106  for (const auto & out : getParam<MultiMooseEnum>("generate_output"))
107  {
108  std::string lower(out);
109  std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
110  _generate_output.push_back(lower);
111  }
112 
113  // Error if volumetric locking correction is true for 1D problems
114  if (_ndisp == 1 && getParam<bool>("volumetric_locking_correction"))
115  mooseError("Volumetric locking correction should be set to false for 1D problems.");
116 }
117 
118 void
120 {
121  //
122  // Consistency check for the coordinate system
123  //
125 
126  //
127  // Gather info from all other TensorMechanicsAction
128  //
130 
131  //
132  // Deal with the optional AuxVariable based tensor quantity output
133  //
135 
136  //
137  // Meta action which optionally spawns other actions
138  //
139  if (_current_task == "meta_action")
140  {
142  {
143  // Set the action parameters
144  const std::string type = "GeneralizedPlaneStrainAction";
145  auto action_params = _action_factory.getValidParams(type);
146  action_params.set<bool>("_built_by_moose") = true;
147  action_params.set<std::string>("registered_identifier") = "(AutoBuilt)";
148  action_params.applyParameters(parameters(), {"use_displaced_mesh"});
149  action_params.set<bool>("use_displaced_mesh") = _use_displaced_mesh;
150  if (isParamValid("pressure_factor"))
151  action_params.set<Real>("factor") = getParam<Real>("pressure_factor");
152 
153  // Create and add the action to the warehouse
154  auto action = MooseSharedNamespace::static_pointer_cast<MooseObjectAction>(
155  _action_factory.create(type, name() + "_gps", action_params));
156  _awh.addActionBlock(action);
157  }
158  }
159 
160  //
161  // Add variables (optional)
162  //
163  else if (_current_task == "add_variable" && getParam<bool>("add_variables"))
164  {
165  // determine necessary order
166  const bool second = _problem->mesh().hasSecondOrderElements();
167 
168  // Loop through the displacement variables
169  for (const auto & disp : _displacements)
170  {
171  // Create displacement variables
172  _problem->addVariable(disp,
173  FEType(Utility::string_to_enum<Order>(second ? "SECOND" : "FIRST"),
174  Utility::string_to_enum<FEFamily>("LAGRANGE")),
175  1.0,
176  _subdomain_id_union.empty() ? nullptr : &_subdomain_id_union);
177  }
178  }
179 
180  //
181  // Add Strain Materials
182  //
183  else if (_current_task == "add_material")
184  {
185  std::string type;
186 
187  //
188  // no plane strain
189  //
191  {
192  std::map<std::pair<Moose::CoordinateSystemType, StrainAndIncrement>, std::string> type_map = {
193  {{Moose::COORD_XYZ, StrainAndIncrement::SmallTotal}, "ComputeSmallStrain"},
194  {{Moose::COORD_XYZ, StrainAndIncrement::SmallIncremental},
195  "ComputeIncrementalSmallStrain"},
196  {{Moose::COORD_XYZ, StrainAndIncrement::FiniteIncremental}, "ComputeFiniteStrain"},
197  {{Moose::COORD_RZ, StrainAndIncrement::SmallTotal}, "ComputeAxisymmetricRZSmallStrain"},
198  {{Moose::COORD_RZ, StrainAndIncrement::SmallIncremental},
199  "ComputeAxisymmetricRZIncrementalStrain"},
200  {{Moose::COORD_RZ, StrainAndIncrement::FiniteIncremental},
201  "ComputeAxisymmetricRZFiniteStrain"},
202  {{Moose::COORD_RSPHERICAL, StrainAndIncrement::SmallTotal},
203  "ComputeRSphericalSmallStrain"},
204  {{Moose::COORD_RSPHERICAL, StrainAndIncrement::SmallIncremental},
205  "ComputeRSphericalIncrementalStrain"},
206  {{Moose::COORD_RSPHERICAL, StrainAndIncrement::FiniteIncremental},
207  "ComputeRSphericalFiniteStrain"}};
208 
209  auto type_it = type_map.find(std::make_pair(_coord_system, _strain_and_increment));
210  if (type_it != type_map.end())
211  type = type_it->second;
212  else
213  mooseError("Unsupported strain formulation");
214  }
217  {
218  std::map<StrainAndIncrement, std::string> type_map = {
219  {StrainAndIncrement::SmallTotal, "ComputePlaneSmallStrain"},
220  {StrainAndIncrement::SmallIncremental, "ComputePlaneIncrementalStrain"},
221  {StrainAndIncrement::FiniteIncremental, "ComputePlaneFiniteStrain"}};
222 
223  // choose kernel type based on coordinate system
224  auto type_it = type_map.find(_strain_and_increment);
225  if (type_it != type_map.end())
226  type = type_it->second;
227  else
228  mooseError("Unsupported coordinate system for plane strain.");
229  }
230  else
231  mooseError("Unsupported planar formulation");
232 
233  // set material parameters
234  auto params = _factory.getValidParams(type);
235  params.applyParameters(parameters(),
236  {"displacements", "use_displaced_mesh", "scalar_out_of_plane_strain"});
237 
238  params.set<std::vector<VariableName>>("displacements") = _coupled_displacements;
239  params.set<bool>("use_displaced_mesh") = false;
240  if (isParamValid("scalar_out_of_plane_strain"))
241  params.set<std::vector<VariableName>>("scalar_out_of_plane_strain") = {
242  getParam<NonlinearVariableName>("scalar_out_of_plane_strain")};
243 
244  _problem->addMaterial(type, name() + "_strain", params);
245  }
246 
247  //
248  // Add Stress Divergence Kernels
249  //
250  else if (_current_task == "add_kernel")
251  {
252  auto tensor_kernel_type = getKernelType();
253  auto params = getKernelParameters(tensor_kernel_type);
254 
255  for (unsigned int i = 0; i < _ndisp; ++i)
256  {
257  std::string kernel_name = "TM_" + name() + Moose::stringify(i);
258 
259  params.set<unsigned int>("component") = i;
260  params.set<NonlinearVariableName>("variable") = _displacements[i];
261 
262  if (_save_in.size() == _ndisp)
263  params.set<std::vector<AuxVariableName>>("save_in") = {_save_in[i]};
264  if (_diag_save_in.size() == _ndisp)
265  params.set<std::vector<AuxVariableName>>("diag_save_in") = {_diag_save_in[i]};
266 
267  _problem->addKernel(tensor_kernel_type, kernel_name, params);
268  }
269  }
270 }
271 
272 void
274 {
275  //
276  // Do the coordinate system check only once the problem is created
277  //
278  if (_current_task == "setup_mesh_complete")
279  {
280  // get subdomain IDs
281  for (auto & name : _subdomain_names)
282  _subdomain_ids.insert(_mesh->getSubdomainID(name));
283  }
284 
285  if (_current_task == "validate_coordinate_systems")
286  {
287  // use either block restriction list or list of all subdomains in the mesh
288  const auto & check_subdomains =
289  _subdomain_ids.empty() ? _problem->mesh().meshSubdomains() : _subdomain_ids;
290  if (check_subdomains.empty())
291  mooseError("No subdomains found");
292 
293  // make sure all subdomains are using the same coordinate system
294  _coord_system = _problem->getCoordSystem(*check_subdomains.begin());
295  for (auto subdomain : check_subdomains)
296  if (_problem->getCoordSystem(subdomain) != _coord_system)
297  mooseError("The TensorMechanics action requires all subdomains to have the same coordinate "
298  "system.");
299  }
300 }
301 
302 void
304 {
305  //
306  // Add variables (optional)
307  //
308  if (_current_task == "add_aux_variable" && getParam<bool>("add_variables"))
309  {
310  // Loop through output aux variables
311  for (auto out : _generate_output)
312  {
313  // Create output helper aux variables
314  _problem->addAuxVariable(out,
315  FEType(Utility::string_to_enum<Order>("CONSTANT"),
316  Utility::string_to_enum<FEFamily>("MONOMIAL")),
317  _subdomain_id_union.empty() ? nullptr : &_subdomain_id_union);
318  }
319  }
320 
321  //
322  // Add output AuxKernels
323  //
324  else if (_current_task == "add_aux_kernel")
325  {
326  // Loop through output aux variables
327  for (auto out : _generate_output)
328  {
329  std::string type = "";
330  InputParameters params = emptyInputParameters();
331 
332  // RankTwoAux
333  for (const auto & r2a : _ranktwoaux_table)
334  for (unsigned int a = 0; a < 3; ++a)
335  for (unsigned int b = 0; b < 3; ++b)
336  if (r2a.first + '_' + _component_table[a] + _component_table[b] == out)
337  {
338  type = "RankTwoAux";
339  params = _factory.getValidParams(type);
340  params.set<MaterialPropertyName>("rank_two_tensor") = r2a.second;
341  params.set<unsigned int>("index_i") = a;
342  params.set<unsigned int>("index_j") = b;
343  }
344 
345  // RankTwoScalarAux
346  for (const auto & r2sa : _ranktwoscalaraux_table)
347  for (const auto & t : r2sa.second.second)
348  if (r2sa.first + '_' + t == out)
349  {
350  const auto r2a = _ranktwoaux_table.find(t);
351  if (r2a != _ranktwoaux_table.end())
352  {
353  type = "RankTwoScalarAux";
354  params = _factory.getValidParams(type);
355  params.set<MaterialPropertyName>("rank_two_tensor") = r2a->second;
356  params.set<MooseEnum>("scalar_type") = r2sa.second.first;
357  }
358  else
359  mooseError("Internal error. The permitted tensor shortcuts in "
360  "'_ranktwoscalaraux_table' must be keys in the '_ranktwoaux_table'.");
361  }
362 
363  if (type != "")
364  {
365  params.applyParameters(parameters());
366  params.set<AuxVariableName>("variable") = out;
367  params.set<MultiMooseEnum>("execute_on") = "timestep_end";
368  _problem->addAuxKernel(type, out + '_' + name(), params);
369  }
370  else
371  mooseError("Unable to add output AuxKernel");
372  }
373  }
374 }
375 
376 void
378 {
379  //
380  // Gather info about all other master actions when we add variables
381  //
382  if (_current_task == "validate_coordinate_systems" && getParam<bool>("add_variables"))
383  {
384  auto actions = _awh.getActions<TensorMechanicsAction>();
385  for (const auto & action : actions)
386  {
387  const auto size_before = _subdomain_id_union.size();
388  const auto added_size = action->_subdomain_ids.size();
389  _subdomain_id_union.insert(action->_subdomain_ids.begin(), action->_subdomain_ids.end());
390  const auto size_after = _subdomain_id_union.size();
391 
392  if (size_after != size_before + added_size)
393  mooseError("The block restrictions in the TensorMechanics/Master actions must be "
394  "non-overlapping.");
395 
396  if (added_size == 0 && actions.size() > 1)
397  mooseError("No TensorMechanics/Master action can be block unrestricted if more than one "
398  "TensorMechanics/Master action is specified.");
399  }
400  }
401 }
402 
403 std::string
405 {
406  std::map<Moose::CoordinateSystemType, std::string> type_map = {
407  {Moose::COORD_XYZ, "StressDivergenceTensors"},
408  {Moose::COORD_RZ, "StressDivergenceRZTensors"},
409  {Moose::COORD_RSPHERICAL, "StressDivergenceRSphericalTensors"}};
410 
411  // choose kernel type based on coordinate system
412  auto type_it = type_map.find(_coord_system);
413  if (type_it != type_map.end())
414  return type_it->second;
415  else
416  mooseError("Unsupported coordinate system");
417 }
418 
419 InputParameters
421 {
422  InputParameters params = _factory.getValidParams(type);
423  params.applyParameters(parameters(),
424  {"displacements", "use_displaced_mesh", "save_in", "diag_save_in"});
425 
426  params.set<std::vector<VariableName>>("displacements") = _coupled_displacements;
427  params.set<bool>("use_displaced_mesh") = _use_displaced_mesh;
428 
429  return params;
430 }
enum TensorMechanicsAction::Strain _strain
virtual std::string getKernelType()
std::set< SubdomainID > _subdomain_ids
set generated from the passed in vector of subdomain names
std::vector< VariableName > _coupled_displacements
virtual InputParameters getKernelParameters(std::string type)
std::vector< NonlinearVariableName > _displacements
displacement variables
enum TensorMechanicsAction::StrainAndIncrement _strain_and_increment
static const std::vector< char > _component_table
static const std::map< std::string, std::pair< std::string, std::vector< std::string > > > _ranktwoscalaraux_table
std::set< SubdomainID > _subdomain_id_union
set generated from the combined block restrictions of all TensorMechanics/Master action blocks ...
std::vector< std::string > _generate_output
output aux variables to generate for sclar stress/strain tensor quantities
static MultiMooseEnum outputPropertiesType()
static const std::map< std::string, std::string > _ranktwoaux_table
table data for output generation
std::vector< AuxVariableName > _save_in
residual debugging
InputParameters validParams< TensorMechanicsActionBase >()
TensorMechanicsAction(const InputParameters &params)
std::vector< AuxVariableName > _diag_save_in
bool _use_displaced_mesh
use displaced mesh (true unless _strain is SMALL)
Strain
strain formulation
InputParameters validParams< TensorMechanicsAction >()
std::vector< SubdomainName > _subdomain_names
if this vector is not empty the variables, kernels and materials are restricted to these subdomains ...
enum TensorMechanicsAction::PlanarFormulation _planar_formulation
PlanarFormulation
use an out of plane stress/strain formulation
Moose::CoordinateSystemType _coord_system