Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <array>
7 : #include <unordered_map>
8 : #include <utility>
9 :
10 : #include "Evolution/DiscontinuousGalerkin/Limiters/MinmodHelpers.hpp"
11 : #include "Utilities/Gsl.hpp"
12 : #include "Utilities/TMPL.hpp"
13 :
14 : /// \cond
15 : class DataVector;
16 : template <size_t VolumeDim>
17 : class Direction;
18 : template <size_t Dim, typename T>
19 : class DirectionMap;
20 : template <size_t VolumeDim>
21 : class Element;
22 : template <size_t VolumeDim>
23 : class ElementId;
24 : template <size_t VolumeDim>
25 : class Mesh;
26 :
27 : namespace boost {
28 : template <class T>
29 : struct hash;
30 : } // namespace boost
31 : /// \endcond
32 :
33 1 : namespace Limiters::Tci {
34 :
35 : // Implements the TVB troubled-cell indicator from Cockburn1999.
36 : template <size_t VolumeDim>
37 0 : bool tvb_minmod_indicator(
38 : gsl::not_null<Minmod_detail::BufferWrapper<VolumeDim>*> buffer,
39 : double tvb_constant, const DataVector& u, const Mesh<VolumeDim>& mesh,
40 : const Element<VolumeDim>& element,
41 : const std::array<double, VolumeDim>& element_size,
42 : const DirectionMap<VolumeDim, double>& effective_neighbor_means,
43 : const DirectionMap<VolumeDim, double>& effective_neighbor_sizes);
44 :
45 : // Implements the TVB troubled-cell indicator from Cockburn1999 for several
46 : // tensors. Returns true if any component of any tensor needs limiting.
47 : //
48 : // Expects type `PackagedData` to contain, as in Limiters::Minmod:
49 : // - a variable `means` that is a `TaggedTuple<Tags::Mean<Tags>...>`
50 : // - a variable `element_size` that is a `std::array<double, VolumeDim>`
51 : template <size_t VolumeDim, typename PackagedData, typename... Tags>
52 0 : bool tvb_minmod_indicator(
53 : const double tvb_constant, const typename Tags::type&... tensors,
54 : const Mesh<VolumeDim>& mesh, const Element<VolumeDim>& element,
55 : const std::array<double, VolumeDim>& element_size,
56 : const std::unordered_map<DirectionalId<VolumeDim>, PackagedData,
57 : boost::hash<DirectionalId<VolumeDim>>>&
58 : neighbor_data) {
59 : Minmod_detail::BufferWrapper<VolumeDim> buffer(mesh);
60 : const auto effective_neighbor_sizes =
61 : Minmod_detail::compute_effective_neighbor_sizes(element, neighbor_data);
62 :
63 : // Ideally, as soon as one component is found that needs limiting, then we
64 : // would exit the TCI early with return value `true`. But there is no natural
65 : // way to return early from the pack expansion. So we use this bool to keep
66 : // track of whether a previous component needed limiting... and if so, then
67 : // we simply skip any work.
68 : bool some_component_needs_limiting = false;
69 : const auto wrap_tci_one_tensor = [&](auto tag, const auto tensor) {
70 : if (some_component_needs_limiting) {
71 : // Skip this tensor completely
72 : return '0';
73 : }
74 :
75 : for (size_t tensor_storage_index = 0; tensor_storage_index < tensor.size();
76 : ++tensor_storage_index) {
77 : const auto effective_neighbor_means =
78 : Minmod_detail::compute_effective_neighbor_means<decltype(tag)>(
79 : tensor_storage_index, element, neighbor_data);
80 :
81 : const DataVector& u = tensor[tensor_storage_index];
82 : const bool component_needs_limiting = tvb_minmod_indicator(
83 : make_not_null(&buffer), tvb_constant, u, mesh, element, element_size,
84 : effective_neighbor_means, effective_neighbor_sizes);
85 :
86 : if (component_needs_limiting) {
87 : some_component_needs_limiting = true;
88 : // Skip remaining components of this tensor
89 : return '0';
90 : }
91 : }
92 : return '0';
93 : };
94 : expand_pack(wrap_tci_one_tensor(Tags{}, tensors)...);
95 : return some_component_needs_limiting;
96 : }
97 :
98 : } // namespace Limiters::Tci
|