https://mooseframework.inl.gov
HeatTransferFromHeatStructure3D1Phase.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 #include "FlowChannel1Phase.h"
13 #include "FlowModelSinglePhase.h"
14 #include "THMMesh.h"
15 #include "MooseMesh.h"
16 #include "ClosuresBase.h"
17 #include "HeatConductionModel.h"
18 
20 
23 {
25 
26  params.makeParamRequired<FunctionName>("P_hf");
27  params.makeParamNotRequired<std::string>("flow_channel");
28  params.suppressParameter<std::string>("flow_channel");
29  params.set<std::string>("flow_channel", true) = "";
30  params.addRequiredParam<std::vector<std::string>>(
31  "flow_channels", "List of flow channel component names to connect to");
32  params.addRequiredParam<BoundaryName>(
33  "boundary", "The name of the heat structure boundary this heat transfer is applied on.");
34  params.addRequiredParam<std::string>("hs", "Heat structure name");
35  params.addClassDescription("Connects multiple 1-phase flow channels and a 3D heat structure");
36 
37  return params;
38 }
39 
41  const InputParameters & parameters)
43  _flow_channel_names(getParam<std::vector<std::string>>("flow_channels")),
44  _boundary(getParam<BoundaryName>("boundary")),
45  _hs_name(getParam<std::string>("hs")),
46  _mesh_alignment(constMesh()),
47  _layered_average_uo_direction(MooseEnum("x y z"))
48 {
49  for (const auto & fch_name : _flow_channel_names)
50  addDependency(fch_name);
52 }
53 
54 const libMesh::FEType &
56 {
58 }
59 
60 void
62 {
63  if (hasComponentByName<HeatStructureFromFile3D>(_hs_name))
64  {
65  std::vector<dof_id_type> fchs_elem_ids;
66  for (unsigned int i = 0; i < _flow_channel_names.size(); i++)
67  {
68  auto fch_name = _flow_channel_names[i];
69  if (hasComponentByName<FlowChannel1Phase>(fch_name))
70  {
71  const FlowChannel1Phase & flow_channel = getComponentByName<FlowChannel1Phase>(fch_name);
72  fchs_elem_ids.insert(fchs_elem_ids.end(),
73  flow_channel.getElementIDs().begin(),
74  flow_channel.getElementIDs().end());
75  }
76  }
77 
78  const auto & hs = getComponentByName<HeatStructureFromFile3D>(_hs_name);
79  if (hs.hasBoundary(_boundary))
80  {
81  _mesh_alignment.initialize(fchs_elem_ids, hs.getBoundaryInfo(_boundary));
82 
83  for (const auto & fc_elem_id : fchs_elem_ids)
84  {
86  {
87  const auto & hs_elem_ids = _mesh_alignment.getCoupledSecondaryElemIDs(fc_elem_id);
88  for (const auto & hs_elem_id : hs_elem_ids)
89  getTHMProblem().augmentSparsity(fc_elem_id, hs_elem_id);
90  }
91  }
92  }
93  }
94 }
95 
98  const std::string & flow_channel_name) const
99 {
100  const FlowChannel1Phase & flow_channel = getComponentByName<FlowChannel1Phase>(flow_channel_name);
101  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  if (x_dir_norm == 1 && y_dir_norm == 0 && z_dir_norm == 0)
106  return EAxisAlignment::X;
107  else if (x_dir_norm == 0 && y_dir_norm == 1 && z_dir_norm == 0)
108  return EAxisAlignment::Y;
109  else if (x_dir_norm == 0 && y_dir_norm == 0 && z_dir_norm == 1)
110  return EAxisAlignment::Z;
111  else
112  {
113  logError(
114  "The flow channel '", flow_channel_name, "' must be aligned with the x-, y-, or z- axis.");
115  return EAxisAlignment::INVALID;
116  }
117 }
118 
119 void
121 {
123 
124  std::vector<EAxisAlignment> fch_axis_alignment;
125  std::vector<unsigned int> fch_num_elems;
126  std::vector<Real> fch_lengths;
127  for (const auto & fch_name : _flow_channel_names)
128  {
129  checkComponentOfTypeExistsByName<FlowChannel1Phase>(fch_name);
130 
131  if (hasComponentByName<FlowChannel1Phase>(fch_name))
132  {
133  const FlowChannel1Phase & flow_channel = getComponentByName<FlowChannel1Phase>(fch_name);
134 
135  flow_channel.addHeatTransferName(name());
136  fch_axis_alignment.push_back(getFlowChannelAxisAlignment(fch_name));
137 
138  const auto subdomain_names = flow_channel.getSubdomainNames();
140  _flow_channel_subdomains.end(), subdomain_names.begin(), subdomain_names.end());
141 
142  const auto & closures = flow_channel.getClosuresObjects();
143  _flow_channel_closures.insert(_flow_channel_closures.end(), closures.begin(), closures.end());
144 
145  fch_num_elems.push_back(flow_channel.getNumElems());
146 
147  fch_lengths.push_back(flow_channel.getLength());
148  }
149  }
150 
151  // check that all flow channels have the same axis alignment
152  if (fch_axis_alignment.size() > 1)
153  {
154  for (unsigned int i = 1; i < fch_axis_alignment.size(); i++)
155  if (fch_axis_alignment[i] != fch_axis_alignment[0])
156  logError("Flow channel '",
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  if (fch_axis_alignment.size() > 0 && fch_axis_alignment[0] != EAxisAlignment::INVALID)
163  _layered_average_uo_direction = fch_axis_alignment[0];
164 
165  // check that all flow channels have the same number of elements
166  if (fch_num_elems.size() > 1)
167  {
168  for (unsigned int i = 1; i < fch_num_elems.size(); i++)
169  if (fch_num_elems[i] != fch_num_elems[0])
170  logError("Flow channel '",
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  if (fch_num_elems.size() > 0)
178  _num_layers = fch_num_elems[0];
179 
180  // check that all flow channels have the same length
181  if (fch_lengths.size() > 1)
182  {
183  for (unsigned int i = 1; i < fch_lengths.size(); i++)
184  if (fch_lengths[i] != fch_lengths[0])
185  logError("Flow channel '",
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 }
193 
194 void
196 {
198 
199  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  const std::string suffix = flow_channel.getHeatTransferNamesSuffix(name());
209  }
210  }
211 }
212 
213 void
215 {
217 
218  for (unsigned int i = 0; i < _flow_channel_closures.size(); i++)
219  {
220  auto & clsr = _flow_channel_closures[i];
221  if (clsr != nullptr && hasComponentByName<FlowChannel1Phase>(_flow_channel_names[i]))
222  clsr->checkHeatTransfer(*this, getComponentByName<FlowChannel1Phase>(_flow_channel_names[i]));
223  }
224 
225  if (hasComponentByName<HeatStructureFromFile3D>(_hs_name))
226  {
227  const auto & hs = getComponentByName<HeatStructureFromFile3D>(_hs_name);
228  if (!hs.hasBoundary(_boundary))
229  logError("The boundary '", _boundary, "' does not exist on the component '", _hs_name, "'.");
230  }
231  else
232  logError("The component '", _hs_name, "' is not a HeatStructureFromFile3D component.");
233 }
234 
235 void
237 {
239  false, _P_hf_name, getTHMProblem().getFlowFEType(), _flow_channel_subdomains);
240 
241  _P_hf_fn_name = getParam<FunctionName>("P_hf");
242 
243  if (!_app.isRestarting())
245 
252 
253  // wall temperature initial condition
254  if (!getTHMProblem().hasInitialConditionsFromFile() && !_app.isRestarting())
255  {
256  const HeatStructureFromFile3D & hs = getComponentByName<HeatStructureFromFile3D>(_hs_name);
258  }
259 }
260 
261 void
263 {
265 
266  for (unsigned int i = 0; i < _flow_channel_closures.size(); i++)
267  {
268  _flow_channel_closures[i]->addMooseObjectsHeatTransfer(
269  *this, getComponentByName<FlowChannel1Phase>(_flow_channel_names[i]));
270  }
271 
273  execute_on = {EXEC_INITIAL, EXEC_LINEAR, EXEC_NONLINEAR};
274 
275  std::vector<Point> fch_positions;
276  for (const auto & fch_name : _flow_channel_names)
277  {
278  const FlowChannel1Phase & flow_channel = getComponentByName<FlowChannel1Phase>(fch_name);
279  fch_positions.push_back(flow_channel.getPosition());
280  }
281 
282  const UserObjectName T_wall_avg_uo_name = genName(name(), "T_wall_avg_uo");
283  {
284  const std::string class_name = "NearestPointLayeredSideAverage";
285  InputParameters params = _factory.getValidParams(class_name);
286  params.set<std::vector<VariableName>>("variable") = {HeatConductionModel::TEMPERATURE};
287  params.set<std::vector<BoundaryName>>("boundary") = {_boundary};
288  params.set<ExecFlagEnum>("execute_on") = execute_on;
289  params.set<MooseEnum>("direction") = _layered_average_uo_direction;
290  params.set<unsigned int>("num_layers") = _num_layers;
291  params.set<std::vector<Point>>("points") = fch_positions;
292  getTHMProblem().addUserObject(class_name, T_wall_avg_uo_name, params);
293  }
294  {
295  std::string class_name = "SpatialUserObjectAux";
296  InputParameters params = _factory.getValidParams(class_name);
297  params.set<std::vector<SubdomainName>>("block") = _flow_channel_subdomains;
298  params.set<AuxVariableName>("variable") = _T_wall_name;
299  params.set<ExecFlagEnum>("execute_on") = execute_on;
300  params.set<UserObjectName>("user_object") = T_wall_avg_uo_name;
301  getTHMProblem().addAuxKernel(class_name, genName(name(), "T_wall_transfer"), params);
302  }
303  {
304  const std::string class_name = "ADOneD3EqnEnergyHeatFluxFromHeatStructure3D";
305  InputParameters params = _factory.getValidParams(class_name);
306  params.set<std::vector<SubdomainName>>("block") = _flow_channel_subdomains;
307  params.set<std::vector<VariableName>>("P_hf") = {_P_hf_name};
308  params.set<MaterialPropertyName>("Hw") = _Hw_1phase_name;
309  params.set<UserObjectName>("user_object") = T_wall_avg_uo_name;
310  params.set<MaterialPropertyName>("T") = FlowModelSinglePhase::TEMPERATURE;
311  params.set<NonlinearVariableName>("variable") = FlowModelSinglePhase::RHOEA;
312  getTHMProblem().addKernel(class_name, genName(name(), "heat_flux_kernel"), params);
313  }
314 
315  const UserObjectName heat_transfer_uo_name = genName(name(), "heat_flux_uo");
316  {
317  const std::string class_name = "ADHeatTransferFromHeatStructure3D1PhaseUserObject";
318  InputParameters params = _factory.getValidParams(class_name);
319  params.set<std::vector<SubdomainName>>("block") = _flow_channel_subdomains;
320  params.set<MeshAlignment1D3D *>("_mesh_alignment") = &_mesh_alignment;
321  params.set<std::vector<VariableName>>("P_hf") = {_P_hf_name};
322  params.set<MaterialPropertyName>("Hw") = _Hw_1phase_name;
323  params.set<MaterialPropertyName>("T") = FlowModelSinglePhase::TEMPERATURE;
324  params.set<ExecFlagEnum>("execute_on") = execute_on;
325  getTHMProblem().addUserObject(class_name, heat_transfer_uo_name, params);
326  }
327  {
328  const std::string class_name = "ADConvectionHeatTransfer3DBC";
329  InputParameters params = _factory.getValidParams(class_name);
330  params.set<std::vector<BoundaryName>>("boundary") = {_boundary};
331  params.set<NonlinearVariableName>("variable") = HeatConductionModel::TEMPERATURE;
332  params.set<UserObjectName>("ht_uo") = heat_transfer_uo_name;
333  getTHMProblem().addBoundaryCondition(class_name, genName(name(), "heat_flux_bc"), params);
334  }
335 }
virtual void initSecondary() override
Perform secondary initialization, which relies on init() being called for all components.
virtual void setupMesh() override
Performs mesh setup such as creating mesh or naming mesh sets.
std::string genName(const std::string &prefix, unsigned int id, const std::string &suffix="") const
Build a name from a prefix, number and possible suffix.
unsigned int _num_layers
Number of layers in the flow channel direction.
VariableName _T_wall_name
wall temperature name
static const std::string TEMPERATURE
THMProblem & getTHMProblem() const
Gets the THM problem.
Definition: Component.C:135
void addDependency(const std::string &dependency)
Adds a component name to the list of dependencies.
Definition: Component.C:129
std::vector< std::shared_ptr< ClosuresBase > > getClosuresObjects() const
Get the used closures object(s)
Heat structure component that loads the mesh from an ExodusII file.
const std::vector< dof_id_type > & getElementIDs() const
Gets the element IDs corresponding to this component.
Definition: Component.C:299
void initialize(const std::vector< dof_id_type > &primary_elem_ids, const std::vector< std::tuple< dof_id_type, unsigned short int >> &secondary_boundary_info)
Extracts mesh information and builds the mapping.
T & set(const std::string &name, bool quiet_mode=false)
FunctionName getInitialT() const
Gets the initial temperature function name.
virtual RealVectorValue getDirection() const
InputParameters getValidParams(const std::string &name) const
static const std::string HEAT_TRANSFER_COEFFICIENT_WALL
registerMooseObject("ThermalHydraulicsApp", HeatTransferFromHeatStructure3D1Phase)
virtual void addAuxKernel(const std::string &kernel_name, const std::string &name, InputParameters &parameters)
virtual void addKernel(const std::string &kernel_name, const std::string &name, InputParameters &parameters)
MaterialPropertyName _Hw_1phase_name
1-phase wall heat transfer coefficient name
virtual const libMesh::FEType & getFEType() override
Get the FE type for wall temperature variable.
bool isRestarting() const
virtual const std::string & name() const
HeatTransferFromHeatStructure3D1Phase(const InputParameters &parameters)
const std::vector< std::string > & _flow_channel_names
name of the connected flow channel
void addRequiredParam(const std::string &name, const std::string &doc_string)
void suppressParameter(const std::string &name)
void addFunctionIC(const VariableName &var_name, const std::string &func_name, const std::vector< SubdomainName > &block_names)
Definition: Simulation.C:532
virtual void addBoundaryCondition(const std::string &bc_name, const std::string &name, InputParameters &parameters)
ExecFlagEnum getDefaultExecFlagEnum()
void logError(Args &&... args) const
Logs an error.
Definition: Component.h:215
virtual void init() override
Initializes the component.
VariableName _P_hf_name
heated perimeter name
virtual void check() const
Check the component integrity.
Definition: Component.h:301
virtual void check() const override
Check the component integrity.
void addSimVariable(bool nl, const VariableName &name, libMesh::FEType fe_type, Real scaling_factor=1.0)
Queues a variable of type MooseVariableScalar to be added to the nonlinear or aux system...
Definition: Simulation.C:271
TypeVector< Real > unit() const
CONSTANT
Single-component, single-phase flow channel.
static const std::string TEMPERATURE_WALL
Definition: FlowModel.h:108
virtual EAxisAlignment getFlowChannelAxisAlignment(const std::string &flow_channel_name) const
static const std::string TEMPERATURE
void addHeatTransferName(const std::string &ht_name) const
Adds the name of a heat transfer component to the flow channel&#39;s list.
virtual void addMooseObjects() override
MooseEnum _layered_average_uo_direction
Direction for layered average user objects.
virtual void init()
Initializes the component.
Definition: Component.h:290
const ExecFlagType EXEC_LINEAR
virtual void initSecondary()
Perform secondary initialization, which relies on init() being called for all components.
Definition: Component.h:296
Base class for heat transfer connections from temperature for 1-phase flow.
MONOMIAL
static const libMesh::FEType & feType()
Get the FE type used for heat conduction.
void makeParamNotRequired(const std::string &name)
std::vector< std::shared_ptr< ClosuresBase > > _flow_channel_closures
Closures associated with each flow channel.
const ExecFlagType EXEC_NONLINEAR
static const std::string HEAT_FLUX_PERIMETER
Definition: FlowModel.h:105
static const std::string Z
Definition: NS.h:169
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
MooseApp & _app
MaterialPropertyName _q_wall_name
wall heat flux name
Factory & _factory
The Factory associated with the MooseApp.
Definition: Component.h:446
virtual std::vector< std::shared_ptr< UserObject > > addUserObject(const std::string &user_object_name, const std::string &name, InputParameters &parameters)
FunctionName _P_hf_fn_name
heated perimeter function name
static const std::string HEAT_FLUX_WALL
Definition: FlowModel.h:104
MeshAlignment1D3D _mesh_alignment
Mesh alignment object.
void makeParamRequired(const std::string &name)
std::string getHeatTransferNamesSuffix(const std::string &ht_name) const
Gets suffix to add to heat-transfer-related names in a heat transfer component.
void addClassDescription(const std::string &doc_string)
const BoundaryName & _boundary
Boundary names for which the boundary component applies.
static const std::string RHOEA
const std::vector< dof_id_type > & getCoupledSecondaryElemIDs(const dof_id_type &primary_elem_id) const
Gets the coupled secondary element IDs for a given primary element ID.
virtual const std::vector< SubdomainName > & getSubdomainNames() const
Gets the subdomain names for this component.
Definition: Component.C:307
std::vector< SubdomainName > _flow_channel_subdomains
Subdomains corresponding to the connected flow channel.
Connects a 1-phase flow channel and a 3D heat structure.
Builds mapping between a 1D subdomain and a 3D boundary.
virtual void augmentSparsity(const dof_id_type &elem_id1, const dof_id_type &elem_id2)
Hint how to augment sparsity pattern between two elements.
Definition: Simulation.C:71
const std::string & _hs_name
Heat structure name.
bool hasCoupledSecondaryElemIDs(const dof_id_type &primary_elem_id) const
Returns true if the given primary element ID has coupled secondary elements.
const ExecFlagType EXEC_INITIAL