Finite Volume Solver  prototype
A framework to build finite volume solvers for the AG Klein at the Freie Universität Berlin.
HyperbolicMethod.hpp
Go to the documentation of this file.
1 // Copyright (c) 2019 Maikel Nadolski
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to deal
5 // in the Software without restriction, including without limitation the rights
6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 // copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so, subject to the following conditions:
9 //
10 // The above copyright notice and this permission notice shall be included in
11 // all copies or substantial portions of the Software.
12 //
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 // SOFTWARE.
20 
21 #ifndef FUB_HYPERBOLIC_METHOD_HPP
22 #define FUB_HYPERBOLIC_METHOD_HPP
23 
24 #include "fub/Direction.hpp"
25 #include "fub/Duration.hpp"
26 #include "fub/core/type_traits.hpp"
27 
28 #include <memory>
29 #include <type_traits>
30 
31 namespace fub {
32 
33 /// \defgroup PolymorphicValueType Polymorphic Value Types
34 /// \brief This group summarizes all types which have a polymorphic behaviour.
35 
36 ///////////////////////////////////////////////////////////////////////////////
37 // Strategy Interfaces
38 
39 namespace detail {
40 template <typename IntegratorContext> struct ReconstructionBase {
41  virtual ~ReconstructionBase() = default;
42  virtual std::unique_ptr<ReconstructionBase> Clone() const = 0;
43  virtual void CompleteFromCons(IntegratorContext& context, int level,
44  Duration dt) = 0;
45 };
46 
47 template <typename IntegratorContext> struct TimeIntegratorBase {
48  virtual ~TimeIntegratorBase() = default;
49  virtual std::unique_ptr<TimeIntegratorBase> Clone() const = 0;
50  virtual void UpdateConservatively(IntegratorContext& context, int level,
51  Duration dt, Direction dir) = 0;
52 };
53 
54 template <typename IntegratorContext> struct FluxMethodBase {
55  virtual ~FluxMethodBase() = default;
56  virtual std::unique_ptr<FluxMethodBase> Clone() const = 0;
57  virtual void PreAdvanceHierarchy(IntegratorContext& context) = 0;
58  virtual Duration ComputeStableDt(IntegratorContext& context, int level,
59  Direction dir) = 0;
60  virtual void ComputeNumericFluxes(IntegratorContext& context, int level,
61  Duration dt, Direction dir) = 0;
62  virtual int GetStencilWidth() const = 0;
63 };
64 } // namespace detail
65 
66 ///////////////////////////////////////////////////////////////////////////////
67 // Polymorphic Classes
68 
69 /// \ingroup PolymorphicValueType
70 /// This is a polymorphic wrapper class for reconstruction strategies used by
71 /// \a IntegratorContext.
72 template <typename IntegratorContext> class AnyReconstruction {
73 public:
74  AnyReconstruction() = delete;
75 
78 
79  AnyReconstruction(AnyReconstruction&& other) noexcept = default;
80  AnyReconstruction& operator=(AnyReconstruction&& other) noexcept = default;
81 
82  template <typename R,
83  typename = std::enable_if_t<!decays_to<R, AnyReconstruction>()>>
84  AnyReconstruction(R&& r); // NOLINT
85 
86  void CompleteFromCons(IntegratorContext& context, int level, Duration dt);
87 
88 private:
89  std::unique_ptr<detail::ReconstructionBase<IntegratorContext>> reconstruct_;
90 };
91 
92 /// \ingroup PolymorphicValueType
93 /// This is a polymorphic wrapper class for TimeIntegator strategies used by
94 /// \a IntegratorContext.
95 template <typename IntegratorContext> class AnyTimeIntegrator {
96 public:
97  AnyTimeIntegrator() = delete;
98 
101 
102  AnyTimeIntegrator(AnyTimeIntegrator&& other) noexcept = default;
103  AnyTimeIntegrator& operator=(AnyTimeIntegrator&& other) noexcept = default;
104 
105  template <typename R,
106  typename = std::enable_if_t<!decays_to<R, AnyTimeIntegrator>()>>
107  AnyTimeIntegrator(R&& r); // NOLINT
108 
109  void UpdateConservatively(IntegratorContext& context, int level, Duration dt,
110  Direction dir);
111 
112 private:
113  std::unique_ptr<detail::TimeIntegratorBase<IntegratorContext>> integrator_;
114 };
115 
116 /// \ingroup PolymorphicValueType FluxMethod
117 /// This is a polymorphic wrapper class for FluxMethod strategies used by
118 /// \a IntegratorContext.
119 template <typename IntegratorContext> class AnyFluxMethod {
120 public:
121  AnyFluxMethod() = delete;
122 
123  AnyFluxMethod(const AnyFluxMethod& other);
124  AnyFluxMethod& operator=(const AnyFluxMethod& other);
125 
126  AnyFluxMethod(AnyFluxMethod&& other) noexcept = default;
127  AnyFluxMethod& operator=(AnyFluxMethod&& other) noexcept = default;
128 
129  template <typename R,
130  typename = std::enable_if_t<!decays_to<R, AnyFluxMethod>()>>
131  AnyFluxMethod(R&& r); // NOLINT
132 
133  Duration ComputeStableDt(IntegratorContext& context, int level,
134  Direction dir);
135 
136  void PreAdvanceHierarchy(IntegratorContext& context);
137 
138  void ComputeNumericFluxes(IntegratorContext& context, int level, Duration dt,
139  Direction dir);
140 
141  int GetStencilWidth() const;
142 
143 private:
144  std::unique_ptr<detail::FluxMethodBase<IntegratorContext>> flux_method_;
145 };
146 
147 ///////////////////////////////////////////////////////////////////////////////
148 // Collection of Strategies
149 
150 template <typename IntegratorContext> struct HyperbolicMethod {
154 };
155 
156 ///////////////////////////////////////////////////////////////////////////////
157 // IMPLEMENTATION
158 
159 ///////////////////////////////////////////////////////////////////////////////
160 // Reconstruction
161 
162 template <typename IntegratorContext>
164  const AnyReconstruction& other)
165  : reconstruct_{other.reconstruct_ ? other.reconstruct_->Clone() : nullptr} {
166 }
167 
168 template <typename IntegratorContext>
171  const AnyReconstruction& other) {
172  if (other.reconstruct_) {
173  reconstruct_ = other.reconstruct_->Clone();
174  } else {
175  reconstruct_ = nullptr;
176  }
177  return *this;
178 }
179 
180 template <typename IntegratorContext>
182  IntegratorContext& context, int level, Duration dt) {
183  reconstruct_->CompleteFromCons(context, level, dt);
184 }
185 
186 namespace detail {
187 template <typename IntegratorContext, typename R>
188 struct ReconstructionWrapper : ReconstructionBase<IntegratorContext> {
189  ReconstructionWrapper(const R& rec) : rec_{rec} {}
190  ReconstructionWrapper(R&& rec) : rec_{std::move(rec)} {}
191  std::unique_ptr<ReconstructionBase<IntegratorContext>>
192  Clone() const override {
193  return std::make_unique<ReconstructionWrapper>(rec_);
194  }
195  void CompleteFromCons(IntegratorContext& context, int level,
196  Duration dt) override {
197  rec_.CompleteFromCons(context, level, dt);
198  }
199  R rec_;
200 };
201 } // namespace detail
202 
203 template <typename IntegratorContext>
204 template <typename R, typename>
206  : reconstruct_(
207  std::make_unique<detail::ReconstructionWrapper<IntegratorContext,
208  std::decay_t<R>>>(
209  std::forward<R>(rec))) {}
210 
211 ///////////////////////////////////////////////////////////////////////////////
212 // TimeIntegrator
213 
214 template <typename IntegratorContext>
216  const AnyTimeIntegrator& other)
217  : integrator_{other.integrator_ ? other.integrator_->Clone() : nullptr} {}
218 
219 template <typename IntegratorContext>
222  const AnyTimeIntegrator& other) {
223  if (other.integrator_) {
224  integrator_ = other.integrator_->Clone();
225  } else {
226  integrator_ = nullptr;
227  }
228  return *this;
229 }
230 
231 template <typename IntegratorContext>
233  IntegratorContext& context, int level, Duration dt, Direction dir) {
234  integrator_->UpdateConservatively(context, level, dt, dir);
235 }
236 
237 namespace detail {
238 template <typename IntegratorContext, typename I>
239 struct TimeIntegratorWrapper : TimeIntegratorBase<IntegratorContext> {
240  TimeIntegratorWrapper(const I& integrator) : integrator_{integrator} {}
241  TimeIntegratorWrapper(I&& integrator) : integrator_{std::move(integrator)} {}
242  std::unique_ptr<TimeIntegratorBase<IntegratorContext>>
243  Clone() const override {
244  return std::make_unique<TimeIntegratorWrapper>(integrator_);
245  }
246  void UpdateConservatively(IntegratorContext& context, int level, Duration dt,
247  Direction dir) override {
248  integrator_.UpdateConservatively(context, level, dt, dir);
249  }
250  I integrator_;
251 };
252 } // namespace detail
253 
254 template <typename IntegratorContext>
255 template <typename I, typename>
257  : integrator_(
258  std::make_unique<detail::TimeIntegratorWrapper<IntegratorContext,
259  std::decay_t<I>>>(
260  std::forward<I>(integrator))) {}
261 
262 ///////////////////////////////////////////////////////////////////////////////
263 // FluxMethod
264 
265 template <typename IntegratorContext>
267  : flux_method_{other.flux_method_ ? other.flux_method_->Clone() : nullptr} {
268 }
269 
270 template <typename IntegratorContext>
273  if (other.flux_method_) {
274  flux_method_ = other.flux_method_->Clone();
275  } else {
276  flux_method_ = nullptr;
277  }
278  return *this;
279 }
280 
281 template <typename IntegratorContext>
283  IntegratorContext& context) {
284  flux_method_->PreAdvanceHierarchy(context);
285 }
286 
287 template <typename IntegratorContext>
288 Duration
290  int level, Direction dir) {
291  return flux_method_->ComputeStableDt(context, level, dir);
292 }
293 
294 template <typename IntegratorContext>
296  IntegratorContext& context, int level, Duration dt, Direction dir) {
297  flux_method_->ComputeNumericFluxes(context, level, dt, dir);
298 }
299 
300 template <typename IntegratorContext>
302  return flux_method_->GetStencilWidth();
303 }
304 
305 namespace detail {
306 template <typename I, typename... Args>
307 using PreAdvanceHierarchyT =
308  decltype(std::declval<I>().PreAdvanceHierarchy(std::declval<Args>()...));
309 
310 template <typename IntegratorContext, typename I>
311 struct FluxMethodWrapper : FluxMethodBase<IntegratorContext> {
312  FluxMethodWrapper(const I& flux_method) : flux_method_{flux_method} {}
313  FluxMethodWrapper(I&& flux_method) : flux_method_{std::move(flux_method)} {}
314  std::unique_ptr<FluxMethodBase<IntegratorContext>> Clone() const override {
315  return std::make_unique<FluxMethodWrapper>(flux_method_);
316  }
317  Duration ComputeStableDt(IntegratorContext& context, int level,
318  Direction dir) override {
319  return flux_method_.ComputeStableDt(context, level, dir);
320  }
321  void ComputeNumericFluxes(IntegratorContext& context, int level, Duration dt,
322  Direction dir) override {
323  flux_method_.ComputeNumericFluxes(context, level, dt, dir);
324  }
325  int GetStencilWidth() const override {
326  return flux_method_.GetStencilWidth();
327  }
328  void PreAdvanceHierarchy(IntegratorContext& context) override {
329  if constexpr (is_detected<PreAdvanceHierarchyT, I&,
330  IntegratorContext&>::value) {
331  flux_method_.PreAdvanceHierarchy(context);
332  }
333  }
334  I flux_method_;
335 };
336 } // namespace detail
337 
338 template <typename IntegratorContext>
339 template <typename I, typename>
341  : flux_method_(
342  std::make_unique<
343  detail::FluxMethodWrapper<IntegratorContext, std::decay_t<I>>>(
344  std::forward<I>(flux_method))) {}
345 } // namespace fub
346 #endif
This is a polymorphic wrapper class for FluxMethod strategies used by IntegratorContext.
Definition: HyperbolicMethod.hpp:119
AnyFluxMethod(AnyFluxMethod &&other) noexcept=default
AnyFluxMethod & operator=(AnyFluxMethod &&other) noexcept=default
std::unique_ptr< detail::FluxMethodBase< IntegratorContext > > flux_method_
Definition: HyperbolicMethod.hpp:144
void ComputeNumericFluxes(IntegratorContext &context, int level, Duration dt, Direction dir)
Definition: HyperbolicMethod.hpp:295
int GetStencilWidth() const
Definition: HyperbolicMethod.hpp:301
Duration ComputeStableDt(IntegratorContext &context, int level, Direction dir)
Definition: HyperbolicMethod.hpp:289
AnyFluxMethod & operator=(const AnyFluxMethod &other)
Definition: HyperbolicMethod.hpp:272
void PreAdvanceHierarchy(IntegratorContext &context)
Definition: HyperbolicMethod.hpp:282
AnyFluxMethod()=delete
This is a polymorphic wrapper class for reconstruction strategies used by IntegratorContext.
Definition: HyperbolicMethod.hpp:72
AnyReconstruction(AnyReconstruction &&other) noexcept=default
std::unique_ptr< detail::ReconstructionBase< IntegratorContext > > reconstruct_
Definition: HyperbolicMethod.hpp:89
AnyReconstruction & operator=(AnyReconstruction &&other) noexcept=default
AnyReconstruction & operator=(const AnyReconstruction &other)
Definition: HyperbolicMethod.hpp:170
void CompleteFromCons(IntegratorContext &context, int level, Duration dt)
Definition: HyperbolicMethod.hpp:181
This is a polymorphic wrapper class for TimeIntegator strategies used by IntegratorContext.
Definition: HyperbolicMethod.hpp:95
void UpdateConservatively(IntegratorContext &context, int level, Duration dt, Direction dir)
Definition: HyperbolicMethod.hpp:232
std::unique_ptr< detail::TimeIntegratorBase< IntegratorContext > > integrator_
Definition: HyperbolicMethod.hpp:113
AnyTimeIntegrator & operator=(AnyTimeIntegrator &&other) noexcept=default
AnyTimeIntegrator & operator=(const AnyTimeIntegrator &other)
Definition: HyperbolicMethod.hpp:221
AnyTimeIntegrator(AnyTimeIntegrator &&other) noexcept=default
void CompleteFromCons(Equation &&equation, Complete< std::decay_t< Equation >> &complete, const Conservative< std::decay_t< Equation >> &cons)
Definition: CompleteFromCons.hpp:42
decltype(std::declval< Context >().PreAdvanceHierarchy(std::declval< Args >()...)) PreAdvanceHierarchy
A template typedef to detect the member function.
Definition: Meta.hpp:36
The fub namespace.
Definition: AnyBoundaryCondition.hpp:31
std::chrono::duration< double > Duration
Definition: Duration.hpp:31
Direction
This is a type safe type to denote a dimensional split direction.
Definition: Direction.hpp:30
Definition: HyperbolicMethod.hpp:150
AnyTimeIntegrator< IntegratorContext > time_integrator
Definition: HyperbolicMethod.hpp:152
AnyReconstruction< IntegratorContext > reconstruction
Definition: HyperbolicMethod.hpp:153
AnyFluxMethod< IntegratorContext > flux_method
Definition: HyperbolicMethod.hpp:151
This file adds basic type traits utilities which are not yet implemented in all standard libraries.