Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <array>
7 : #include <cstddef>
8 : #include <optional>
9 : #include <unordered_map>
10 : #include <vector>
11 :
12 : #include "DataStructures/DataBox/Tag.hpp"
13 : #include "Domain/Block.hpp"
14 : #include "Domain/Creators/Tags/Domain.hpp"
15 : #include "Domain/Domain.hpp"
16 : #include "Domain/ElementDistribution.hpp"
17 : #include "Domain/Structure/ElementId.hpp"
18 : #include "Domain/Tags/ElementDistribution.hpp"
19 : #include "Evolution/DiscontinuousGalerkin/OnlyDgBlockIds.hpp"
20 : #include "Evolution/DiscontinuousGalerkin/OptionTags.hpp"
21 : #include "Evolution/DiscontinuousGalerkin/UsingSubcell.hpp"
22 : #include "Parallel/GlobalCache.hpp"
23 : #include "Utilities/ErrorHandling/Error.hpp"
24 : #include "Utilities/TMPL.hpp"
25 :
26 : namespace evolution::dg {
27 : /*!
28 : * \brief Returns the per-element extents to use in place of `initial_extents`
29 : * when weighting the elements that run the finite-difference subcell scheme by
30 : * their finite-difference grid instead of their DG grid (see
31 : * `evolution::dg::Tags::UseSubcellGridPointsForDistribution`).
32 : *
33 : * An element gets an entry if it starts on the subcell grid, i.e. if
34 : * - its block is not in `only_dg_block_ids`,
35 : * - it does not border a block in `only_dg_block_ids`, and
36 : * - it is not on an external boundary, unless
37 : * `subcell_enabled_at_external_boundary` is `true`.
38 : *
39 : * These conditions must match those in
40 : * `evolution::dg::subcell::Actions::Initialize`. The entry is the number of
41 : * finite-difference grid points \f$2N-1\f$ corresponding to the \f$N\f$ DG
42 : * grid points in `initial_extents`, matching the subcell mesh built by
43 : * `evolution::dg::subcell::fd::mesh`. All other elements always run on the
44 : * DG grid and so are omitted from the returned map.
45 : */
46 : template <size_t Dim>
47 : std::unordered_map<ElementId<Dim>, std::array<size_t, Dim>>
48 1 : compute_weighting_extents_override(
49 : const std::vector<size_t>& only_dg_block_ids,
50 : const std::vector<Block<Dim>>& blocks,
51 : const std::vector<std::array<size_t, Dim>>& initial_refinement_levels,
52 : const std::vector<std::array<size_t, Dim>>& initial_extents,
53 : bool subcell_enabled_at_external_boundary);
54 :
55 : namespace Tags {
56 : /// \ingroup DataBoxTagsGroup
57 : /// Tag that holds whether to use the number of finite-difference subcell
58 : /// grid points (instead of the number of DG grid points) when weighting
59 : /// elements that start on the subcell grid for the
60 : /// `domain::Tags::ElementDistribution` (see
61 : /// `evolution::dg::compute_weighting_extents_override`).
62 : ///
63 : /// Errors unless the `ElementDistribution` is
64 : /// `domain::ElementWeight::NumGridPoints`, since that is the only weight
65 : /// whose cost depends on the extents in a way that makes substituting the
66 : /// subcell extents meaningful.
67 1 : struct UseSubcellGridPointsForDistribution : db::SimpleTag {
68 0 : using type = bool;
69 0 : using option_tags =
70 : tmpl::list<OptionTags::UseSubcellGridPointsForDistribution,
71 : domain::OptionTags::ElementDistribution>;
72 :
73 0 : static constexpr bool pass_metavariables = false;
74 0 : static type create_from_options(
75 : const bool use_subcell_grid_points,
76 : const std::optional<domain::ElementWeight>& element_weight) {
77 : // `ElementWeight::NumGridPoints` is the only weight for which
78 : // substituting the subcell extents produces the intended cost ratio.
79 : // `ElementWeight::Uniform` ignores the extents entirely, so the option
80 : // would silently do nothing. `ElementWeight::NumGridPointsAndGridSpacing`
81 : // derives a minimum grid spacing from the extents by building a DG mesh,
82 : // which for the subcell extents describes neither the DG grid nor the
83 : // (uniform) finite-difference grid, and so mis-weights the cost.
84 : //
85 : // This could be improved in the future by telling
86 : // `domain::get_element_costs()` about the finite-difference grid, so that
87 : // `ElementWeight::NumGridPointsAndGridSpacing` can be supported too.
88 : if (use_subcell_grid_points and
89 : element_weight != std::optional{domain::ElementWeight::NumGridPoints}) {
90 : ERROR(
91 : "UseSubcellGridPointsForDistribution is only supported with "
92 : "ElementDistribution: NumGridPoints. Either set "
93 : "UseSubcellGridPointsForDistribution to false or set "
94 : "ElementDistribution to NumGridPoints.");
95 : }
96 : return use_subcell_grid_points;
97 : }
98 : };
99 : } // namespace Tags
100 :
101 : /// \brief The global cache tags needed to distribute elements, for use as the
102 : /// `const_global_cache_tags` of a component that creates the elements.
103 : ///
104 : /// The subcell-specific tags are only included for executables with DG-subcell
105 : /// support, since the options they are built from only exist there.
106 : template <typename Metavariables, size_t Dim>
107 1 : using element_distribution_cache_tags = tmpl::append<
108 : tmpl::list<domain::Tags::Domain<Dim>, domain::Tags::ElementDistribution>,
109 : tmpl::conditional_t<using_subcell_v<Metavariables>,
110 : tmpl::list<Tags::UseSubcellGridPointsForDistribution,
111 : Tags::OnlyDgBlockIds<Dim>>,
112 : tmpl::list<>>>;
113 :
114 : /*!
115 : * \brief Reads `element_distribution_cache_tags` out of the \p cache and
116 : * returns the `weighting_extents_override` to pass to
117 : * `Parallel::create_elements_using_distribution`.
118 : *
119 : * Always `std::nullopt` for executables without DG-subcell support, and for
120 : * those with it whenever
121 : * `evolution::dg::Tags::UseSubcellGridPointsForDistribution` is `false`.
122 : */
123 : template <size_t Dim, typename Metavariables>
124 : std::optional<std::unordered_map<ElementId<Dim>, std::array<size_t, Dim>>>
125 1 : weighting_extents_override_from_cache(
126 : const Parallel::GlobalCache<Metavariables>& cache,
127 : const std::vector<std::array<size_t, Dim>>& initial_refinement_levels,
128 : const std::vector<std::array<size_t, Dim>>& initial_extents) {
129 : if constexpr (using_subcell_v<Metavariables>) {
130 : if (Parallel::get<Tags::UseSubcellGridPointsForDistribution>(cache)) {
131 : return {compute_weighting_extents_override(
132 : Parallel::get<Tags::OnlyDgBlockIds<Dim>>(cache),
133 : Parallel::get<domain::Tags::Domain<Dim>>(cache).blocks(),
134 : initial_refinement_levels, initial_extents,
135 : Metavariables::SubcellOptions::subcell_enabled_at_external_boundary)};
136 : }
137 : }
138 : return std::nullopt;
139 : }
140 : } // namespace evolution::dg
|