https://mooseframework.inl.gov
Loading...
Searching...
No Matches
ThermalContactAction.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 "GapHeatTransfer.h"
15#include "libmesh/string_to_enum.h"
16#include "GapConductance.h"
18#include "NonlinearSystem.h"
19
20// Counter for naming materials
21static unsigned int materials_counter = 0;
22
23// Counter for naming dirac kernels
24static unsigned int dirac_counter = 0;
25
26// Counter for naming BCs
27static unsigned int bcs_counter = 0;
28
29// Counter for naming aux kernels
30static unsigned int aux_kenels_counter = 0;
31
32registerMooseAction("HeatTransferApp", ThermalContactAction, "add_aux_kernel");
33registerMooseAction("HeatTransferApp", ThermalContactAction, "add_aux_variable");
34registerMooseAction("HeatTransferApp", ThermalContactAction, "add_bc");
35registerMooseAction("HeatTransferApp", ThermalContactAction, "add_dirac_kernel");
36registerMooseAction("HeatTransferApp", ThermalContactAction, "add_material");
37registerMooseAction("HeatTransferApp", ThermalContactAction, "add_secondary_flux_vector");
38
41{
44 "Action that controls the creation of all of the necessary objects for "
45 "calculation of Thermal Contact");
46
47 params.addParam<std::string>(
48 "gap_aux_type",
49 "GapValueAux",
50 "A string representing the Moose object that will be used for computing the gap size");
51 params.addRequiredParam<NonlinearVariableName>("variable", "The variable for thermal contact");
52 params.addParam<std::vector<BoundaryName>>(
53 "primary", "The list of boundary IDs referring to primary sidesets");
54 params.addRequiredParam<std::vector<BoundaryName>>(
55 "secondary", "The list of boundary IDs referring to secondary sidesets");
56 params.addRangeCheckedParam<Real>("tangential_tolerance",
57 "tangential_tolerance>=0",
58 "Tangential distance to extend edges of contact surfaces");
59 params.addRangeCheckedParam<Real>(
60 "normal_smoothing_distance",
61 "normal_smoothing_distance>=0 & normal_smoothing_distance<=1",
62 "Distance from edge in parametric coordinates over which to smooth contact normal");
63 params.addParam<std::string>("normal_smoothing_method",
64 "Method to use to smooth normals (edge_based|nodal_normal_based)");
65
67 params.addParam<MooseEnum>("order", orders, "The finite element order");
68
69 params.addParam<bool>(
70 "warnings", false, "Whether to output warning messages concerning nodes not being found");
71 params.addParam<bool>(
72 "quadrature", false, "Whether or not to use quadrature point based gap heat transfer");
73 params.addRangeCheckedParam<Real>("penalty",
74 1e3,
75 "penalty>0",
76 "The penalty used in the residual and Jacobian calculations "
77 "when using the GapPerfectConductance model");
78 params.addParam<std::string>(
79 "appended_property_name", "", "Name appended to material properties to make them unique");
80 params.addRequiredParam<std::string>(
81 "type",
82 "A string representing the Moose object that will be used for heat conduction over the gap");
83
84 params.addParam<std::vector<VariableName>>(
85 "displacements",
86 "The displacements appropriate for the simulation geometry and coordinate system");
87
88 params.addParam<std::vector<AuxVariableName>>(
89 "save_in", {}, "The Auxiliary Variable to (optionally) save the boundary flux in");
90 params.addRangeCheckedParam<Real>("gap_conductivity",
91 1.0,
92 "gap_conductivity>0",
93 "The thermal conductivity of the gap material");
94 params.addParam<FunctionName>(
95 "gap_conductivity_function",
96 "Thermal conductivity of the gap material as a function. Multiplied by gap_conductivity.");
97 params.addParam<std::vector<VariableName>>(
98 "gap_conductivity_function_variable",
99 "Variable to be used in gap_conductivity_function in place of time");
100 params.addParam<VariableName>("secondary_gap_offset",
101 "Offset to gap distance from secondary side");
102 params.addParam<VariableName>("mapped_primary_gap_offset",
103 "Offset to gap distance mapped from primary side");
104 params.addParam<bool>(
105 "check_boundary_restricted",
106 true,
107 "Whether to check for multiple element sides on the boundary for the boundary restricted, "
108 "element aux variable set up for thermal contact enforcement. Setting this to false will "
109 "allow contribution to a single element's elemental value(s) from multiple boundary sides "
110 "on the same element (example: when the restricted boundary exists on two or more sides "
111 "of an element, such as at a corner of a mesh");
112
115
117
118 params.addParamNamesToGroup("primary secondary", "Gap surface definition");
120 "tangential_tolerance normal_smoothing_distance normal_smoothing_method",
121 "Gap edge and edge normal smoothing");
122 params.addParamNamesToGroup("gap_aux_type secondary_gap_offset mapped_primary_gap_offset",
123 "Gap size");
124 params.addParamNamesToGroup("order quadrature", "Integration");
126 "gap_conductivity gap_conductivity_function gap_conductivity_function_variable",
127 "Gap conductivity");
128 params.addParamNamesToGroup("save_in check_boundary_restricted warnings",
129 "Diagnostics and debug");
130
131 return params;
132}
133
135 : Action(params),
136 _quadrature(getParam<bool>("quadrature")),
137 _order(getParam<MooseEnum>("order")),
138 _penetration_var_name(_quadrature ? "qpoint_penetration" : "penetration"),
139 _gap_value_name("paired_" + getParam<NonlinearVariableName>("variable")),
140 _gap_conductivity_name("paired_k_" + getParam<NonlinearVariableName>("variable")),
141 _boundary_pairs(getParam<BoundaryName, BoundaryName>("primary", "secondary"))
142{
143 if (!params.get<bool>("check_boundary_restricted"))
144 {
145 if (_quadrature)
146 paramInfo(
147 "check_boundary_restricted",
148 "This parameter is set to 'false'. Although thermal contact ",
149 "will be correctly enforced, the contact-related output may have issues ",
150 "in cases where where more than one face of an element belongs to a contact surface ",
151 "because the values from only one of the faces will be reported.");
152 else
153 paramError("check_boundary_restricted",
154 "This parameter cannot be 'false' when 'quadrature=false'");
155 }
156 if (params.isParamSetByUser("penalty") &&
157 getParam<std::string>("type") != "GapPerfectConductance")
158 paramError("penalty",
159 "This parameter should only be set by the user when 'type=GapPerfectConductance'.");
160}
161
162void
164{
165 if (_current_task == "add_aux_kernel")
167 else if (_current_task == "add_aux_variable")
169 else if (_current_task == "add_bc")
170 addBCs();
171 else if (_current_task == "add_dirac_kernel")
173 else if (_current_task == "add_material")
174 addMaterials();
175 else if (_current_task == "add_secondary_flux_vector")
177}
178
179void
181{
182 for (const auto & contact_pair : _boundary_pairs)
183 {
184 // Add gap aux kernel
185 {
186 InputParameters params = _factory.getValidParams(getParam<std::string>("gap_aux_type"));
187
189 {"tangential_tolerance",
190 "normal_smoothing_distance",
191 "normal_smoothing_method",
192 "order",
193 "warnings",
194 "search_method",
195 "check_boundary_restricted"});
196 params.set<AuxVariableName>("variable") = _gap_value_name;
197 params.set<ExecFlagEnum>("execute_on", true) = {EXEC_INITIAL, EXEC_LINEAR};
198
199 params.set<std::vector<BoundaryName>>("boundary") = {contact_pair.second};
200 params.set<BoundaryName>("paired_boundary") = contact_pair.first;
201 params.set<VariableName>("paired_variable") = getParam<NonlinearVariableName>("variable");
202
203 _problem->addAuxKernel(getParam<std::string>("gap_aux_type"),
204 "gap_value_" + name() + "_" + Moose::stringify(aux_kenels_counter),
205 params);
206
207 if (_quadrature)
208 {
209 params.set<std::vector<BoundaryName>>("boundary") = {contact_pair.first};
210 params.set<BoundaryName>("paired_boundary") = contact_pair.second;
211
212 _problem->addAuxKernel(getParam<std::string>("gap_aux_type"),
213 "gap_value_primary_" + name() + "_" +
215 params);
216 }
217 }
218
219 // Add penetration aux kernel
220 {
221 InputParameters params = _factory.getValidParams("PenetrationAux");
222
224 {"tangential_tolerance",
225 "normal_smoothing_distance",
226 "normal_smoothing_method",
227 "order",
228 "search_method",
229 "check_boundary_restricted"});
230 params.set<AuxVariableName>("variable") = _penetration_var_name;
231 if (isParamValid("secondary_gap_offset"))
232 params.set<std::vector<VariableName>>("secondary_gap_offset") = {
233 getParam<VariableName>("secondary_gap_offset")};
234 if (isParamValid("mapped_primary_gap_offset"))
235 params.set<std::vector<VariableName>>("mapped_primary_gap_offset") = {
236 getParam<VariableName>("mapped_primary_gap_offset")};
237 params.set<ExecFlagEnum>("execute_on", true) = {EXEC_INITIAL, EXEC_LINEAR};
238 params.set<std::vector<BoundaryName>>("boundary") = {contact_pair.second};
239 params.set<BoundaryName>("paired_boundary") = contact_pair.first;
240
241 _problem->addAuxKernel("PenetrationAux",
242 "penetration_" + name() + "_" + Moose::stringify(aux_kenels_counter++),
243 params);
244 }
245 }
246}
247
248void
250{
251 // We need to add variables only once per variable name. However, we don't know how many unique
252 // variable names we will have. So, we'll always add them.
253
254 auto order = getParam<MooseEnum>("order");
255 std::string family = "LAGRANGE";
256
257 if (_quadrature)
258 {
259 order = "CONSTANT";
260 family = "MONOMIAL";
261 }
262
263 auto var_type =
264 AddVariableAction::variableType(FEType(order, Utility::string_to_enum<FEFamily>(family)));
265 auto var_params = _factory.getValidParams(var_type);
266 var_params.set<MooseEnum>("order") = order;
267 var_params.set<MooseEnum>("family") = family;
268
269 _problem->addAuxVariable(var_type, _penetration_var_name, var_params);
270 _problem->addAuxVariable(var_type, _gap_value_name, var_params);
271}
272
273void
275{
276 for (const auto & contact_pair : _boundary_pairs)
277 {
278 const std::string object_name = getParam<std::string>("type");
279 InputParameters params = _factory.getValidParams(object_name);
280 params.applyParameters(parameters());
281
282 if (object_name == "GapPerfectConductance")
283 {
284 params.set<Real>("penalty") = getParam<Real>("penalty");
285 params.set<std::vector<VariableName>>("gap_distance") = {"penetration"};
286 params.set<std::vector<VariableName>>("gap_temp") = {_gap_value_name};
287 params.set<std::vector<BoundaryName>>("boundary") = {contact_pair.second};
288 _problem->addBoundaryCondition(
289 object_name, "gap_bc_" + name() + "_" + Moose::stringify(bcs_counter), params);
290 }
291 else
292 {
293 if (_quadrature)
294 {
295 params.set<BoundaryName>("paired_boundary") = contact_pair.first;
296 params.set<bool>("use_displaced_mesh") = true;
297 }
298 else
299 {
300 params.set<std::vector<VariableName>>("gap_distance") = {"penetration"};
301 params.set<std::vector<VariableName>>("gap_temp") = {_gap_value_name};
302 }
303
304 params.set<std::vector<BoundaryName>>("boundary") = {contact_pair.second};
305
306 _problem->addBoundaryCondition(
307 object_name, "gap_bc_" + name() + "_" + Moose::stringify(bcs_counter), params);
308
309 if (_quadrature)
310 {
311 // Swap primary and secondary for this one
312 params.set<std::vector<BoundaryName>>("boundary") = {contact_pair.first};
313 params.set<BoundaryName>("paired_boundary") = contact_pair.second;
314
315 _problem->addBoundaryCondition(
316 object_name, "gap_bc_primary_" + name() + "_" + Moose::stringify(bcs_counter), params);
317 }
318 }
319 bcs_counter++;
320 }
321}
322
323void
325{
326 if (_quadrature)
327 return;
328
329 for (const auto & contact_pair : _boundary_pairs)
330 {
331 const std::string object_name = "GapHeatPointSourceMaster";
332 InputParameters params = _factory.getValidParams(object_name);
334 {"tangential_tolerance",
335 "normal_smoothing_distance",
336 "normal_smoothing_method",
337 "order",
338 "search_method",
339 "variable"});
340 params.set<BoundaryName>("boundary") = contact_pair.first;
341 params.set<BoundaryName>("secondary") = contact_pair.second;
342
343 _problem->addDiracKernel(
344 object_name, object_name + "_" + name() + "_" + Moose::stringify(dirac_counter++), params);
345 }
346}
347
348void
350{
351 if (getParam<std::string>("type") != "GapHeatTransfer")
352 return;
353
354 if (parameters().isParamSetByUser("gap_conductance"))
355 {
356 if (parameters().isParamSetByUser("gap_conductivity") ||
357 parameters().isParamSetByUser("gap_conductivity_function"))
359 "Cannot specify both gap_conductance and gap_conductivity or gap_conductivity_function");
360
361 for (const auto & contact_pair : _boundary_pairs)
362 {
363 const std::string object_type = "GapConductanceConstant";
364 InputParameters params = _factory.getValidParams(object_type);
365 params.applyParameters(parameters());
366 params.set<std::vector<BoundaryName>>("boundary") = {contact_pair.second};
367 _problem->addMaterial(object_type,
368 name() + "_" + "gap_value" + "_" + Moose::stringify(materials_counter),
369 params);
370
371 if (_quadrature)
372 {
373 params.set<std::vector<BoundaryName>>("boundary") = {contact_pair.first};
374 _problem->addMaterial(object_type,
375 name() + "_" + "gap_value_primary" + "_" +
377 params);
378 }
380 }
381 }
382 else
383 {
384 const std::string object_type = "GapConductance";
385
386 for (const auto & contact_pair : _boundary_pairs)
387 {
388 InputParameters params = _factory.getValidParams(object_type);
389 params.applyParameters(parameters(), {"variable"});
390
391 params.set<std::vector<VariableName>>("variable") = {
392 getParam<NonlinearVariableName>("variable")};
393 params.set<std::vector<BoundaryName>>("boundary") = {contact_pair.second};
394
395 if (_quadrature)
396 params.set<BoundaryName>("paired_boundary") = contact_pair.first;
397 else
398 {
399 params.set<std::vector<VariableName>>("gap_temp") = {_gap_value_name};
400 params.set<std::vector<VariableName>>("gap_distance") = {"penetration"};
401 }
402
403 _problem->addMaterial(object_type,
404 name() + "_" + "gap_value" + "_" + Moose::stringify(materials_counter),
405 params);
406
407 if (_quadrature)
408 {
409 params.set<BoundaryName>("paired_boundary") = contact_pair.second;
410 params.set<std::vector<BoundaryName>>("boundary") = {contact_pair.first};
411
412 _problem->addMaterial(object_type,
413 name() + "_" + "gap_value_primary" + "_" +
415 params);
416 }
418 }
419 }
420}
421
422void
424{
425 _problem->getNonlinearSystemBase(/*nl_sys_num=*/0)
426 .addVector("secondary_flux", false, libMesh::GHOSTED);
427 _problem->getNonlinearSystemBase(/*nl_sys_num=*/0).zeroVectorForResidual("secondary_flux");
428
429 // It is risky to apply this optimization to contact problems
430 // since the problem configuration may be changed during Jacobian
431 // evaluation. We therefore turn it off for all contact problems so that
432 // PETSc-3.8.4 or higher will have the same behavior as PETSc-3.8.3 or older.
433 if (!_problem->isSNESMFReuseBaseSetbyUser())
434 _problem->setSNESMFReuseBase(false, false);
435}
436
437void
439{
440 if (!_quadrature)
441 return;
442
443 for (const auto & contact_pair : _boundary_pairs)
444 {
445 const auto & object_name = getParam<std::string>("type");
446 auto params = _factory.getValidParams(object_name);
447 params.applyParameters(parameters());
448
449 params.set<BoundaryName>("paired_boundary") = contact_pair.first;
450 params.set<bool>("use_displaced_mesh") = true;
451 params.set<std::vector<BoundaryName>>("boundary") = {contact_pair.second};
452 addRelationshipManagers(input_rm_type, params);
453 }
454}
const ExecFlagType EXEC_INITIAL
const ExecFlagType EXEC_LINEAR
static unsigned int bcs_counter
static unsigned int dirac_counter
registerMooseAction("HeatTransferApp", ThermalContactAction, "add_aux_kernel")
static unsigned int materials_counter
static unsigned int aux_kenels_counter
static InputParameters validParams()
std::shared_ptr< FEProblemBase > & _problem
const std::string & _current_task
static MooseEnum getNonlinearVariableOrders()
static std::string variableType(const libMesh::FEType &fe_type, const bool is_fv=false, const bool is_array=false)
InputParameters getValidParams(const std::string &name) const
static InputParameters actionParameters()
static InputParameters actionParameters()
static InputParameters validParams()
void applySpecificParameters(const InputParameters &common, const std::vector< std::string > &include, bool allow_private=false)
void addParamNamesToGroup(const std::string &space_delim_names, const std::string group_name)
bool isParamSetByUser(const std::string &name) const
void addRequiredParam(const std::string &name, const std::string &doc_string)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
std::vector< std::pair< R1, R2 > > get(const std::string &param1, const std::string &param2) const
void addClassDescription(const std::string &doc_string)
T & set(const std::string &name, bool quiet_mode=false)
void addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
void applyParameters(const InputParameters &common, const std::vector< std::string > &exclude={}, const bool allow_private=false)
const InputParameters & parameters() const
void paramInfo(const std::string &param, Args... args) const
const std::string & name() const
void paramError(const std::string &param, Args... args) const
bool isParamSetByUser(const std::string &name) const
void mooseError(Args &&... args) const
bool isParamValid(const std::string &name) const
Factory & _factory
const std::vector< std::pair< BoundaryName, BoundaryName > > _boundary_pairs
Primary/Secondary boundary name pairs for thermal contact.
virtual void addRelationshipManagers(Moose::RelationshipManagerType input_rm) override
ThermalContactAction(const InputParameters &params)
virtual void act() override
virtual void addSecondaryFluxVector()
const AuxVariableName _gap_value_name
static InputParameters validParams()
const AuxVariableName _penetration_var_name
std::string stringify(const T &t)
RelationshipManagerType