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