https://mooseframework.inl.gov
MortarGapHeatTransferAction.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 "AddVariableAction.h"
13 #include "FEProblem.h"
14 #include "libmesh/string_to_enum.h"
15 #include "NonlinearSystem.h"
16 
18 #include "GapFluxModelRadiation.h"
19 #include "GapFluxModelConduction.h"
20 
21 #include <algorithm>
22 
23 registerMooseAction("HeatTransferApp", MortarGapHeatTransferAction, "append_mesh_generator");
24 registerMooseAction("HeatTransferApp", MortarGapHeatTransferAction, "add_mortar_variable");
25 registerMooseAction("HeatTransferApp", MortarGapHeatTransferAction, "add_constraint");
26 registerMooseAction("HeatTransferApp", MortarGapHeatTransferAction, "add_user_object");
27 
30 {
32  params.addClassDescription(
33  "Action that controls the creation of all of the necessary objects for "
34  "calculation of heat transfer through an open/closed gap using a mortar formulation and a "
35  "modular design approach");
36 
37  params.addParam<Real>("thermal_lm_scaling",
38  1.,
39  "Scaling factor to apply to the thermal Lagrange multiplier variable");
40 
44 
45  params.addParam<bool>(
46  "correct_edge_dropping",
47  true,
48  "Whether to enable correct edge dropping treatment for mortar constraints. When disabled "
49  "any Lagrange Multiplier degree of freedom on a secondary element without full primary "
50  "contributions will be set (strongly) to 0.");
51 
52  params.makeParamNotRequired<SubdomainName>("primary_subdomain");
53  params.makeParamNotRequired<SubdomainName>("secondary_subdomain");
54  params.makeParamNotRequired<Real>("gap_conductivity");
55 
56  params.addParam<MultiMooseEnum>(
57  "gap_flux_options", MortarGapHeatTransfer::gapFluxPhysics, "The gap flux models to build");
58 
59  params.addParam<std::vector<UserObjectName>>(
60  "user_created_gap_flux_models",
61  {},
62  "The name of the user objects created by the user to represent gap heat transfer physics");
63 
64  params.addParamNamesToGroup("primary_subdomain secondary_subdomain", "Gap surface definition");
65  params.addParamNamesToGroup("gap_flux_options user_created_gap_flux_models", "Gap flux models");
66  params.addParamNamesToGroup("thermal_lm_scaling correct_edge_dropping",
67  "Thermal Lagrange multiplier");
68 
69  return params;
70 }
71 
73  : Action(params),
74  _user_provided_mortar_meshes(false),
75  _user_provided_gap_flux_models(
76  getParam<std::vector<UserObjectName>>("user_created_gap_flux_models").size() > 0 ? true
77  : false)
78 
79 {
80  if (getParam<MultiMooseEnum>("gap_flux_options").size() > 0 && _user_provided_gap_flux_models)
81  paramError(
82  "gap_flux_options",
83  "Either create user objects for the action in the input file or provide the desire physics "
84  "to the action via the gap_flux_options parameter. Mixed use is not supported");
85 
86  for (unsigned int i = 0; i < getParam<MultiMooseEnum>("gap_flux_options").size(); i++)
87  _gap_flux_models.push_back(static_cast<MortarGapHeatTransfer::UserObjectToBuild>(
88  getParam<MultiMooseEnum>("gap_flux_options").get(i)));
89 
90  // We do not currently support building more than one condution or more than one radiation user
91  // object from this action.
92  const unsigned int conduction_build_uos =
93  cast_int<unsigned int>(std::count(_gap_flux_models.cbegin(),
94  _gap_flux_models.cend(),
96  const unsigned int radiation_build_uos =
97  cast_int<unsigned int>(std::count(_gap_flux_models.cbegin(),
98  _gap_flux_models.cend(),
100 
101  if (conduction_build_uos > 1 || radiation_build_uos > 1)
102  paramError("gap_flux_options",
103  "You cannot choose to have more than one conduction or more than one radiation user "
104  "objects when they are built by the action. If you want to superimpose multiple "
105  "physics, you can choose to create your own user objects and pass them to this "
106  "action via 'user_created_gap_flux_models'");
107 
108  if (params.isParamSetByUser("primary_subdomain") &&
109  params.isParamSetByUser("secondary_subdomain"))
110  {
111  mooseInfo("Mortar gap heat transfer action is using the lower-dimensional domains provided by "
112  "the user");
114  }
115  else
116  mooseInfo("Mortar gap heat transfer action is creating new lower-dimensional domains");
117 
119  mooseInfo(
120  "User decided to create user objects to model physics for the mortar gap heat transfer "
121  "action independently, i.e. not through the mortar gap heat transfer action.");
122  else
123  mooseInfo("The mortar gap heat transfer action will add gap heat transfer physics according to "
124  "the gap_flux_options input parameter");
125 
126  const bool wrong_parameters_provided =
128  (params.isParamSetByUser("gap_conductivity") ||
129  params.isParamSetByUser("primary_emissivity") ||
130  params.isParamSetByUser("secondary_emissivity") ||
131  params.isParamSetByUser("gap_conductivity_function") ||
132  params.isParamSetByUser("gap_conductivity_function_variable") ||
133  params.isParamSetByUser("min_gap"));
134 
135  if (wrong_parameters_provided)
136  paramError(
137  "user_created_gap_flux_models",
138  "The mortar gap heat transfer action requires that the input file defines user objects "
139  "with physics or adds physics parameters directly into the action. You have provided both "
140  "user objects and physics parameters (e.g. emissivities, gap conductance, etc.).");
141 }
142 
143 void
145 {
146  if (_current_task == "append_mesh_generator")
147  addMortarMesh();
148  else if (_current_task == "add_mortar_variable")
150  if (_current_task == "add_constraint")
151  addConstraints();
152  else if (_current_task == "add_user_object")
154  addUserObjects();
155 }
156 
157 void
159 {
161  {
162  std::string action_name = MooseUtils::shortName(name());
163 
164  const MeshGeneratorName primary_name = action_name + "_primary_subdomain" + "_generator";
165  const MeshGeneratorName secondary_name = action_name + "_secondary_subdomain" + "_generator";
166 
167  auto primary_params = _factory.getValidParams("LowerDBlockFromSidesetGenerator");
168  auto secondary_params = _factory.getValidParams("LowerDBlockFromSidesetGenerator");
169 
170  primary_params.set<SubdomainName>("new_block_name") = action_name + "_primary_subdomain";
171  secondary_params.set<SubdomainName>("new_block_name") = action_name + "_secondary_subdomain";
172 
173  primary_params.set<std::vector<BoundaryName>>("sidesets") = {
174  getParam<BoundaryName>("primary_boundary")};
175  secondary_params.set<std::vector<BoundaryName>>("sidesets") = {
176  getParam<BoundaryName>("secondary_boundary")};
177 
178  _app.appendMeshGenerator("LowerDBlockFromSidesetGenerator", primary_name, primary_params);
179  _app.appendMeshGenerator("LowerDBlockFromSidesetGenerator", secondary_name, secondary_params);
180  }
181 }
182 
183 void
185 {
187  std::string action_name = MooseUtils::shortName(name());
188 
189  auto params = MortarConstraintBase::validParams();
190  params.set<bool>("use_displaced_mesh") = getParam<bool>("use_displaced_mesh");
191  params.set<BoundaryName>("primary_boundary") = getParam<BoundaryName>("primary_boundary");
192  params.set<BoundaryName>("secondary_boundary") = getParam<BoundaryName>("secondary_boundary");
193 
195  {
196  params.set<SubdomainName>("primary_subdomain") = getParam<SubdomainName>("primary_subdomain");
197  params.set<SubdomainName>("secondary_subdomain") =
198  getParam<SubdomainName>("secondary_subdomain");
199  }
200  else
201  {
202  params.set<SubdomainName>("primary_subdomain") = action_name + "_primary_subdomain";
203  params.set<SubdomainName>("secondary_subdomain") = action_name + "_secondary_subdomain";
204  }
205 
206  addRelationshipManagers(input_rm_type, params);
207 }
208 
209 void
211 {
213 
214  InputParameters params = _factory.getValidParams("MooseVariableBase");
215 
216  const std::string & temperature = getParam<std::vector<VariableName>>("temperature")[0];
217  std::string action_name = MooseUtils::shortName(name());
218 
219  if (!_problem->hasVariable(temperature))
220  mooseError("Temperature variable is missing");
221 
222  const auto primal_type =
223  _problem->getVariable(0, temperature, Moose::VarKindType::VAR_SOLVER).feType();
224  const int lm_order = primal_type.order.get_order();
225 
226  if (primal_type.family != LAGRANGE)
227  mooseError("The mortar thermal action can only be used with LAGRANGE finite elements");
228 
229  params.set<MooseEnum>("family") = Utility::enum_to_string<FEFamily>(primal_type.family);
230  params.set<MooseEnum>("order") = Utility::enum_to_string<Order>(libMesh::OrderWrapper{lm_order});
231 
233  params.set<std::vector<SubdomainName>>("block") = {
234  getParam<SubdomainName>("secondary_subdomain")};
235  else
236  params.set<std::vector<SubdomainName>>("block") = {action_name + "_secondary_subdomain"};
237 
238  params.set<std::vector<Real>>("scaling") = {getParam<Real>("thermal_lm_scaling")};
239  auto fe_type = AddVariableAction::feType(params);
240  auto var_type = AddVariableAction::variableType(fe_type);
241 
242  _problem->addVariable(var_type, action_name + "_thermal_lm", params);
243 }
244 
245 void
247 {
249 
250  InputParameters params = _factory.getValidParams("ModularGapConductanceConstraint");
251  const std::string action_name = MooseUtils::shortName(name());
252 
253  params.applyParameters(parameters());
254  params.set<bool>("use_displaced_mesh") = true;
255 
256  params.set<BoundaryName>("primary_boundary") = getParam<BoundaryName>("primary_boundary");
257  params.set<BoundaryName>("secondary_boundary") = getParam<BoundaryName>("secondary_boundary");
258 
260  {
261  params.set<SubdomainName>("primary_subdomain") = getParam<SubdomainName>("primary_subdomain");
262  params.set<SubdomainName>("secondary_subdomain") =
263  getParam<SubdomainName>("secondary_subdomain");
264  }
265  else
266  {
267  params.set<SubdomainName>("primary_subdomain") = action_name + "_primary_subdomain";
268  params.set<SubdomainName>("secondary_subdomain") = action_name + "_secondary_subdomain";
269  }
270 
271  params.set<NonlinearVariableName>("variable") = action_name + "_thermal_lm";
272 
273  params.set<VariableName>("secondary_variable") =
274  getParam<std::vector<VariableName>>("temperature")[0];
275 
277  {
278  std::vector<UserObjectName> uoname_strings(0);
279 
280  for (const auto & uo_name : _gap_flux_models)
281  {
283  uoname_strings.push_back("gap_flux_model_conduction_object_" +
286  uoname_strings.push_back("gap_flux_model_radiation_object_" +
288  }
289 
290  params.set<std::vector<UserObjectName>>("gap_flux_models") = uoname_strings;
291  }
292  else
293  params.set<std::vector<UserObjectName>>("gap_flux_models") =
294  getParam<std::vector<UserObjectName>>("user_created_gap_flux_models");
295 
296  _problem->addConstraint(
297  "ModularGapConductanceConstraint", action_name + "_ModularGapConductanceConstraint", params);
298 }
299 
300 void
302 {
303  // Evaluate whether we have sufficient information from the user to skip building the
304  // lower-dimensional domains.
306 
307  // We may have available lower-dimensional domains (e.g. from a mechanical contact action), whose
308  // subdomains can be reused for adding mortar variables and constraints.
310  coreMortarMesh();
311 }
312 
313 void
315 {
316  // It is risky to apply this optimization to contact problems
317  // since the problem configuration may be changed during Jacobian
318  // evaluation. We therefore turn it off for all contact problems so that
319  // PETSc-3.8.4 or higher will have the same behavior as PETSc-3.8.3 or older.
320  mooseAssert(_problem, "Problem pointer is null");
321 
322  if (!_problem->isSNESMFReuseBaseSetbyUser())
323  _problem->setSNESMFReuseBase(false, false);
324 
325  for (const auto & uo_name : _gap_flux_models)
326  {
328  {
329  auto var_params = _factory.getValidParams("GapFluxModelConduction");
330 
331  var_params.set<std::vector<VariableName>>("temperature") =
332  getParam<std::vector<VariableName>>("temperature");
333  var_params.set<Real>("gap_conductivity") = getParam<Real>("gap_conductivity");
334 
335  if (isParamValid("gap_conductivity_function"))
336  var_params.set<FunctionName>("gap_conductivity_function") =
337  getParam<FunctionName>("gap_conductivity_function");
338 
339  if (isParamValid("gap_conductivity_function_variable"))
340  var_params.set<std::vector<VariableName>>("gap_conductivity_function_variable") =
341  getParam<std::vector<VariableName>>("gap_conductivity_function_variable");
342 
343  var_params.set<Real>("min_gap") = getParam<Real>("min_gap");
344  var_params.set<unsigned int>("min_gap_order") = getParam<unsigned int>("min_gap_order");
345 
346  var_params.set<std::vector<BoundaryName>>("boundary") =
347  getParam<std::vector<BoundaryName>>("boundary");
348 
349  var_params.set<bool>("use_displaced_mesh") = true;
350 
351  _problem->addUserObject("GapFluxModelConduction",
352  "gap_flux_model_conduction_object_" + MooseUtils::shortName(name()),
353  var_params);
354  }
356 
357  {
358  auto var_params = _factory.getValidParams("GapFluxModelRadiation");
359 
360  var_params.set<Real>("stefan_boltzmann") = getParam<Real>("stefan_boltzmann");
361  var_params.set<Real>("primary_emissivity") = getParam<Real>("primary_emissivity");
362  var_params.set<Real>("secondary_emissivity") = getParam<Real>("secondary_emissivity");
363 
364  var_params.set<std::vector<BoundaryName>>("boundary") =
365  getParam<std::vector<BoundaryName>>("boundary");
366 
367  var_params.set<std::vector<VariableName>>("temperature") =
368  getParam<std::vector<VariableName>>("temperature");
369 
370  var_params.set<bool>("use_displaced_mesh") = true;
371 
372  _problem->addUserObject("GapFluxModelRadiation",
373  "gap_flux_model_radiation_object_" + MooseUtils::shortName(name()),
374  var_params);
375  }
376  }
377 }
378 
379 void
381 {
382  if (parameters().isParamSetByUser("primary_subdomain") &&
383  parameters().isParamSetByUser("secondary_subdomain"))
384  {
386  }
387  else
389 }
LAGRANGE
bool isUltimateMaster() const
std::vector< MortarGapHeatTransfer::UserObjectToBuild > _gap_flux_models
RelationshipManagerType
registerMooseAction("HeatTransferApp", MortarGapHeatTransferAction, "append_mesh_generator")
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void mooseInfo(Args &&... args) const
MooseApp & _app
T & set(const std::string &name, bool quiet_mode=false)
InputParameters getValidParams(const std::string &name) const
static InputParameters validParams()
void applyParameters(const InputParameters &common, const std::vector< std::string > &exclude={}, const bool allow_private=false)
static const std::string temperature
Definition: NS.h:59
static InputParameters validParams()
virtual const std::string & name() const
std::string shortName(const std::string &name)
static InputParameters validParams()
bool isParamValid(const std::string &name) const
Factory & _factory
static InputParameters validParams()
const T & getParam(const std::string &name) const
const std::string & _current_task
const MooseMesh * masterMesh() const
static std::string variableType(const libMesh::FEType &fe_type, const bool is_fv=false, const bool is_array=false)
static InputParameters validParams()
void paramError(const std::string &param, Args... args) const
const MeshGenerator & appendMeshGenerator(const std::string &type, const std::string &name, InputParameters params)
bool isParamSetByUser(const std::string &name) const
bool isParamSetByUser(const std::string &nm) const
static libMesh::FEType feType(const InputParameters &params)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual void addRelationshipManagers(Moose::RelationshipManagerType input_rm_type) override
const MultiMooseEnum gapFluxPhysics("conduction radiation")
void mooseError(Args &&... args) const
void addClassDescription(const std::string &doc_string)
std::shared_ptr< FEProblemBase > & _problem
const InputParameters & parameters() const
bool isRecovering() const
MortarGapHeatTransferAction(const InputParameters &params)