LCOV - code coverage report
Current view: top level - src/components - VolumeJunction1Phase.C (source / functions) Hit Total Coverage
Test: idaholab/moose thermal_hydraulics: #32971 (54bef8) with base c6cf66 Lines: 212 215 98.6 %
Date: 2026-05-29 20:41:18 Functions: 11 11 100.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 "VolumeJunction1Phase.h"
      11             : #include "FlowModelSinglePhase.h"
      12             : #include "THMMesh.h"
      13             : 
      14             : registerMooseObject("ThermalHydraulicsApp", VolumeJunction1Phase);
      15             : 
      16             : const unsigned int VolumeJunction1Phase::N_EQ = 5;
      17             : 
      18             : InputParameters
      19        1174 : VolumeJunction1Phase::validParams()
      20             : {
      21        1174 :   InputParameters params = FlowJunction1Phase::validParams();
      22             : 
      23        2348 :   params.addRequiredParam<Real>("volume", "Volume of the junction [m^3]");
      24        2348 :   params.addRequiredParam<Point>("position", "Spatial position of the center of the junction [m]");
      25             : 
      26        2348 :   params.addParam<FunctionName>("initial_p", "Initial pressure [Pa]");
      27        2348 :   params.addParam<FunctionName>("initial_T", "Initial temperature [K]");
      28        2348 :   params.addParam<FunctionName>("initial_vel_x", "Initial velocity in x-direction [m/s]");
      29        2348 :   params.addParam<FunctionName>("initial_vel_y", "Initial velocity in y-direction [m/s]");
      30        2348 :   params.addParam<FunctionName>("initial_vel_z", "Initial velocity in z-direction [m/s]");
      31             : 
      32        2348 :   params.addParam<Real>("scaling_factor_rhoV", 1.0, "Scaling factor for rho*V [-]");
      33        2348 :   params.addParam<Real>("scaling_factor_rhouV", 1.0, "Scaling factor for rho*u*V [-]");
      34        2348 :   params.addParam<Real>("scaling_factor_rhovV", 1.0, "Scaling factor for rho*v*V [-]");
      35        2348 :   params.addParam<Real>("scaling_factor_rhowV", 1.0, "Scaling factor for rho*w*V [-]");
      36        2348 :   params.addParam<Real>("scaling_factor_rhoEV", 1.0, "Scaling factor for rho*E*V [-]");
      37             : 
      38        2348 :   params.addParam<Real>("K", 0., "Form loss factor [-]");
      39        2348 :   params.addParam<Real>("A_ref", "Reference area [m^2]");
      40             : 
      41        3522 :   params.addParam<bool>("apply_velocity_scaling",
      42        2348 :                         false,
      43             :                         "Set to true to apply the scaling to the normal velocity. See "
      44             :                         "documentation for more information.");
      45             : 
      46        2348 :   params.declareControllable("K");
      47        1174 :   params.addClassDescription("Junction between 1-phase flow channels that has a non-zero volume");
      48             : 
      49        1174 :   return params;
      50           0 : }
      51             : 
      52         587 : VolumeJunction1Phase::VolumeJunction1Phase(const InputParameters & params)
      53             :   : FlowJunction1Phase(params),
      54             : 
      55         587 :     _volume(getParam<Real>("volume")),
      56        1174 :     _position(getParam<Point>("position")),
      57             : 
      58        1174 :     _scaling_factor_rhoV(getParam<Real>("scaling_factor_rhoV")),
      59        1174 :     _scaling_factor_rhouV(getParam<Real>("scaling_factor_rhouV")),
      60        1174 :     _scaling_factor_rhovV(getParam<Real>("scaling_factor_rhovV")),
      61        1174 :     _scaling_factor_rhowV(getParam<Real>("scaling_factor_rhowV")),
      62        1174 :     _scaling_factor_rhoEV(getParam<Real>("scaling_factor_rhoEV")),
      63             : 
      64         587 :     _rhoV_var_name(junctionVariableName("rhoV")),
      65         587 :     _rhouV_var_name(junctionVariableName("rhouV")),
      66         587 :     _rhovV_var_name(junctionVariableName("rhovV")),
      67         587 :     _rhowV_var_name(junctionVariableName("rhowV")),
      68         587 :     _rhoEV_var_name(junctionVariableName("rhoEV")),
      69         587 :     _pressure_var_name(junctionVariableName("p")),
      70         587 :     _temperature_var_name(junctionVariableName("T")),
      71         587 :     _velocity_var_name(junctionVariableName("vel")),
      72             : 
      73        1174 :     _K(getParam<Real>("K")),
      74        2149 :     _A_ref(isParamValid("A_ref") ? getParam<Real>("A_ref") : _zero)
      75             : {
      76             :   // Note: 'A_ref' can be required by child classes
      77        1200 :   if (!params.isParamRequired("A_ref") && params.isParamSetByUser("A_ref") &&
      78         639 :       !params.isParamSetByUser("K"))
      79           2 :     logWarning("Parameter 'A_ref' is specified, but 'K' is not specified, so the junction will "
      80             :                "behave as if there were no form loss.");
      81         587 : }
      82             : 
      83             : void
      84         587 : VolumeJunction1Phase::setupMesh()
      85             : {
      86         587 :   FlowJunction1Phase::setupMesh();
      87             : 
      88             :   // Add a NodeElem to the mesh
      89         587 :   auto * node = addNode(_position);
      90         587 :   auto * elem = addNodeElement(node->id());
      91         587 :   _junction_subdomain_id = mesh().getNextSubdomainId();
      92         587 :   elem->subdomain_id() = _junction_subdomain_id;
      93         587 :   setSubdomainInfo(_junction_subdomain_id, name());
      94             : 
      95             :   // Add coupling between the flow channel end elements and the NodeElem
      96             :   const auto & elem_ids = getConnectedElementIDs();
      97        1885 :   for (unsigned int i = 0; i < elem_ids.size(); i++)
      98        1298 :     getTHMProblem().augmentSparsity(elem_ids[i], elem->id());
      99         587 : }
     100             : 
     101             : void
     102         567 : VolumeJunction1Phase::check() const
     103             : {
     104         567 :   FlowJunction1Phase::check();
     105             : 
     106             :   bool ics_set =
     107        1129 :       getTHMProblem().hasInitialConditionsFromFile() ||
     108        3859 :       (isParamValid("initial_p") && isParamValid("initial_T") && isParamValid("initial_vel_x") &&
     109        2751 :        isParamValid("initial_vel_y") && isParamValid("initial_vel_z"));
     110             : 
     111         567 :   if (!ics_set && !_app.isRestarting())
     112             :   {
     113             :     // create a list of the missing IC parameters
     114             :     const std::vector<std::string> ic_params{
     115          24 :         "initial_p", "initial_T", "initial_vel_x", "initial_vel_y", "initial_vel_z"};
     116           4 :     std::ostringstream oss;
     117          24 :     for (const auto & ic_param : ic_params)
     118          20 :       if (!isParamValid(ic_param))
     119          20 :         oss << " " << ic_param;
     120             : 
     121           4 :     logError("The following initial condition parameters are missing:", oss.str());
     122           4 :   }
     123             : 
     124             :   // https://github.com/idaholab/moose/issues/28670
     125         567 :   if (getTHMProblem().hasInitialConditionsFromFile() && libMesh::n_threads() > 1 &&
     126           0 :       _app.n_processors() > 1)
     127           0 :     mooseDocumentedError("moose",
     128             :                          28670,
     129             :                          "Using initial conditions from a file for VolumeJunction1Phase is "
     130             :                          "currently not tested for parallel threading.");
     131         575 : }
     132             : 
     133             : void
     134         564 : VolumeJunction1Phase::addVariables()
     135             : {
     136         564 :   addJunctionVariable(true, _rhoV_var_name, _scaling_factor_rhoV);
     137         564 :   addJunctionVariable(true, _rhouV_var_name, _scaling_factor_rhouV);
     138         564 :   addJunctionVariable(true, _rhovV_var_name, _scaling_factor_rhovV);
     139         564 :   addJunctionVariable(true, _rhowV_var_name, _scaling_factor_rhowV);
     140         564 :   addJunctionVariable(true, _rhoEV_var_name, _scaling_factor_rhoEV);
     141             : 
     142         564 :   addJunctionVariable(false, _pressure_var_name);
     143         564 :   addJunctionVariable(false, _temperature_var_name);
     144         564 :   addJunctionVariable(false, _velocity_var_name);
     145             : 
     146        3863 :   if (isParamValid("initial_p") && isParamValid("initial_T") && isParamValid("initial_vel_x") &&
     147        3299 :       isParamValid("initial_vel_y") && isParamValid("initial_vel_z"))
     148             :   {
     149         547 :     addVolumeJunctionIC(_rhoV_var_name, "rhoV");
     150         547 :     addVolumeJunctionIC(_rhouV_var_name, "rhouV");
     151         547 :     addVolumeJunctionIC(_rhovV_var_name, "rhovV");
     152         547 :     addVolumeJunctionIC(_rhowV_var_name, "rhowV");
     153         547 :     addVolumeJunctionIC(_rhoEV_var_name, "rhoEV");
     154             : 
     155         547 :     addVolumeJunctionIC(_pressure_var_name, "p");
     156         547 :     addVolumeJunctionIC(_temperature_var_name, "T");
     157        1094 :     addVolumeJunctionIC(_velocity_var_name, "vel");
     158             :   }
     159         564 : }
     160             : 
     161             : void
     162         298 : VolumeJunction1Phase::buildVolumeJunctionUserObject()
     163             : {
     164         298 :   ExecFlagEnum execute_on(MooseUtils::getDefaultExecFlagEnum());
     165        1490 :   execute_on = {EXEC_INITIAL, EXEC_LINEAR, EXEC_NONLINEAR};
     166             : 
     167             :   {
     168         298 :     const std::string class_name = "ADVolumeJunction1PhaseUserObject";
     169         298 :     InputParameters params = _factory.getValidParams(class_name);
     170         298 :     params.set<bool>("use_scalar_variables") = false;
     171         298 :     params.set<subdomain_id_type>("junction_subdomain_id") = _junction_subdomain_id;
     172         298 :     params.set<std::vector<BoundaryName>>("boundary") = _boundary_names;
     173         596 :     params.set<std::vector<Real>>("normals") = _normals;
     174         298 :     params.set<std::vector<processor_id_type>>("processor_ids") = getConnectedProcessorIDs();
     175         298 :     params.set<std::vector<UserObjectName>>("numerical_flux_names") = _numerical_flux_names;
     176         298 :     params.set<Real>("volume") = _volume;
     177         894 :     params.set<std::vector<VariableName>>("A") = {FlowModel::AREA};
     178         894 :     params.set<std::vector<VariableName>>("rhoA") = {FlowModelSinglePhase::RHOA};
     179         894 :     params.set<std::vector<VariableName>>("rhouA") = {FlowModelSinglePhase::RHOUA};
     180         894 :     params.set<std::vector<VariableName>>("rhoEA") = {FlowModelSinglePhase::RHOEA};
     181         894 :     params.set<std::vector<VariableName>>("rhoV") = {_rhoV_var_name};
     182         894 :     params.set<std::vector<VariableName>>("rhouV") = {_rhouV_var_name};
     183         894 :     params.set<std::vector<VariableName>>("rhovV") = {_rhovV_var_name};
     184         894 :     params.set<std::vector<VariableName>>("rhowV") = {_rhowV_var_name};
     185         894 :     params.set<std::vector<VariableName>>("rhoEV") = {_rhoEV_var_name};
     186         298 :     params.set<Real>("K") = _K;
     187         298 :     params.set<Real>("A_ref") = _A_ref;
     188         298 :     params.set<UserObjectName>("fp") = _fp_name;
     189         596 :     params.set<bool>("apply_velocity_scaling") = getParam<bool>("apply_velocity_scaling");
     190         298 :     params.set<ExecFlagEnum>("execute_on") = execute_on;
     191         298 :     getTHMProblem().addUserObject(class_name, _junction_uo_name, params);
     192         298 :     connectObject(params, _junction_uo_name, "K");
     193         298 :   }
     194         596 : }
     195             : 
     196             : void
     197         564 : VolumeJunction1Phase::addMooseObjects()
     198             : {
     199         564 :   buildVolumeJunctionUserObject();
     200             : 
     201             :   // Add BC to each of the connected flow channels
     202        1805 :   for (std::size_t i = 0; i < _boundary_names.size(); i++)
     203             :   {
     204             :     const std::vector<NonlinearVariableName> var_names = {
     205        4964 :         FlowModelSinglePhase::RHOA, FlowModelSinglePhase::RHOUA, FlowModelSinglePhase::RHOEA};
     206        4964 :     for (std::size_t j = 0; j < var_names.size(); j++)
     207             :     {
     208        3723 :       const std::string class_name = "ADVolumeJunction1PhaseBC";
     209        3723 :       InputParameters params = _factory.getValidParams(class_name);
     210       11169 :       params.set<std::vector<BoundaryName>>("boundary") = {_boundary_names[i]};
     211        3723 :       params.set<Real>("normal") = _normals[i];
     212        3723 :       params.set<NonlinearVariableName>("variable") = var_names[j];
     213        7446 :       params.set<UserObjectName>("volume_junction_uo") = _junction_uo_name;
     214        3723 :       params.set<unsigned int>("connection_index") = i;
     215       11169 :       params.set<std::vector<VariableName>>("A_elem") = {FlowModel::AREA};
     216       11169 :       params.set<std::vector<VariableName>>("A_linear") = {FlowModel::AREA_LINEAR};
     217       11169 :       params.set<std::vector<VariableName>>("rhoA") = {FlowModelSinglePhase::RHOA};
     218       11169 :       params.set<std::vector<VariableName>>("rhouA") = {FlowModelSinglePhase::RHOUA};
     219       11169 :       params.set<std::vector<VariableName>>("rhoEA") = {FlowModelSinglePhase::RHOEA};
     220        3723 :       params.set<bool>("implicit") = getTHMProblem().getImplicitTimeIntegrationFlag();
     221        7446 :       getTHMProblem().addBoundaryCondition(
     222        3723 :           class_name, genName(name(), i, var_names[j] + ":" + class_name), params);
     223        3723 :     }
     224        1241 :   }
     225             : 
     226             :   // Add kernels for the junction
     227         564 :   std::vector<NonlinearVariableName> var_names(N_EQ);
     228         564 :   var_names[RHOV_INDEX] = _rhoV_var_name;
     229         564 :   var_names[RHOUV_INDEX] = _rhouV_var_name;
     230         564 :   var_names[RHOVV_INDEX] = _rhovV_var_name;
     231         564 :   var_names[RHOWV_INDEX] = _rhowV_var_name;
     232         564 :   var_names[RHOEV_INDEX] = _rhoEV_var_name;
     233        3384 :   for (std::size_t i = 0; i < N_EQ; i++)
     234             :   {
     235             :     {
     236        2820 :       const std::string class_name = "ADTimeDerivative";
     237        2820 :       InputParameters params = _factory.getValidParams(class_name);
     238        2820 :       params.set<NonlinearVariableName>("variable") = var_names[i];
     239        2820 :       const std::string obj_name = genName(name(), var_names[i], "td");
     240        2820 :       params.set<std::vector<SubdomainName>>("block") = getSubdomainNames();
     241        2820 :       getTHMProblem().addKernel(class_name, obj_name, params);
     242        2820 :     }
     243             :     {
     244        2820 :       const std::string class_name = "ADVolumeJunctionAdvectionKernel";
     245        2820 :       InputParameters params = _factory.getValidParams(class_name);
     246        2820 :       params.set<NonlinearVariableName>("variable") = var_names[i];
     247        5640 :       params.set<UserObjectName>("volume_junction_uo") = _junction_uo_name;
     248        2820 :       params.set<unsigned int>("equation_index") = i;
     249        2820 :       const std::string obj_name = genName(name(), var_names[i], "vja_sk");
     250        2820 :       params.set<std::vector<SubdomainName>>("block") = getSubdomainNames();
     251        2820 :       getTHMProblem().addKernel(class_name, obj_name, params);
     252        2820 :     }
     253             :   }
     254             : 
     255             :   const std::vector<std::pair<std::string, VariableName>> quantities = {
     256         564 :       {"pressure", _pressure_var_name},
     257         564 :       {"temperature", _temperature_var_name},
     258        2256 :       {"speed", _velocity_var_name}};
     259        2256 :   for (const auto & quantity_and_name : quantities)
     260             :   {
     261        1692 :     const std::string class_name = "VolumeJunction1PhaseAux";
     262        1692 :     InputParameters params = _factory.getValidParams(class_name);
     263        3384 :     params.set<AuxVariableName>("variable") = quantity_and_name.second;
     264        1692 :     params.set<MooseEnum>("quantity") = quantity_and_name.first;
     265        1692 :     params.set<Real>("volume") = _volume;
     266        5076 :     params.set<std::vector<VariableName>>("rhoV") = {_rhoV_var_name};
     267        5076 :     params.set<std::vector<VariableName>>("rhouV") = {_rhouV_var_name};
     268        5076 :     params.set<std::vector<VariableName>>("rhovV") = {_rhovV_var_name};
     269        5076 :     params.set<std::vector<VariableName>>("rhowV") = {_rhowV_var_name};
     270        5076 :     params.set<std::vector<VariableName>>("rhoEV") = {_rhoEV_var_name};
     271        1692 :     params.set<UserObjectName>("fp") = _fp_name;
     272        3384 :     const std::string obj_name = genName(name(), quantity_and_name.first + "_aux");
     273        1692 :     params.set<std::vector<SubdomainName>>("block") = getSubdomainNames();
     274        1692 :     getTHMProblem().addAuxKernel(class_name, obj_name, params);
     275        1692 :   }
     276             : 
     277             :   // An error message results if there is any block without a material, so
     278             :   // until this restriction is removed, we must add a dummy material that
     279             :   // computes no material properties.
     280             :   {
     281         564 :     const std::string class_name = "GenericConstantMaterial";
     282         564 :     InputParameters params = _factory.getValidParams(class_name);
     283         564 :     params.set<std::vector<SubdomainName>>("block") = getSubdomainNames();
     284         564 :     params.set<std::vector<std::string>>("prop_names") = {};
     285         564 :     params.set<std::vector<Real>>("prop_values") = {};
     286        1128 :     getTHMProblem().addMaterial(class_name, genName(name(), "dummy_mat"), params);
     287         564 :   }
     288        1128 : }
     289             : 
     290             : std::string
     291        5233 : VolumeJunction1Phase::junctionVariableName(const std::string & var_base) const
     292             : {
     293        5233 :   return var_base;
     294             : }
     295             : 
     296             : void
     297        5019 : VolumeJunction1Phase::addJunctionVariable(bool is_nonlinear,
     298             :                                           const VariableName & var,
     299             :                                           Real scaling_factor)
     300             : {
     301        5019 :   auto & problem = getTHMProblem();
     302             : 
     303             :   const libMesh::FEType fe_type(CONSTANT, MONOMIAL);
     304        5019 :   const auto & subdomains = getSubdomainNames();
     305             : 
     306        5019 :   if (is_nonlinear)
     307        2820 :     problem.addSimVariable(is_nonlinear, var, fe_type, subdomains, scaling_factor);
     308             :   else
     309        2199 :     problem.addSimVariable(is_nonlinear, var, fe_type, subdomains);
     310        5019 : }
     311             : 
     312             : void
     313         475 : VolumeJunction1Phase::addJunctionIC(const VariableName & var, Real value)
     314             : {
     315         475 :   getTHMProblem().addConstantIC(var, value, getSubdomainNames());
     316         475 : }
     317             : 
     318             : void
     319        4376 : VolumeJunction1Phase::addVolumeJunctionIC(const VariableName & var, const std::string & quantity)
     320             : {
     321        4376 :   const std::string class_name = "VolumeJunction1PhaseIC";
     322        4376 :   InputParameters params = _factory.getValidParams(class_name);
     323        4376 :   params.set<std::vector<SubdomainName>>("block") = getSubdomainNames();
     324        4376 :   params.set<VariableName>("variable") = var;
     325        4376 :   params.set<MooseEnum>("quantity") = quantity;
     326        4376 :   params.applySpecificParameters(parameters(),
     327             :                                  {"initial_p",
     328             :                                   "initial_T",
     329             :                                   "initial_vel_x",
     330             :                                   "initial_vel_y",
     331             :                                   "initial_vel_z",
     332             :                                   "volume",
     333             :                                   "position"});
     334        4376 :   params.set<UserObjectName>("fluid_properties") = _fp_name;
     335        8752 :   getTHMProblem().addSimInitialCondition(class_name, genName(name(), var, "ic"), params);
     336        8752 : }

Generated by: LCOV version 1.14