https://mooseframework.inl.gov
Loading...
Searching...
No Matches
ADGateValve1PhaseUserObject.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
11#include "THMIndicesVACE.h"
13#include "Function.h"
14#include "Numerics.h"
15#include "metaphysicl/parallel_numberarray.h"
16#include "metaphysicl/parallel_dualnumber.h"
17#include "metaphysicl/parallel_semidynamicsparsenumberarray.h"
18#include "libmesh/parallel_algebra.h"
19
21
22const std::vector<std::pair<std::string, unsigned int>>
24 std::pair<std::string, unsigned int>("rhoA", THMVACE1D::MASS),
25 std::pair<std::string, unsigned int>("rhouA", THMVACE1D::MOMENTUM),
26 std::pair<std::string, unsigned int>("rhoEA", THMVACE1D::ENERGY)};
27
30{
32
33 params.addRequiredParam<Real>("open_area_fraction",
34 "Fraction of possible flow area that is open");
35 params.addParam<Real>("open_area_fraction_min", 1e-10, "Minimum open area fraction");
36
37 params.addRequiredCoupledVar("A", "Cross-sectional area of connected flow channels, elemental");
38 params.addRequiredCoupledVar("A_linear",
39 "Cross-sectional area of connected flow channels, linear");
40 params.addRequiredCoupledVar("rhoA", "rho*A of the connected flow channels");
41 params.addRequiredCoupledVar("rhouA", "rhou*A of the connected flow channels");
42 params.addRequiredCoupledVar("rhoEA", "rhoE*A of the connected flow channels");
43
44 params.addRequiredParam<UserObjectName>("numerical_flux", "Numerical flux user object name");
45
46 params.addRequiredParam<std::string>("component_name", "Name of the associated component");
47
48 params.addClassDescription("Gate valve user object for 1-phase flow");
49
50 params.declareControllable("open_area_fraction");
51
52 return params;
53}
54
57
58 _f_open(getParam<Real>("open_area_fraction")),
59 _f_open_min(getParam<Real>("open_area_fraction_min")),
60
61 _A(adCoupledValue("A")),
62 _A_linear(adCoupledValue("A_linear")),
63 _rhoA(adCoupledValue("rhoA")),
64 _rhouA(adCoupledValue("rhouA")),
65 _rhoEA(adCoupledValue("rhoEA")),
66
67 _rhoA_jvar(coupled("rhoA")),
68 _rhouA_jvar(coupled("rhouA")),
69 _rhoEA_jvar(coupled("rhoEA")),
70
71 _p(getADMaterialProperty<Real>("p")),
72
73 _numerical_flux(getUserObject<ADNumericalFlux3EqnBase>("numerical_flux")),
74
75 _component_name(getParam<std::string>("component_name")),
76
77 _dir(getMaterialProperty<RealVectorValue>("direction")),
78
79 _solutions(_n_connections),
80 _fluxes(_n_connections, std::vector<ADReal>(THMVACE1D::N_FLUX_OUTPUTS, 0)),
81 _dof_indices(_n_connections, std::vector<dof_id_type>(THMVACE1D::N_FLUX_OUTPUTS, 0)),
82
83 _stored_p(_n_connections),
84
85 _elem_ids(_n_connections),
86 _local_side_ids(_n_connections),
87
88 _areas(_n_connections),
89 _directions(_n_connections)
90{
91}
92
93void
95{
96 _connection_indices.clear();
97
98 std::vector<ADReal> zero(THMVACE1D::N_FLUX_INPUTS, ADReal(0.));
99 for (auto & s : _solutions)
100 s = zero;
101 for (unsigned int i = 0; i < THMVACE1D::N_FLUX_OUTPUTS; i++)
102 {
103 _fluxes[0][i] = 0;
104 _fluxes[1][i] = 0;
105 }
106}
107
108void
110{
111 // Get connection index
112 const unsigned int c = getBoundaryIDIndex();
113 _connection_indices.push_back(c);
114
115 // Store DoF indices
116 for (const auto & varname_eq_index_pair : _varname_eq_index_pairs)
117 {
118 MooseVariable * var = getVar(varname_eq_index_pair.first, 0);
119 auto && dofs = var->dofIndices();
120 mooseAssert(dofs.size() == 1, "There should be only one DoF index.");
121 _dof_indices[c][varname_eq_index_pair.second] = dofs[0];
122 }
123
124 // Store solution vector for connection, evaluated at the connection, where the area is A_linear,
125 // so that both flow channels receive the same flux, as on flow channel interior faces
126 const ADReal A_ratio = _A_linear[0] / _A[0];
127 std::vector<ADReal> U(THMVACE1D::N_FLUX_INPUTS, ADReal(0.));
128 U[THMVACE1D::RHOA] = _rhoA[0] * A_ratio;
129 U[THMVACE1D::RHOUA] = _rhouA[0] * A_ratio;
130 U[THMVACE1D::RHOEA] = _rhoEA[0] * A_ratio;
132 _solutions[c] = U;
133
134 // Store element ID and local side ID for connection
135 _elem_ids[c] = _current_elem->id();
137
138 // Store direction and area of channel at junction (used for error-checking)
139 _areas[c] = _A_linear[0];
140 _directions[c] = _dir[0];
141
142 _stored_p[c] = _p[0];
143}
144
145void
147{
148 const auto & junction_uo = cast_ref<const ADGateValve1PhaseUserObject &>(uo);
149
150 // Store the data computed/retrieved in the other threads
151 for (unsigned int i = 0; i < junction_uo._connection_indices.size(); i++)
152 {
153 const unsigned int c = junction_uo._connection_indices[i];
154
155 _dof_indices[c] = junction_uo._dof_indices[c];
156 _solutions[c] = junction_uo._solutions[c];
157 _elem_ids[c] = junction_uo._elem_ids[c];
158 _local_side_ids[c] = junction_uo._local_side_ids[c];
159 _areas[c] = junction_uo._areas[c];
160 _directions[c] = junction_uo._directions[c];
161 _stored_p[c] = junction_uo._stored_p[c];
162 }
163}
164
165void
167{
168 // Check direction compatibility
170 mooseError(_component_name, ": The connected channels must be parallel at the junction.");
171
172 for (unsigned int i = 0; i < _n_connections; i++)
173 {
174 processor_id_type owner_proc = _processor_ids[i];
175 comm().broadcast(_elem_ids[i], owner_proc, true);
176 comm().broadcast(_local_side_ids[i], owner_proc, true);
177 comm().broadcast(_solutions[i], owner_proc, true);
178 comm().broadcast(_directions[i], owner_proc, true);
179 comm().broadcast(_areas[i], owner_proc, true);
180 comm().broadcast(_stored_p[i], owner_proc, true);
181 }
182
183 const Real & n1_dot_d1 = _normal[0];
184 const Real d1_dot_d2 = _directions[0] * _directions[1];
185
186 const ADReal & A1 = _areas[0];
187 const ADReal & A2 = _areas[1];
188 const ADReal A = std::min(A1, A2);
189 const ADReal A_flow = _f_open * A;
190
191 if (_f_open > _f_open_min)
192 {
193 // compute flow contribution
194 std::vector<ADReal> U_flow1 = _solutions[0];
195 std::vector<ADReal> U_flow2 = _solutions[1];
196 U_flow1[THMVACE1D::AREA] = A_flow;
197 U_flow2[THMVACE1D::AREA] = A_flow;
198 for (unsigned int i = 0; i < THMVACE1D::N_FLUX_OUTPUTS; i++)
199 {
200 U_flow1[i] *= A_flow / A1;
201 U_flow2[i] *= A_flow / A2;
202 }
203 U_flow2[THMVACE1D::RHOUA] *= d1_dot_d2;
204
206 _local_side_ids[0], _elem_ids[0], true, U_flow1, U_flow2, n1_dot_d1);
207
209 _local_side_ids[0], _elem_ids[0], false, U_flow1, U_flow2, n1_dot_d1);
210 _fluxes[1][THMVACE1D::RHOA] *= d1_dot_d2;
211 _fluxes[1][THMVACE1D::RHOEA] *= d1_dot_d2;
212 }
213
214 // compute wall contribution
215 for (unsigned int c = 0; c < _n_connections; c++)
216 {
217 const ADReal A_wall = _areas[c] - A_flow;
218 _fluxes[c][THMVACE1D::RHOUA] += _stored_p[c] * A_wall;
219 }
220}
221
222const std::vector<ADReal> &
223ADGateValve1PhaseUserObject::getFlux(const unsigned int & connection_index) const
224{
225 Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
226
227 return _fluxes[connection_index];
228}
registerMooseObject("ThermalHydraulicsApp", ADGateValve1PhaseUserObject)
DualNumber< Real, DNDerivativeType, true > ADReal
Provides common interfaces for flow junction user objects.
unsigned int getBoundaryIDIndex()
Gets the index of the currently executing boundary within the vector of boundary IDs given to this Si...
static InputParameters validParams()
std::vector< unsigned int > _processor_ids
Owners of each side of the junction.
const unsigned int _n_connections
Number of connected flow channels.
const std::vector< Real > & _normal
Flow channel outward normals or junction inward normals.
Gate valve user object for 1-phase flow.
std::vector< ADReal > _areas
Areas at each connection.
static const std::vector< std::pair< std::string, unsigned int > > _varname_eq_index_pairs
Pairs of variable names vs. their corresponding equation indices.
const ADMaterialProperty< Real > & _p
Pressure material property.
virtual void threadJoin(const UserObject &uo) override
std::vector< unsigned int > _connection_indices
Connection indices for this thread.
const ADVariableValue & _rhoA
rho*A of the connected flow channels
const std::string & _component_name
Name of the associated component.
std::vector< RealVectorValue > _directions
Directions at each connection.
const MaterialProperty< RealVectorValue > & _dir
Direction material property.
std::vector< std::vector< ADReal > > _solutions
Solution vectors for each connection.
std::vector< std::vector< dof_id_type > > _dof_indices
Degree of freedom indices; first index is connection, second is equation.
const Real & _f_open_min
Minimum open area fraction.
std::vector< std::vector< ADReal > > _fluxes
Flux vector.
const std::vector< ADReal > & getFlux(const unsigned int &connection_index) const override
Gets the flux vector for a connection.
ADGateValve1PhaseUserObject(const InputParameters &params)
const ADVariableValue & _A
Cross-sectional area of connected flow channels, elemental.
const Real & _f_open
Fraction of possible flow area that is open.
std::vector< unsigned int > _elem_ids
Element IDs for each connection.
std::vector< unsigned int > _local_side_ids
Local side IDs for each connection.
const ADNumericalFlux3EqnBase & _numerical_flux
Numerical flux user object.
std::vector< ADReal > _stored_p
Stored pressure for each connection.
const ADVariableValue & _rhoEA
rho*E*A of the connected flow channels
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
Base class for computing numerical fluxes for FlowModelSinglePhase.
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)
void mooseError(Args &&... args) const
const std::vector< dof_id_type > & dofIndices() const final
virtual const std::vector< ADReal > & getFlux(const unsigned int iside, const dof_id_type ielem, bool res_side_is_left, const std::vector< ADReal > &UL_1d, const std::vector< ADReal > &UR_1d, Real nLR_dot_d) const
Gets the 1D flux vector for an element/side combination.
const unsigned int & _current_side
const Elem *const & _current_elem
void broadcast(T &data, const unsigned int root_id=0, const bool identical_sizes=false) const
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 1D.
bool areParallelVectors(const RealVectorValue &a, const RealVectorValue &b, const Real &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
Tests if two real-valued vectors are parallel within some absolute tolerance.
Definition Numerics.C:26