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 <cstdlib>
8 : #include <unordered_map>
9 : #include <utility>
10 :
11 : #include "DataStructures/Tags.hpp"
12 : #include "DataStructures/Tensor/Tensor.hpp"
13 : #include "Domain/Tags.hpp"
14 : #include "Evolution/DiscontinuousGalerkin/Limiters/Minmod.hpp"
15 : #include "Evolution/DiscontinuousGalerkin/Limiters/MinmodType.hpp"
16 : #include "Evolution/DiscontinuousGalerkin/Limiters/Tags.hpp"
17 : #include "Evolution/Systems/NewtonianEuler/Limiters/VariablesToLimit.hpp"
18 : #include "Evolution/Systems/NewtonianEuler/Tags.hpp"
19 : #include "Options/String.hpp"
20 : #include "PointwiseFunctions/Hydro/EquationsOfState/EquationOfState.hpp"
21 : #include "PointwiseFunctions/Hydro/TagsDeclarations.hpp"
22 : #include "Utilities/Gsl.hpp"
23 : #include "Utilities/TMPL.hpp"
24 :
25 : /// \cond
26 : class DataVector;
27 : template <size_t VolumeDim>
28 : class Direction;
29 : template <size_t VolumeDim>
30 : class Element;
31 : template <size_t VolumeDim>
32 : class ElementId;
33 : template <size_t VolumeDim>
34 : class Mesh;
35 : template <size_t VolumeDim>
36 : class OrientationMap;
37 :
38 : namespace boost {
39 : template <class T>
40 : struct hash;
41 : } // namespace boost
42 :
43 : namespace PUP {
44 : class er;
45 : } // namespace PUP
46 :
47 : namespace domain {
48 : namespace Tags {
49 : template <size_t Dim, typename Frame>
50 : struct Coordinates;
51 : template <size_t VolumeDim>
52 : struct Element;
53 : template <size_t VolumeDim>
54 : struct Mesh;
55 : template <size_t VolumeDim>
56 : struct SizeOfElement;
57 : } // namespace Tags
58 : } // namespace domain
59 : /// \endcond
60 :
61 : namespace NewtonianEuler {
62 : namespace Limiters {
63 :
64 : /// \ingroup LimitersGroup
65 : /// \brief A minmod-based generalized slope limiter for the NewtonianEuler
66 : /// system.
67 : ///
68 : /// Implements the three minmod-based generalized slope limiters from
69 : /// \cite Cockburn1999 Sec. 2.4: \f$\Lambda\Pi^1\f$, \f$\Lambda\Pi^N\f$, and
70 : /// MUSCL. See the documentation of the system-agnostic ::Limiters::Minmod
71 : /// limiter for a general discussion of the algorithm and the various options
72 : /// that control the action of the limiter.
73 : ///
74 : /// This implemention is specialized to the NewtonianEuler evolution system.
75 : /// By specializing the limiter to the system, we can add two features that
76 : /// improve its robustness:
77 : /// - the limiter can be applied to the system's characteristic variables. This
78 : /// is the recommendation of the reference, because it reduces spurious
79 : /// oscillations in the post-limiter solution.
80 : /// - after limiting, the solution can be processed to remove any remaining
81 : /// unphysical values like negative densities and pressures. We do this by
82 : /// scaling the solution around its mean (a "flattener" or "bounds-preserving"
83 : /// filter). Note: the flattener is applied to all elements, including those
84 : /// where the limiter did not act to reduce the solution's slopes.
85 : template <size_t VolumeDim>
86 1 : class Minmod {
87 : public:
88 0 : using ConservativeVarsMinmod = ::Limiters::Minmod<
89 : VolumeDim, tmpl::list<NewtonianEuler::Tags::MassDensityCons,
90 : NewtonianEuler::Tags::MomentumDensity<VolumeDim>,
91 : NewtonianEuler::Tags::EnergyDensity>>;
92 :
93 0 : struct VariablesToLimit {
94 0 : using type = NewtonianEuler::Limiters::VariablesToLimit;
95 0 : static type suggested_value() {
96 : return NewtonianEuler::Limiters::VariablesToLimit::Characteristic;
97 : }
98 0 : static constexpr Options::String help = {
99 : "Variable representation on which to apply the limiter"};
100 : };
101 0 : struct ApplyFlattener {
102 0 : using type = bool;
103 0 : static constexpr Options::String help = {
104 : "Flatten after limiting to restore pointwise positivity"};
105 : };
106 0 : using options =
107 : tmpl::list<typename ConservativeVarsMinmod::Type, VariablesToLimit,
108 : typename ConservativeVarsMinmod::TvbConstant, ApplyFlattener,
109 : typename ConservativeVarsMinmod::DisableForDebugging>;
110 0 : static constexpr Options::String help = {
111 : "A Minmod limiter specialized to the NewtonianEuler system"};
112 0 : static std::string name() { return "NewtonianEulerMinmod"; };
113 :
114 0 : explicit Minmod(::Limiters::MinmodType minmod_type,
115 : NewtonianEuler::Limiters::VariablesToLimit vars_to_limit,
116 : double tvb_constant, bool apply_flattener,
117 : bool disable_for_debugging = false);
118 :
119 0 : Minmod() = default;
120 0 : Minmod(const Minmod& /*rhs*/) = default;
121 0 : Minmod& operator=(const Minmod& /*rhs*/) = default;
122 0 : Minmod(Minmod&& /*rhs*/) = default;
123 0 : Minmod& operator=(Minmod&& /*rhs*/) = default;
124 0 : ~Minmod() = default;
125 :
126 : // NOLINTNEXTLINE(google-runtime-references)
127 0 : void pup(PUP::er& p);
128 :
129 0 : using PackagedData = typename ConservativeVarsMinmod::PackagedData;
130 0 : using package_argument_tags =
131 : typename ConservativeVarsMinmod::package_argument_tags;
132 :
133 : /// \brief Package data for sending to neighbor elements.
134 1 : void package_data(gsl::not_null<PackagedData*> packaged_data,
135 : const Scalar<DataVector>& mass_density_cons,
136 : const tnsr::I<DataVector, VolumeDim>& momentum_density,
137 : const Scalar<DataVector>& energy_density,
138 : const Mesh<VolumeDim>& mesh,
139 : const std::array<double, VolumeDim>& element_size,
140 : const OrientationMap<VolumeDim>& orientation_map) const;
141 :
142 0 : using limit_tags =
143 : tmpl::list<NewtonianEuler::Tags::MassDensityCons,
144 : NewtonianEuler::Tags::MomentumDensity<VolumeDim>,
145 : NewtonianEuler::Tags::EnergyDensity>;
146 0 : using limit_argument_tags = tmpl::list<
147 : domain::Tags::Mesh<VolumeDim>, domain::Tags::Element<VolumeDim>,
148 : domain::Tags::Coordinates<VolumeDim, Frame::ElementLogical>,
149 : domain::Tags::SizeOfElement<VolumeDim>,
150 : domain::Tags::DetInvJacobian<Frame::ElementLogical, Frame::Inertial>,
151 : ::hydro::Tags::EquationOfState<false, 2>>;
152 :
153 : /// \brief Limits the solution on the element.
154 1 : bool operator()(
155 : gsl::not_null<Scalar<DataVector>*> mass_density_cons,
156 : gsl::not_null<tnsr::I<DataVector, VolumeDim>*> momentum_density,
157 : gsl::not_null<Scalar<DataVector>*> energy_density,
158 : const Mesh<VolumeDim>& mesh, const Element<VolumeDim>& element,
159 : const tnsr::I<DataVector, VolumeDim, Frame::ElementLogical>&
160 : logical_coords,
161 : const std::array<double, VolumeDim>& element_size,
162 : const Scalar<DataVector>& det_inv_logical_to_inertial_jacobian,
163 : const EquationsOfState::EquationOfState<false, 2>& equation_of_state,
164 : const std::unordered_map<DirectionalId<VolumeDim>, PackagedData,
165 : boost::hash<DirectionalId<VolumeDim>>>&
166 : neighbor_data) const;
167 :
168 : private:
169 : template <size_t LocalDim>
170 : // NOLINTNEXTLINE(readability-redundant-declaration) false positive
171 0 : friend bool operator==(const Minmod<LocalDim>& lhs,
172 : const Minmod<LocalDim>& rhs);
173 :
174 0 : ::Limiters::MinmodType minmod_type_;
175 0 : NewtonianEuler::Limiters::VariablesToLimit vars_to_limit_;
176 0 : double tvb_constant_;
177 0 : bool apply_flattener_;
178 0 : bool disable_for_debugging_;
179 0 : ConservativeVarsMinmod conservative_vars_minmod_;
180 : };
181 :
182 : template <size_t VolumeDim>
183 0 : bool operator!=(const Minmod<VolumeDim>& lhs, const Minmod<VolumeDim>& rhs);
184 :
185 : } // namespace Limiters
186 : } // namespace NewtonianEuler
|