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 
10 #include "DataStructures/DataBox/PrefixHelpers.hpp"
14 #include "NumericalAlgorithms/DiscontinuousGalerkin/BoundarySchemes/FirstOrder/BoundaryData.hpp"
16 #include "NumericalAlgorithms/DiscontinuousGalerkin/MortarHelpers.hpp"
17 #include "NumericalAlgorithms/DiscontinuousGalerkin/NumericalFluxes/NumericalFluxHelpers.hpp"
18 #include "NumericalAlgorithms/DiscontinuousGalerkin/Protocols.hpp"
20 #include "NumericalAlgorithms/Spectral/Projection.hpp"
22 #include "Utilities/ProtocolHelpers.hpp"
23 #include "Utilities/Requires.hpp"
24 #include "Utilities/TMPL.hpp"
25 
26 namespace dg {
27 /// Functionality related to the first-order DG scheme.
28 namespace FirstOrderScheme {
29 
30 /*!
31  * \brief Compute the boundary flux contribution and lift it to the volume.
32  *
33  * This computes the numerical flux minus the flux dotted into the interface
34  * normal, projects the result to the face mesh if necessary, and then lifts it
35  * to the volume (still presented only on the face mesh as all other points are
36  * zero).
37  *
38  * Projection must happen after the numerical flux calculation so that the
39  * elements on either side of the mortar calculate the same result. Projection
40  * must happen before flux lifting because we want the factor of the magnitude
41  * of the unit normal added during the lift to cancel the Jacobian factor in
42  * integrals to preserve conservation; this only happens if the two operations
43  * are done on the same grid.
44  */
45 template <size_t FaceDim, typename NumericalFluxType, typename AllFieldsTags,
46  typename AllExtraDataTags,
47  Requires<tt::conforms_to_v<NumericalFluxType,
48  dg::protocols::NumericalFlux>> = nullptr>
49 Variables<typename NumericalFluxType::variables_tags> boundary_flux(
51  local_boundary_data,
53  remote_boundary_data,
54  const NumericalFluxType& numerical_flux_computer,
55  const Scalar<DataVector>& magnitude_of_face_normal,
56  const size_t extent_perpendicular_to_boundary,
57  const Mesh<FaceDim>& face_mesh, const Mesh<FaceDim>& mortar_mesh,
58  const MortarSize<FaceDim>& mortar_size) noexcept {
59  using variables_tags = typename NumericalFluxType::variables_tags;
60 
61  // Compute the Tags::NormalDotNumericalFlux from local and remote data
62  Variables<db::wrap_tags_in<::Tags::NormalDotNumericalFlux, variables_tags>>
63  normal_dot_numerical_fluxes{mortar_mesh.number_of_grid_points()};
64  dg::NumericalFluxes::normal_dot_numerical_fluxes(
65  make_not_null(&normal_dot_numerical_fluxes), numerical_flux_computer,
66  local_boundary_data, remote_boundary_data);
67 
68  // Subtract the local Tags::NormalDotFlux
69  tmpl::for_each<variables_tags>([&normal_dot_numerical_fluxes,
70  &local_boundary_data](
71  const auto tag_v) noexcept {
72  using tag = tmpl::type_from<decltype(tag_v)>;
73  auto& numerical_flux =
74  get<::Tags::NormalDotNumericalFlux<tag>>(normal_dot_numerical_fluxes);
75  const auto& local_flux =
76  get<::Tags::NormalDotFlux<tag>>(local_boundary_data.field_data);
77  for (size_t i = 0; i < numerical_flux.size(); ++i) {
78  numerical_flux[i] -= local_flux[i];
79  }
80  });
81 
82  // Project from the mortar back to the face if needed
83  auto projected_fluxes =
85  ? project_from_mortar(normal_dot_numerical_fluxes, face_mesh,
87  : std::move(normal_dot_numerical_fluxes);
88 
89  // Lift flux to the volume. We still only need to provide it on the face
90  // because it is zero everywhere else.
91  return lift_flux(std::move(projected_fluxes),
92  extent_perpendicular_to_boundary, magnitude_of_face_normal);
93 }
94 
95 } // namespace FirstOrderScheme
96 } // namespace dg
Spectral::needs_projection
bool needs_projection(const Mesh< Dim > &mesh1, const Mesh< Dim > &mesh2, const std::array< ChildSize, Dim > &child_sizes) noexcept
Determine whether data needs to be projected between a child mesh and its parent mesh....
LiftFlux.hpp
dg::lift_flux
void lift_flux(const gsl::not_null< Variables< tmpl::list< BoundaryCorrectionTags... >> * > boundary_correction_terms, const size_t extent_perpendicular_to_boundary, Scalar< DataVector > magnitude_of_face_normal) noexcept
Lifts the flux contribution from an interface to the volume.
Definition: LiftFlux.hpp:42
dg::protocols::NumericalFlux
Defines the interface for DG numerical fluxes.
Definition: Protocols.hpp:90
Spectral.hpp
algorithm
dg
Functionality related to discontinuous Galerkin schemes.
Definition: ComputeNonconservativeBoundaryFluxes.hpp:23
dg::SimpleBoundaryData
Distinguishes between field data, which can be projected to a mortar, and extra data,...
Definition: SimpleBoundaryData.hpp:32
cstddef
array
dg::project_from_mortar
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
Definition: MortarHelpers.hpp:85
Variables.hpp
Mesh
Holds the number of grid points, basis, and quadrature in each direction of the computational grid.
Definition: Mesh.hpp:48
Scalar
Tensor< T, Symmetry<>, index_list<> > Scalar
Definition: TypeAliases.hpp:21
dg::mortar_mesh
Mesh< Dim > mortar_mesh(const Mesh< Dim > &face_mesh1, const Mesh< Dim > &face_mesh2) noexcept
Tensor.hpp
Requires.hpp
make_not_null
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,...
Definition: Gsl.hpp:880
Requires
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
dg::FirstOrderScheme::boundary_flux
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:49
Prefixes.hpp
dg::mortar_size
MortarSize< Dim - 1 > mortar_size(const ElementId< Dim > &self, const ElementId< Dim > &neighbor, size_t dimension, const OrientationMap< Dim > &orientation) noexcept
TMPL.hpp
Mesh.hpp