Finite Volume Solver  prototype
A framework to build finite volume solvers for the AG Klein at the Freie Universität Berlin.
AMReX/FluxMethodAdapter.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_AMREX_FLUX_METHOD_HPP
22 #define FUB_AMREX_FLUX_METHOD_HPP
23 
24 #include "fub/AMReX/ForEachFab.hpp"
27 
28 #include "fub/Execution.hpp"
29 #include "fub/State.hpp"
30 
31 #include <AMReX_MultiFab.H>
32 
33 namespace fub::amrex {
34 
35 /// \ingroup FluxMethod
36 template <typename Tag, typename FM> struct FluxMethodAdapter {
37  using Equation = std::decay_t<decltype(std::declval<FM&>().GetEquation())>;
38  static const int Rank = Equation::Rank();
39 
40  FluxMethodAdapter(const FM& fm) : FluxMethodAdapter(Tag(), fm) {}
41  FluxMethodAdapter(Tag, const FM& fm);
42 
43  Duration ComputeStableDt(IntegratorContext& context, int level,
44  Direction dir);
45 
46  void ComputeNumericFluxes(IntegratorContext& context, int level, Duration dt,
47  Direction dir);
48 
49  int GetStencilWidth() const;
50 
52 };
53 
54 template <typename FM>
55 FluxMethodAdapter(const FM& fm)
56  ->FluxMethodAdapter<execution::OpenMpSimdTag, FM>;
57 
58 template <typename Tag, typename FM>
59 FluxMethodAdapter(Tag, const FM& fm)->FluxMethodAdapter<Tag, FM>;
60 
61 template <typename Tag, typename FM>
63  : flux_method_{fm} {}
64 
65 template <typename T, typename... Args>
67  decltype(std::declval<T>().ComputeStableDt(std::declval<Args>()...));
68 
69 template <typename Tag, typename FM>
71  int level, Direction dir) {
72  if constexpr (is_detected<ComputeStableDt_t, FM&, IntegratorContext&, int,
73  Direction>::value) {
74  return flux_method_->ComputeStableDt(context, level, dir);
75  } else {
76  const ::amrex::Geometry& geom = context.GetGeometry(level);
77  const double dx = geom.CellSize(int(dir));
78  double min_dt = std::numeric_limits<double>::max();
79  const ::amrex::MultiFab& scratch = context.GetScratch(level);
80  FUB_ASSERT(!scratch.contains_nan());
81  if constexpr (std::is_base_of<execution::OpenMpTag, Tag>::value) {
82 #if defined(_OPENMP) && defined(AMREX_USE_OMP)
83 #pragma omp parallel reduction(min : min_dt)
84 #endif
85  for (::amrex::MFIter mfi(scratch,
86  ::amrex::IntVect(AMREX_D_DECL(1024000, 8, 8)));
87  mfi.isValid(); ++mfi) {
88  const ::amrex::Box cell_box = mfi.growntilebox();
89  auto&& equation = flux_method_->GetEquation();
91  MakeView<const Complete<Equation>>(scratch[mfi], equation,
92  cell_box);
93  const Duration dt(
94  flux_method_->ComputeStableDt(Tag(), states, dx, dir));
95  min_dt = std::min(min_dt, dt.count());
96  }
97  double local_count = min_dt;
98  return Duration(local_count);
99  } else {
100  for (::amrex::MFIter mfi(scratch); mfi.isValid(); ++mfi) {
101  const ::amrex::Box cell_box = mfi.growntilebox();
102  auto&& equation = flux_method_->GetEquation();
104  MakeView<const Complete<Equation>>(scratch[mfi], equation,
105  cell_box);
106  const Duration dt(
107  flux_method_->ComputeStableDt(Tag(), states, dx, dir));
108  min_dt = std::min(min_dt, dt.count());
109  }
110  double local_count = min_dt;
111  return Duration(local_count);
112  }
113  }
114 }
115 
116 template <typename T, typename... Args>
118  decltype(std::declval<T>().ComputeNumericFluxes(std::declval<Args>()...));
119 
120 template <typename Tag, typename FM>
122  IntegratorContext& context, int level, Duration dt, Direction dir) {
124  int, Duration, Direction>::value) {
125  flux_method_->ComputeNumericFluxes(context, level, dt, dir);
126  } else {
127  const ::amrex::Geometry& geom = context.GetGeometry(level);
128  ::amrex::MultiFab& fluxes = context.GetFluxes(level, dir);
129  const ::amrex::MultiFab& scratch = context.GetScratch(level);
130  const int dir_v = int(dir);
131  const double dx = geom.CellSize(dir_v);
132  FUB_ASSERT(!scratch.contains_nan());
133  const int stencil = GetStencilWidth();
134  ForEachFab(Tag(), fluxes, [&](::amrex::MFIter& mfi) {
135  // Get a view of all complete state variables
136  const ::amrex::Box face_tilebox = mfi.growntilebox();
137  const ::amrex::Box cell_validbox = scratch[mfi].box();
138  const auto [cell_box, face_box] = GetCellsAndFacesInStencilRange(
139  cell_validbox, face_tilebox, stencil, dir);
140  auto&& equation = flux_method_->GetEquation();
142  MakeView<const Complete<Equation>>(scratch[mfi], equation, cell_box);
144  MakeView<Conservative<Equation>>(fluxes[mfi], equation, face_box);
145  // Pass views to implementation
146  flux_method_->ComputeNumericFluxes(Tag(), flux, states, dt, dx, dir);
147  });
148  FUB_ASSERT(!fluxes.contains_nan());
149  }
150 }
151 
152 template <typename Tag, typename FM>
154  return flux_method_->GetStencilWidth();
155 }
156 
157 } // namespace fub::amrex
158 
159 #endif
#define FUB_ASSERT(x)
Definition: assert.hpp:39
This class is used by the HypebrolicSplitLevelIntegrator and delegates AMR related tasks to the AMReX...
Definition: AMReX/IntegratorContext.hpp:49
::amrex::MultiFab & GetScratch(int level)
Returns the MultiFab associated with level data with ghost cells on the specifed level number and dir...
::amrex::MultiFab & GetFluxes(int level, Direction dir)
Returns the MultiFab associated with flux data on the specifed level number and direction.
const ::amrex::Geometry & GetGeometry(int level) const
Returns the geometry object for the specified refinement level.
void ForEachFab(Tag, const ::amrex::FabArrayBase &fabarray, F function)
Iterate through all local FArrayBox objects in a MultiFab.
Definition: ForEachFab.hpp:34
The amrex namespace.
Definition: AverageState.hpp:33
FluxMethodAdapter(const FM &fm) -> FluxMethodAdapter< execution::OpenMpSimdTag, FM >
std::array<::amrex::Box, 2 > GetCellsAndFacesInStencilRange(const ::amrex::Box &cell_tilebox, const ::amrex::Box &face_validbox, int stencil_width, Direction dir)
decltype(std::declval< T >().ComputeStableDt(std::declval< Args >()...)) ComputeStableDt_t
Definition: AMReX/FluxMethodAdapter.hpp:67
decltype(std::declval< T >().ComputeNumericFluxes(std::declval< Args >()...)) ComputeNumericFluxes_t
Definition: AMReX/FluxMethodAdapter.hpp:118
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
IndexBox< Rank > Box(const BasicView< State, Layout, Rank > &view)
Definition: State.hpp:486
typename detail::LocalType< Tag, T >::type Local
Definition: Execution.hpp:56
Definition: State.hpp:403
Definition: AMReX/FluxMethodAdapter.hpp:36
Local< Tag, FM > flux_method_
Definition: AMReX/FluxMethodAdapter.hpp:51
int GetStencilWidth() const
Definition: AMReX/FluxMethodAdapter.hpp:153
Duration ComputeStableDt(IntegratorContext &context, int level, Direction dir)
Definition: AMReX/FluxMethodAdapter.hpp:70
FluxMethodAdapter(const FM &fm)
Definition: AMReX/FluxMethodAdapter.hpp:40
void ComputeNumericFluxes(IntegratorContext &context, int level, Duration dt, Direction dir)
Definition: AMReX/FluxMethodAdapter.hpp:121
static const int Rank
Definition: AMReX/FluxMethodAdapter.hpp:38
std::decay_t< decltype(std::declval< FM & >().GetEquation())> Equation
Definition: AMReX/FluxMethodAdapter.hpp:37
Definition: Execution.hpp:39
This is std::true_type if Op<Args...> is a valid SFINAE expression.
Definition: type_traits.hpp:92