LCOV - code coverage report
Current view: top level - src/components - HeatTransferFromHeatStructure3D1Phase.C (source / functions) Hit Total Coverage
Test: idaholab/moose thermal_hydraulics: #30301 (3b550b) with base 2ad78d Lines: 165 168 98.2 %
Date: 2025-07-30 13:02:48 Functions: 9 10 90.0 %
Legend: Lines: hit not hit

          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 : }

Generated by: LCOV version 1.14