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