https://mooseframework.inl.gov
ComputeLinearFVGreenGaussGradientFaceThread.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 "LinearSystem.h"
13 #include "PetscVectorReader.h"
14 #include "FEProblemBase.h"
15 
17  FEProblemBase & fe_problem, const unsigned int linear_system_num)
18  : _fe_problem(fe_problem),
19  _dim(_fe_problem.mesh().dimension()),
20  _linear_system_number(linear_system_num),
21  _linear_system(libMesh::cast_ref<libMesh::LinearImplicitSystem &>(
22  _fe_problem.getLinearSystem(_linear_system_number).system())),
23  _system_number(_linear_system.number()),
24  _new_gradient(_fe_problem.getLinearSystem(_linear_system_number).newGradientContainer())
25 {
26 }
27 
30  : _fe_problem(x._fe_problem),
31  _dim(x._dim),
32  _linear_system_number(x._linear_system_number),
33  _linear_system(x._linear_system),
34  _system_number(x._system_number),
35  // This will be the vector we work on since the old gradient might still be needed
36  // to compute extrapolated boundary conditions for example.
37  _new_gradient(x._new_gradient)
38 {
39 }
40 
41 void
43 {
44  ParallelUniqueId puid;
45  _tid = puid.id;
46 
47  unsigned int size = 0;
48 
49  for (const auto & variable :
51  {
52  _current_var = dynamic_cast<MooseLinearVariableFV<Real> *>(variable);
53  mooseAssert(_current_var,
54  "This should be a linear FV variable, did we somehow add a nonlinear variable to "
55  "the linear system?");
57  {
58  if (!size)
59  size = range.size();
60 
61  std::vector<std::vector<Real>> new_values_elem(_new_gradient.size(),
62  std::vector<Real>(size, 0.0));
63  std::vector<std::vector<Real>> new_values_neighbor(_new_gradient.size(),
64  std::vector<Real>(size, 0.0));
65  std::vector<dof_id_type> dof_indices_elem(size, 0);
66  std::vector<dof_id_type> dof_indices_neighbor(size, 0);
67 
68  {
70 
71  // Iterate over all the face infos in the range
72  auto face_iterator = range.begin();
73  for (const auto & face_i : make_range(size))
74  {
75  const auto & face_info = *face_iterator;
76 
77  const auto current_face_type =
78  face_info->faceType(std::make_pair(_current_var->number(), _system_number));
79 
80  // First we check if this face is internal to the variable, if yes, contribute to both
81  // sides
82  if (current_face_type == FaceInfo::VarFaceNeighbors::BOTH)
83  {
84  dof_indices_elem[face_i] =
85  face_info->elemInfo()->dofIndices()[_system_number][_current_var->number()];
86  dof_indices_neighbor[face_i] =
87  face_info->neighborInfo()->dofIndices()[_system_number][_current_var->number()];
88 
89  const auto face_value =
90  Moose::FV::linearInterpolation(solution_reader(dof_indices_elem[face_i]),
91  solution_reader(dof_indices_neighbor[face_i]),
92  *face_info,
93  true);
94 
95  const auto contribution =
96  face_info->normal() * face_info->faceArea() * face_info->faceCoord() * face_value;
97 
98  for (const auto i : make_range(_dim))
99  {
100  new_values_elem[i][face_i] = contribution(i);
101  new_values_neighbor[i][face_i] = -contribution(i);
102  }
103  }
104  // If this face is on the boundary of the block where the variable is defined, we
105  // check for boundary conditions. If we don't find any we use an automatic one-term
106  // expansion to compute the face value.
107  else if (current_face_type == FaceInfo::VarFaceNeighbors::ELEM ||
108  current_face_type == FaceInfo::VarFaceNeighbors::NEIGHBOR)
109  {
110  auto * bc_pointer =
111  _current_var->getBoundaryCondition(*face_info->boundaryIDs().begin());
112 
113  if (bc_pointer)
114  bc_pointer->setupFaceData(face_info, current_face_type);
115 
116  const auto * const elem_info = current_face_type == FaceInfo::VarFaceNeighbors::ELEM
117  ? face_info->elemInfo()
118  : face_info->neighborInfo();
119 
120  // We have to account for cases when this face is an internal boundary and the normal
121  // points in the wrong direction
122  const auto multiplier =
123  current_face_type == FaceInfo::VarFaceNeighbors::ELEM ? 1.0 : -1.0;
124  auto & dof_id_container = current_face_type == FaceInfo::VarFaceNeighbors::ELEM
125  ? dof_indices_elem
126  : dof_indices_neighbor;
127  auto & contribution_container = current_face_type == FaceInfo::VarFaceNeighbors::ELEM
128  ? new_values_elem
129  : new_values_neighbor;
130 
131  dof_id_container[face_i] =
132  elem_info->dofIndices()[_system_number][_current_var->number()];
133 
134  // If we don't have a boundary condition, then it's a natural condition. We'll use a
135  // one-term expansion approximation in that case
136  const auto contribution = multiplier * face_info->normal() * face_info->faceArea() *
137  face_info->faceCoord() *
138  (bc_pointer ? bc_pointer->computeBoundaryValue()
139  : solution_reader(dof_id_container[face_i]));
140  for (const auto i : make_range(_dim))
141  contribution_container[i][face_i] = contribution(i);
142  }
143  face_iterator++;
144  }
145  }
146  for (const auto i : make_range(_dim))
147  {
148  _new_gradient[i]->add_vector(new_values_elem[i].data(), dof_indices_elem);
149  _new_gradient[i]->add_vector(new_values_neighbor[i].data(), dof_indices_neighbor);
150  }
151  }
152  }
153 }
154 
155 void
158 {
159 }
The gradient in a volume using Green Gauss theorem and a cell-centered finite-volume approximation ca...
const std::vector< MooseVariableFieldBase * > & getVariables(THREAD_ID tid)
Definition: SystemBase.h:752
void join(const ComputeLinearFVGreenGaussGradientFaceThread &y)
Join threads at the end of the execution.
unsigned int number() const
Get variable number coming from libMesh.
Tnew cast_ref(Told &oldvar)
void setupFaceData(const FaceInfo *face_info, const FaceInfo::VarFaceNeighbors face_type)
Set current face info.
MeshBase & mesh
MooseLinearVariableFV< Real > * _current_var
Pointer to the current variable.
void operator()(const FaceInfoRange &range)
Operator which is used to execute the thread over a certain iterator range.
LinearFVBoundaryCondition * getBoundaryCondition(const BoundaryID bd_id) const
Get the boundary condition object which corresponds to the given boundary ID.
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
libMesh::CompareTypes< T, T2 >::supertype linearInterpolation(const T &value1, const T2 &value2, const FaceInfo &fi, const bool one_is_elem, const InterpMethod interp_method=InterpMethod::Average)
A simple linear interpolation of values between cell centers to a cell face.
Definition: MathFVUtils.h:150
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
StoredRange< MooseMesh::const_face_info_iterator, const FaceInfo * > FaceInfoRange
A class which helps with repeated reading from a petsc vector.
std::vector< std::unique_ptr< NumericVector< Number > > > & _new_gradient
Cache for the new gradient which is being built.
ComputeLinearFVGreenGaussGradientFaceThread(FEProblemBase &fe_problem, const unsigned int linear_system_num)
Class constructor.
const unsigned int _system_number
Global system number (the number of this system in the libmesh equation system)
LinearSystem & getLinearSystem(unsigned int sys_num)
Get non-constant reference to a linear system.
IntRange< T > make_range(T beg, T end)
std::unique_ptr< NumericVector< Number > > current_local_solution
virtual bool needsGradientVectorStorage() const override
Check if cell gradient computations were requested for this variable.
const libMesh::LinearImplicitSystem & _linear_system
Reference to the linear system at libmesh level.
const unsigned int _linear_system_number
The number of the linear system on which this thread is acting.