LCOV - code coverage report
Current view: top level - src/userobjects - ADShaftConnectedCompressor1PhaseUserObject.C (source / functions) Hit Total Coverage
Test: idaholab/moose thermal_hydraulics: #31706 (f8ed4a) with base bb0a08 Lines: 199 208 95.7 %
Date: 2025-11-03 17:29:56 Functions: 16 16 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 "ADShaftConnectedCompressor1PhaseUserObject.h"
      11             : #include "SinglePhaseFluidProperties.h"
      12             : #include "VolumeJunction1Phase.h"
      13             : #include "MooseVariableScalar.h"
      14             : #include "THMIndicesVACE.h"
      15             : #include "Function.h"
      16             : #include "Numerics.h"
      17             : #include "metaphysicl/parallel_numberarray.h"
      18             : #include "metaphysicl/parallel_dualnumber.h"
      19             : #include "metaphysicl/parallel_semidynamicsparsenumberarray.h"
      20             : #include "libmesh/parallel_algebra.h"
      21             : 
      22             : registerMooseObject("ThermalHydraulicsApp", ADShaftConnectedCompressor1PhaseUserObject);
      23             : 
      24             : InputParameters
      25         233 : ADShaftConnectedCompressor1PhaseUserObject::validParams()
      26             : {
      27         233 :   InputParameters params = ADVolumeJunction1PhaseUserObject::validParams();
      28         233 :   params += ADShaftConnectableUserObjectInterface::validParams();
      29             : 
      30         466 :   params.addParam<BoundaryName>("inlet", "Compressor inlet");
      31         466 :   params.addParam<BoundaryName>("outlet", "Compressor outlet");
      32         466 :   params.addRequiredParam<Point>("di_out", "Direction of connected outlet");
      33         466 :   params.addRequiredParam<bool>("treat_as_turbine", "Treat the compressor as a turbine?");
      34         466 :   params.addRequiredParam<Real>("omega_rated", "Rated compressor speed [rad/s]");
      35         466 :   params.addRequiredParam<Real>("mdot_rated", "Rated compressor mass flow rate [kg/s]");
      36         466 :   params.addRequiredParam<Real>("rho0_rated",
      37             :                                 "Rated compressor inlet stagnation fluid density [kg/m^3]");
      38         466 :   params.addRequiredParam<Real>("c0_rated", "Rated compressor inlet stagnation sound speed [m/s]");
      39         466 :   params.addRequiredParam<Real>("speed_cr_fr", "Compressor speed threshold for friction [-]");
      40         466 :   params.addRequiredParam<Real>("tau_fr_const", "Compressor friction constant [N-m]");
      41         466 :   params.addRequiredParam<std::vector<Real>>("tau_fr_coeff", "Friction coefficients [N-m]");
      42         466 :   params.addRequiredParam<Real>("speed_cr_I", "Compressor speed threshold for inertia [-]");
      43         466 :   params.addRequiredParam<Real>("inertia_const", "Compressor inertia constant [kg-m^2]");
      44         466 :   params.addRequiredParam<std::vector<Real>>("inertia_coeff",
      45             :                                              "Compressor inertia coefficients [kg-m^2]");
      46         466 :   params.addRequiredParam<std::vector<Real>>(
      47             :       "speeds",
      48             :       "Relative corrected speeds. Order of speeds needs correspond to the "
      49             :       "orders of `Rp_functions` and `eff_functions` [-]");
      50         466 :   params.addRequiredParam<std::vector<FunctionName>>(
      51             :       "Rp_functions",
      52             :       "Functions of pressure ratio versus relative corrected flow. Each function is for a "
      53             :       "different, constant relative corrected speed. The order of function names should correspond "
      54             :       "to the order of speeds in the `speeds` parameter [-]");
      55         466 :   params.addRequiredParam<std::vector<FunctionName>>(
      56             :       "eff_functions",
      57             :       "Functions of adiabatic efficiency versus relative corrected flow. Each function is for a "
      58             :       "different, constant relative corrected speed. The order of function names should correspond "
      59             :       "to the order of speeds in the `speeds` parameter [-]");
      60         466 :   params.addRequiredParam<Real>("min_pressure_ratio", "Minimum pressure ratio");
      61         466 :   params.addRequiredParam<Real>("max_pressure_ratio", "Maximum pressure ratio");
      62         466 :   params.addRequiredParam<std::string>("compressor_name",
      63             :                                        "Name of the instance of this compressor component");
      64         466 :   params.addRequiredCoupledVar("omega", "Shaft rotational speed [rad/s]");
      65             : 
      66         233 :   params.addClassDescription("Computes and caches flux and residual vectors for a 1-phase "
      67             :                              "compressor. Also computes compressor torque "
      68             :                              "and delta_p which is passed to the connected shaft");
      69             : 
      70         233 :   return params;
      71           0 : }
      72             : 
      73         125 : ADShaftConnectedCompressor1PhaseUserObject::ADShaftConnectedCompressor1PhaseUserObject(
      74         125 :     const InputParameters & params)
      75             :   : ADVolumeJunction1PhaseUserObject(params),
      76             :     ADShaftConnectableUserObjectInterface(this),
      77             : 
      78         125 :     _di_out(getParam<Point>("di_out")),
      79         250 :     _treat_as_turbine(getParam<bool>("treat_as_turbine")),
      80         250 :     _omega_rated(getParam<Real>("omega_rated")),
      81         250 :     _mdot_rated(getParam<Real>("mdot_rated")),
      82         250 :     _rho0_rated(getParam<Real>("rho0_rated")),
      83         250 :     _c0_rated(getParam<Real>("c0_rated")),
      84         250 :     _speed_cr_fr(getParam<Real>("speed_cr_fr")),
      85         250 :     _tau_fr_const(getParam<Real>("tau_fr_const")),
      86         250 :     _tau_fr_coeff(getParam<std::vector<Real>>("tau_fr_coeff")),
      87         250 :     _speed_cr_I(getParam<Real>("speed_cr_I")),
      88         250 :     _inertia_const(getParam<Real>("inertia_const")),
      89         250 :     _inertia_coeff(getParam<std::vector<Real>>("inertia_coeff")),
      90         250 :     _speeds(getParam<std::vector<Real>>("speeds")),
      91         250 :     _Rp_function_names(getParam<std::vector<FunctionName>>("Rp_functions")),
      92         250 :     _eff_function_names(getParam<std::vector<FunctionName>>("eff_functions")),
      93         125 :     _n_speeds(_speeds.size()),
      94         125 :     _Rp_functions(_n_speeds),
      95         125 :     _eff_functions(_n_speeds),
      96         250 :     _Rp_min(getParam<Real>("min_pressure_ratio")),
      97         250 :     _Rp_max(getParam<Real>("max_pressure_ratio")),
      98         250 :     _compressor_name(getParam<std::string>("compressor_name")),
      99         250 :     _omega(adCoupledScalarValue("omega"))
     100             : {
     101         125 :   if (_n_speeds != _Rp_function_names.size() || _n_speeds != _eff_function_names.size())
     102           0 :     mooseError("The number of entries of speeds needs to equal the number of entries of "
     103             :                "Rp_functions and eff_functions");
     104             : 
     105             :   // Store functions and check to make sure there is no self-reference.
     106        1092 :   for (unsigned int i = 0; i < _n_speeds; i++)
     107             :   {
     108         967 :     if (_Rp_function_names[i] == name() || _eff_function_names[i] == name())
     109           0 :       mooseError(name(), ": This function cannot use its own name in the 'functions' parameter.");
     110             : 
     111         967 :     _Rp_functions[i] = &getFunctionByName(_Rp_function_names[i]);
     112         967 :     _eff_functions[i] = &getFunctionByName(_eff_function_names[i]);
     113             :   }
     114         125 : }
     115             : 
     116             : void
     117         109 : ADShaftConnectedCompressor1PhaseUserObject::initialSetup()
     118             : {
     119         109 :   ADVolumeJunction1PhaseUserObject::initialSetup();
     120             : 
     121         109 :   ADShaftConnectableUserObjectInterface::setupConnections(
     122         109 :       ADVolumeJunctionBaseUserObject::_n_connections, ADVolumeJunctionBaseUserObject::_n_flux_eq);
     123         109 : }
     124             : 
     125             : void
     126       12847 : ADShaftConnectedCompressor1PhaseUserObject::initialize()
     127             : {
     128       12847 :   ADVolumeJunction1PhaseUserObject::initialize();
     129       12847 :   ADShaftConnectableUserObjectInterface::initialize();
     130             : 
     131       12847 :   _isentropic_torque = 0;
     132       12847 :   _dissipation_torque = 0;
     133       12847 :   _friction_torque = 0;
     134       12847 :   _delta_p = 0;
     135       12847 :   _Rp = 0;
     136       12847 :   _eff = 0;
     137       12847 :   _flow_rel_corr = 0;
     138       12847 :   _speed_rel_corr = 0;
     139       12847 : }
     140             : 
     141             : void
     142       21358 : ADShaftConnectedCompressor1PhaseUserObject::execute()
     143             : {
     144       21358 :   ADVolumeJunctionBaseUserObject::storeConnectionData();
     145       21358 :   ADShaftConnectableUserObjectInterface::setConnectionData(
     146       21358 :       ADVolumeJunctionBaseUserObject::_flow_channel_dofs);
     147             : 
     148       21358 :   const unsigned int c = getBoundaryIDIndex();
     149             : 
     150       21358 :   computeFluxesAndResiduals(c);
     151       21358 : }
     152             : 
     153             : void
     154       21358 : ADShaftConnectedCompressor1PhaseUserObject::computeFluxesAndResiduals(const unsigned int & c)
     155             : {
     156       21358 :   ADVolumeJunction1PhaseUserObject::computeFluxesAndResiduals(c);
     157             : 
     158             :   using std::isinf, std::min, std::max, std::abs, std::isnan;
     159             : 
     160             :   // inlet c=0 established in component
     161       21358 :   if (c == 0)
     162             :   {
     163       10679 :     const ADReal rhoA_in = _rhoA[0];
     164       10679 :     const ADReal rhouA_in = _rhouA[0];
     165       10679 :     const ADReal rhoEA_in = _rhoEA[0];
     166       10679 :     const ADReal e_in = THM::e_from_arhoA_arhouA_arhoEA(rhoA_in, rhouA_in, rhoEA_in);
     167       10679 :     const ADReal v_in = _A[0] / rhoA_in;
     168       10679 :     const ADReal p_in = _fp.p_from_v_e(v_in, e_in);
     169             :     const ADReal vel_in = rhouA_in / rhoA_in;
     170             : 
     171             :     // static entropy is equal to stagnation entropy by definition of the stagnation state
     172       10679 :     const ADReal s_in = _fp.s_from_v_e(v_in, e_in);
     173       10679 :     const ADReal s_out = s_in;
     174             : 
     175             :     // isentropic: dH/m = Vdp/m
     176             :     // h0, T0, and c0 are constant for adiabatic flows
     177       10679 :     const ADReal h0_in = e_in + p_in * v_in + 0.5 * vel_in * vel_in;
     178       10679 :     const ADReal p0_in = _fp.p_from_h_s(h0_in, s_in);
     179       10679 :     const ADReal rho0_in = _fp.rho_from_p_s(p0_in, s_in);
     180       10679 :     const ADReal v0_in = 1.0 / rho0_in;
     181       10679 :     const ADReal e0_in = _fp.e_from_p_rho(p0_in, rho0_in);
     182       10679 :     const ADReal c0_in = _fp.c_from_v_e(v0_in, e0_in);
     183       10679 :     const ADReal flow_A = rhouA_in * _rho0_rated * _c0_rated;
     184             : 
     185       21358 :     const ADReal flow_B = _mdot_rated * rho0_in * c0_in;
     186       10679 :     _flow_rel_corr = flow_A / flow_B;
     187       32037 :     _speed_rel_corr = (_omega[0] / _omega_rated) * (_c0_rated / c0_in);
     188             : 
     189             :     // If _speed_rel_corr == _speeds[0], then the lower index x1 is determined to be -1
     190       10679 :     if (_speed_rel_corr == _speeds[0])
     191             :     {
     192          68 :       _Rp = _Rp_functions[0]->value(_flow_rel_corr, ADPoint());
     193          68 :       _eff = _eff_functions[0]->value(_flow_rel_corr, ADPoint());
     194             :     }
     195       10611 :     else if (isnan(_speed_rel_corr)) // NaN; unguarded, gives segmentation fault
     196             :     {
     197           0 :       _Rp = std::nan("");
     198           0 :       _eff = std::nan("");
     199             :     }
     200             :     else // linear interpolation/extrapolation
     201             :     {
     202             :       unsigned int x1, x2;
     203       10611 :       if (_speed_rel_corr < _speeds[0]) // extrapolation past minimum
     204             :       {
     205             :         x1 = 0;
     206             :         x2 = 1;
     207             :       }
     208        5819 :       else if (_speed_rel_corr > _speeds.back()) // extrapolation past maximum
     209             :       {
     210           0 :         x1 = _n_speeds - 1;
     211           0 :         x2 = x1 - 1;
     212             :       }
     213             :       else // interpolation
     214             :       {
     215        5819 :         auto x1_iter = std::lower_bound(_speeds.begin(), _speeds.end(), _speed_rel_corr);
     216        5819 :         auto x2_iter = std::upper_bound(_speeds.begin(), _speeds.end(), _speed_rel_corr);
     217             : 
     218        5819 :         x1 = (x1_iter - _speeds.begin()) - 1; // _speeds index for entry <= _speed_rel_corr
     219        5819 :         x2 = (x2_iter - _speeds.begin());     // _speeds index for entry > _speed_rel_corr
     220             :       }
     221             : 
     222       10611 :       const Real x1_spd = _speeds[x1];
     223       10611 :       const Real x2_spd = _speeds[x2];
     224             : 
     225       10611 :       const ADReal y1_Rp = _Rp_functions[x1]->value(_flow_rel_corr, ADPoint());
     226       10611 :       const ADReal y2_Rp = _Rp_functions[x2]->value(_flow_rel_corr, ADPoint());
     227       21222 :       const ADReal Rp_m = (y2_Rp - y1_Rp) / (x2_spd - x1_spd);
     228       10611 :       _Rp = y1_Rp + (_speed_rel_corr - x1_spd) * Rp_m;
     229             : 
     230       10611 :       const ADReal y1_eff = _eff_functions[x1]->value(_flow_rel_corr, ADPoint());
     231       10611 :       const ADReal y2_eff = _eff_functions[x2]->value(_flow_rel_corr, ADPoint());
     232       21222 :       const ADReal eff_m = (y2_eff - y1_eff) / (x2_spd - x1_spd);
     233       10611 :       _eff = y1_eff + (_speed_rel_corr - x1_spd) * eff_m;
     234             :     }
     235             : 
     236             :     // Apply bounds
     237       10679 :     _Rp = max(_Rp_min, min(_Rp_max, _Rp));
     238             : 
     239             :     // Invert if treating as turbine
     240             :     ADReal Rp_comp, eff_comp;
     241       10679 :     if (_treat_as_turbine)
     242             :     {
     243        9584 :       Rp_comp = 1.0 / _Rp;
     244        9584 :       eff_comp = 1.0 / _eff;
     245             :     }
     246             :     else
     247             :     {
     248        5887 :       Rp_comp = _Rp;
     249        5887 :       eff_comp = _eff;
     250             :     }
     251             : 
     252             :     const ADReal p0_out = p0_in * Rp_comp;
     253       10679 :     const ADReal rho0_out_isen = _fp.rho_from_p_s(p0_out, s_out);
     254             : 
     255       10679 :     const ADReal e0_out_isen = _fp.e_from_p_rho(p0_out, rho0_out_isen);
     256             : 
     257       10679 :     _delta_p = p0_in * (Rp_comp - 1.0);
     258             : 
     259       10679 :     if (MooseUtils::absoluteFuzzyEqual(_omega[0], 0.0))
     260             :     {
     261         116 :       _isentropic_torque = 0.0;
     262         116 :       _dissipation_torque = 0.0;
     263             :     }
     264             :     else
     265             :     {
     266       10563 :       const ADReal h0_out_isen = THM::h_from_e_p_rho(e0_out_isen, p0_out, rho0_out_isen);
     267       31689 :       _isentropic_torque = -(rhouA_in / _omega[0]) * (h0_out_isen - h0_in); // tau_isen
     268             : 
     269       10563 :       const ADReal g_x = h0_out_isen - h0_in + h0_in * eff_comp;
     270             :       const ADReal h0_out = g_x / eff_comp;
     271             : 
     272       31689 :       _dissipation_torque = -(rhouA_in / _omega[0]) * (h0_out - h0_out_isen);
     273             :     }
     274             : 
     275       10679 :     const ADReal alpha = _omega[0] / _omega_rated;
     276             : 
     277       10679 :     if (alpha < _speed_cr_I)
     278             :     {
     279        1095 :       _moment_of_inertia += _inertia_const;
     280             :     }
     281             :     else
     282             :     {
     283       19168 :       _moment_of_inertia += _inertia_coeff[0] + _inertia_coeff[1] * abs(alpha) +
     284        9584 :                             _inertia_coeff[2] * alpha * alpha +
     285       19168 :                             _inertia_coeff[3] * abs(alpha * alpha * alpha);
     286             :     }
     287             : 
     288             :     // friction torque
     289             :     Real sign;
     290       10679 :     if (_omega[0] >= 0)
     291       10679 :       sign = -1;
     292             :     else
     293           0 :       sign = 1;
     294       10679 :     if (alpha < _speed_cr_fr)
     295             :     {
     296           0 :       _friction_torque = sign * _tau_fr_const;
     297             :     }
     298             :     else
     299             :     {
     300             :       _friction_torque =
     301       21358 :           sign * (_tau_fr_coeff[0] + _tau_fr_coeff[1] * abs(alpha) +
     302       32037 :                   _tau_fr_coeff[2] * alpha * alpha + _tau_fr_coeff[3] * abs(alpha * alpha * alpha));
     303             :     }
     304             : 
     305       21358 :     _torque += _isentropic_torque + _dissipation_torque + _friction_torque;
     306             : 
     307             :     // compute momentum and energy source terms
     308             :     // a negative torque value results in a positive S_energy
     309       21358 :     const ADReal S_energy = -(_isentropic_torque + _dissipation_torque) * _omega[0];
     310             : 
     311       21358 :     const ADRealVectorValue S_momentum = _delta_p * _A_ref * _di_out;
     312             : 
     313       10679 :     _residual[VolumeJunction1Phase::RHOEV_INDEX] -= S_energy;
     314             : 
     315       10679 :     _residual[VolumeJunction1Phase::RHOUV_INDEX] -= S_momentum(0);
     316       10679 :     _residual[VolumeJunction1Phase::RHOVV_INDEX] -= S_momentum(1);
     317       10679 :     _residual[VolumeJunction1Phase::RHOWV_INDEX] -= S_momentum(2);
     318             :   }
     319       21358 : }
     320             : 
     321             : ADReal
     322        7082 : ADShaftConnectedCompressor1PhaseUserObject::getIsentropicTorque() const
     323             : {
     324        7082 :   return _isentropic_torque;
     325             : }
     326             : 
     327             : ADReal
     328        7082 : ADShaftConnectedCompressor1PhaseUserObject::getDissipationTorque() const
     329             : {
     330        7082 :   return _dissipation_torque;
     331             : }
     332             : 
     333             : ADReal
     334        7082 : ADShaftConnectedCompressor1PhaseUserObject::getFrictionTorque() const
     335             : {
     336        7082 :   return _friction_torque;
     337             : }
     338             : 
     339             : ADReal
     340        7082 : ADShaftConnectedCompressor1PhaseUserObject::getCompressorDeltaP() const
     341             : {
     342        7082 :   return _delta_p;
     343             : }
     344             : 
     345             : ADReal
     346        1214 : ADShaftConnectedCompressor1PhaseUserObject::getPressureRatio() const
     347             : {
     348        1214 :   return _Rp;
     349             : }
     350             : 
     351             : ADReal
     352        1214 : ADShaftConnectedCompressor1PhaseUserObject::getEfficiency() const
     353             : {
     354        1214 :   return _eff;
     355             : }
     356             : ADReal
     357        1214 : ADShaftConnectedCompressor1PhaseUserObject::getRelativeCorrectedMassFlowRate() const
     358             : {
     359        1214 :   return _flow_rel_corr;
     360             : }
     361             : ADReal
     362        1214 : ADShaftConnectedCompressor1PhaseUserObject::getRelativeCorrectedSpeed() const
     363             : {
     364        1214 :   return _speed_rel_corr;
     365             : }
     366             : 
     367             : void
     368       11219 : ADShaftConnectedCompressor1PhaseUserObject::finalize()
     369             : {
     370       11219 :   ADVolumeJunction1PhaseUserObject::finalize();
     371       11219 :   ADShaftConnectableUserObjectInterface::finalize();
     372             : 
     373       11219 :   ADShaftConnectableUserObjectInterface::setupJunctionData(
     374       11219 :       ADVolumeJunctionBaseUserObject::_scalar_dofs);
     375       22438 :   ADShaftConnectableUserObjectInterface::setOmegaDofs(getScalarVar("omega", 0));
     376             : 
     377       11219 :   comm().sum(_isentropic_torque);
     378       11219 :   comm().sum(_dissipation_torque);
     379       11219 :   comm().sum(_friction_torque);
     380       11219 :   comm().sum(_delta_p);
     381       11219 :   comm().sum(_Rp);
     382       11219 :   comm().sum(_eff);
     383       11219 :   comm().sum(_flow_rel_corr);
     384       11219 :   comm().sum(_speed_rel_corr);
     385       11219 : }
     386             : 
     387             : void
     388        1628 : ADShaftConnectedCompressor1PhaseUserObject::threadJoin(const UserObject & uo)
     389             : {
     390        1628 :   ADVolumeJunction1PhaseUserObject::threadJoin(uo);
     391        1628 :   ADShaftConnectableUserObjectInterface::threadJoin(uo);
     392             : 
     393             :   const auto & scpuo = static_cast<const ADShaftConnectedCompressor1PhaseUserObject &>(uo);
     394        1628 :   _isentropic_torque += scpuo._isentropic_torque;
     395        1628 :   _dissipation_torque += scpuo._dissipation_torque;
     396        1628 :   _friction_torque += scpuo._friction_torque;
     397        1628 :   _delta_p += scpuo._delta_p;
     398        1628 :   _Rp += scpuo._Rp;
     399        1628 :   _eff += scpuo._eff;
     400        1628 :   _flow_rel_corr += scpuo._flow_rel_corr;
     401        1628 :   _speed_rel_corr += scpuo._speed_rel_corr;
     402        1628 : }

Generated by: LCOV version 1.14