46 Assert(values.begin() != values.end(), dealii::ExcMessage(
"Container must not be empty."));
49 for (
unsigned int i = 0; i < n_components; ++i)
52 const bool all_positive =
53 std::all_of(values.begin(), values.end(), [i](TensorType v) { return v[i] > 0; });
54 const bool all_negative =
55 std::all_of(values.begin(), values.end(), [i](TensorType v) { return v[i] < 0; });
57 if (not(all_positive or all_negative))
59 result[i] =
typename TensorType::value_type(0.);
64 auto it = std::min_element(values.begin(),
66 [i](
const TensorType &a,
const TensorType &b) {
67 return std::abs(a[i]) < std::abs(b[i]);
80 const std::vector<number> &tvb_constant,
81 const number cell_size)
83 Assert(values.begin() != values.end(), dealii::ExcMessage(
"Container must not be empty."));
84 Assert(tvb_constant.size() == n_components,
86 "The size of the TVB constant vector must match the number of components."));
89 std::array<bool, n_components> below_limit_mask;
90 for (
unsigned int i = 0; i < n_components; ++i)
92 if (std::abs(values[0][i]) <= tvb_constant[i] * cell_size * cell_size)
94 below_limit_mask[i] =
true;
98 below_limit_mask[i] =
false;
102 if (std::all_of(below_limit_mask.begin(), below_limit_mask.end(), [](
bool v) { return v; }))
104 for (
unsigned int i = 0; i < n_components; ++i)
105 result[i] = values[0][i];
109 result = tvd_minmod<n_components, TensorType, Container>(values);
114 for (
unsigned int i = 0; i < n_components; ++i)
116 if (below_limit_mask[i])
117 result[i] = values[0][i];
127 const std::vector<std::pair<dealii::Tensor<1, n_components, number>,
128 dealii::Tensor<1, n_components, dealii::Tensor<1, dim, number>>>>
129 &cell_average_values,
130 const typename dealii::Triangulation<dim>::active_cell_iterator &cell,
133 std::array<dealii::Tensor<1, n_components, number>, dim> limited_slopes;
135 for (
unsigned int d = 0; d < dim; ++d)
137 boost::container::small_vector<dealii::Tensor<1, n_components, number>, 3>
139 minmod_input_values.emplace_back();
140 for (
unsigned int i = 0; i < n_components; ++i)
141 minmod_input_values[0][i] = cell_average_values[cell->active_cell_index()].second[i][d];
142 for (
unsigned int face_no = 0; face_no < 2; ++face_no)
144 unsigned int face_index = 2 * d + face_no;
145 const auto neighbor = cell->neighbor(face_index);
147 if (!cell->at_boundary(face_index))
149 number distance_to_neighbor;
150 dealii::Tensor<1, n_components, number> neighbor_cell_average_value;
151 if ((cell->level() == neighbor->level() and neighbor->is_active()) or dim == 1)
154 distance_to_neighbor = cell->center().distance(neighbor->center());
155 neighbor_cell_average_value =
156 cell_average_values[neighbor->active_cell_index()].first;
158 else if (cell->level() == neighbor->level() and !neighbor->is_active())
163 cell->reference_cell().is_hyper_cube() and
164 neighbor->reference_cell().is_hyper_cube(),
166 "The minmod limiter currently only supports 3D hexahedral meshes with isotropic refinement."));
172 distance_to_neighbor =
173 0.5 * cell->extent_in_direction(d) +
174 0.25 * cell->neighbor_child_on_subface(face_index, 0)->extent_in_direction(d);
177 constexpr unsigned int n_subfaces = dealii::Utilities::fixed_power<dim - 1>(2);
178 for (
unsigned int subface = 0; subface < n_subfaces; ++subface)
180 neighbor_cell_average_value +=
181 cell_average_values[cell->neighbor_child_on_subface(face_index, subface)
182 ->active_cell_index()]
185 neighbor_cell_average_value /= n_subfaces;
191 cell->reference_cell().is_hyper_cube() and
192 neighbor->reference_cell().is_hyper_cube(),
194 "The minmod limiter currently only supports 3D hexahedral meshes with isotropic refinement."));
197 auto vec_neighbor_to_cell = cell->center() - neighbor->center();
198 distance_to_neighbor =
199 cell->extent_in_direction(d) * 0.5 + 0.25 * neighbor->extent_in_direction(d);
200 for (
unsigned int c = 0; c < n_components; ++c)
201 neighbor_cell_average_value[c] =
202 cell_average_values[neighbor->active_cell_index()].first[c] +
203 (vec_neighbor_to_cell[d] - 0.5 * cell->extent_in_direction(d) -
204 0.25 * neighbor->extent_in_direction(d)) *
205 cell_average_values[neighbor->active_cell_index()].second[c][d];
210 minmod_input_values.push_back(
211 (cell_average_values[cell->active_cell_index()].first -
212 neighbor_cell_average_value) /
213 distance_to_neighbor);
217 minmod_input_values.push_back(
218 (neighbor_cell_average_value -
219 cell_average_values[cell->active_cell_index()].first) /
220 distance_to_neighbor);
225 switch (limiter_data.
type)
227 case LimiterType::tvd_minmod:
230 dealii::Tensor<1, n_components, number>,
231 boost::container::small_vector<dealii::Tensor<1, n_components, number>, 3>>(
232 minmod_input_values);
234 case LimiterType::tvb_minmod:
238 dealii::Tensor<1, n_components, number>,
239 boost::container::small_vector<dealii::Tensor<1, n_components, number>, 3>>(
240 minmod_input_values, limiter_data.
tvb_constant, cell->extent_in_direction(d));
243 AssertThrow(
false, dealii::ExcMessage(
"Unknown limiter type."));
246 return limited_slopes;
258 const VectorType &src,
264 AssertThrow(mf_context.
mf.get_dof_handler(mf_context.
dof_idx).get_fe().degree == 1,
266 "The minmod type limiter currently only supports linear elements (degree 1)."));
268 const auto cell_average_values =
269 compute_cell_average_quantities<dim, number, n_components>(mf_context, src);
275 const std::function<void(
const dealii::MatrixFree<dim, number, VectorizedArrayType> &,
278 const std::pair<unsigned int, unsigned int> &)>
279 limit_loop = [&](
const dealii::MatrixFree<dim, number, VectorizedArrayType> &matrix_free,
281 const VectorType &src,
282 const std::pair<unsigned int, unsigned int> &cell_range) {
287 dealii::MatrixFreeOperators::CellwiseInverseMassMatrix<dim, -1, n_components, number> inverse(
290 std::vector<VectorizedArrayType> limited_values(
291 n_components * fe_cell_integrator.quadrature_point_indices().size());
293 for (
unsigned int cell = cell_range.first; cell < cell_range.second; ++cell)
295 fe_cell_integrator.reinit(cell);
296 fe_cell_integrator.gather_evaluate(src, dealii::EvaluationFlags::values);
300 dealii::Tensor<1, n_components, dealii::Tensor<1, dim, VectorizedArrayType>>
303 dealii::Point<dim, VectorizedArrayType> cell_centers;
304 for (
unsigned int i = 0; i < mf_context.
mf.n_active_entries_per_cell_batch(cell); ++i)
305 for (
unsigned int d = 0; d < dim; ++d)
306 cell_centers[d][i] = cells[i]->center()[d];
308 dealii::Tensor<1, n_components, VectorizedArrayType> cell_average_values_cell;
309 for (
unsigned int i = 0; i < mf_context.
mf.n_active_entries_per_cell_batch(cell); ++i)
311 for (
unsigned int c = 0; c < n_components; ++c)
312 cell_average_values_cell[c][i] =
313 cell_average_values[cells[i]->active_cell_index()].first[c];
316 for (
const unsigned int q : fe_cell_integrator.quadrature_point_indices())
318 dealii::Tensor<1, dim, VectorizedArrayType> vector_to_dof =
319 fe_cell_integrator.quadrature_point(q) - cell_centers;
328 for (
unsigned int lane = 0;
329 lane < mf_context.
mf.n_active_entries_per_cell_batch(cell);
332 std::array<dealii::Tensor<1, n_components, number>, dim> limited_slope_lane =
333 compute_minmod_type_limited_slopes<dim, n_components, number>(
334 cell_average_values, cells[lane], limiter_data);
336 for (
unsigned int c = 0; c < n_components; ++c)
337 for (
unsigned int d = 0; d < dim; ++d)
338 limited_slopes[c][d][lane] = limited_slope_lane[d][c];
342 for (
unsigned int c = 0; c < n_components; ++c)
343 limited_values[c * fe_cell_integrator.quadrature_point_indices().size() + q] =
344 cell_average_values_cell[c] + limited_slopes[c] * vector_to_dof;
347 inverse.transform_from_q_points_to_basis(n_components,
348 limited_values.data(),
349 fe_cell_integrator.begin_dof_values());
350 fe_cell_integrator.set_dof_values(dst);
354 dst.zero_out_ghost_values();
355 mf_context.
mf.cell_loop(limit_loop, dst, src,
true);
356 dst.update_ghost_values();
std::array< dealii::Tensor< 1, n_components, number >, dim > compute_minmod_type_limited_slopes(const std::vector< std::pair< dealii::Tensor< 1, n_components, number >, dealii::Tensor< 1, n_components, dealii::Tensor< 1, dim, number > > > > &cell_average_values, const typename dealii::Triangulation< dim >::active_cell_iterator &cell, const LimiterData< number > &limiter_data)
Definition limiters.templates.hpp:126
Definition matrix_free_util.hpp:21
unsigned int quad_idx
Definition matrix_free_util.hpp:24
const dealii::MatrixFree< dim, Number > & mf
Definition matrix_free_util.hpp:22
unsigned int dof_idx
Definition matrix_free_util.hpp:23