https://mooseframework.inl.gov
CoupledHeatTransferAction.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 
12 #include "FEProblem.h"
13 
14 registerMooseAction("ThermalHydraulicsApp", CoupledHeatTransferAction, "add_bc");
15 registerMooseAction("ThermalHydraulicsApp", CoupledHeatTransferAction, "add_user_object");
16 registerMooseAction("ThermalHydraulicsApp", CoupledHeatTransferAction, "add_transfer");
17 
20 {
22 
23  params.addClassDescription(
24  "Action that creates the necessary objects, for the solid side, to couple a "
25  "solid heat conduction region to a 1-D flow channel via convective heat transfer");
26 
27  params.addRequiredParam<std::vector<BoundaryName>>("boundary",
28  "Boundary name(s) on the solid side");
29  params.addRequiredParam<VariableName>("T", "Solid side temperature variable");
30  params.addRequiredParam<VariableName>(
31  "T_wall", "Variable on the flow channel side into which to transfer the solid temperature");
32  params.addRequiredParam<std::vector<VariableName>>(
33  "T_fluid", "Variable(s) on the solid side into which to transfer the fluid temperature(s)");
34  params.addRequiredParam<std::vector<VariableName>>(
35  "htc",
36  "Variable(s) on the solid side into which to transfer the heat transfer coefficient(s)");
37  params.addParam<std::vector<VariableName>>(
38  "kappa", "Variables on the solid side into which to transfer the wall contact fractions");
39  params.addParam<std::vector<UserObjectName>>(
40  "T_fluid_user_objects", "Spatial user object(s) holding the fluid temperature values");
41  params.addParam<std::vector<UserObjectName>>(
42  "htc_user_objects", "Spatial user object(s) holding the heat transfer coefficient values");
43  params.addDeprecatedParam<UserObjectName>(
44  "T_fluid_user_object",
45  "Spatial user object holding the fluid temperature values",
46  "This parameter is deprecated in favor of 'T_fluid_user_objects' (just add an 's' to "
47  "parameter name).");
48  params.addDeprecatedParam<UserObjectName>(
49  "htc_user_object",
50  "Spatial user object holding the heat transfer coefficient values",
51  "This parameter is deprecated in favor of 'htc_user_objects' (just add an 's' to parameter "
52  "name).");
53  params.addParam<std::vector<UserObjectName>>(
54  "kappa_user_objects", "Spatial user object(s) holding the wall contact fraction values");
55 
56  MooseEnum directions("x y z");
58  "direction",
59  directions,
60  "The direction of the layers.",
61  "The usage of 'direction' and 'num_layers' is deprecated. Use 'position', 'orientation', "
62  "'rotation', 'length', and 'n_elems' instead. The latter parameters correspond to the "
63  "parameters of the same names in the coupled flow channel component.");
64  params.addDeprecatedParam<unsigned int>(
65  "num_layers",
66  "The number of layers.",
67  "The usage of 'direction' and 'num_layers' is deprecated. Use 'position', 'orientation', "
68  "'rotation', 'length', and 'n_elems' instead. The latter parameters correspond to the "
69  "parameters of the same names in the coupled flow channel component.");
70 
71  params.addParam<Point>("position", "Start position of axis in 3-D space [m]");
72  params.addParam<RealVectorValue>(
73  "orientation",
74  "Direction of axis from start position to end position (no need to normalize)");
75  params.addParam<Real>("rotation", 0.0, "Angle of rotation about the x-axis [degrees]");
76  params.addParam<std::vector<Real>>("length", "Length of each axial section [m]");
77  params.addParam<std::vector<unsigned int>>("n_elems", "Number of elements in each axial section");
78 
79  params.addRequiredParam<std::string>("multi_app", "The name of the multi-app.");
80 
81  params.addRangeCheckedParam<std::vector<Real>>(
82  "fixed_bounding_box_size",
83  "fixed_bounding_box_size >= 0",
84  "The 'fixed_bounding_box_size' value to use for each MultiAppGeneralFieldUserObjectTransfer. "
85  "If this parameter is not provided, a greedy search will be used instead of bounding boxes, "
86  "which may be slower.");
87 
88  params.addParam<std::vector<Point>>(
89  "positions", "Sub-app positions. Each set of 3 values represents a Point.");
90  params.addParam<FileName>(
91  "positions_file",
92  "Name of file containing sub-app positions. Each set of 3 values represents a Point.");
94  return params;
95 }
96 
98  : Action(params),
99 
100  _boundary(getParam<std::vector<BoundaryName>>("boundary")),
101 
102  _T_solid_var_name(getParam<VariableName>("T")),
103  _T_wall_var_name(getParam<VariableName>("T_wall")),
104  _T_fluid_var_names(getParam<std::vector<VariableName>>("T_fluid")),
105  _htc_var_names(getParam<std::vector<VariableName>>("htc")),
106 
107  _n_phases(_T_fluid_var_names.size()),
108 
109  _T_wall_user_object_name(name() + "_T_avg_uo"),
110 
111  _multi_app_name(getParam<std::string>("multi_app"))
112 {
113  if (isParamValid("T_fluid_user_objects"))
114  _T_fluid_user_object_names = getParam<std::vector<UserObjectName>>("T_fluid_user_objects");
115  else if (isParamValid("T_fluid_user_object"))
116  _T_fluid_user_object_names = {getParam<UserObjectName>("T_fluid_user_object")};
117  else
118  mooseError("The parameter 'T_fluid_user_objects' must be specified.");
119 
120  if (isParamValid("htc_user_objects"))
121  _htc_user_object_names = getParam<std::vector<UserObjectName>>("htc_user_objects");
122  else if (isParamValid("htc_user_object"))
123  _htc_user_object_names = {getParam<UserObjectName>("htc_user_object")};
124  else
125  mooseError("The parameter 'htc_user_objects' must be specified.");
126 
127  if (_htc_var_names.size() != _n_phases || _T_fluid_user_object_names.size() != _n_phases ||
129  mooseError("The parameters 'T_fluid', 'htc', 'T_fluid_user_objects', and 'htc_user_objects' "
130  "must have the same numbers of elements.");
131 
132  if (_n_phases == 1)
133  {
134  if (isParamValid("kappa") || isParamValid("kappa_user_objects"))
135  mooseError("If there is only one phase (e.g., only one element in 'T_fluid'), then the "
136  "parameters 'kappa' and 'kappa_user_objects' must not be provided.");
137  }
138  else
139  {
140  if (!isParamValid("kappa") || !isParamValid("kappa_user_objects"))
141  mooseError("If there is more than one phase (e.g., more than one element in 'T_fluid'), then "
142  "the parameters 'kappa' and 'kappa_user_objects' must be provided.");
143  else
144  {
145  _kappa_var_names = getParam<std::vector<VariableName>>("kappa");
146  _kappa_user_object_names = getParam<std::vector<UserObjectName>>("kappa_user_objects");
148  mooseError("The parameters 'kappa' and 'kappa_user_objects' must have the same number of "
149  "elements as 'T_fluid'.");
150  }
151  }
152 
153  if (isParamValid("orientation"))
154  {
155  const auto & orientation = getParam<RealVectorValue>("orientation");
157  mooseError("The direction given by the parameter 'orientation' must be aligned with the x, "
158  "y, or z axis.");
159  }
160 }
161 
162 void
164 {
165  if (_current_task == "add_bc")
166  addBCs();
167  else if (_current_task == "add_user_object")
168  addUserObjects();
169  else if (_current_task == "add_transfer")
170  addTransfers();
171 }
172 
173 void
175 {
176  for (unsigned int k = 0; k < _n_phases; k++)
177  {
178  const std::string class_name = "CoupledConvectiveHeatFluxBC";
179  InputParameters params = _factory.getValidParams(class_name);
180  params.set<NonlinearVariableName>("variable") = _T_solid_var_name;
181  params.set<std::vector<BoundaryName>>("boundary") = {_boundary};
182  params.set<std::vector<VariableName>>("T_infinity") = {_T_fluid_var_names[k]};
183  params.set<std::vector<VariableName>>("htc") = {_htc_var_names[k]};
184  if (_n_phases > 1)
185  params.set<std::vector<VariableName>>("scale_factor") = {_kappa_var_names[k]};
186  _problem->addBoundaryCondition(class_name, name() + "_bc" + std::to_string(k), params);
187  }
188 }
189 
190 void
192 {
193  // Solid temperature spatial user object
194  {
195  const std::string class_name = "NearestPointLayeredSideAverage";
196  InputParameters params = _factory.getValidParams(class_name);
197  params.set<std::vector<VariableName>>("variable") = {_T_solid_var_name};
198  params.set<std::vector<BoundaryName>>("boundary") = {_boundary};
199 
200  // set sub-app positions
201  if (isParamValid("positions"))
202  params.set<std::vector<Point>>("points") = getParam<std::vector<Point>>("positions");
203  else if (isParamValid("positions_file"))
204  params.set<FileName>("points_file") = getParam<FileName>("positions_file");
205  else
206  params.set<std::vector<Point>>("points") = {Point(0, 0, 0)};
207 
208  // set layers
209  if (isParamValid("direction") && isParamValid("num_layers"))
210  {
211  params.set<MooseEnum>("direction") = getParam<MooseEnum>("direction");
212  params.set<unsigned int>("num_layers") = getParam<unsigned int>("num_layers");
213  }
214  else if (isParamValid("position") && isParamValid("orientation") && isParamValid("length") &&
215  isParamValid("n_elems"))
216  {
217  const auto & position = getParam<Point>("position");
218  const auto & orientation = getParam<RealVectorValue>("orientation");
219  const auto & rotation = getParam<Real>("rotation");
220  const auto & lengths = getParam<std::vector<Real>>("length");
221  const auto & n_elems = getParam<std::vector<unsigned int>>("n_elems");
222 
223  params.set<MooseEnum>("direction") =
225  params.set<std::vector<Real>>("bounds") =
227  position, orientation, rotation, lengths, n_elems);
228  }
229  else
230  mooseError(
231  "The parameters 'position', 'orientation', 'length', and 'n_elems' must be provided.");
232 
233  _problem->addUserObject(class_name, _T_wall_user_object_name, params);
234  }
235 }
236 
237 void
239 {
240  // Transfers to the flow channel application
241 
242  const bool skip_coordinate_collapsing = getParam<bool>("skip_coordinate_collapsing");
243 
244  const bool use_bounding_boxes = isParamValid("fixed_bounding_box_size");
245  std::vector<Real> fixed_bounding_box_size;
246  if (use_bounding_boxes)
247  fixed_bounding_box_size = getParam<std::vector<Real>>("fixed_bounding_box_size");
248 
249  {
250  const std::string class_name = "MultiAppGeneralFieldUserObjectTransfer";
251  InputParameters params = _factory.getValidParams(class_name);
252  params.set<MultiAppName>("to_multi_app") = _multi_app_name;
253  params.set<UserObjectName>("source_user_object") = {_T_wall_user_object_name};
254  params.set<std::vector<AuxVariableName>>("variable") = {_T_wall_var_name};
255  params.set<bool>("skip_coordinate_collapsing") = skip_coordinate_collapsing;
256  params.set<bool>("error_on_miss") = true;
257  if (use_bounding_boxes)
258  params.set<std::vector<Real>>("fixed_bounding_box_size") = fixed_bounding_box_size;
259  else
260  {
261  params.set<bool>("use_bounding_boxes") = false;
262  params.set<bool>("greedy_search") = true;
263  }
264  _problem->addTransfer(class_name, name() + "_T_solid_transfer", params);
265  }
266 
267  // Transfers from the flow channel application. Note that
268  // Note that MultiAppGeneralFieldNearestLocationTransfer should be more optimal
269  // choice in parallel calculations, while MultiAppGeneralFieldUserObjectTransfer should
270  // be more optimal in serial calculations. If these transfers prove to be a significant time
271  // burden, we may want to provide an option to switch these transfer classes.
272  for (unsigned int k = 0; k < _n_phases; k++)
273  {
274  {
275  const std::string class_name = "MultiAppGeneralFieldUserObjectTransfer";
276  InputParameters params = _factory.getValidParams(class_name);
277  params.set<MultiAppName>("from_multi_app") = _multi_app_name;
278  params.set<UserObjectName>("source_user_object") = _T_fluid_user_object_names[k];
279  params.set<std::vector<AuxVariableName>>("variable") = {_T_fluid_var_names[k]};
280  params.set<bool>("skip_coordinate_collapsing") = skip_coordinate_collapsing;
281  params.set<bool>("error_on_miss") = true;
282  if (use_bounding_boxes)
283  params.set<std::vector<Real>>("fixed_bounding_box_size") = fixed_bounding_box_size;
284  else
285  {
286  params.set<bool>("use_bounding_boxes") = false;
287  params.set<bool>("greedy_search") = true;
288  }
289  _problem->addTransfer(class_name, name() + "_T_fluid_transfer" + std::to_string(k), params);
290  }
291  {
292  const std::string class_name = "MultiAppGeneralFieldUserObjectTransfer";
293  InputParameters params = _factory.getValidParams(class_name);
294  params.set<MultiAppName>("from_multi_app") = _multi_app_name;
295  params.set<UserObjectName>("source_user_object") = _htc_user_object_names[k];
296  params.set<std::vector<AuxVariableName>>("variable") = {_htc_var_names[k]};
297  params.set<bool>("skip_coordinate_collapsing") = skip_coordinate_collapsing;
298  params.set<bool>("error_on_miss") = true;
299  if (use_bounding_boxes)
300  params.set<std::vector<Real>>("fixed_bounding_box_size") = fixed_bounding_box_size;
301  else
302  {
303  params.set<bool>("use_bounding_boxes") = false;
304  params.set<bool>("greedy_search") = true;
305  }
306  _problem->addTransfer(class_name, name() + "_htc_transfer" + std::to_string(k), params);
307  }
308  if (_n_phases > 1)
309  {
310  const std::string class_name = "MultiAppGeneralFieldUserObjectTransfer";
311  InputParameters params = _factory.getValidParams(class_name);
312  params.set<MultiAppName>("from_multi_app") = _multi_app_name;
313  params.set<UserObjectName>("source_user_object") = _kappa_user_object_names[k];
314  params.set<std::vector<AuxVariableName>>("variable") = {_kappa_var_names[k]};
315  params.set<bool>("skip_coordinate_collapsing") = skip_coordinate_collapsing;
316  params.set<bool>("error_on_miss") = true;
317  if (use_bounding_boxes)
318  params.set<std::vector<Real>>("fixed_bounding_box_size") = fixed_bounding_box_size;
319  else
320  {
321  params.set<bool>("use_bounding_boxes") = false;
322  params.set<bool>("greedy_search") = true;
323  }
324  _problem->addTransfer(class_name, name() + "_kappa_transfer" + std::to_string(k), params);
325  }
326  }
327 }
CoupledHeatTransferAction(const InputParameters &params)
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)
static InputParameters validParams()
const VariableName _T_wall_var_name
Variable on the flow channel side into which to transfer the solid temperature.
T & set(const std::string &name, bool quiet_mode=false)
const std::vector< VariableName > _T_fluid_var_names
Variable(s) on the solid side into which to transfer the fluid temperature(s)
InputParameters getValidParams(const std::string &name) const
const VariableName _T_solid_var_name
Solid side temperature variable name.
virtual const std::string & name() const
void addRequiredParam(const std::string &name, const std::string &doc_string)
const std::vector< VariableName > _htc_var_names
Variable(s) on the solid side into which to transfer the heat transfer coefficient(s) ...
static const std::string directions[3]
Definition: NS.h:22
bool isParamValid(const std::string &name) const
Factory & _factory
Action that creates the necessary objects, for the solid side, to couple a solid heat conduction regi...
MultiAppName _multi_app_name
Name of the THM multi-app.
registerMooseAction("ThermalHydraulicsApp", CoupledHeatTransferAction, "add_bc")
static InputParameters validParams()
const std::string name
Definition: Setup.h:20
const unsigned int _n_phases
Number of fluid phases.
const std::string & _current_task
const UserObjectName _T_wall_user_object_name
User object name with solid temperature.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
MooseEnum getAlignmentAxis() const
Gets an axis MooseEnum for the axis the component is aligned with.
std::vector< UserObjectName > _htc_user_object_names
Spatial user object(s) holding the heat transfer coefficient values.
void mooseError(Args &&... args) const
void addClassDescription(const std::string &doc_string)
std::shared_ptr< FEProblemBase > & _problem
static void addSkipCoordCollapsingParam(InputParameters &params)
std::vector< UserObjectName > _kappa_user_object_names
Spatial user objects holding the wall contact fraction values.
void addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
std::vector< BoundaryName > _boundary
Boundary where the BC is applied.
std::vector< VariableName > _kappa_var_names
Variables on the solid side into which to transfer the wall contact fractions.
std::vector< Real > getElementBoundaryCoordinates() const
Gets the element boundary coordinates for the aligned axis.
virtual bool isValid() const override
static const std::string k
Definition: NS.h:130
std::vector< UserObjectName > _T_fluid_user_object_names
Spatial user object(s) holding the fluid temperature values.