27 const std::vector<std::unique_ptr<NumericVector<Number>>> & raw_gradient,
28 std::vector<std::unique_ptr<NumericVector<Number>>> & temporary_limited_gradient,
30 const std::unordered_set<unsigned int> & requested_variables)
31 : _fe_problem(fe_problem),
32 _dim(_fe_problem.
mesh().dimension()),
34 _libmesh_system(system.system()),
35 _system_number(_libmesh_system.number()),
36 _raw_gradient(raw_gradient),
37 _limiter_type(limiter_type),
38 _requested_variables(requested_variables),
39 _temporary_limited_gradient(temporary_limited_gradient)
66 mooseError(
"ComputeLinearFVLimitedGradientThread currently supports only the Venkatakrishnan "
69 unsigned int size = 0;
87 std::vector<Real>(size, 0.0));
88 std::vector<dof_id_type> dof_indices(size, 0);
91 std::vector<PetscVectorReader> grad_reader;
92 grad_reader.reserve(raw_grad_container.size());
93 for (
const auto dim_index : index_range(raw_grad_container))
94 grad_reader.emplace_back(*raw_grad_container[dim_index]);
96 mooseAssert(raw_grad_container.size() >=
_dim,
97 "Raw gradient container has fewer components than mesh dimension.");
99 "Limited gradient container has fewer components than mesh dimension.");
101 auto elem_iterator = range.begin();
102 for (
const auto elem_i : make_range(size))
104 const auto & elem_info = *elem_iterator;
114 dof_indices[elem_i] = dof;
116 const Real phi_elem = solution_reader(dof);
117 Real max_value = phi_elem;
118 Real min_value = phi_elem;
121 const Elem *
const elem = elem_info->elem();
122 for (
const auto side : make_range(elem->n_sides()))
124 const Elem *
const neighbor = elem->neighbor_ptr(side);
132 const dof_id_type neighbor_dof =
137 const Real phi_neighbor = solution_reader(neighbor_dof);
138 max_value = std::max(max_value, phi_neighbor);
139 min_value = std::min(min_value, phi_neighbor);
143 VectorValue<Real> raw_grad;
145 for (
const auto dim_index : make_range(
_dim))
146 raw_grad(dim_index) = grad_reader[dim_index](dof);
149 if (std::abs(max_value - min_value) < 1e-14)
151 for (
const auto dim_index : make_range(
_dim))
152 temporary_values[dim_index][elem_i] = raw_grad(dim_index);
157 const Point & elem_centroid = elem_info->centroid();
159 for (
const auto side : make_range(elem->n_sides()))
161 const Elem *
const neighbor = elem->neighbor_ptr(side);
169 const dof_id_type neighbor_dof =
175 const Elem *
const fi_elem = elem_has_face_info ? elem : neighbor;
176 const unsigned int fi_side =
177 elem_has_face_info ? side : neighbor->which_neighbor_am_i(elem);
180 "Missing FaceInfo for neighboring elements with centroid " +
183 " while computing limited gradients.");
185 const Point face_point = fi->faceCentroid();
187 const Real delta_face = raw_grad * (face_point - elem_centroid);
189 Real h = elem->hmin();
190 Real grad_mag = raw_grad.norm();
192 Real eps = 0.1 * (grad_mag * h) * (grad_mag * h) + 1e-20;
194 const Real delta_max = std::abs(max_value - phi_elem) + eps;
195 const Real delta_min = std::abs(min_value - phi_elem) + eps;
197 const Real rf = (delta_face >= 0.0) ? std::abs(delta_face) / delta_max
198 : std::abs(delta_face) / delta_min;
200 const Real beta = (2.0 * rf + 1.0) / (rf * (2.0 * rf + 1.0) + 1.0);
201 alpha = std::min(alpha, beta);
204 const VectorValue<Real> limited_grad = alpha * raw_grad;
205 for (
const auto dim_index : make_range(
_dim))
206 temporary_values[dim_index][elem_i] = limited_grad(dim_index);
209 for (
const auto dim_index : make_range(
_dim))