https://mooseframework.inl.gov
Loading...
Searching...
No Matches
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
12#include "Numerics.h"
13#include "THMIndicesVACE.h"
14#include "BoundaryFluxBase.h"
15
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
66void
68{
69 const auto & pps = static_cast<const SpecificImpulse1Phase &>(y);
70 _thrust += pps._thrust;
71 _mass_flow_rate += pps._mass_flow_rate;
72}
73
74void
80
81Real
83{
84 return _value;
85}
86
87void
102
103void
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}
const std::vector< double > y
registerMooseObject("ThermalHydraulicsApp", SpecificImpulse1Phase)
void ErrorVector unsigned int
A base class for computing/caching fluxes at boundaries.
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 const VariableValue & coupledValue(const std::string &var_name, unsigned int comp=0) const
virtual bool isTransient() const override
void addRequiredParam(const std::string &name, const std::string &doc_string)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
T & set(const std::string &name, bool quiet_mode=false)
void addCoupledVar(const std::string &name, const std::string &doc_string)
void paramError(const std::string &param, Args... args) const
void mooseWarning(Args &&... args) const
static InputParameters validParams()
const unsigned int & _current_side
const QBase *const & _qrule
const MooseArray< Point > & _normals
const Elem *const & _current_elem
Common class for single phase fluid properties.
Estimates specific impulse from fluid state at the boundary.
virtual void threadJoin(const UserObject &y) override
virtual void finalize() override
SpecificImpulse1Phase(const InputParameters &parameters)
const Real _tol
bisection tolerance
const MaterialProperty< Real > & _H
the total enthalpy including mechanical energy
const unsigned int _n_components
Number of components in the solution vector used to compute the flux.
const bool _cumulative
if the specific impulse is accumulated over timesteps
const MaterialProperty< Real > & _e
internal energy
const SinglePhaseFluidProperties & _fp
fluid property user object
virtual Real getValue() const override
std::vector< const VariableValue * > _U
Variables to pass to boundary flux user object, in the correct order.
Real & _accumulated_mass_flow_rate
accumulated mass flow rate over time
const BoundaryFluxBase & _boundary_uo
Boundary user object.
virtual void initialize() override
Real _mass_flow_rate
total mass flow rate
const MaterialProperty< Real > & _T
fluid temperature
const unsigned int _max_nit
maximum number of iterations for bisection
Real _value
The value of this post-processor.
virtual void execute() override
static InputParameters validParams()
const Real _p_exit
the outlet pressure, user supplied value
Real & _accumulated_thrust
accumulated thrust over time
const MaterialProperty< Real > & _v
specific volume
void gatherSum(T &value)
FEProblemBase & _fe_problem
static const Real gravity_const
Definition Numerics.h:26