https://mooseframework.inl.gov
ADSpecificImpulse1Phase.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 "ADBoundaryFluxBase.h"
15 
16 registerMooseObject("ThermalHydraulicsApp", ADSpecificImpulse1Phase);
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<ADBoundaryFluxBase>(_boundary_uo_name)),
46  _p_exit(getParam<Real>("p_exit")),
47  _H(getADMaterialPropertyByName<Real>("H")),
48  _v(getADMaterialPropertyByName<Real>("v")),
49  _e(getADMaterialPropertyByName<Real>("e")),
50  _T(getADMaterialPropertyByName<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(&adCoupledValue("variables", i));
64 }
65 
66 void
68 {
69  const ADSpecificImpulse1Phase & pps = static_cast<const ADSpecificImpulse1Phase &>(y);
70  _thrust += pps._thrust;
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<ADReal> 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(MetaPhysicL::raw_value(flux[0]));
115 
116  // get entropy at inlet (= entropy at outlet because process is isentropic)
117  Real entropy_in =
118  _fp.s_from_v_e(MetaPhysicL::raw_value(_v[qp]), MetaPhysicL::raw_value(_e[qp]));
119 
120  // compute outlet enthalpy from entropy at inlet (isentropic flow)
121  // and pressure at outlet, need to do bisection because h_from_s_p does not
122  // exist, it is better to work with temperature because s(p, T) is available
123 
124  // upper bound of temperature is the inlet temperature
125  Real T_up = MetaPhysicL::raw_value(_T[qp]);
126 
127  // compute entropy associated with T_up
128  Real entropy_up = _fp.s_from_p_T(_p_exit, T_up);
129 
130  // lower bound for temperature is 0.1 K
131  Real T_low = 0.1;
132 
133  // compute entropy associated with T_low
134  Real entropy_low = _fp.s_from_p_T(_p_exit, T_low);
135 
136  // compute the midpoint temperature
137  Real T_mid = 0.5 * (T_up + T_low);
138 
139  // the current guess for entropy
140  Real entropy_mid = _fp.s_from_p_T(_p_exit, T_mid);
141 
142  // main bisection loop
143  unsigned int nit = 0;
144  while (std::abs(1 - entropy_mid / entropy_in) > _tol)
145  {
146  // check if we are over/underestimating to select either up/down
147  if ((entropy_mid - entropy_in > 0) == (entropy_up - entropy_low > 0))
148  {
149  T_up = T_mid;
150  entropy_up = entropy_mid;
151  }
152  else
153  {
154  T_low = T_mid;
155  entropy_low = entropy_mid;
156  }
157 
158  // update guess for T_mid
159  T_mid = 0.5 * (T_up + T_low);
160 
161  // update the guess for entropy
162  entropy_mid = _fp.s_from_p_T(_p_exit, T_mid);
163 
164  ++nit;
165 
166  if (nit == _max_nit)
167  {
168  mooseDoOnce(mooseWarning("Bisection in ADSpecificImpulse1Phase did not converge"));
169  break;
170  }
171  }
172 
173  // the enthalpy evaluated at _p_exit and T_mid
174  Real h_exit = _fp.h_from_p_T(_p_exit, T_mid);
175 
176  // compute outlet speed
177  Real vel_exit = std::sqrt(2.0 * (MetaPhysicL::raw_value(_H[qp]) - h_exit));
178  _thrust += std::abs(vel_exit * MetaPhysicL::raw_value(flux[0]));
179  }
180 }
virtual const std::vector< ADReal > & getFlux(unsigned int iside, dof_id_type ielem, const std::vector< ADReal > &uvec1, const RealVectorValue &dwave) const
Get the boundary flux vector.
const Real _tol
bisection tolerance
Real _value
The value of this post-processor.
virtual Real getValue() const override
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)
ADSpecificImpulse1Phase(const InputParameters &parameters)
const ADBoundaryFluxBase & _boundary_uo
Boundary user object.
T & set(const std::string &name, bool quiet_mode=false)
const unsigned int _max_nit
maximum number of iterations for bisection
auto raw_value(const Eigen::Map< T > &in)
const ADVariableValue & adCoupledValue(const std::string &var_name, unsigned int comp=0) const
virtual void threadJoin(const UserObject &y) override
const ADMaterialProperty< Real > & _H
the total enthalpy including mechanical energy
const std::vector< double > y
static InputParameters validParams()
const ADMaterialProperty< Real > & _e
internal energy
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 _mass_flow_rate
total mass flow rate
Real & _accumulated_mass_flow_rate
accumulated mass flow rate over time
void gatherSum(T &value)
const unsigned int _n_components
Number of components in the solution vector used to compute the flux.
std::vector< const ADVariableValue * > _U
Variables to pass to boundary flux user object, in the correct order.
const SinglePhaseFluidProperties & _fp
fluid property user object
const ADMaterialProperty< Real > & _v
specific volume
Common class for single phase fluid properties.
Real & _accumulated_thrust
accumulated thrust over time
const Real _p_exit
the outlet pressure, user supplied value
void paramError(const std::string &param, Args... args) const
virtual void execute() override
A base class for computing/caching fluxes at boundaries.
void addCoupledVar(const std::string &name, const std::string &doc_string)
const bool _cumulative
if the specific impulse is accumulated over timesteps
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
FEProblemBase & _fe_problem
registerMooseObject("ThermalHydraulicsApp", ADSpecificImpulse1Phase)
Estimates specific impulse from fluid state at the boundary.
static InputParameters validParams()
const QBase *const & _qrule
const MooseArray< Point > & _normals
static const Real gravity_const
Definition: Numerics.h:26
void addClassDescription(const std::string &doc_string)
virtual void initialize() override
virtual void finalize() override
const Elem *const & _current_elem
virtual bool isTransient() const override
void ErrorVector unsigned int
const ADMaterialProperty< Real > & _T
fluid temperature