https://mooseframework.inl.gov
Loading...
Searching...
No Matches
ComputeLinearFVLimitedGradientThread.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
12#include "GradientLimiterType.h"
13#include "SystemBase.h"
14#include "PetscVectorReader.h"
15#include "FEProblemBase.h"
16#include "FVUtils.h"
17
18#include "libmesh/dof_object.h"
19#include "libmesh/petsc_vector.h"
20
21#include <algorithm>
22#include <cmath>
23#include <limits>
24
26 FEProblemBase & fe_problem,
27 SystemBase & system,
28 std::vector<std::unique_ptr<NumericVector<Number>>> & gradient,
29 const Moose::FV::GradientLimiterType limiter_type,
30 const std::unordered_set<unsigned int> & requested_variables)
31 : _fe_problem(fe_problem),
32 _dim(_fe_problem.mesh().dimension()),
33 _system(system),
34 _libmesh_system(system.system()),
35 _system_number(_libmesh_system.number()),
36 _gradient(gradient),
37 _gradient_data(gradient.size()),
38 _owns_gradient_data(true),
39 _limiter_type(limiter_type),
40 _requested_variables(requested_variables)
41{
42 for (const auto dim_index : index_range(_gradient))
43 {
44 auto & gradient_vector =
45 libMesh::cast_ref<libMesh::PetscVector<Number> &>(*_gradient[dim_index]);
46 _gradient_data[dim_index] = gradient_vector.get_array();
47 }
48}
49
52 : _fe_problem(x._fe_problem),
53 _dim(x._dim),
54 _system(x._system),
55 _libmesh_system(x._libmesh_system),
56 _system_number(x._system_number),
57 _gradient(x._gradient),
58 _gradient_data(x._gradient_data),
59 _owns_gradient_data(false),
60 _limiter_type(x._limiter_type),
61 _requested_variables(x._requested_variables)
62{
63}
64
66{
68 for (const auto dim_index : index_range(_gradient))
69 {
70 auto & gradient_vector =
71 libMesh::cast_ref<libMesh::PetscVector<Number> &>(*_gradient[dim_index]);
72 gradient_vector.restore_array();
73 }
74}
75
76void
78{
80 _tid = puid.id;
81
83 mooseError("ComputeLinearFVLimitedGradientThread currently supports only the Venkatakrishnan "
84 "limiter.");
85
86 mooseAssert(_gradient.size() >= _dim,
87 "Gradient container has fewer components than mesh dimension.");
88
89 // All gradient component vectors have the same layout because they are
90 // clones of the same system vector.
91 auto & first_gradient_vector =
92 libMesh::cast_ref<libMesh::PetscVector<Number> &>(*_gradient.front());
93
94 for (const auto & variable : _system.getVariables(_tid))
95 {
96 _current_var = dynamic_cast<MooseLinearVariableFV<Real> *>(variable);
97 if (!_current_var)
98 continue;
99
101 continue;
102
104 continue;
105
107
108 for (auto elem_iterator = range.begin(); elem_iterator != range.end(); ++elem_iterator)
109 {
110 const auto & elem_info = *elem_iterator;
111
112 if (!_current_var->hasBlocks(elem_info->subdomain_id()))
113 continue;
114
115 const dof_id_type dof = elem_info->dofIndices()[_system_number][_current_var->number()];
117 continue;
118
119 const auto local_dof = first_gradient_vector.map_global_to_local_index(dof);
120
121 const Real phi_elem = solution_reader(dof);
122 Real max_value = phi_elem;
123 Real min_value = phi_elem;
124
125 // Gather one-ring min/max solution values.
126 const Elem * const elem = elem_info->elem();
127 for (const auto side : make_range(elem->n_sides()))
128 {
129 const Elem * const neighbor = elem->neighbor_ptr(side);
130 if (!neighbor)
131 continue;
132
133 const auto & neighbor_info = _fe_problem.mesh().elemInfo(neighbor->id());
134 if (!_current_var->hasBlocks(neighbor_info.subdomain_id()))
135 continue;
136
137 const dof_id_type neighbor_dof =
138 neighbor_info.dofIndices()[_system_number][_current_var->number()];
139 if (neighbor_dof == libMesh::DofObject::invalid_id)
140 continue;
141
142 const Real phi_neighbor = solution_reader(neighbor_dof);
143 max_value = std::max(max_value, phi_neighbor);
144 min_value = std::min(min_value, phi_neighbor);
145 }
146
147 // Copy this cell's raw gradient before modifying the gradient storage.
148 VectorValue<Real> raw_grad;
149 raw_grad.zero();
150 for (const auto dim_index : make_range(_dim))
151 raw_grad(dim_index) = _gradient_data[dim_index][local_dof];
152
153 // If the stencil is constant (or nearly constant), leave the raw
154 // gradient unchanged.
155 if (std::abs(max_value - min_value) < 1e-14)
156 continue;
157
158 Real alpha = 1.0;
159 const Point & elem_centroid = elem_info->centroid();
160
161 for (const auto side : make_range(elem->n_sides()))
162 {
163 const Elem * const neighbor = elem->neighbor_ptr(side);
164 if (!neighbor)
165 continue;
166
167 const auto & neighbor_info = _fe_problem.mesh().elemInfo(neighbor->id());
168 if (!_current_var->hasBlocks(neighbor_info.subdomain_id()))
169 continue;
170
171 const dof_id_type neighbor_dof =
172 neighbor_info.dofIndices()[_system_number][_current_var->number()];
173 if (neighbor_dof == libMesh::DofObject::invalid_id)
174 continue;
175
176 const bool elem_has_face_info = Moose::FV::elemHasFaceInfo(*elem, neighbor);
177 const Elem * const fi_elem = elem_has_face_info ? elem : neighbor;
178 const unsigned int fi_side =
179 elem_has_face_info ? side : neighbor->which_neighbor_am_i(elem);
180
181 const auto * fi = _fe_problem.mesh().faceInfo(fi_elem, fi_side);
182 mooseAssert(fi,
183 "Missing FaceInfo for neighboring elements with centroid " +
184 Moose::stringify(elem_info->centroid()) + " and " +
185 Moose::stringify(neighbor->vertex_average()) +
186 " while computing limited gradients.");
187
188 const Point face_point = fi->faceCentroid();
189 const Real delta_face = raw_grad * (face_point - elem_centroid);
190
191 const Real h = elem->hmin();
192 const Real grad_mag = raw_grad.norm();
193
194 const Real eps = 0.1 * (grad_mag * h) * (grad_mag * h) + 1e-20;
195
196 const Real delta_max = std::abs(max_value - phi_elem) + eps;
197 const Real delta_min = std::abs(min_value - phi_elem) + eps;
198
199 const Real rf = (delta_face >= 0.0) ? std::abs(delta_face) / delta_max
200 : std::abs(delta_face) / delta_min;
201
202 const Real beta = (2.0 * rf + 1.0) / (rf * (2.0 * rf + 1.0) + 1.0);
203 alpha = std::min(alpha, beta);
204 }
205
206 // No neighboring gradient values are needed, so it is safe to replace
207 // this cell's raw gradient once its limiter coefficient is known.
208 for (const auto dim_index : make_range(_dim))
209 _gradient_data[dim_index][local_dof] = alpha * raw_grad(dim_index);
210 }
211 }
212}
213
214void
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
Compute limited cell gradients for linear FV variables.
const std::unordered_set< unsigned int > & _requested_variables
Variable numbers that requested the current limiter.
const unsigned int _system_number
Global system number in the libMesh equation system.
std::vector< std::unique_ptr< NumericVector< Number > > > & _gradient
Gradient storage limited in place.
MooseLinearVariableFV< Real > * _current_var
Pointer to the current variable we are operating on.
SystemBase & _system
The system wrapper this thread operates on.
const bool _owns_gradient_data
True only for the original thread object that acquired and must restore the arrays.
FEProblemBase & _fe_problem
Reference to the problem.
StoredRange< MooseMesh::const_elem_info_iterator, const ElemInfo * > ElemInfoRange
ComputeLinearFVLimitedGradientThread(FEProblemBase &fe_problem, SystemBase &system, std::vector< std::unique_ptr< NumericVector< Number > > > &gradient, const Moose::FV::GradientLimiterType limiter_type, const std::unordered_set< unsigned int > &requested_variables)
Class constructor.
const libMesh::System & _libmesh_system
Reference to the libMesh system backing the wrapper system.
std::vector< Number * > _gradient_data
Writable local arrays, one per gradient component.
const Moose::FV::GradientLimiterType _limiter_type
The type of limiter requested.
void join(const ComputeLinearFVLimitedGradientThread &y)
Join threads at the end of the execution.
const unsigned int _dim
The dimension of the domain.
void operator()(const ElemInfoRange &range)
Apply the limiter over the provided element range.
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
virtual MooseMesh & mesh() override
This class provides variable solution interface for linear finite volume problems.
virtual bool needsGradientVectorStorage() const override
Check if cell gradient computations were requested for this variable.
const std::vector< const FaceInfo * > & faceInfo() const
Accessor for local FaceInfo objects.
Definition MooseMesh.h:2347
const ElemInfo & elemInfo(const dof_id_type id) const
Accessor for the elemInfo object for a given element ID.
Definition MooseMesh.C:4000
unsigned int number() const
Get variable number coming from libMesh.
bool hasBlocks(const SubdomainID id) const override
Returns whether the functor is defined on this block.
A class which helps with repeated reading from a petsc vector.
Base class for a system (of equations)
Definition SystemBase.h:87
const std::vector< MooseVariableFieldBase * > & getVariables(THREAD_ID tid)
Definition SystemBase.h:770
static constexpr dof_id_type invalid_id
std::unique_ptr< NumericVector< Number > > current_local_solution
MeshBase & mesh
bool elemHasFaceInfo(const Elem &elem, const Elem *const neighbor)
This function infers based on elements if the faceinfo between them belongs to the element or not.
Definition FVUtils.C:21
GradientLimiterType
Cell-gradient limiter variants used for MUSCL-style reconstructions.
@ Venkatakrishnan
Venkatakrishnan limiter (smooth, multidimensional).
std::string stringify(const T &t)
conversion to string
Definition Conversion.h:64