Finite Volume Solver  prototype
A framework to build finite volume solvers for the AG Klein at the Freie Universität Berlin.
boundary_condition/IsentropicPressureExpansion.hpp
Go to the documentation of this file.
1 // Copyright (c) 2020 Maikel Nadolski
2 // Copyright (c) 2020 Christian Zenker
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a copy
5 // of this software and associated documentation files (the "Software"), to deal
6 // in the Software without restriction, including without limitation the rights
7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 // copies of the Software, and to permit persons to whom the Software is
9 // furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 // SOFTWARE.
21 
22 #ifndef FUB_AMREX_BOUNDARY_CONDITION_ISENTROPIC_PRESSURE_EXPANSION_HPP
23 #define FUB_AMREX_BOUNDARY_CONDITION_ISENTROPIC_PRESSURE_EXPANSION_HPP
24 
27 
28 namespace fub::amrex {
29 
30 inline std::array<std::ptrdiff_t, 1>
31 MapToSrc(const std::array<std::ptrdiff_t, 1>& dest,
32  const ::amrex::Geometry& geom, int side, Direction dir) {
33  const int boundary = (side == 0) * geom.Domain().smallEnd(int(dir)) +
34  (side == 1) * geom.Domain().bigEnd(int(dir));
35  const auto distance = dest[std::size_t(dir)] - boundary;
36  const int sign = int((distance > 0) - (distance < 0));
37  std::array<std::ptrdiff_t, 1> src{dest};
38  src[std::size_t(dir)] -= static_cast<int>(2 * distance - sign);
39  // src[std::size_t(dir)] = boundary;
40  return src;
41 }
42 
43 /// \ingroup BoundaryCondition
44 ///
45 /// \brief This boundary models an isentropic pressure expansion for the
46 /// one-dimensional ideal gas equations for mixtures.
47 template <typename EulerEquation> class IsentropicPressureExpansion {
48 public:
49  IsentropicPressureExpansion(const EulerEquation& eq,
50  const IsentropicPressureBoundaryOptions& options);
51 
52  IsentropicPressureExpansion(const EulerEquation& eq, double outer_pressure,
53  Direction dir, int side);
54 
55  void FillBoundary(::amrex::MultiFab& mf, const GriddingAlgorithm& gridding,
56  int level);
57 
58  void FillBoundary(::amrex::MultiFab& mf, const GriddingAlgorithm& gridding,
59  int level, Direction dir);
60 
61  void FillBoundary(::amrex::MultiFab& mf, const ::amrex::Geometry& geom);
62 
63 private:
64  EulerEquation equation_;
67  int side_;
68 };
69 
70 template <typename EulerEquation>
71 void ExpandState(EulerEquation& eq, Complete<EulerEquation>& dest,
72  const Complete<EulerEquation>& src, double pressure_dest,
73  double efficiency) {
74  const auto old_velocity = euler::Velocity(eq, src);
75  const double rhoE_kin = euler::KineticEnergy(src.density, src.momentum);
76  static constexpr int N = EulerEquation::Rank();
77  dest = src;
78  dest.momentum = Array<double, N, 1>::Zero();
79  dest.energy = src.energy - rhoE_kin;
80  const double h_before = (dest.energy + dest.pressure) / dest.density;
81  euler::SetIsentropicPressure(eq, dest, dest, pressure_dest);
82  const double h_after = (dest.energy + dest.pressure) / dest.density;
83  const double h_diff = h_after - h_before;
84  const double e_kin_new =
85  2.0 * (1.0 - efficiency) * h_diff + old_velocity.matrix().squaredNorm();
86  FUB_ASSERT(e_kin_new >= 0);
87  const Array<double, N, 1> u_border =
88  std::sqrt(e_kin_new) * old_velocity.matrix().normalized();
89  dest.momentum = dest.density * u_border;
90  dest.energy = dest.energy + euler::KineticEnergy(dest.density, dest.momentum);
91 }
92 
93 template <typename EulerEquation>
95  const EulerEquation& eq, const IsentropicPressureBoundaryOptions& options)
96  : equation_{eq}, outer_pressure_{options.outer_pressure},
97  dir_{options.direction}, side_{options.side} {}
98 
99 template <typename EulerEquation>
101  const EulerEquation& eq, double outer_pressure, Direction dir, int side)
102  : equation_{eq}, outer_pressure_{outer_pressure}, dir_{dir}, side_{side} {}
103 
104 template <typename EulerEquation>
106  ::amrex::MultiFab& mf, const GriddingAlgorithm& gridding, int level) {
107  FillBoundary(mf, gridding.GetPatchHierarchy().GetGeometry(level));
108 }
109 
110 template <typename EulerEquation>
112  ::amrex::MultiFab& mf, const GriddingAlgorithm& gridding, int level,
113  Direction dir) {
114  if (dir == dir_) {
115  FillBoundary(mf, gridding, level);
116  }
117 }
118 
119 template <typename EulerEquation>
121  ::amrex::MultiFab& mf, const ::amrex::Geometry& geom) {
122  const int ngrow = mf.nGrow(int(dir_));
123  ::amrex::Box grown_box = geom.growNonPeriodicDomain(ngrow);
124  ::amrex::BoxList boundaries =
125  ::amrex::complementIn(grown_box, ::amrex::BoxList{geom.Domain()});
126  Complete<EulerEquation> state{equation_};
127  Complete<EulerEquation> expanded{equation_};
128  if (boundaries.isEmpty()) {
129  return;
130  }
131  ForEachFab(execution::seq, mf, [&](const ::amrex::MFIter& mfi) {
132  ::amrex::FArrayBox& fab = mf[mfi];
133  for (const ::amrex::Box& boundary : boundaries) {
134  ::amrex::Box shifted =
135  ::amrex::shift(boundary, int(dir_), GetSign(side_) * ngrow);
136  if (!geom.Domain().intersects(shifted)) {
137  continue;
138  }
139  ::amrex::Box box_to_fill = mfi.growntilebox() & boundary;
140  if (!box_to_fill.isEmpty()) {
141  auto states = MakeView<Complete<EulerEquation>>(fab, equation_,
142  mfi.growntilebox());
143  ForEachIndex(AsIndexBox<EulerEquation::Rank()>(box_to_fill),
144  [&](auto... is) {
145  Index<EulerEquation::Rank()> dest{is...};
146  Index<EulerEquation::Rank()> src =
147  MapToSrc(dest, geom, side_, dir_);
148  Load(state, states, src);
149  ExpandState(equation_, expanded, state, outer_pressure_, 1.0);
150  Store(states, expanded, dest);
151  });
152  }
153  }
154  });
155 }
156 
157 } // namespace fub::amrex
158 
159 #endif
#define FUB_ASSERT(x)
Definition: assert.hpp:39
This class modifies and initializes a PatchLevel in a PatchHierarchy.
Definition: AMReX/GriddingAlgorithm.hpp:60
PatchHierarchy & GetPatchHierarchy() noexcept
Definition: AMReX/GriddingAlgorithm.hpp:108
This boundary models an isentropic pressure expansion for the one-dimensional ideal gas equations for...
Definition: boundary_condition/IsentropicPressureExpansion.hpp:47
void FillBoundary(::amrex::MultiFab &mf, const GriddingAlgorithm &gridding, int level)
Definition: boundary_condition/IsentropicPressureExpansion.hpp:105
int side_
Definition: boundary_condition/IsentropicPressureExpansion.hpp:67
IsentropicPressureExpansion(const EulerEquation &eq, const IsentropicPressureBoundaryOptions &options)
Definition: boundary_condition/IsentropicPressureExpansion.hpp:94
Direction dir_
Definition: boundary_condition/IsentropicPressureExpansion.hpp:66
double outer_pressure_
Definition: boundary_condition/IsentropicPressureExpansion.hpp:65
EulerEquation equation_
Definition: boundary_condition/IsentropicPressureExpansion.hpp:64
const ::amrex::Geometry & GetGeometry(int level) const
Returns a Geometry object for a specified 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
void ExpandState(EulerEquation &eq, Complete< EulerEquation > &dest, const Complete< EulerEquation > &src, double pressure_dest, double efficiency)
Definition: boundary_condition/IsentropicPressureExpansion.hpp:71
void ForEachIndex(const ::amrex::Box &box, F function)
Definition: ForEachIndex.hpp:29
IndexBox< Rank > AsIndexBox(const ::amrex::Box &box)
Definition: ViewFArrayBox.hpp:51
std::array< std::ptrdiff_t, 1 > MapToSrc(const std::array< std::ptrdiff_t, 1 > &dest, const ::amrex::Geometry &geom, int side, Direction dir)
Definition: boundary_condition/IsentropicPressureExpansion.hpp:31
double KineticEnergy(double density, const Eigen::Array< double, Dim, 1 > &momentum) noexcept
Definition: EulerEquation.hpp:28
constexpr struct fub::euler::SetIsentropicPressureFn SetIsentropicPressure
constexpr struct fub::euler::VelocityFn Velocity
constexpr SequentialTag seq
Definition: Execution.hpp:31
std::conditional_t< N==1||M==1, Eigen::Array< T, N, M >, Eigen::Array< T, N, M, Eigen::RowMajor > > Array
Definition: Eigen.hpp:50
void Load(State &state, const BasicView< const State, Layout, Rank > &view, const std::array< std::ptrdiff_t, State::Equation::Rank()> &index)
Definition: State.hpp:640
int GetSign(int side)
Definition: AnyBoundaryCondition.hpp:104
Direction
This is a type safe type to denote a dimensional split direction.
Definition: Direction.hpp:30
std::array< std::ptrdiff_t, static_cast< std::size_t >(Rank)> Index
Definition: PatchDataView.hpp:34
void Store(const BasicView< Conservative< Eq >, Layout, Eq::Rank()> &view, const Conservative< Eq > &state, const std::array< std::ptrdiff_t, Eq::Rank()> &index)
Definition: State.hpp:663
IndexBox< Rank > Box(const BasicView< State, Layout, Rank > &view)
Definition: State.hpp:486
Definition: boundary_condition/IsentropicPressureBoundary.hpp:38