BoundaryFlux.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
6 #include <algorithm>
7 #include <array>
8 #include <cstddef>
9 
14 #include "Domain/Mesh.hpp"
15 #include "NumericalAlgorithms/DiscontinuousGalerkin/BoundarySchemes/FirstOrder/BoundaryData.hpp"
17 #include "NumericalAlgorithms/DiscontinuousGalerkin/MortarHelpers.hpp"
18 #include "NumericalAlgorithms/DiscontinuousGalerkin/NumericalFluxes/NumericalFluxHelpers.hpp"
19 #include "NumericalAlgorithms/DiscontinuousGalerkin/Protocols.hpp"
21 #include "Utilities/ProtocolHelpers.hpp"
22 #include "Utilities/Requires.hpp"
23 #include "Utilities/TMPL.hpp"
24 
25 namespace dg {
26 /// Functionality related to the first-order DG scheme.
27 namespace FirstOrderScheme {
28 
29 /*!
30  * \brief Compute the boundary flux contribution and lift it to the volume.
31  *
32  * This computes the numerical flux minus the flux dotted into the interface
33  * normal, projects the result to the face mesh if necessary, and then lifts it
34  * to the volume (still presented only on the face mesh as all other points are
35  * zero).
36  *
37  * Projection must happen after the numerical flux calculation so that the
38  * elements on either side of the mortar calculate the same result. Projection
39  * must happen before flux lifting because we want the factor of the magnitude
40  * of the unit normal added during the lift to cancel the Jacobian factor in
41  * integrals to preserve conservation; this only happens if the two operations
42  * are done on the same grid.
43  */
44 template <size_t FaceDim, typename NumericalFluxType, typename AllFieldsTags,
45  typename AllExtraDataTags,
46  Requires<tt::conforms_to_v<NumericalFluxType,
47  dg::protocols::NumericalFlux>> = nullptr>
48 Variables<typename NumericalFluxType::variables_tags> boundary_flux(
50  local_boundary_data,
52  remote_boundary_data,
53  const NumericalFluxType& numerical_flux_computer,
54  const Scalar<DataVector>& magnitude_of_face_normal,
55  const size_t extent_perpendicular_to_boundary,
56  const Mesh<FaceDim>& face_mesh, const Mesh<FaceDim>& mortar_mesh,
57  const MortarSize<FaceDim>& mortar_size) noexcept {
58  using variables_tags = typename NumericalFluxType::variables_tags;
59 
60  // Compute the Tags::NormalDotNumericalFlux from local and remote data
61  Variables<db::wrap_tags_in<::Tags::NormalDotNumericalFlux, variables_tags>>
62  normal_dot_numerical_fluxes{mortar_mesh.number_of_grid_points()};
63  dg::NumericalFluxes::normal_dot_numerical_fluxes(
64  make_not_null(&normal_dot_numerical_fluxes), numerical_flux_computer,
65  local_boundary_data, remote_boundary_data);
66 
67  // Subtract the local Tags::NormalDotFlux
68  tmpl::for_each<variables_tags>([&normal_dot_numerical_fluxes,
69  &local_boundary_data](
70  const auto tag_v) noexcept {
71  using tag = tmpl::type_from<decltype(tag_v)>;
72  auto& numerical_flux =
73  get<::Tags::NormalDotNumericalFlux<tag>>(normal_dot_numerical_fluxes);
74  const auto& local_flux =
75  get<::Tags::NormalDotFlux<tag>>(local_boundary_data.field_data);
76  for (size_t i = 0; i < numerical_flux.size(); ++i) {
77  numerical_flux[i] -= local_flux[i];
78  }
79  });
80 
81  // Project from the mortar back to the face if needed
82  auto projected_fluxes =
84  ? project_from_mortar(normal_dot_numerical_fluxes, face_mesh,
86  : std::move(normal_dot_numerical_fluxes);
87 
88  // Lift flux to the volume. We still only need to provide it on the face
89  // because it is zero everywhere else.
90  return lift_flux(std::move(projected_fluxes),
91  extent_perpendicular_to_boundary, magnitude_of_face_normal);
92 }
93 
94 } // namespace FirstOrderScheme
95 } // namespace dg
Functionality related to discontinuous Galerkin schemes.
Definition: ApplyBoundaryFluxesLocalTimeStepping.hpp:33
Holds the number of grid points, basis, and quadrature in each direction of the computational grid...
Definition: Mesh.hpp:50
Mesh< Dim > mortar_mesh(const Mesh< Dim > &face_mesh1, const Mesh< Dim > &face_mesh2) noexcept
Find a mesh for a mortar capable of representing data from either of two faces.
Definition: MortarHelpers.cpp:19
Define prefixes for DataBox tags.
Variables< typename NumericalFluxType::variables_tags > boundary_flux(const dg::SimpleBoundaryData< AllFieldsTags, AllExtraDataTags > &local_boundary_data, const dg::SimpleBoundaryData< AllFieldsTags, AllExtraDataTags > &remote_boundary_data, const NumericalFluxType &numerical_flux_computer, const Scalar< DataVector > &magnitude_of_face_normal, const size_t extent_perpendicular_to_boundary, const Mesh< FaceDim > &face_mesh, const Mesh< FaceDim > &mortar_mesh, const MortarSize< FaceDim > &mortar_size) noexcept
Compute the boundary flux contribution and lift it to the volume.
Definition: BoundaryFlux.hpp:48
Defines the type alias Requires.
bool needs_projection(const Mesh< Dim > &face_mesh, const Mesh< Dim > &mortar_mesh, const MortarSize< Dim > &mortar_size) noexcept
Determine whether data on an element face needs to be projected to a mortar. If no projection is nece...
Definition: MortarHelpers.hpp:70
Variables< Tags > project_from_mortar(const Variables< Tags > &vars, const Mesh< Dim > &face_mesh, const Mesh< Dim > &mortar_mesh, const MortarSize< Dim > &mortar_size) noexcept
Project variables from a mortar to a face.
Definition: MortarHelpers.hpp:106
Distinguishes between field data, which can be projected to a mortar, and extra data, which will not be projected.
Definition: SimpleBoundaryData.hpp:35
std::array< Spectral::MortarSize, Dim - 1 > mortar_size(const ElementId< Dim > &self, const ElementId< Dim > &neighbor, const size_t dimension, const OrientationMap< Dim > &orientation) noexcept
Determine the size of the mortar (i.e., the part of the face it covers) for communicating with a neig...
Definition: MortarHelpers.cpp:36
Defines function lift_flux.
Defines class Variables.
Defines the class template Mesh.
Defines classes for Tensor.
constexpr bool conforms_to_v
Checks if the ConformingType conforms to the Protocol.
Definition: ProtocolHelpers.hpp:52
Wraps the template metaprogramming library used (brigand)
gsl::not_null< T * > make_not_null(T *ptr) noexcept
Construct a not_null from a pointer. Often this will be done as an implicit conversion, but it may be necessary to perform the conversion explicitly when type deduction is desired.
Definition: Gsl.hpp:879
typename Requires_detail::requires_impl< B >::template_error_type_failed_to_meet_requirements_on_template_parameters Requires
Express requirements on the template parameters of a function or class, replaces std::enable_if_t ...
Definition: Requires.hpp:67
Defines classes SimpleTag, PrefixTag, ComputeTag and several functions for retrieving tag info...
auto lift_flux(Variables< tmpl::list< FluxTags... >> flux, const size_t extent_perpendicular_to_boundary, Scalar< DataVector > magnitude_of_face_normal) noexcept -> Variables< tmpl::list< db::remove_tag_prefix< FluxTags >... >>
Lifts the flux contribution from an interface to the volume.
Definition: LiftFlux.hpp:40
Tensor< T, Symmetry<>, index_list<> > Scalar
Scalar type.
Definition: TypeAliases.hpp:21