https://mooseframework.inl.gov
SpecificImpulse1Phase.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 
10 #include "SpecificImpulse1Phase.h"
12 #include "Numerics.h"
13 #include "THMIndicesVACE.h"
14 #include "BoundaryFluxBase.h"
15 
16 registerMooseObject("ThermalHydraulicsApp", SpecificImpulse1Phase);
17 
20 {
22  params.addRequiredParam<Real>("p_exit", "Outlet pressure at nozzle exit");
23  params.addRequiredParam<UserObjectName>("fp", "Single-phase fluid properties");
24  params.addParam<Real>(
25  "bisection_tolerance", 1e-4, "Tolerance for bisection to find h(entropy_in, p_out)");
26  params.addParam<unsigned int>(
27  "bisection_max_it",
28  100,
29  "Maximum number of iterations for bisection to find h(entropy_in, p_out)");
30  params.addParam<bool>("cumulative",
31  true,
32  "If specific impulse is accumulated over timesteps. If false, then "
33  "instantaneous value is computed");
34  params.addCoupledVar("variables", "Single-phase flow variables");
35  params.set<std::vector<VariableName>>("variables") = {"rhoA", "rhouA", "rhoEA", "A"};
36  params.addClassDescription("Estimates specific impulse from fluid state at a boundary");
37  return params;
38 }
39 
41  : SidePostprocessor(parameters),
42  _n_components(THMVACE1D::N_FLUX_INPUTS),
43  _boundary_name(getParam<std::vector<BoundaryName>>("boundary")[0]),
44  _boundary_uo_name(_boundary_name + ":boundary_uo"),
45  _boundary_uo(getUserObjectByName<BoundaryFluxBase>(_boundary_uo_name)),
46  _p_exit(getParam<Real>("p_exit")),
47  _H(getMaterialPropertyByName<Real>("H")),
48  _v(getMaterialPropertyByName<Real>("v")),
49  _e(getMaterialPropertyByName<Real>("e")),
50  _T(getMaterialPropertyByName<Real>("T")),
51  _fp(getUserObject<SinglePhaseFluidProperties>("fp")),
52  _tol(getParam<Real>("bisection_tolerance")),
53  _max_nit(getParam<unsigned int>("bisection_max_it")),
54  _cumulative(getParam<bool>("cumulative")),
55  _accumulated_mass_flow_rate(declareRestartableData<Real>("accumulated_mass_flow_rate", 0)),
56  _accumulated_thrust(declareRestartableData<Real>("accumulated_thrust", 0)),
57  _value(0.0)
58 {
60  paramError("cumulative", "Must be false unless problem is transient");
61 
62  for (unsigned int i = 0; i < _n_components; i++)
63  _U.push_back(&coupledValue("variables", i));
64 }
65 
66 void
68 {
69  const auto & pps = static_cast<const SpecificImpulse1Phase &>(y);
70  _thrust += pps._thrust;
71  _mass_flow_rate += pps._mass_flow_rate;
72 }
73 
74 void
76 {
77  _mass_flow_rate = 0;
78  _thrust = 0;
79 }
80 
81 Real
83 {
84  return _value;
85 }
86 
87 void
89 {
92 
93  if (_cumulative)
94  {
98  }
99  else
101 }
102 
103 void
105 {
106  for (unsigned int qp = 0; qp < _qrule->n_points(); qp++)
107  {
108  std::vector<Real> U(_n_components);
109  for (unsigned int i = 0; i < _n_components; i++)
110  U[i] = (*_U[i])[qp];
111 
112  const auto & flux = _boundary_uo.getFlux(_current_side, _current_elem->id(), U, _normals[qp]);
113 
114  _mass_flow_rate += std::abs(flux[0]);
115 
116  // get entropy at inlet (= entropy at outlet because process is isentropic)
117  Real entropy_in = _fp.s_from_v_e(_v[qp], _e[qp]);
118 
119  // compute outlet enthalpy from entropy at inlet (isentropic flow)
120  // and pressure at outlet, need to do bisection because h_from_s_p does not
121  // exist, it is better to work with temperature because s(p, T) is available
122 
123  // upper bound of temperature is the inlet temperature
124  Real T_up = _T[qp];
125 
126  // compute entropy associated with T_up
127  Real entropy_up = _fp.s_from_p_T(_p_exit, T_up);
128 
129  // lower bound for temperature is 0.1 K
130  Real T_low = 0.1;
131 
132  // compute entropy associated with T_low
133  Real entropy_low = _fp.s_from_p_T(_p_exit, T_low);
134 
135  // compute the midpoint temperature
136  Real T_mid = 0.5 * (T_up + T_low);
137 
138  // the current guess for entropy
139  Real entropy_mid = _fp.s_from_p_T(_p_exit, T_mid);
140 
141  // main bisection loop
142  unsigned int nit = 0;
143  while (std::abs(1 - entropy_mid / entropy_in) > _tol)
144  {
145  // check if we are over/underestimating to select either up/down
146  if ((entropy_mid - entropy_in > 0) == (entropy_up - entropy_low > 0))
147  {
148  T_up = T_mid;
149  entropy_up = entropy_mid;
150  }
151  else
152  {
153  T_low = T_mid;
154  entropy_low = entropy_mid;
155  }
156 
157  // update guess for T_mid
158  T_mid = 0.5 * (T_up + T_low);
159 
160  // update the guess for entropy
161  entropy_mid = _fp.s_from_p_T(_p_exit, T_mid);
162 
163  ++nit;
164 
165  if (nit == _max_nit)
166  {
167  mooseDoOnce(mooseWarning("Bisection in SpecificImpulse1Phase did not converge"));
168  break;
169  }
170  }
171 
172  // the enthalpy evaluated at _p_exit and T_mid
173  Real h_exit = _fp.h_from_p_T(_p_exit, T_mid);
174 
175  // compute outlet speed
176  Real vel_exit = std::sqrt(2.0 * (_H[qp] - h_exit));
177  _thrust += std::abs(vel_exit * flux[0]);
178  }
179 }
registerMooseObject("ThermalHydraulicsApp", SpecificImpulse1Phase)
const Real _p_exit
the outlet pressure, user supplied value
virtual const std::vector< Real > & getFlux(unsigned int iside, dof_id_type ielem, const std::vector< Real > &uvec1, const RealVectorValue &dwave) const
Get the boundary flux vector.
virtual void initialize() override
static InputParameters validParams()
SpecificImpulse1Phase(const InputParameters &parameters)
const unsigned int & _current_side
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
const MaterialProperty< Real > & _e
internal energy
T & set(const std::string &name, bool quiet_mode=false)
const unsigned int _max_nit
maximum number of iterations for bisection
const unsigned int _n_components
Number of components in the solution vector used to compute the flux.
Estimates specific impulse from fluid state at the boundary.
virtual Real getValue() const override
const std::vector< double > y
const MaterialProperty< Real > & _T
fluid temperature
static const unsigned int N_FLUX_INPUTS
Number of numerical flux function inputs for 3D.
void mooseWarning(Args &&... args) const
void addRequiredParam(const std::string &name, const std::string &doc_string)
Real & _accumulated_mass_flow_rate
accumulated mass flow rate over time
A base class for computing/caching fluxes at boundaries.
Real _value
The value of this post-processor.
const MaterialProperty< Real > & _v
specific volume
virtual void threadJoin(const UserObject &y) override
virtual const VariableValue & coupledValue(const std::string &var_name, unsigned int comp=0) const
void gatherSum(T &value)
const Real _tol
bisection tolerance
Common class for single phase fluid properties.
void paramError(const std::string &param, Args... args) const
const MaterialProperty< Real > & _H
the total enthalpy including mechanical energy
void addCoupledVar(const std::string &name, const std::string &doc_string)
Real _mass_flow_rate
total mass flow rate
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
std::vector< const VariableValue * > _U
Variables to pass to boundary flux user object, in the correct order.
FEProblemBase & _fe_problem
virtual void finalize() override
static InputParameters validParams()
const QBase *const & _qrule
virtual void execute() override
const MooseArray< Point > & _normals
const BoundaryFluxBase & _boundary_uo
Boundary user object.
static const Real gravity_const
Definition: Numerics.h:26
void addClassDescription(const std::string &doc_string)
const SinglePhaseFluidProperties & _fp
fluid property user object
Real & _accumulated_thrust
accumulated thrust over time
const Elem *const & _current_elem
virtual bool isTransient() const override
const bool _cumulative
if the specific impulse is accumulated over timesteps
void ErrorVector unsigned int