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 "HeatTransferFromHeatStructure3D1Phase.h"
11 : #include "FlowChannel1Phase.h"
12 : #include "HeatStructureFromFile3D.h"
13 : #include "FlowModelSinglePhase.h"
14 : #include "THMMesh.h"
15 : #include "MooseMesh.h"
16 : #include "ClosuresBase.h"
17 : #include "HeatConductionModel.h"
18 :
19 : registerMooseObject("ThermalHydraulicsApp", HeatTransferFromHeatStructure3D1Phase);
20 :
21 : InputParameters
22 102 : HeatTransferFromHeatStructure3D1Phase::validParams()
23 : {
24 102 : InputParameters params = HeatTransferFromTemperature1Phase::validParams();
25 :
26 102 : params.makeParamRequired<FunctionName>("P_hf");
27 102 : params.makeParamNotRequired<std::string>("flow_channel");
28 102 : params.suppressParameter<std::string>("flow_channel");
29 102 : params.set<std::string>("flow_channel", true) = "";
30 204 : params.addRequiredParam<std::vector<std::string>>(
31 : "flow_channels", "List of flow channel component names to connect to");
32 204 : params.addRequiredParam<BoundaryName>(
33 : "boundary", "The name of the heat structure boundary this heat transfer is applied on.");
34 204 : params.addRequiredParam<std::string>("hs", "Heat structure name");
35 102 : params.addClassDescription("Connects multiple 1-phase flow channels and a 3D heat structure");
36 :
37 102 : return params;
38 0 : }
39 :
40 51 : HeatTransferFromHeatStructure3D1Phase::HeatTransferFromHeatStructure3D1Phase(
41 51 : const InputParameters & parameters)
42 : : HeatTransferFromTemperature1Phase(parameters),
43 51 : _flow_channel_names(getParam<std::vector<std::string>>("flow_channels")),
44 102 : _boundary(getParam<BoundaryName>("boundary")),
45 102 : _hs_name(getParam<std::string>("hs")),
46 51 : _mesh_alignment(constMesh()),
47 204 : _layered_average_uo_direction(MooseEnum("x y z"))
48 : {
49 136 : for (const auto & fch_name : _flow_channel_names)
50 85 : addDependency(fch_name);
51 51 : addDependency(_hs_name);
52 51 : }
53 :
54 : const libMesh::FEType &
55 0 : HeatTransferFromHeatStructure3D1Phase::getFEType()
56 : {
57 0 : return HeatConductionModel::feType();
58 : }
59 :
60 : void
61 51 : HeatTransferFromHeatStructure3D1Phase::setupMesh()
62 : {
63 51 : if (hasComponentByName<HeatStructureFromFile3D>(_hs_name))
64 : {
65 : std::vector<dof_id_type> fchs_elem_ids;
66 132 : for (unsigned int i = 0; i < _flow_channel_names.size(); i++)
67 : {
68 83 : auto fch_name = _flow_channel_names[i];
69 : if (hasComponentByName<FlowChannel1Phase>(fch_name))
70 : {
71 : const FlowChannel1Phase & flow_channel = getComponentByName<FlowChannel1Phase>(fch_name);
72 81 : fchs_elem_ids.insert(fchs_elem_ids.end(),
73 81 : flow_channel.getElementIDs().begin(),
74 81 : flow_channel.getElementIDs().end());
75 : }
76 : }
77 :
78 49 : const auto & hs = getComponentByName<HeatStructureFromFile3D>(_hs_name);
79 49 : if (hs.hasBoundary(_boundary))
80 : {
81 47 : _mesh_alignment.initialize(fchs_elem_ids, hs.getBoundaryInfo(_boundary));
82 :
83 727 : for (const auto & fc_elem_id : fchs_elem_ids)
84 : {
85 680 : if (_mesh_alignment.hasCoupledSecondaryElemIDs(fc_elem_id))
86 : {
87 634 : const auto & hs_elem_ids = _mesh_alignment.getCoupledSecondaryElemIDs(fc_elem_id);
88 2886 : for (const auto & hs_elem_id : hs_elem_ids)
89 2252 : getTHMProblem().augmentSparsity(fc_elem_id, hs_elem_id);
90 : }
91 : }
92 : }
93 : }
94 51 : }
95 :
96 : HeatTransferFromHeatStructure3D1Phase::EAxisAlignment
97 83 : HeatTransferFromHeatStructure3D1Phase::getFlowChannelAxisAlignment(
98 : const std::string & flow_channel_name) const
99 : {
100 : const FlowChannel1Phase & flow_channel = getComponentByName<FlowChannel1Phase>(flow_channel_name);
101 83 : RealVectorValue direction = flow_channel.getDirection().unit();
102 : Real x_dir_norm = std::abs(direction * RealVectorValue(1, 0, 0));
103 : Real y_dir_norm = std::abs(direction * RealVectorValue(0, 1, 0));
104 : Real z_dir_norm = std::abs(direction * RealVectorValue(0, 0, 1));
105 83 : if (x_dir_norm == 1 && y_dir_norm == 0 && z_dir_norm == 0)
106 : return EAxisAlignment::X;
107 75 : else if (x_dir_norm == 0 && y_dir_norm == 1 && z_dir_norm == 0)
108 : return EAxisAlignment::Y;
109 73 : else if (x_dir_norm == 0 && y_dir_norm == 0 && z_dir_norm == 1)
110 : return EAxisAlignment::Z;
111 : else
112 : {
113 2 : logError(
114 : "The flow channel '", flow_channel_name, "' must be aligned with the x-, y-, or z- axis.");
115 2 : return EAxisAlignment::INVALID;
116 : }
117 : }
118 :
119 : void
120 51 : HeatTransferFromHeatStructure3D1Phase::init()
121 : {
122 51 : ConnectorBase::init();
123 :
124 : std::vector<EAxisAlignment> fch_axis_alignment;
125 : std::vector<unsigned int> fch_num_elems;
126 : std::vector<Real> fch_lengths;
127 136 : for (const auto & fch_name : _flow_channel_names)
128 : {
129 85 : checkComponentOfTypeExistsByName<FlowChannel1Phase>(fch_name);
130 :
131 : if (hasComponentByName<FlowChannel1Phase>(fch_name))
132 : {
133 : const FlowChannel1Phase & flow_channel = getComponentByName<FlowChannel1Phase>(fch_name);
134 :
135 83 : flow_channel.addHeatTransferName(name());
136 83 : fch_axis_alignment.push_back(getFlowChannelAxisAlignment(fch_name));
137 :
138 83 : const auto subdomain_names = flow_channel.getSubdomainNames();
139 83 : _flow_channel_subdomains.insert(
140 : _flow_channel_subdomains.end(), subdomain_names.begin(), subdomain_names.end());
141 :
142 : const auto & closures = flow_channel.getClosuresObjects();
143 83 : _flow_channel_closures.insert(_flow_channel_closures.end(), closures.begin(), closures.end());
144 :
145 83 : fch_num_elems.push_back(flow_channel.getNumElems());
146 :
147 83 : fch_lengths.push_back(flow_channel.getLength());
148 83 : }
149 : }
150 :
151 : // check that all flow channels have the same axis alignment
152 51 : if (fch_axis_alignment.size() > 1)
153 : {
154 68 : for (unsigned int i = 1; i < fch_axis_alignment.size(); i++)
155 34 : if (fch_axis_alignment[i] != fch_axis_alignment[0])
156 4 : logError("Flow channel '",
157 4 : _flow_channel_names[i],
158 : "' has a different axis alignment (",
159 : fch_axis_alignment[i],
160 : "). Make sure all flow channels are aligned with the same axis.");
161 : }
162 51 : if (fch_axis_alignment.size() > 0 && fch_axis_alignment[0] != EAxisAlignment::INVALID)
163 47 : _layered_average_uo_direction = fch_axis_alignment[0];
164 :
165 : // check that all flow channels have the same number of elements
166 51 : if (fch_num_elems.size() > 1)
167 : {
168 68 : for (unsigned int i = 1; i < fch_num_elems.size(); i++)
169 34 : if (fch_num_elems[i] != fch_num_elems[0])
170 2 : logError("Flow channel '",
171 2 : _flow_channel_names[i],
172 : "' has ",
173 : fch_num_elems[i],
174 : " elements which is inconsistent with the rest of the flow channels. Make sure "
175 : "all flow channels have the same number of elements.");
176 : }
177 51 : if (fch_num_elems.size() > 0)
178 49 : _num_layers = fch_num_elems[0];
179 :
180 : // check that all flow channels have the same length
181 51 : if (fch_lengths.size() > 1)
182 : {
183 68 : for (unsigned int i = 1; i < fch_lengths.size(); i++)
184 34 : if (fch_lengths[i] != fch_lengths[0])
185 2 : logError("Flow channel '",
186 2 : _flow_channel_names[i],
187 : "' has length equal to ",
188 : fch_lengths[i],
189 : " which is inconsistent with the rest of the flow channels. Make sure all flow "
190 : "channels have the length.");
191 : }
192 51 : }
193 :
194 : void
195 51 : HeatTransferFromHeatStructure3D1Phase::initSecondary()
196 : {
197 : ConnectorBase::initSecondary();
198 :
199 136 : for (const auto & fch_name : _flow_channel_names)
200 : {
201 : if (hasComponentByName<FlowChannel1Phase>(fch_name))
202 : {
203 : const FlowChannel1Phase & flow_channel = getComponentByName<FlowChannel1Phase>(fch_name);
204 83 : const std::string suffix = flow_channel.getHeatTransferNamesSuffix(name());
205 83 : _P_hf_name = FlowModel::HEAT_FLUX_PERIMETER + suffix;
206 83 : _T_wall_name = FlowModel::TEMPERATURE_WALL + suffix;
207 83 : _q_wall_name = FlowModel::HEAT_FLUX_WALL + suffix;
208 166 : _Hw_1phase_name = FlowModelSinglePhase::HEAT_TRANSFER_COEFFICIENT_WALL + suffix;
209 : }
210 : }
211 51 : }
212 :
213 : void
214 46 : HeatTransferFromHeatStructure3D1Phase::check() const
215 : {
216 46 : ConnectorBase::check();
217 :
218 124 : for (unsigned int i = 0; i < _flow_channel_closures.size(); i++)
219 : {
220 : auto & clsr = _flow_channel_closures[i];
221 78 : if (clsr != nullptr && hasComponentByName<FlowChannel1Phase>(_flow_channel_names[i]))
222 78 : clsr->checkHeatTransfer(*this, getComponentByName<FlowChannel1Phase>(_flow_channel_names[i]));
223 : }
224 :
225 46 : if (hasComponentByName<HeatStructureFromFile3D>(_hs_name))
226 : {
227 : const auto & hs = getComponentByName<HeatStructureFromFile3D>(_hs_name);
228 44 : if (!hs.hasBoundary(_boundary))
229 2 : logError("The boundary '", _boundary, "' does not exist on the component '", _hs_name, "'.");
230 : }
231 : else
232 2 : logError("The component '", _hs_name, "' is not a HeatStructureFromFile3D component.");
233 46 : }
234 :
235 : void
236 37 : HeatTransferFromHeatStructure3D1Phase::addVariables()
237 : {
238 37 : getTHMProblem().addSimVariable(
239 37 : false, _P_hf_name, getTHMProblem().getFlowFEType(), _flow_channel_subdomains);
240 :
241 37 : _P_hf_fn_name = getParam<FunctionName>("P_hf");
242 :
243 37 : if (!_app.isRestarting())
244 37 : getTHMProblem().addFunctionIC(_P_hf_name, _P_hf_fn_name, _flow_channel_subdomains);
245 :
246 37 : getTHMProblem().addSimVariable(false,
247 : FlowModel::TEMPERATURE_WALL,
248 : libMesh::FEType(CONSTANT, MONOMIAL),
249 : _flow_channel_subdomains);
250 37 : getTHMProblem().addSimVariable(
251 37 : false, _T_wall_name, libMesh::FEType(CONSTANT, MONOMIAL), _flow_channel_subdomains);
252 :
253 : // wall temperature initial condition
254 37 : if (!getTHMProblem().hasInitialConditionsFromFile() && !_app.isRestarting())
255 : {
256 33 : const HeatStructureFromFile3D & hs = getComponentByName<HeatStructureFromFile3D>(_hs_name);
257 66 : getTHMProblem().addFunctionIC(_T_wall_name, hs.getInitialT(), _flow_channel_subdomains);
258 : }
259 37 : }
260 :
261 : void
262 37 : HeatTransferFromHeatStructure3D1Phase::addMooseObjects()
263 : {
264 37 : HeatTransferBase::addMooseObjects();
265 :
266 98 : for (unsigned int i = 0; i < _flow_channel_closures.size(); i++)
267 : {
268 61 : _flow_channel_closures[i]->addMooseObjectsHeatTransfer(
269 61 : *this, getComponentByName<FlowChannel1Phase>(_flow_channel_names[i]));
270 : }
271 :
272 37 : ExecFlagEnum execute_on(MooseUtils::getDefaultExecFlagEnum());
273 185 : execute_on = {EXEC_INITIAL, EXEC_LINEAR, EXEC_NONLINEAR};
274 :
275 : std::vector<Point> fch_positions;
276 98 : for (const auto & fch_name : _flow_channel_names)
277 : {
278 : const FlowChannel1Phase & flow_channel = getComponentByName<FlowChannel1Phase>(fch_name);
279 122 : fch_positions.push_back(flow_channel.getPosition());
280 : }
281 :
282 74 : const UserObjectName T_wall_avg_uo_name = genName(name(), "T_wall_avg_uo");
283 : {
284 37 : const std::string class_name = "NearestPointLayeredSideAverage";
285 37 : InputParameters params = _factory.getValidParams(class_name);
286 111 : params.set<std::vector<VariableName>>("variable") = {HeatConductionModel::TEMPERATURE};
287 111 : params.set<std::vector<BoundaryName>>("boundary") = {_boundary};
288 37 : params.set<ExecFlagEnum>("execute_on") = execute_on;
289 37 : params.set<MooseEnum>("direction") = _layered_average_uo_direction;
290 37 : params.set<unsigned int>("num_layers") = _num_layers;
291 37 : params.set<std::vector<Point>>("points") = fch_positions;
292 37 : getTHMProblem().addUserObject(class_name, T_wall_avg_uo_name, params);
293 37 : }
294 : {
295 37 : std::string class_name = "SpatialUserObjectAux";
296 37 : InputParameters params = _factory.getValidParams(class_name);
297 37 : params.set<std::vector<SubdomainName>>("block") = _flow_channel_subdomains;
298 74 : params.set<AuxVariableName>("variable") = _T_wall_name;
299 37 : params.set<ExecFlagEnum>("execute_on") = execute_on;
300 37 : params.set<UserObjectName>("user_object") = T_wall_avg_uo_name;
301 74 : getTHMProblem().addAuxKernel(class_name, genName(name(), "T_wall_transfer"), params);
302 37 : }
303 : {
304 37 : const std::string class_name = "ADOneD3EqnEnergyHeatFluxFromHeatStructure3D";
305 37 : InputParameters params = _factory.getValidParams(class_name);
306 74 : params.set<std::vector<SubdomainName>>("block") = _flow_channel_subdomains;
307 111 : params.set<std::vector<VariableName>>("P_hf") = {_P_hf_name};
308 37 : params.set<MaterialPropertyName>("Hw") = _Hw_1phase_name;
309 74 : params.set<UserObjectName>("user_object") = T_wall_avg_uo_name;
310 74 : params.set<MaterialPropertyName>("T") = FlowModelSinglePhase::TEMPERATURE;
311 74 : params.set<NonlinearVariableName>("variable") = FlowModelSinglePhase::RHOEA;
312 74 : getTHMProblem().addKernel(class_name, genName(name(), "heat_flux_kernel"), params);
313 37 : }
314 :
315 74 : const UserObjectName heat_transfer_uo_name = genName(name(), "heat_flux_uo");
316 : {
317 37 : const std::string class_name = "ADHeatTransferFromHeatStructure3D1PhaseUserObject";
318 37 : InputParameters params = _factory.getValidParams(class_name);
319 37 : params.set<std::vector<SubdomainName>>("block") = _flow_channel_subdomains;
320 37 : params.set<MeshAlignment1D3D *>("_mesh_alignment") = &_mesh_alignment;
321 111 : params.set<std::vector<VariableName>>("P_hf") = {_P_hf_name};
322 74 : params.set<MaterialPropertyName>("Hw") = _Hw_1phase_name;
323 74 : params.set<MaterialPropertyName>("T") = FlowModelSinglePhase::TEMPERATURE;
324 37 : params.set<ExecFlagEnum>("execute_on") = execute_on;
325 37 : getTHMProblem().addUserObject(class_name, heat_transfer_uo_name, params);
326 37 : }
327 : {
328 37 : const std::string class_name = "ADConvectionHeatTransfer3DBC";
329 37 : InputParameters params = _factory.getValidParams(class_name);
330 111 : params.set<std::vector<BoundaryName>>("boundary") = {_boundary};
331 74 : params.set<NonlinearVariableName>("variable") = HeatConductionModel::TEMPERATURE;
332 37 : params.set<UserObjectName>("ht_uo") = heat_transfer_uo_name;
333 74 : getTHMProblem().addBoundaryCondition(class_name, genName(name(), "heat_flux_bc"), params);
334 37 : }
335 148 : }
|