Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <algorithm>
7 :
8 : #include "DataStructures/Variables.hpp"
9 : #include "Utilities/ErrorHandling/Assert.hpp"
10 : #include "Utilities/TMPL.hpp"
11 :
12 : namespace evolution::dg::subcell {
13 : /*!
14 : * \brief Troubled cell indicator using a relaxed discrete maximum principle,
15 : * comparing the solution on two grids at the same point in time.
16 : *
17 : * Checks that the subcell solution \f$\underline{u}\f$ and the DG solution
18 : * \f$u\f$ satisfy
19 : *
20 : * \f{align*}{ \min(u)-\delta \le \underline{u} \le \max(u)+\delta \f}
21 : *
22 : * where
23 : *
24 : * \f{align*}{ \delta = \max\left[\delta_0, \epsilon(\max(u) - \min(u))\right]
25 : * \f}
26 : *
27 : * where \f$\delta_0\f$ and \f$\epsilon\f$ are constants controlling the maximum
28 : * absolute and relative change allowed when projecting the DG solution to the
29 : * subcell grid. We currently specify one value of \f$\delta_0\f$ and
30 : * \f$\epsilon\f$ for all variables, but this could be generalized to choosing
31 : * the allowed variation in a variable-specific manner.
32 : *
33 : * If all checks are passed and cell is not troubled, returns an integer `0`.
34 : * Otherwise returns 1-based index of the tag in the input Variables that fails
35 : * the check. For instance, if we have
36 : *
37 : * - `Variables<tmpl::list<DgVar1, DgVar2, DgVar3>>` for `dg_evolved_vars`
38 : * - `Variables<tmpl::list<SubVar1, SubVar2, SubVar3>>` for
39 : * `subcell_evolved_vars`
40 : *
41 : * as inputs and TCI flags the second pair `DgVar2` and `SubVar2` not satisfying
42 : * two-mesh RDMP criteria, returned value is `2` since the second pair of tags
43 : * failed the check.
44 : *
45 : * \note Once a single pair of tags fails to satisfy the check, checks for the
46 : * remaining part of the input variables are skipped. In the example above, for
47 : * instance if the second pair (`DgVar2`,`SubVar2`) is flagged, the third pair
48 : * (`DgVar3`,`SubVar3`) is ignored and not checked.
49 : *
50 : */
51 : template <typename... DgEvolvedVarsTags, typename... SubcellEvolvedVarsTags>
52 1 : int two_mesh_rdmp_tci(
53 : const Variables<tmpl::list<DgEvolvedVarsTags...>>& dg_evolved_vars,
54 : const Variables<tmpl::list<SubcellEvolvedVarsTags...>>&
55 : subcell_evolved_vars,
56 : const double rdmp_delta0, const double rdmp_epsilon) {
57 : static_assert(sizeof...(DgEvolvedVarsTags) ==
58 : sizeof...(SubcellEvolvedVarsTags));
59 : ASSERT(rdmp_delta0 > 0.0, "The RDMP delta0 parameter must be positive.");
60 : ASSERT(rdmp_epsilon > 0.0, "The RDMP epsilon parameter must be positive.");
61 :
62 : bool cell_is_troubled = false;
63 : int tci_status = 0;
64 : size_t tag_index = 0;
65 :
66 : tmpl::for_each<
67 : tmpl::list<tmpl::list<DgEvolvedVarsTags, SubcellEvolvedVarsTags>...>>(
68 : [&cell_is_troubled, &tag_index, &dg_evolved_vars, rdmp_delta0,
69 : rdmp_epsilon, &subcell_evolved_vars, &tci_status](auto tag_v) {
70 : if (cell_is_troubled) {
71 : return;
72 : }
73 :
74 : using tags_list = tmpl::type_from<decltype(tag_v)>;
75 : using tag = tmpl::front<tags_list>;
76 : using inactive_tag = tmpl::back<tags_list>;
77 : const auto& dg_var = get<tag>(dg_evolved_vars);
78 : const auto& subcell_var = get<inactive_tag>(subcell_evolved_vars);
79 :
80 : for (auto dg_it = dg_var.begin(), subcell_it = subcell_var.begin();
81 : dg_it != dg_var.end() and subcell_it != subcell_var.end();
82 : (void)++dg_it, (void)++subcell_it) {
83 : ASSERT(not cell_is_troubled,
84 : "If a cell has already been marked as troubled during the "
85 : "two mesh RDMP TCI, we should not be continuing to check "
86 : "other variables.");
87 : using std::max;
88 : using std::min;
89 :
90 : const double max_dg = max(*dg_it);
91 : const double min_dg = min(*dg_it);
92 : const double max_subcell = max(*subcell_it);
93 : const double min_subcell = min(*subcell_it);
94 : const double delta =
95 : max(rdmp_delta0, rdmp_epsilon * (max_dg - min_dg));
96 : cell_is_troubled =
97 : max_subcell > max_dg + delta or min_subcell < min_dg - delta;
98 : if (cell_is_troubled) {
99 : tci_status = static_cast<int>(tag_index + 1);
100 : return;
101 : }
102 : ++tag_index;
103 : }
104 : });
105 : return tci_status;
106 : }
107 : } // namespace evolution::dg::subcell
|