https://mooseframework.inl.gov
ADJunctionOneToOne1PhaseUserObject.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"
12 #include "FlowModel1PhaseUtils.h"
15 #include "Numerics.h"
16 #include "metaphysicl/parallel_numberarray.h"
17 #include "metaphysicl/parallel_dualnumber.h"
18 #include "metaphysicl/parallel_semidynamicsparsenumberarray.h"
19 #include "libmesh/parallel_algebra.h"
20 
22 
23 const std::vector<std::pair<std::string, unsigned int>>
25  std::pair<std::string, unsigned int>("rhoA", THMVACE1D::MASS),
26  std::pair<std::string, unsigned int>("rhouA", THMVACE1D::MOMENTUM),
27  std::pair<std::string, unsigned int>("rhoEA", THMVACE1D::ENERGY)};
28 
30 
33 {
36 
37  params.addRequiredCoupledVar(
38  "A_elem", "Piecewise constant cross-sectional area of connected flow channels");
39  params.addRequiredCoupledVar("A_linear",
40  "Piecewise linear cross-sectional area of connected flow channels");
41  params.addRequiredCoupledVar("rhoA", "rho*A of the connected flow channels");
42  params.addRequiredCoupledVar("rhouA", "rhou*A of the connected flow channels");
43  params.addRequiredCoupledVar("rhoEA", "rhoE*A of the connected flow channels");
44 
45  params.addRequiredParam<UserObjectName>("fluid_properties",
46  "Name of fluid properties user object");
47 
48  params.addRequiredParam<UserObjectName>("numerical_flux", "Numerical flux user object name");
49 
50  params.addRequiredParam<std::string>("junction_name", "Name of the junction component");
51 
52  params.addClassDescription(
53  "Computes flux between two subdomains for 1-phase one-to-one junction");
54 
55  return params;
56 }
57 
59  const InputParameters & params)
60  : ADFlowJunctionUserObject(params),
62 
63  _A_linear(adCoupledValue("A_linear")),
64 
65  _A_var(getVar("A_elem", 0)),
66  _rhoA_var(getVar("rhoA", 0)),
67  _rhouA_var(getVar("rhouA", 0)),
68  _rhoEA_var(getVar("rhoEA", 0)),
69 
70  _fp(getUserObject<SinglePhaseFluidProperties>("fluid_properties")),
71 
72  _numerical_flux(getUserObject<ADNumericalFlux3EqnBase>("numerical_flux")),
73 
74  _junction_name(getParam<std::string>("junction_name")),
75 
76  _dir(getMaterialProperty<RealVectorValue>("direction")),
77 
78  _primitive_solutions(_n_connections),
79  _neighbor_primitive_solutions(_n_connections),
80 
81  _fluxes(_n_connections),
82  _dof_indices(_n_connections, std::vector<dof_id_type>(THMVACE1D::N_FLUX_OUTPUTS, 0)),
83 
84  _elem_ids(_n_connections),
85  _local_side_ids(_n_connections),
86 
87  _areas_linear(_n_connections),
88  _directions(_n_connections),
89  _positions(_n_connections),
90  _neighbor_positions(_n_connections),
91  _delta_x(_n_connections),
92  _has_neighbor(_n_connections)
93 {
99 }
100 
101 void
103 {
104  _connection_indices.clear();
105 
106  // Broadcasts require vectors on all processes to have the same size
107  std::vector<ADReal> zero(THMVACE1D::N_PRIM_VARS, ADReal(0.));
108  for (unsigned int c = 0; c < _n_connections; c++)
109  {
112  }
113 }
114 
115 void
117 {
118  // Get connection index
119  const unsigned int c = getBoundaryIDIndex();
120  _connection_indices.push_back(c);
121 
122  // Store DoF indices
123  for (const auto & varname_eq_index_pair : _varname_eq_index_pairs)
124  {
125  MooseVariable * var = getVar(varname_eq_index_pair.first, 0);
126  auto && dofs = var->dofIndices();
127  mooseAssert(dofs.size() == 1, "There should be only one DoF index.");
128  _dof_indices[c][varname_eq_index_pair.second] = dofs[0];
129  }
130 
131  // Store primitive solution vectors for connection
132  const auto U_avg =
133  FlowModel1PhaseUtils::getElementalSolutionVector<true>(_current_elem, _U_vars, _is_implicit);
134  _primitive_solutions[c] = FlowModel1PhaseUtils::computePrimitiveSolutionVector<true>(U_avg, _fp);
135 
136  // Get the neighbor solution and position. There should be one neighbor, unless
137  // there is only one element in the subdomain. Because broadcasting requires
138  // data sizes to be allocated on all processes, we cannot work with a vector
139  // of a size not known upfront, so we work with a single neighbor and have
140  // a flag that states whether there is one or zero neighbors.
141  std::vector<std::vector<GenericReal<true>>> W_neighbor;
142  std::vector<Point> x_neighbor;
143  getNeighborPrimitiveVariables(_current_elem, W_neighbor, x_neighbor);
144  if (W_neighbor.size() == 1)
145  {
146  _neighbor_primitive_solutions[c] = W_neighbor[0];
147  _neighbor_positions[c] = x_neighbor[0];
148  _has_neighbor[c] = true;
149  }
150  else
151  _has_neighbor[c] = false;
152 
153  // Store element ID and local side ID for connection
154  _elem_ids[c] = _current_elem->id();
156 
157  // Store direction, area, and position of channel at junction
158  _areas_linear[c] = _A_linear[0];
159  _directions[c] = _dir[0];
160  _positions[c] = _q_point[0];
161  _delta_x[c] = (_positions[c] - _current_elem->vertex_average()) * _directions[c];
162 }
163 
164 void
166 {
167  const auto & junction_uo = static_cast<const ADJunctionOneToOne1PhaseUserObject &>(uo);
168 
169  // Store the data computed/retrieved in the other threads
170  for (unsigned int i = 0; i < junction_uo._connection_indices.size(); i++)
171  {
172  const unsigned int c = junction_uo._connection_indices[i];
173 
174  _dof_indices[c] = junction_uo._dof_indices[c];
175  _primitive_solutions[c] = junction_uo._primitive_solutions[c];
176  _neighbor_primitive_solutions[c] = junction_uo._neighbor_primitive_solutions[c];
177  _elem_ids[c] = junction_uo._elem_ids[c];
178  _local_side_ids[c] = junction_uo._local_side_ids[c];
179  _areas_linear[c] = junction_uo._areas_linear[c];
180  _directions[c] = junction_uo._directions[c];
181  _positions[c] = junction_uo._positions[c];
182  _neighbor_positions[c] = junction_uo._neighbor_positions[c];
183  _delta_x[c] = junction_uo._delta_x[c];
184  _has_neighbor[c] = junction_uo._has_neighbor[c];
185  }
186 }
187 
188 void
190 {
191  for (unsigned int i = 0; i < _n_connections; i++)
192  {
193  processor_id_type owner_proc = _processor_ids[i];
194  comm().broadcast(_primitive_solutions[i], owner_proc, true);
195  comm().broadcast(_neighbor_primitive_solutions[i], owner_proc, true);
196  comm().broadcast(_elem_ids[i], owner_proc, true);
197  comm().broadcast(_local_side_ids[i], owner_proc, true);
198  comm().broadcast(_areas_linear[i], owner_proc, true);
199  comm().broadcast(_directions[i], owner_proc, true);
200  comm().broadcast(_positions[i], owner_proc, true);
201  comm().broadcast(_neighbor_positions[i], owner_proc, true);
202  comm().broadcast(_delta_x[i], owner_proc, true);
203 
204  // Vectors of bools are special, so we must broadcast a single bool instead
205  bool has_neighbor = _has_neighbor[i];
206  comm().broadcast(has_neighbor, owner_proc, true);
207  _has_neighbor[i] = has_neighbor;
208  }
209 
210  const auto & W0_avg = _primitive_solutions[0];
211  const auto & W1_avg = _primitive_solutions[1];
212 
213  // Multiplier for possibly different coordinate systems
214  const Real dir_mult = -_normal[0] * _normal[1];
215  auto W0_ref = W0_avg;
216  auto W1_ref = W1_avg;
217  W0_ref[THMVACE1D::VELOCITY] *= dir_mult;
218  W1_ref[THMVACE1D::VELOCITY] *= dir_mult;
219 
220  std::vector<std::vector<GenericReal<true>>> W_neighbor0;
221  std::vector<Point> x_neighbor0;
222  if (_has_neighbor[0])
223  {
224  W_neighbor0.push_back(_neighbor_primitive_solutions[0]);
225  x_neighbor0.push_back(_neighbor_positions[0]);
226  }
227 
228  std::vector<std::vector<GenericReal<true>>> W_neighbor1;
229  std::vector<Point> x_neighbor1;
230  if (_has_neighbor[1])
231  {
232  W_neighbor1.push_back(_neighbor_primitive_solutions[1]);
233  x_neighbor1.push_back(_neighbor_positions[1]);
234  }
235 
236  const auto slopes0 = getBoundaryElementSlopes(
237  W0_avg, _positions[0], _directions[0], W_neighbor0, x_neighbor0, W1_ref);
238  const auto slopes1 = getBoundaryElementSlopes(
239  W1_avg, _positions[1], _directions[1], W_neighbor1, x_neighbor1, W0_ref);
240 
241  auto W0 = W0_avg;
242  auto W1 = W1_avg;
243  for (unsigned int m = 0; m < THMVACE1D::N_PRIM_VARS; m++)
244  {
245  W0[m] = W0_avg[m] + slopes0[m] * _delta_x[0];
246  W1[m] = W1_avg[m] + slopes1[m] * _delta_x[1];
247  }
248 
249  auto U0 =
250  FlowModel1PhaseUtils::computeConservativeSolutionVector<true>(W0, _areas_linear[0], _fp);
251  auto U1 =
252  FlowModel1PhaseUtils::computeConservativeSolutionVector<true>(W1, _areas_linear[1], _fp);
253  U1[THMVACE1D::RHOUA] *= dir_mult;
254 
255  _fluxes[0] = _numerical_flux.getFlux(_local_side_ids[0], _elem_ids[0], true, U0, U1, _normal[0]);
256 
257  _fluxes[1] = _numerical_flux.getFlux(_local_side_ids[0], _elem_ids[0], false, U0, U1, _normal[0]);
258  _fluxes[1][THMVACE1D::RHOA] *= dir_mult;
259  _fluxes[1][THMVACE1D::RHOEA] *= dir_mult;
260 }
261 
262 const std::vector<ADReal> &
263 ADJunctionOneToOne1PhaseUserObject::getFlux(const unsigned int & connection_index) const
264 {
265  Threads::spin_mutex::scoped_lock lock(_spin_mutex);
266 
267  return _fluxes[connection_index];
268 }
269 
270 std::vector<ADReal>
272 {
273  const auto U =
274  FlowModel1PhaseUtils::getElementalSolutionVector<true>(elem, _U_vars, _is_implicit);
275  return FlowModel1PhaseUtils::computePrimitiveSolutionVector<true>(U, _fp);
276 }
const ADVariableValue & _A_linear
Piecewise linear cross-sectional area of connected flow channels.
std::vector< RealVectorValue > _directions
Directions at each connection.
std::vector< Point > _positions
Positions at each connection.
virtual void getNeighborPrimitiveVariables(const Elem *elem, std::vector< std::vector< GenericReal< is_ad >>> &W_neighbor, std::vector< Point > &x_neighbor) const
Gets the primitive solution vector and position of neighbor(s)
const unsigned int & _current_side
virtual std::vector< ADReal > computeElementPrimitiveVariables(const Elem *elem) const override
Computes the cell-average primitive variable values for an element.
unsigned int getBoundaryIDIndex()
Gets the index of the currently executing boundary within the vector of boundary IDs given to this Si...
std::vector< std::vector< dof_id_type > > _dof_indices
Degree of freedom indices; first index is connection, second is equation.
virtual void threadJoin(const UserObject &uo) override
const Parallel::Communicator & comm() const
const MooseArray< Point > & _q_point
MooseVariable * getVar(const std::string &var_name, unsigned int comp)
const Number zero
std::vector< std::vector< ADReal > > _fluxes
Flux vector.
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.
std::vector< unsigned int > _elem_ids
Element IDs for each connection.
void addRequiredParam(const std::string &name, const std::string &doc_string)
static const std::vector< std::pair< std::string, unsigned int > > _varname_eq_index_pairs
Pairs of variable names vs. their corresponding equation indices.
uint8_t processor_id_type
std::vector< bool > _has_neighbor
Flags for each connection having a neighbor.
std::vector< std::vector< ADReal > > _primitive_solutions
Primitive solution vectors for each connection.
const std::vector< dof_id_type > & dofIndices() const final
const std::vector< ADReal > & getFlux(const unsigned int &connection_index) const override
Gets the flux vector for a connection.
std::vector< unsigned int > _connection_indices
Connection indices for this thread.
std::vector< ADReal > _areas_linear
Piecewise linear areas at each connection.
std::vector< GenericReal< is_ad > > getBoundaryElementSlopes(const std::vector< GenericReal< is_ad >> &W_elem, const Point &x_elem, const RealVectorValue &dir, std::vector< std::vector< GenericReal< is_ad >>> W_neighbor, std::vector< Point > x_neighbor, const std::vector< GenericReal< is_ad >> &W_boundary) const
Gets limited slopes for the primitive variables in the 1-D direction for boundary element...
Common class for single phase fluid properties.
Base class for computing numerical fluxes for FlowModelSinglePhase.
Computes flux between two subdomains for 1-phase one-to-one junction.
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.
Provides common interfaces for flow junction user objects.
void broadcast(T &data, const unsigned int root_id=0, const bool identical_sizes=false) const
std::vector< MooseVariable * > _U_vars
Conservative solution variables.
void addRequiredCoupledVar(const std::string &name, const std::string &doc_string)
static const unsigned int N_PRIM_VARS
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
std::vector< std::vector< ADReal > > _neighbor_primitive_solutions
Primitive solution vectors for each connection&#39;s neighbor.
Interface class for 1-D slope reconstruction.
const SinglePhaseFluidProperties & _fp
fluid properties user object
void addClassDescription(const std::string &doc_string)
std::vector< Real > _delta_x
Position changes for each connection.
const std::vector< Real > & _normal
Flow channel outward normals or junction inward normals.
const MaterialProperty< RealVectorValue > & _dir
Direction material property.
const Elem *const & _current_elem
const ADNumericalFlux3EqnBase & _numerical_flux
Numerical flux user object.
registerMooseObject("ThermalHydraulicsApp", ADJunctionOneToOne1PhaseUserObject)
std::vector< Point > _neighbor_positions
Positions at each connection&#39;s neighbor.
std::vector< unsigned int > _local_side_ids
Local side IDs for each connection.
static InputParameters validParams()
ADJunctionOneToOne1PhaseUserObject(const InputParameters &params)
static const unsigned int N_FLUX_OUTPUTS
Number of numerical flux function outputs for 3D.
uint8_t dof_id_type
static Threads::spin_mutex _spin_mutex
Thread lock.