https://mooseframework.inl.gov
ADVolumeJunction1PhaseUserObject.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 "THMIndicesVACE.h"
13 #include "VolumeJunction1Phase.h"
15 #include "Numerics.h"
16 #include "THMUtils.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 
23 
26 {
28 
29  params.addRequiredCoupledVar("A", "Cross-sectional area of connected flow channels");
30  params.addRequiredCoupledVar("rhoA", "rho*A of the connected flow channels");
31  params.addRequiredCoupledVar("rhouA", "rhou*A of the connected flow channels");
32  params.addRequiredCoupledVar("rhoEA", "rhoE*A of the connected flow channels");
33 
34  params.addRequiredCoupledVar("rhoV", "rho*V of the junction");
35  params.addRequiredCoupledVar("rhouV", "rho*u*V of the junction");
36  params.addRequiredCoupledVar("rhovV", "rho*v*V of the junction");
37  params.addRequiredCoupledVar("rhowV", "rho*w*V of the junction");
38  params.addRequiredCoupledVar("rhoEV", "rho*E*V of the junction");
39 
40  params.addRequiredParam<UserObjectName>("fp", "Fluid properties user object name");
41 
42  params.addRequiredParam<Real>("K", "Form loss coefficient [-]");
43  params.addRequiredParam<Real>("A_ref", "Reference area [m^2]");
44 
45  params.addParam<bool>("apply_velocity_scaling",
46  false,
47  "Set to true to apply the scaling to the normal velocity. See "
48  "documentation for more information.");
49 
50  params.addClassDescription(
51  "Computes and caches flux and residual vectors for a 1-phase volume junction");
52 
53  params.declareControllable("K");
54  return params;
55 }
56 
59 
60  _A(adCoupledValue("A")),
61  _rhoA(adCoupledValue("rhoA")),
62  _rhouA(adCoupledValue("rhouA")),
63  _rhoEA(adCoupledValue("rhoEA")),
64 
65  _K(getParam<Real>("K")),
66  _A_ref(getParam<Real>("A_ref")),
67 
68  _apply_velocity_scaling(getParam<bool>("apply_velocity_scaling")),
69 
70  _fp(getUserObject<SinglePhaseFluidProperties>("fp"))
71 {
76 
83 
90 
92  for (std::size_t i = 0; i < _n_connections; i++)
93  _numerical_flux_uo[i] = &getUserObjectByName<ADNumericalFlux3EqnBase>(_numerical_flux_names[i]);
94 }
95 
96 void
98 {
99  const Real din = _normal[c];
100  const RealVectorValue di = _dir[0];
101  const RealVectorValue ni = di * din;
102  const Real nJi_dot_di = -din;
103 
104  std::vector<ADReal> Ui(THMVACE3D::N_FLUX_INPUTS, 0.);
105  Ui[THMVACE3D::RHOA] = _rhoA[0];
106  Ui[THMVACE3D::RHOUA] = _rhouA[0] * di(0);
107  Ui[THMVACE3D::RHOVA] = _rhouA[0] * di(1);
108  Ui[THMVACE3D::RHOWA] = _rhouA[0] * di(2);
109  Ui[THMVACE3D::RHOEA] = _rhoEA[0];
110  Ui[THMVACE3D::AREA] = _A[0];
111 
112  const auto flux_3d = compute3DFlux(*(_numerical_flux_uo[c]), Ui, ni);
113 
115  _flux[c][THMVACE1D::MASS] = flux_3d[THMVACE3D::MASS] * nJi_dot_di;
117  _flux[c][THMVACE1D::ENERGY] = flux_3d[THMVACE3D::ENERGY] * nJi_dot_di;
118 
119  const bool is_primary_connection = (c == 0);
120  const auto residual = computeResidual(flux_3d, Ui, ni, is_primary_connection);
121 
122  for (const auto i : index_range(_residual))
123  _residual[i] += residual[i];
124 }
125 
126 std::vector<ADReal>
128  const std::vector<ADReal> & Ui,
129  const RealVectorValue & ni) const
130 {
131  using std::abs, std::max, std::min;
132 
133  const RealVectorValue nJi = -ni;
134 
135  RealVectorValue t1, t2;
137 
138  const auto & Ai = Ui[THMVACE3D::AREA];
139 
145 
146  std::vector<ADReal> UJi(THMVACE3D::N_FLUX_INPUTS, 0.);
147  UJi[THMVACE3D::RHOA] = rhoV / _volume * Ai;
149  {
150  const auto & rhoAi = Ui[THMVACE3D::RHOA];
151  const auto & rhouAi = Ui[THMVACE3D::RHOUA];
152  const auto & rhovAi = Ui[THMVACE3D::RHOVA];
153  const auto & rhowAi = Ui[THMVACE3D::RHOWA];
154  const auto & rhoEAi = Ui[THMVACE3D::RHOEA];
155 
156  const ADRealVectorValue uveci(rhouAi / rhoAi, rhovAi / rhoAi, rhowAi / rhoAi);
157  const ADReal uni = uveci * nJi;
158 
159  const ADReal rhoJ = rhoV / _volume;
160  const ADReal vJ = 1.0 / rhoJ;
161  const ADRealVectorValue uvecJ(rhouV / rhoV, rhovV / rhoV, rhowV / rhoV);
162  const ADReal eJ = rhoEV / rhoV - 0.5 * uvecJ * uvecJ;
163 
164  const ADReal unJ = uvecJ * nJi;
165  const ADReal ut1J = uvecJ * t1;
166  const ADReal ut2J = uvecJ * t2;
167 
168  const ADReal rhoi = rhoAi / Ai;
169  const ADReal vi = 1.0 / rhoi;
170  const ADReal ei = rhoEAi / rhoAi - 0.5 * uni * uni;
171 
172  const ADReal ci = _fp.c_from_v_e(vi, ei);
173  const ADReal cJ = _fp.c_from_v_e(vJ, eJ);
174  const ADReal cmax = max(ci, cJ);
175 
176  const ADReal uni_sign = (uni > 0) - (uni < 0);
177  const ADReal factor = 0.5 * (1.0 - uni_sign) * min(abs(uni - unJ) / cmax, 1.0);
178 
179  const ADReal unJ_mod = uni - factor * (uni - unJ);
180  const ADRealVectorValue uvecJ_mod = unJ_mod * nJi + ut1J * t1 + ut2J * t2;
181  const ADReal EJ_mod = eJ + 0.5 * uvecJ_mod * uvecJ_mod;
182 
183  UJi[THMVACE3D::RHOUA] = rhoJ * uvecJ_mod(0) * Ai;
184  UJi[THMVACE3D::RHOVA] = rhoJ * uvecJ_mod(1) * Ai;
185  UJi[THMVACE3D::RHOWA] = rhoJ * uvecJ_mod(2) * Ai;
186  UJi[THMVACE3D::RHOEA] = rhoJ * EJ_mod * Ai;
187  }
188  else
189  {
190  UJi[THMVACE3D::RHOUA] = rhouV / _volume * Ai;
191  UJi[THMVACE3D::RHOVA] = rhovV / _volume * Ai;
192  UJi[THMVACE3D::RHOWA] = rhowV / _volume * Ai;
193  UJi[THMVACE3D::RHOEA] = rhoEV / _volume * Ai;
194  }
195  UJi[THMVACE3D::AREA] = Ai;
196 
197  std::vector<ADReal> FL, FR;
198  numerical_flux.calcFlux(UJi, Ui, nJi, t1, t2, FL, FR);
199 
200  return FL;
201 }
202 
203 std::vector<ADReal>
204 ADVolumeJunction1PhaseUserObject::computeResidual(const std::vector<ADReal> & flux_3d,
205  const std::vector<ADReal> & Ui,
206  const RealVectorValue & ni,
207  bool is_primary_connection) const
208 {
209  using std::abs;
210 
211  const RealVectorValue nJi = -ni;
212 
213  RealVectorValue t1, t2;
215 
216  const auto & Ai = Ui[THMVACE3D::AREA];
217 
223 
224  const ADReal rhoJ = rhoV / _volume;
225  const ADReal vJ = 1.0 / rhoJ;
226  const ADRealVectorValue uvecJ(rhouV / rhoV, rhovV / rhoV, rhowV / rhoV);
227  const ADReal eJ = rhoEV / rhoV - 0.5 * uvecJ * uvecJ;
228  const ADReal pJ = _fp.p_from_v_e(vJ, eJ);
229 
230  std::vector<ADReal> residual(_n_scalar_eq, 0.0);
231 
232  if (is_primary_connection && std::abs(_K) > 1e-10)
233  {
234  const auto & rhoAi = Ui[THMVACE3D::RHOA];
235  const auto & rhouAi = Ui[THMVACE3D::RHOUA];
236  const auto & rhovAi = Ui[THMVACE3D::RHOVA];
237  const auto & rhowAi = Ui[THMVACE3D::RHOWA];
238  const auto & rhoEAi = Ui[THMVACE3D::RHOEA];
239 
240  const ADRealVectorValue uveci(rhouAi / rhoAi, rhovAi / rhoAi, rhowAi / rhoAi);
241  const ADReal uni = uveci * nJi;
242 
243  const ADReal v_in = THM::v_from_rhoA_A(rhoAi, Ai);
244  const ADReal rhouA2 = rhouAi * rhouAi;
245  const ADReal e_in = rhoEAi / rhoAi - 0.5 * rhouA2 / (rhoAi * rhoAi);
246  const ADReal p_in = _fp.p_from_v_e(v_in, e_in);
247  const ADReal s0_in = _fp.s_from_v_e(v_in, e_in);
248  const ADReal T_in = _fp.T_from_v_e(v_in, e_in);
249  const ADReal h_in = _fp.h_from_p_T(p_in, T_in);
250  const ADReal velin2 = uni * uni;
251  const ADReal h0_in = h_in + 0.5 * velin2;
252  const ADReal p0_in = _fp.p_from_h_s(h0_in, s0_in);
253  ADReal S_loss;
254  if (_A_ref == 0)
255  S_loss = _K * (p0_in - p_in) * Ai;
256  else
257  S_loss = _K * (p0_in - p_in) * _A_ref;
258  if (uni > 0) // flow is out of the junction
259  {
260  residual[VolumeJunction1Phase::RHOUV_INDEX] -= ni(0) * S_loss;
261  residual[VolumeJunction1Phase::RHOVV_INDEX] -= ni(1) * S_loss;
262  residual[VolumeJunction1Phase::RHOWV_INDEX] -= ni(2) * S_loss;
263  }
264  else
265  {
266  residual[VolumeJunction1Phase::RHOUV_INDEX] += ni(0) * S_loss;
267  residual[VolumeJunction1Phase::RHOVV_INDEX] += ni(1) * S_loss;
268  residual[VolumeJunction1Phase::RHOWV_INDEX] += ni(2) * S_loss;
269  }
270  residual[VolumeJunction1Phase::RHOEV_INDEX] += S_loss * abs(uni);
271  }
272 
273  const ADRealVectorValue flux_mom_n = flux_3d[THMVACE3D::MOM_NORM] * nJi +
274  flux_3d[THMVACE3D::MOM_TAN1] * t1 +
275  flux_3d[THMVACE3D::MOM_TAN2] * t2;
276  const RealVectorValue ex(1, 0, 0);
277  const RealVectorValue ey(0, 1, 0);
278  const RealVectorValue ez(0, 0, 1);
279 
280  residual[VolumeJunction1Phase::RHOV_INDEX] -= -flux_3d[THMVACE3D::RHOA];
281  residual[VolumeJunction1Phase::RHOUV_INDEX] -= -flux_mom_n * ex - pJ * ni(0) * Ai;
282  residual[VolumeJunction1Phase::RHOVV_INDEX] -= -flux_mom_n * ey - pJ * ni(1) * Ai;
283  residual[VolumeJunction1Phase::RHOWV_INDEX] -= -flux_mom_n * ez - pJ * ni(2) * Ai;
285 
286  return residual;
287 }
288 
289 void
291 {
293  for (unsigned int i = 0; i < _n_scalar_eq; i++)
294  comm().sum(_residual[i]);
295 }
296 
297 std::vector<const MooseVariableBase *>
299 {
300  std::vector<const MooseVariableBase *> vars(THMVACE1D::N_FLUX_OUTPUTS);
301  vars[THMVACE1D::RHOA] = getVar("rhoA", 0);
302  vars[THMVACE1D::RHOUA] = getVar("rhouA", 0);
303  vars[THMVACE1D::RHOEA] = getVar("rhoEA", 0);
304 
305  return vars;
306 }
307 
308 std::vector<const MooseVariableBase *>
310 {
311  std::vector<const MooseVariableBase *> vars(VolumeJunction1Phase::N_EQ);
317 
318  return vars;
319 }
const ADVariableValue & _rhoA
rho*A of the connected flow channels
std::vector< std::vector< ADReal > > _flux
Cached flux vector for each connection.
MetaPhysicL::DualNumber< V, D, asd > abs(const MetaPhysicL::DualNumber< V, D, asd > &a)
std::vector< ADReal > computeResidual(const std::vector< ADReal > &flux_3d, const std::vector< ADReal > &Ui, const RealVectorValue &ni, bool is_primary_connection) const
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void v_from_rhoA_A(Real rhoA, Real A, Real &v, Real &dv_drhoA)
Computes specific volume and its derivatives from rho*A, and area.
Definition: Numerics.C:100
std::vector< std::string > _scalar_variable_names
Vector of coupled variable names for each scalar variable.
char ** vars
const SinglePhaseFluidProperties & _fp
Single-phase fluid properties user object.
virtual std::vector< const MooseVariableBase * > getFlowChannelVariables() const override
Gets the flow channel variables.
const Parallel::Communicator & comm() const
virtual void finalize() override
virtual void computeFluxesAndResiduals(const unsigned int &c) override
Computes and stores the fluxes, the scalar residuals, and their Jacobians.
unsigned int _n_scalar_eq
Number of scalar residual components.
MooseVariable * getVar(const std::string &var_name, unsigned int comp)
const unsigned int _n_connections
Number of connected flow channels.
const std::vector< UserObjectName > & _numerical_flux_names
Names of numerical flux user objects for each connected flow channel.
void addRequiredParam(const std::string &name, const std::string &doc_string)
auto max(const L &left, const R &right)
std::vector< ADReal > _residual
Cached scalar residual vector.
const Real & _volume
Volume of the junction.
std::vector< const ADNumericalFlux3EqnBase * > _numerical_flux_uo
Vector of numerical flux user objects for each connected flow channel.
std::vector< const ADVariableValue * > _junction_var_values
ADVolumeJunction1PhaseUserObject(const InputParameters &params)
std::vector< std::string > _flow_variable_names
Vector of coupled variable names for each flow variable.
const MaterialProperty< RealVectorValue > & _dir
Direction of the element connected to the junction.
static const unsigned int N_EQ
Number of equations for the junction.
const ADVariableValue & _rhoEA
rho*E*A of the connected flow channels
Common class for single phase fluid properties.
std::vector< ADReal > compute3DFlux(const ADNumericalFlux3EqnBase &numerical_flux, const std::vector< ADReal > &Ui, const RealVectorValue &ni) const
Base class for computing numerical fluxes for FlowModelSinglePhase.
Base class for computing and caching flux and residual vectors for a volume junction.
Computes and caches flux and residual vectors for a 1-phase volume junction.
const Real & _K
Form loss coefficient.
static const unsigned int N_FLUX_OUTPUTS
Number of numerical flux function outputs for 1D.
void addRequiredCoupledVar(const std::string &name, const std::string &doc_string)
void computeOrthogonalDirections(const RealVectorValue &n_unnormalized, RealVectorValue &t1, RealVectorValue &t2)
Computes two unit vectors orthogonal to the given vector.
Definition: THMUtils.C:22
const ADVariableValue & _A
Cross-sectional area of connected flow channels.
virtual std::vector< const MooseVariableBase * > getJunctionVariables() const override
Gets the junction variables.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual void calcFlux(const std::vector< ADReal > &UL_3d, const std::vector< ADReal > &UR_3d, const RealVectorValue &nLR, const RealVectorValue &t1, const RealVectorValue &t2, std::vector< ADReal > &FL, std::vector< ADReal > &FR) const =0
Calculates the 3D flux vectors given "left" and "right" states.
void addClassDescription(const std::string &doc_string)
const std::vector< Real > & _normal
Flow channel outward normals or junction inward normals.
registerMooseObject("ThermalHydraulicsApp", ADVolumeJunction1PhaseUserObject)
const bool _apply_velocity_scaling
Apply velocity scaling?
auto min(const L &left, const R &right)
const ADVariableValue & _rhouA
rho*u*A of the connected flow channels
void declareControllable(const std::string &name, std::set< ExecFlagType > execute_flags={})
const ADVariableValue & coupledJunctionValue(const std::string &var_name, unsigned int i=0) const
Gets an AD junction variable value.
auto index_range(const T &sizable)
const MooseVariableBase * getJunctionVar(const std::string &var_name, unsigned int i=0) const
Gets a junction variable.
static const unsigned int N_FLUX_INPUTS
Number of numerical flux function inputs for 3D.