Loading [MathJax]/extensions/tex2jax.js
Finite Volume Solver  prototype
A framework to build finite volume solvers for the AG Klein at the Freie Universität Berlin.
•All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
SubcycleFineFirstSolver.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_SPLIT_LEVEL_INTEGRATOR_HPP
22 #define FUB_HYPERBOLIC_SPLIT_LEVEL_INTEGRATOR_HPP
23 
24 #include "fub/Direction.hpp"
25 #include "fub/Duration.hpp"
26 #include "fub/Equation.hpp"
27 #include "fub/Execution.hpp"
28 #include "fub/Meta.hpp"
29 #include "fub/TimeStepError.hpp"
30 #include "fub/ext/outcome.hpp"
32 
33 #include <stdexcept>
34 
35 #include <mpi.h>
36 
37 namespace fub {
38 
39 /// \defgroup SubcycleSolver Subcycle Solvers
40 /// \brief This groups contains all classes that control the subcycle behaviour
41 /// of a simulation.
42 
43 /// \ingroup SubcycleSolver
44 ///
45 /// \brief This Level Integrator applies a very general AMR integration scheme
46 /// in context of dimensional splitting.
47 ///
48 /// The time integration is split into multiple intermediate steps where each is
49 /// supposed to do a certain task. The detailed implementation of these tasks
50 /// happens in the integrator context object.
51 template <typename LevelIntegrator>
52 class SubcycleFineFirstSolver : public SolverFacade<LevelIntegrator> {
53 private:
55 
56 public:
57  static constexpr int Rank = LevelIntegrator::Rank;
58 
59  explicit SubcycleFineFirstSolver(LevelIntegrator&& integrator)
60  : Base(std::move(integrator)) {}
61 
62  explicit SubcycleFineFirstSolver(const LevelIntegrator& integrator)
63  : Base(integrator) {}
64 
65  /// Returns the total refinement ratio between specified coarse to fine level
66  /// number.
67  int GetTotalRefineRatio(int fine_level, int coarse_level = 0) const;
68 
69  /// Returns a stable time step size for the coarsest refinement level.
70  ///
71  /// For stability it is advised to multiply some additional CFL number < 1.0.
73 
74  /// Advance a specified patch level and all finer levels by time `dt`.
75  ///
76  /// This method subcycles finer levels.
77  ///
78  /// \param[in] level_num An integer denoting the patch level where 0 is the
79  /// coarsest level.
80  ///
81  /// \param[in] direction The dimensional split direction which will be used to
82  /// advance.
83  ///
84  /// \param[in] dt A stable time step size for the level_num-th patch level.
86  std::pair<int, int> subcycle);
87 
89 };
90 
91 // Implementation
92 
93 template <typename LevelIntegrator>
95  int fine_level, int coarse_level) const {
96  int refine_ratio = 1;
97  for (int level = fine_level; level > coarse_level; --level) {
98  refine_ratio *= Base::GetRatioToCoarserLevel(level).max();
99  }
100  return refine_ratio;
101 }
102 
103 template <typename LevelIntegrator>
105  Duration min_dt(std::numeric_limits<double>::max());
106  for (int level_num = 0; Base::LevelExists(level_num); ++level_num) {
107  int ratio = GetTotalRefineRatio(level_num);
108  min_dt = std::min(min_dt, ratio * Base::ComputeStableDt(level_num));
109  }
110  MPI_Comm comm = Base::GetMpiCommunicator();
111  const double local_dt = min_dt.count();
112  double global_min_dt{0};
113  MPI_Allreduce(&local_dt, &global_min_dt, 1, MPI_DOUBLE, MPI_MIN, comm);
114  return Duration(global_min_dt);
115 }
116 
117 template <typename LevelIntegrator>
120  int this_level, Duration dt, std::pair<int, int> subcycle) {
121  // PreAdvanceLevel might regrid all finer levels.
122  // The Context must make sure that scratch data is allocated
123  Base::PreAdvanceLevel(this_level, dt, subcycle);
124 
125  auto scale_dt_on_error = [this](Result<void, TimeStepTooLarge> result) {
126  TimeStepTooLarge error = result.error();
127  int ratio = GetTotalRefineRatio(error.level);
128  error.level = 0;
129  error.dt *= ratio;
130  return error;
131  };
132 
133  // If a finer level exists in the hierarchy, we subcycle that finer level
134  // multiple times and use the fine fluxes on coarse-fine interfaces
135  const int next_level = this_level + 1;
136  if (Base::LevelExists(next_level)) {
137  Base::ResetCoarseFineFluxes(next_level, this_level);
138  const int refine_ratio = Base::GetRatioToCoarserLevel(next_level).max();
139  for (int r = 0; r < refine_ratio; ++r) {
140  auto result =
141  AdvanceLevel(next_level, dt / refine_ratio, {r, refine_ratio});
142  if (!result) {
143  return scale_dt_on_error(result);
144  }
145  }
146  }
147 
149  Base::AdvanceLevelNonRecursively(this_level, dt, subcycle);
150  if (!result) {
151  return scale_dt_on_error(result);
152  }
153  if (Base::LevelExists(next_level)) {
154  Base::ApplyFluxCorrection(next_level, this_level, dt);
155  }
156 
157  // Coarsen inner regions from next finer level to this level.
158  if (Base::LevelExists(next_level)) {
159  Base::CoarsenConservatively(next_level, this_level);
160 
161  // The conservative update and the coarsening happened on conservative
162  // variables. We have to reconstruct the missing variables in the complete
163  // state.
164  Base::CompleteFromCons(this_level, dt);
165  }
166 
167  Base::CopyScratchToData(this_level);
168 
169  // Apply any further context related work after advancing this level.
170  // This function can also indicate if some error occured.
171  // For example the context could detect unphysical states and return a
172  // TooLargeTimeStep error condition.
173  result = Base::PostAdvanceLevel(this_level, dt, subcycle);
174  if (!result) {
175  return scale_dt_on_error(result);
176  }
177  return result;
178 }
179 
180 template <typename LevelIntegrator>
183  return AdvanceLevel(0, dt, {0, 1});
184 }
185 
186 } // namespace fub
187 
188 #endif
Definition: SolverFacade.hpp:29
This Level Integrator applies a very general AMR integration scheme in context of dimensional splitti...
Definition: SubcycleFineFirstSolver.hpp:52
int GetTotalRefineRatio(int fine_level, int coarse_level=0) const
Returns the total refinement ratio between specified coarse to fine level number.
Definition: SubcycleFineFirstSolver.hpp:94
SubcycleFineFirstSolver(const LevelIntegrator &integrator)
Definition: SubcycleFineFirstSolver.hpp:62
SubcycleFineFirstSolver(LevelIntegrator &&integrator)
Definition: SubcycleFineFirstSolver.hpp:59
Result< void, TimeStepTooLarge > AdvanceHierarchy(Duration dt)
Definition: SubcycleFineFirstSolver.hpp:182
Result< void, TimeStepTooLarge > AdvanceLevel(int level_number, Duration dt, std::pair< int, int > subcycle)
Advance a specified patch level and all finer levels by time dt.
Definition: SubcycleFineFirstSolver.hpp:119
Duration ComputeStableDt()
Returns a stable time step size for the coarsest refinement level.
Definition: SubcycleFineFirstSolver.hpp:104
static constexpr int Rank
Definition: SubcycleFineFirstSolver.hpp:57
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 >().PreAdvanceLevel(std::declval< Args >()...)) PreAdvanceLevel
A template typedef to detect the member function.
Definition: Meta.hpp:44
decltype(std::declval< Context >().PostAdvanceLevel(std::declval< Args >()...)) PostAdvanceLevel
A template typedef to detect the member function.
Definition: Meta.hpp:48
The fub namespace.
Definition: AnyBoundaryCondition.hpp:31
std::chrono::duration< double > Duration
Definition: Duration.hpp:31
boost::outcome_v2::result< T, E > Result
Definition: outcome.hpp:32
Definition: TimeStepError.hpp:71
Duration dt
Definition: TimeStepError.hpp:72
int level
Definition: TimeStepError.hpp:73