Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <cstddef>
7 : #include <type_traits>
8 :
9 : #include "DataStructures/DataBox/DataBox.hpp"
10 : #include "Domain/BoundaryConditions/Cartoon.hpp"
11 : #include "Domain/BoundaryConditions/None.hpp"
12 : #include "Domain/BoundaryConditions/Periodic.hpp"
13 : #include "Domain/Structure/Direction.hpp"
14 : #include "Domain/Structure/Element.hpp"
15 : #include "Domain/Structure/ElementId.hpp"
16 : #include "Domain/Tags.hpp"
17 : #include "Evolution/BoundaryCorrection.hpp"
18 : #include "Evolution/DiscontinuousGalerkin/Actions/BoundaryConditionsImpl.hpp"
19 : #include "Evolution/DiscontinuousGalerkin/Actions/ComputeTimeDerivative.hpp"
20 : #include "Evolution/DiscontinuousGalerkin/Actions/ComputeTimeDerivativeHelpers.hpp"
21 : #include "Evolution/DiscontinuousGalerkin/UsingSubcell.hpp"
22 : #include "Parallel/AlgorithmExecution.hpp"
23 : #include "Parallel/GlobalCache.hpp"
24 : #include "Time/LtsMode.hpp"
25 : #include "Time/Tags/LtsMode.hpp"
26 : #include "Utilities/ErrorHandling/Error.hpp"
27 : #include "Utilities/TMPL.hpp"
28 :
29 : /// \cond
30 : namespace tuples {
31 : template <typename...>
32 : class TaggedTuple;
33 : } // namespace tuples
34 : /// \endcond
35 :
36 : namespace evolution::dg::Actions {
37 : namespace detail {
38 : // Per-boundary-condition tags projected from the volume temporaries
39 : // (`dg_interior_temporary_tags`). The inertial coordinates are exempt: the
40 : // boundary-condition path computes them on the face directly from the
41 : // coordinate map instead of projecting them from the volume temporaries.
42 : template <typename DimType, typename BoundaryCondition>
43 : struct boundary_condition_volume_temporary_tags {
44 : using type =
45 : tmpl::remove<typename BoundaryCondition::dg_interior_temporary_tags,
46 : domain::Tags::Coordinates<DimType::value, Frame::Inertial>>;
47 : };
48 :
49 : // Per-boundary-condition tags projected from the volume partial derivatives
50 : // (`dg_interior_deriv_vars_tags`, optional) and from the volume time
51 : // derivative (`dg_interior_dt_vars_tags`, optional).
52 : template <typename BoundaryCondition>
53 : struct boundary_condition_deriv_tags {
54 : using type = get_deriv_vars_from_boundary_condition<BoundaryCondition>;
55 : };
56 : template <typename BoundaryCondition>
57 : struct boundary_condition_dt_tags {
58 : using type = get_dt_vars_from_boundary_condition<BoundaryCondition>;
59 : };
60 :
61 : // Verify that the LDG auxiliary send reads no uninitialized face data, i.e. it
62 : // never projects any of the volume time-derivative buffers (volume
63 : // temporaries, fluxes, partial derivatives), the inverse spatial metric, or
64 : // the volume time derivative to the boundary.
65 : template <typename EvolutionSystem, typename Metavariables>
66 : struct auxiliary_send_projects_no_uninitialized_data_to_face {
67 : private:
68 : using derived_boundary_corrections =
69 : tmpl::at<typename Metavariables::factory_creation::factory_classes,
70 : evolution::BoundaryCorrection>;
71 :
72 : // The Cartoon/None/Periodic marker conditions are handled specially and do
73 : // not declare the interior-data interface (e.g. dg_interior_temporary_tags),
74 : // so they are excluded before inspecting that interface.
75 : using derived_boundary_conditions = tmpl::remove_if<
76 : tmpl::at<typename Metavariables::factory_creation::factory_classes,
77 : typename EvolutionSystem::boundary_conditions_base>,
78 : tmpl::or_<
79 : std::is_base_of<domain::BoundaryConditions::MarkAsCartoon, tmpl::_1>,
80 : std::is_base_of<domain::BoundaryConditions::MarkAsNone, tmpl::_1>,
81 : std::is_base_of<domain::BoundaryConditions::MarkAsPeriodic,
82 : tmpl::_1>>>;
83 :
84 : // Volume temporaries the boundary corrections would need on the face, from
85 : // either packaging interface.
86 : using all_correction_temporary_tags = tmpl::flatten<tmpl::append<
87 : tmpl::transform<derived_boundary_corrections,
88 : get_dg_auxiliary_package_temporary_tags<tmpl::_1>>,
89 : tmpl::transform<derived_boundary_corrections,
90 : get_dg_package_temporary_tags<tmpl::_1>>>>;
91 : // Volume temporaries the boundary conditions would project.
92 : using all_condition_volume_temporary_tags = tmpl::flatten<tmpl::transform<
93 : derived_boundary_conditions,
94 : boundary_condition_volume_temporary_tags<
95 : tmpl::pin<tmpl::size_t<EvolutionSystem::volume_dim>>, tmpl::_1>>>;
96 : // Partial derivatives the boundary conditions would project.
97 : using all_condition_deriv_tags =
98 : tmpl::flatten<tmpl::transform<derived_boundary_conditions,
99 : boundary_condition_deriv_tags<tmpl::_1>>>;
100 : // Volume time derivatives the boundary conditions would project.
101 : using all_condition_dt_tags =
102 : tmpl::flatten<tmpl::transform<derived_boundary_conditions,
103 : boundary_condition_dt_tags<tmpl::_1>>>;
104 :
105 : public:
106 : static constexpr bool value =
107 : // (1) No fluxes are projected (system is flux-free).
108 : tmpl::size<typename EvolutionSystem::flux_variables>::value == 0 and
109 : // (2) The system has no inverse spatial metric to project.
110 : not has_inverse_spatial_metric_tag_v<EvolutionSystem> and
111 : // (3) No boundary correction declares temporaries in either packaging
112 : // interface.
113 : tmpl::size<all_correction_temporary_tags>::value == 0 and
114 : // (4) No boundary condition projects volume temporaries.
115 : tmpl::size<all_condition_volume_temporary_tags>::value == 0 and
116 : // (5) No boundary condition projects partial derivatives.
117 : tmpl::size<all_condition_deriv_tags>::value == 0 and
118 : // (6) No boundary condition projects the volume time derivative.
119 : tmpl::size<all_condition_dt_tags>::value == 0;
120 : };
121 :
122 : template <typename EvolutionSystem, typename Metavariables>
123 : constexpr bool auxiliary_send_projects_no_uninitialized_data_to_face_v =
124 : auxiliary_send_projects_no_uninitialized_data_to_face<EvolutionSystem,
125 : Metavariables>::value;
126 : } // namespace detail
127 :
128 : /*!
129 : * \brief Packages and sends the auxiliary-pass data for the local
130 : * discontinuous Galerkin (LDG) method for auxiliary boundary corrections.
131 : *
132 : * This action performs the *send* half of the LDG auxiliary communication. It
133 : * mirrors the boundary-data portion of `ComputeTimeDerivative::apply`
134 : * (without the time-derivative computation) but uses the auxiliary package-data
135 : * interface (`dg_auxiliary_package_field_tags`, `dg_auxiliary_package_data`,
136 : * `dg_auxiliary_package_data_volume_tags`) and sends to the auxiliary inbox
137 : * channel `evolution::dg::Tags::BoundaryCorrectionAndGhostCellsInbox` with
138 : * `IsAuxiliary` set to `true`.
139 : *
140 : * The action does NOT compute the volume time derivative, fluxes, flux
141 : * divergence, or partial derivatives. It only:
142 : *
143 : * 1. Computes the internal mortar data in auxiliary mode
144 : * (`detail::internal_mortar_data` with `ComputeAuxiliary` set to `true`).
145 : * 2. Applies the auxiliary external boundary conditions
146 : * (`detail::apply_boundary_conditions_on_all_external_faces` with
147 : * `ComputeAuxiliary` set to `true`).
148 : * 3. Sends the packaged auxiliary mortar data to the neighbors on the auxiliary
149 : * inbox channel by the shared implementation
150 : * (`ComputeTimeDerivative_detail::Impl` with `IsAuxiliary` set to `true`).
151 : *
152 : * Only pure-DG executables (no DG-FD subcell) and global time stepping are
153 : * supported for now. The subcell restriction is enforced by a `static_assert`;
154 : * global time stepping is enforced by a runtime error unless `Tags::LtsMode`
155 : * is `LtsMode::Off`. Nonconforming meshes flow through the same shared mortar
156 : * machinery as the physical pass, but are not yet exercised by tests; until
157 : * they are, a runtime error rejects elements with nonconforming neighbors.
158 : */
159 : template <size_t Dim, typename EvolutionSystem, bool UseNodegroupDgElements,
160 : typename VariablesTag = typename EvolutionSystem::variables_tag>
161 1 : struct SendAuxiliaryData
162 : : ComputeTimeDerivative_detail::Impl<Dim, EvolutionSystem, tmpl::list<>,
163 : UseNodegroupDgElements, true,
164 : VariablesTag> {
165 : private:
166 0 : using base =
167 : ComputeTimeDerivative_detail::Impl<Dim, EvolutionSystem, tmpl::list<>,
168 : UseNodegroupDgElements, true,
169 : VariablesTag>;
170 :
171 : public:
172 : template <typename DbTagsList, typename... InboxTags, typename ArrayIndex,
173 : typename ActionList, typename ParallelComponent,
174 : typename Metavariables>
175 0 : static Parallel::iterable_action_return_t apply(
176 : db::DataBox<DbTagsList>& box, tuples::TaggedTuple<InboxTags...>& inboxes,
177 : Parallel::GlobalCache<Metavariables>& cache,
178 : const ArrayIndex& array_index, const ActionList action_list_meta,
179 : const ParallelComponent* const parallel_component_meta) {
180 : static_assert(not evolution::dg::using_subcell_v<Metavariables>,
181 : "The LDG auxiliary pass does not support executables using "
182 : "DG-subcell (the DG-FD hybrid scheme) yet.");
183 : static_assert(not EvolutionSystem::has_primitive_and_conservative_vars,
184 : "The LDG auxiliary pass does not support systems with "
185 : "primitive and conservative variables.");
186 : static_assert(
187 : detail::auxiliary_send_projects_no_uninitialized_data_to_face_v<
188 : EvolutionSystem, Metavariables>,
189 : "The LDG auxiliary pass does not compute the volume time derivative, "
190 : "so it cannot supply volume temporaries, fluxes, partial derivatives, "
191 : "an inverse spatial metric, or interior time derivatives to the "
192 : "auxiliary boundary corrections/conditions. An auxiliary boundary "
193 : "correction or condition "
194 : "registered for this system requires one of these on the boundary, "
195 : "which the auxiliary send does not support.");
196 :
197 : if (db::get<::Tags::LtsMode>(box) != LtsMode::Off) {
198 : ERROR("Local time stepping is not supported for the LDG auxiliary pass.");
199 : }
200 :
201 : const Element<Dim>& element = db::get<domain::Tags::Element<Dim>>(box);
202 : for (const auto& direction_and_neighbors : element.neighbors()) {
203 : if (not direction_and_neighbors.second.are_conforming()) {
204 : ERROR(
205 : "The LDG auxiliary send has not been tested with nonconforming "
206 : "meshes yet. Element "
207 : << element.id() << " has nonconforming neighbors in direction "
208 : << direction_and_neighbors.first << ".");
209 : }
210 : }
211 : return base::apply(box, inboxes, cache, array_index, action_list_meta,
212 : parallel_component_meta);
213 : }
214 : };
215 : } // namespace evolution::dg::Actions
|