https://mooseframework.inl.gov
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 
20 registerMooseObject("ThermalHydraulicsApp", ADGateValve1PhaseUserObject);
21 
22 const 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");
38  params.addRequiredCoupledVar("rhoA", "rho*A of the connected flow channels");
39  params.addRequiredCoupledVar("rhouA", "rhou*A of the connected flow channels");
40  params.addRequiredCoupledVar("rhoEA", "rhoE*A of the connected flow channels");
41 
42  params.addRequiredParam<UserObjectName>("numerical_flux", "Numerical flux user object name");
43 
44  params.addRequiredParam<std::string>("component_name", "Name of the associated component");
45 
46  params.addClassDescription("Gate valve user object for 1-phase flow");
47 
48  params.declareControllable("open_area_fraction");
49 
50  return params;
51 }
52 
54  : ADFlowJunctionUserObject(params),
55 
56  _f_open(getParam<Real>("open_area_fraction")),
57  _f_open_min(getParam<Real>("open_area_fraction_min")),
58 
59  _A(adCoupledValue("A")),
60  _rhoA(adCoupledValue("rhoA")),
61  _rhouA(adCoupledValue("rhouA")),
62  _rhoEA(adCoupledValue("rhoEA")),
63 
64  _rhoA_jvar(coupled("rhoA")),
65  _rhouA_jvar(coupled("rhouA")),
66  _rhoEA_jvar(coupled("rhoEA")),
67 
68  _p(getADMaterialProperty<Real>("p")),
69 
70  _numerical_flux(getUserObject<ADNumericalFlux3EqnBase>("numerical_flux")),
71 
72  _component_name(getParam<std::string>("component_name")),
73 
74  _dir(getMaterialProperty<RealVectorValue>("direction")),
75 
76  _solutions(_n_connections),
77  _fluxes(_n_connections, std::vector<ADReal>(THMVACE1D::N_FLUX_OUTPUTS, 0)),
78  _dof_indices(_n_connections, std::vector<dof_id_type>(THMVACE1D::N_FLUX_OUTPUTS, 0)),
79 
80  _stored_p(_n_connections),
81 
82  _elem_ids(_n_connections),
83  _local_side_ids(_n_connections),
84 
85  _areas(_n_connections),
86  _directions(_n_connections)
87 {
88 }
89 
90 void
92 {
93  _connection_indices.clear();
94 
95  std::vector<ADReal> zero(THMVACE1D::N_FLUX_INPUTS, ADReal(0.));
96  for (auto & s : _solutions)
97  s = zero;
98  for (unsigned int i = 0; i < THMVACE1D::N_FLUX_OUTPUTS; i++)
99  {
100  _fluxes[0][i] = 0;
101  _fluxes[1][i] = 0;
102  }
103 }
104 
105 void
107 {
108  // Get connection index
109  const unsigned int c = getBoundaryIDIndex();
110  _connection_indices.push_back(c);
111 
112  // Store DoF indices
113  for (const auto & varname_eq_index_pair : _varname_eq_index_pairs)
114  {
115  MooseVariable * var = getVar(varname_eq_index_pair.first, 0);
116  auto && dofs = var->dofIndices();
117  mooseAssert(dofs.size() == 1, "There should be only one DoF index.");
118  _dof_indices[c][varname_eq_index_pair.second] = dofs[0];
119  }
120 
121  // Store solution vector for connection
122  std::vector<ADReal> U(THMVACE1D::N_FLUX_INPUTS, ADReal(0.));
123  U[THMVACE1D::RHOA] = _rhoA[0];
124  U[THMVACE1D::RHOUA] = _rhouA[0];
125  U[THMVACE1D::RHOEA] = _rhoEA[0];
126  U[THMVACE1D::AREA] = _A[0];
127  _solutions[c] = U;
128 
129  // Store element ID and local side ID for connection
130  _elem_ids[c] = _current_elem->id();
132 
133  // Store direction and area of channel at junction (used for error-checking)
134  _areas[c] = _A[0];
135  _directions[c] = _dir[0];
136 
137  _stored_p[c] = _p[0];
138 }
139 
140 void
142 {
143  const auto & junction_uo = static_cast<const ADGateValve1PhaseUserObject &>(uo);
144 
145  // Store the data computed/retrieved in the other threads
146  for (unsigned int i = 0; i < junction_uo._connection_indices.size(); i++)
147  {
148  const unsigned int c = junction_uo._connection_indices[i];
149 
150  _dof_indices[c] = junction_uo._dof_indices[c];
151  _solutions[c] = junction_uo._solutions[c];
152  _elem_ids[c] = junction_uo._elem_ids[c];
153  _local_side_ids[c] = junction_uo._local_side_ids[c];
154  _areas[c] = junction_uo._areas[c];
155  _directions[c] = junction_uo._directions[c];
156  _stored_p[c] = junction_uo._stored_p[c];
157  }
158 }
159 
160 void
162 {
163  // Check direction compatibility
165  mooseError(_component_name, ": The connected channels must be parallel at the junction.");
166 
167  for (unsigned int i = 0; i < _n_connections; i++)
168  {
169  processor_id_type owner_proc = _processor_ids[i];
170  comm().broadcast(_elem_ids[i], owner_proc, true);
171  comm().broadcast(_local_side_ids[i], owner_proc, true);
172  comm().broadcast(_solutions[i], owner_proc, true);
173  comm().broadcast(_directions[i], owner_proc, true);
174  comm().broadcast(_areas[i], owner_proc, true);
175  comm().broadcast(_stored_p[i], owner_proc, true);
176  }
177 
178  const Real & n1_dot_d1 = _normal[0];
179  const Real d1_dot_d2 = _directions[0] * _directions[1];
180 
181  const ADReal & A1 = _areas[0];
182  const ADReal & A2 = _areas[1];
183  const ADReal A = std::min(A1, A2);
184  const ADReal A_flow = _f_open * A;
185 
186  if (_f_open > _f_open_min)
187  {
188  // compute flow contribution
189  std::vector<ADReal> U_flow1 = _solutions[0];
190  std::vector<ADReal> U_flow2 = _solutions[1];
191  U_flow1[THMVACE1D::AREA] = A_flow;
192  U_flow2[THMVACE1D::AREA] = A_flow;
193  for (unsigned int i = 0; i < THMVACE1D::N_FLUX_OUTPUTS; i++)
194  {
195  U_flow1[i] *= A_flow / A1;
196  U_flow2[i] *= A_flow / A2;
197  }
198  U_flow2[THMVACE1D::RHOUA] *= d1_dot_d2;
199 
201  _local_side_ids[0], _elem_ids[0], true, U_flow1, U_flow2, n1_dot_d1);
202 
204  _local_side_ids[0], _elem_ids[0], false, U_flow1, U_flow2, n1_dot_d1);
205  _fluxes[1][THMVACE1D::RHOA] *= d1_dot_d2;
206  _fluxes[1][THMVACE1D::RHOEA] *= d1_dot_d2;
207  }
208 
209  // compute wall contribution
210  for (unsigned int c = 0; c < _n_connections; c++)
211  {
212  const ADReal A_wall = _areas[c] - A_flow;
213  _fluxes[c][THMVACE1D::RHOUA] += _stored_p[c] * A_wall;
214  }
215 }
216 
217 const std::vector<ADReal> &
218 ADGateValve1PhaseUserObject::getFlux(const unsigned int & connection_index) const
219 {
220  Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
221 
222  return _fluxes[connection_index];
223 }
std::vector< RealVectorValue > _directions
Directions at each connection.
Gate valve user object for 1-phase flow.
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)
unsigned int getBoundaryIDIndex()
Gets the index of the currently executing boundary within the vector of boundary IDs given to this Si...
static InputParameters validParams()
const Parallel::Communicator & comm() const
std::vector< unsigned int > _connection_indices
Connection indices for this thread.
MooseVariable * getVar(const std::string &var_name, unsigned int comp)
const Number zero
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
const unsigned int _n_connections
Number of connected flow channels.
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.
void addRequiredParam(const std::string &name, const std::string &doc_string)
std::vector< unsigned int > _local_side_ids
Local side IDs for each connection.
const ADNumericalFlux3EqnBase & _numerical_flux
Numerical flux user object.
registerMooseObject("ThermalHydraulicsApp", ADGateValve1PhaseUserObject)
uint8_t processor_id_type
const std::vector< dof_id_type > & dofIndices() const final
const ADMaterialProperty< Real > & _p
Pressure material property.
static const std::vector< std::pair< std::string, unsigned int > > _varname_eq_index_pairs
Pairs of variable names vs. their corresponding equation indices.
std::vector< ADReal > _areas
Areas at each connection.
const ADVariableValue & _rhouA
rho*u*A of the connected flow channels
Base class for computing numerical fluxes for FlowModelSinglePhase.
ADGateValve1PhaseUserObject(const InputParameters &params)
const MaterialProperty< RealVectorValue > & _dir
Direction material property.
const ADVariableValue & _rhoA
rho*A of the connected flow channels
static const unsigned int N_FLUX_INPUTS
Number of numerical flux function inputs for 1D.
std::vector< unsigned int > _processor_ids
Owners of each side of the junction.
std::vector< unsigned int > _elem_ids
Element IDs for each connection.
const std::vector< ADReal > & getFlux(const unsigned int &connection_index) const override
Gets the flux vector for a connection.
Provides common interfaces for flow junction user objects.
const ADVariableValue & _A
Cross-sectional area of connected flow channels.
void broadcast(T &data, const unsigned int root_id=0, const bool identical_sizes=false) const
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)
std::vector< std::vector< ADReal > > _solutions
Solution vectors for each connection.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
std::vector< ADReal > _stored_p
Stored pressure for each connection.
void mooseError(Args &&... args) const
void addClassDescription(const std::string &doc_string)
const std::vector< Real > & _normal
Flow channel outward normals or junction inward normals.
const Elem *const & _current_elem
const ADVariableValue & _rhoEA
rho*E*A of the connected flow channels
virtual void threadJoin(const UserObject &uo) override
const std::string & _component_name
Name of the associated component.
const Real & _f_open_min
Minimum open area fraction.
std::vector< std::vector< ADReal > > _fluxes
Flux vector.
std::vector< std::vector< dof_id_type > > _dof_indices
Degree of freedom indices; first index is connection, second is equation.
void declareControllable(const std::string &name, std::set< ExecFlagType > execute_flags={})
static InputParameters validParams()
const Real & _f_open
Fraction of possible flow area that is open.
static const unsigned int N_FLUX_OUTPUTS
Number of numerical flux function outputs for 3D.
uint8_t dof_id_type