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 "CoupledHeatTransferAction.h"
11 : #include "DiscreteLineSegmentInterface.h"
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 :
18 : InputParameters
19 74 : CoupledHeatTransferAction::validParams()
20 : {
21 74 : InputParameters params = Action::validParams();
22 :
23 74 : 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 148 : params.addRequiredParam<std::vector<BoundaryName>>("boundary",
28 : "Boundary name(s) on the solid side");
29 148 : params.addRequiredParam<VariableName>("T", "Solid side temperature variable");
30 148 : params.addRequiredParam<VariableName>(
31 : "T_wall", "Variable on the flow channel side into which to transfer the solid temperature");
32 148 : params.addRequiredParam<std::vector<VariableName>>(
33 : "T_fluid", "Variable(s) on the solid side into which to transfer the fluid temperature(s)");
34 148 : params.addRequiredParam<std::vector<VariableName>>(
35 : "htc",
36 : "Variable(s) on the solid side into which to transfer the heat transfer coefficient(s)");
37 148 : params.addParam<std::vector<VariableName>>(
38 : "kappa", "Variables on the solid side into which to transfer the wall contact fractions");
39 148 : params.addRequiredParam<std::vector<UserObjectName>>(
40 : "T_fluid_user_objects", "Spatial user object(s) holding the fluid temperature values");
41 148 : params.addRequiredParam<std::vector<UserObjectName>>(
42 : "htc_user_objects", "Spatial user object(s) holding the heat transfer coefficient values");
43 148 : params.addParam<std::vector<UserObjectName>>(
44 : "kappa_user_objects", "Spatial user object(s) holding the wall contact fraction values");
45 :
46 148 : params.addRequiredParam<Point>("position", "Start position of axis in 3-D space [m]");
47 148 : params.addRequiredParam<RealVectorValue>(
48 : "orientation",
49 : "Direction of axis from start position to end position (no need to normalize)");
50 148 : params.addParam<Real>("rotation", 0.0, "Angle of rotation about the x-axis [degrees]");
51 148 : params.addRequiredParam<std::vector<Real>>("length", "Length of each axial section [m]");
52 148 : params.addRequiredParam<std::vector<unsigned int>>("n_elems",
53 : "Number of elements in each axial section");
54 :
55 148 : params.addRequiredParam<std::string>("multi_app", "The name of the multi-app.");
56 :
57 148 : params.addRangeCheckedParam<std::vector<Real>>(
58 : "fixed_bounding_box_size",
59 : "fixed_bounding_box_size >= 0",
60 : "The 'fixed_bounding_box_size' value to use for each MultiAppGeneralFieldUserObjectTransfer. "
61 : "If this parameter is not provided, a greedy search will be used instead of bounding boxes, "
62 : "which may be slower.");
63 :
64 148 : params.addParam<std::vector<Point>>(
65 : "positions", "Sub-app positions. Each set of 3 values represents a Point.");
66 148 : params.addParam<FileName>(
67 : "positions_file",
68 : "Name of file containing sub-app positions. Each set of 3 values represents a Point.");
69 74 : MultiAppTransfer::addSkipCoordCollapsingParam(params);
70 74 : return params;
71 0 : }
72 :
73 74 : CoupledHeatTransferAction::CoupledHeatTransferAction(const InputParameters & params)
74 : : Action(params),
75 :
76 74 : _boundary(getParam<std::vector<BoundaryName>>("boundary")),
77 :
78 74 : _T_solid_var_name(getParam<VariableName>("T")),
79 74 : _T_wall_var_name(getParam<VariableName>("T_wall")),
80 148 : _T_fluid_var_names(getParam<std::vector<VariableName>>("T_fluid")),
81 222 : _htc_var_names(getParam<std::vector<VariableName>>("htc")),
82 :
83 74 : _n_phases(_T_fluid_var_names.size()),
84 :
85 74 : _T_wall_user_object_name(name() + "_T_avg_uo"),
86 148 : _T_fluid_user_object_names(getParam<std::vector<UserObjectName>>("T_fluid_user_objects")),
87 222 : _htc_user_object_names(getParam<std::vector<UserObjectName>>("htc_user_objects")),
88 :
89 222 : _multi_app_name(getParam<std::string>("multi_app"))
90 : {
91 74 : if (_htc_var_names.size() != _n_phases || _T_fluid_user_object_names.size() != _n_phases ||
92 : _htc_user_object_names.size() != _n_phases)
93 0 : mooseError("The parameters 'T_fluid', 'htc', 'T_fluid_user_objects', and 'htc_user_objects' "
94 : "must have the same numbers of elements.");
95 :
96 74 : if (_n_phases == 1)
97 : {
98 200 : if (isParamValid("kappa") || isParamValid("kappa_user_objects"))
99 0 : mooseError("If there is only one phase (e.g., only one element in 'T_fluid'), then the "
100 : "parameters 'kappa' and 'kappa_user_objects' must not be provided.");
101 : }
102 : else
103 : {
104 96 : if (!isParamValid("kappa") || !isParamValid("kappa_user_objects"))
105 0 : mooseError("If there is more than one phase (e.g., more than one element in 'T_fluid'), then "
106 : "the parameters 'kappa' and 'kappa_user_objects' must be provided.");
107 : else
108 : {
109 48 : _kappa_var_names = getParam<std::vector<VariableName>>("kappa");
110 72 : _kappa_user_object_names = getParam<std::vector<UserObjectName>>("kappa_user_objects");
111 24 : if (_kappa_var_names.size() != _n_phases || _kappa_user_object_names.size() != _n_phases)
112 0 : mooseError("The parameters 'kappa' and 'kappa_user_objects' must have the same number of "
113 : "elements as 'T_fluid'.");
114 : }
115 : }
116 :
117 74 : const auto & orientation = getParam<RealVectorValue>("orientation");
118 74 : if (!DiscreteLineSegmentInterface::getAlignmentAxis(orientation).isValid())
119 2 : mooseError("The direction given by the parameter 'orientation' must be aligned with the x, "
120 : "y, or z axis.");
121 72 : }
122 :
123 : void
124 72 : CoupledHeatTransferAction::act()
125 : {
126 72 : if (_current_task == "add_bc")
127 24 : addBCs();
128 48 : else if (_current_task == "add_user_object")
129 24 : addUserObjects();
130 24 : else if (_current_task == "add_transfer")
131 24 : addTransfers();
132 72 : }
133 :
134 : void
135 24 : CoupledHeatTransferAction::addBCs()
136 : {
137 56 : for (unsigned int k = 0; k < _n_phases; k++)
138 : {
139 32 : const std::string class_name = "CoupledConvectiveHeatFluxBC";
140 32 : InputParameters params = _factory.getValidParams(class_name);
141 64 : params.set<NonlinearVariableName>("variable") = _T_solid_var_name;
142 32 : params.set<std::vector<BoundaryName>>("boundary") = {_boundary};
143 96 : params.set<std::vector<VariableName>>("T_infinity") = {_T_fluid_var_names[k]};
144 96 : params.set<std::vector<VariableName>>("htc") = {_htc_var_names[k]};
145 32 : if (_n_phases > 1)
146 48 : params.set<std::vector<VariableName>>("scale_factor") = {_kappa_var_names[k]};
147 64 : _problem->addBoundaryCondition(class_name, name() + "_bc" + std::to_string(k), params);
148 32 : }
149 24 : }
150 :
151 : void
152 24 : CoupledHeatTransferAction::addUserObjects()
153 : {
154 : // Solid temperature spatial user object
155 : {
156 24 : const std::string class_name = "NearestPointLayeredSideAverage";
157 24 : InputParameters params = _factory.getValidParams(class_name);
158 72 : params.set<std::vector<VariableName>>("variable") = {_T_solid_var_name};
159 24 : params.set<std::vector<BoundaryName>>("boundary") = {_boundary};
160 :
161 : // set sub-app positions
162 48 : if (isParamValid("positions"))
163 24 : params.set<std::vector<Point>>("points") = getParam<std::vector<Point>>("positions");
164 32 : else if (isParamValid("positions_file"))
165 0 : params.set<FileName>("points_file") = getParam<FileName>("positions_file");
166 : else
167 32 : params.set<std::vector<Point>>("points") = {Point(0, 0, 0)};
168 :
169 24 : const auto & position = getParam<Point>("position");
170 24 : const auto & orientation = getParam<RealVectorValue>("orientation");
171 24 : const auto & rotation = getParam<Real>("rotation");
172 24 : const auto & lengths = getParam<std::vector<Real>>("length");
173 24 : const auto & n_elems = getParam<std::vector<unsigned int>>("n_elems");
174 :
175 24 : params.set<MooseEnum>("direction") =
176 72 : DiscreteLineSegmentInterface::getAlignmentAxis(orientation);
177 24 : params.set<std::vector<Real>>("bounds") =
178 48 : DiscreteLineSegmentInterface::getElementBoundaryCoordinates(
179 : position, orientation, rotation, lengths, n_elems);
180 :
181 24 : _problem->addUserObject(class_name, _T_wall_user_object_name, params);
182 24 : }
183 24 : }
184 :
185 : void
186 24 : CoupledHeatTransferAction::addTransfers()
187 : {
188 : // Transfers to the flow channel application
189 :
190 48 : const bool skip_coordinate_collapsing = getParam<bool>("skip_coordinate_collapsing");
191 :
192 48 : const bool use_bounding_boxes = isParamValid("fixed_bounding_box_size");
193 : std::vector<Real> fixed_bounding_box_size;
194 24 : if (use_bounding_boxes)
195 0 : fixed_bounding_box_size = getParam<std::vector<Real>>("fixed_bounding_box_size");
196 :
197 : {
198 24 : const std::string class_name = "MultiAppGeneralFieldUserObjectTransfer";
199 24 : InputParameters params = _factory.getValidParams(class_name);
200 24 : params.set<MultiAppName>("to_multi_app") = _multi_app_name;
201 24 : params.set<UserObjectName>("source_user_object") = {_T_wall_user_object_name};
202 72 : params.set<std::vector<AuxVariableName>>("variable") = {_T_wall_var_name};
203 24 : params.set<bool>("skip_coordinate_collapsing") = skip_coordinate_collapsing;
204 24 : params.set<bool>("error_on_miss") = true;
205 24 : if (use_bounding_boxes)
206 0 : params.set<std::vector<Real>>("fixed_bounding_box_size") = fixed_bounding_box_size;
207 : else
208 : {
209 24 : params.set<bool>("use_bounding_boxes") = false;
210 24 : params.set<bool>("greedy_search") = true;
211 : }
212 24 : _problem->addTransfer(class_name, name() + "_T_solid_transfer", params);
213 24 : }
214 :
215 : // Transfers from the flow channel application. Note that
216 : // Note that MultiAppGeneralFieldNearestLocationTransfer should be more optimal
217 : // choice in parallel calculations, while MultiAppGeneralFieldUserObjectTransfer should
218 : // be more optimal in serial calculations. If these transfers prove to be a significant time
219 : // burden, we may want to provide an option to switch these transfer classes.
220 56 : for (unsigned int k = 0; k < _n_phases; k++)
221 : {
222 : {
223 32 : const std::string class_name = "MultiAppGeneralFieldUserObjectTransfer";
224 32 : InputParameters params = _factory.getValidParams(class_name);
225 32 : params.set<MultiAppName>("from_multi_app") = _multi_app_name;
226 64 : params.set<UserObjectName>("source_user_object") = _T_fluid_user_object_names[k];
227 96 : params.set<std::vector<AuxVariableName>>("variable") = {_T_fluid_var_names[k]};
228 32 : params.set<bool>("skip_coordinate_collapsing") = skip_coordinate_collapsing;
229 32 : params.set<bool>("error_on_miss") = true;
230 32 : if (use_bounding_boxes)
231 0 : params.set<std::vector<Real>>("fixed_bounding_box_size") = fixed_bounding_box_size;
232 : else
233 : {
234 32 : params.set<bool>("use_bounding_boxes") = false;
235 32 : params.set<bool>("greedy_search") = true;
236 : }
237 64 : _problem->addTransfer(class_name, name() + "_T_fluid_transfer" + std::to_string(k), params);
238 32 : }
239 : {
240 32 : const std::string class_name = "MultiAppGeneralFieldUserObjectTransfer";
241 32 : InputParameters params = _factory.getValidParams(class_name);
242 64 : params.set<MultiAppName>("from_multi_app") = _multi_app_name;
243 64 : params.set<UserObjectName>("source_user_object") = _htc_user_object_names[k];
244 96 : params.set<std::vector<AuxVariableName>>("variable") = {_htc_var_names[k]};
245 32 : params.set<bool>("skip_coordinate_collapsing") = skip_coordinate_collapsing;
246 32 : params.set<bool>("error_on_miss") = true;
247 32 : if (use_bounding_boxes)
248 0 : params.set<std::vector<Real>>("fixed_bounding_box_size") = fixed_bounding_box_size;
249 : else
250 : {
251 32 : params.set<bool>("use_bounding_boxes") = false;
252 32 : params.set<bool>("greedy_search") = true;
253 : }
254 64 : _problem->addTransfer(class_name, name() + "_htc_transfer" + std::to_string(k), params);
255 32 : }
256 32 : if (_n_phases > 1)
257 : {
258 16 : const std::string class_name = "MultiAppGeneralFieldUserObjectTransfer";
259 16 : InputParameters params = _factory.getValidParams(class_name);
260 32 : params.set<MultiAppName>("from_multi_app") = _multi_app_name;
261 32 : params.set<UserObjectName>("source_user_object") = _kappa_user_object_names[k];
262 48 : params.set<std::vector<AuxVariableName>>("variable") = {_kappa_var_names[k]};
263 16 : params.set<bool>("skip_coordinate_collapsing") = skip_coordinate_collapsing;
264 16 : params.set<bool>("error_on_miss") = true;
265 16 : if (use_bounding_boxes)
266 0 : params.set<std::vector<Real>>("fixed_bounding_box_size") = fixed_bounding_box_size;
267 : else
268 : {
269 16 : params.set<bool>("use_bounding_boxes") = false;
270 16 : params.set<bool>("greedy_search") = true;
271 : }
272 32 : _problem->addTransfer(class_name, name() + "_kappa_transfer" + std::to_string(k), params);
273 16 : }
274 : }
275 128 : }
|