14 #include "DataStructures/DataBox/PrefixHelpers.hpp"
16 #include "DataStructures/DataVector.hpp"
19 #include "DataStructures/VariablesTag.hpp"
20 #include "Domain/CoordinateMaps/Tags.hpp"
21 #include "Domain/InterfaceHelpers.hpp"
24 #include "Domain/TagsTimeDependent.hpp"
25 #include "Evolution/BoundaryCorrectionTags.hpp"
26 #include "Evolution/DiscontinuousGalerkin/Actions/NormalCovectorAndMagnitude.hpp"
27 #include "Evolution/DiscontinuousGalerkin/InboxTags.hpp"
28 #include "Evolution/DiscontinuousGalerkin/MortarData.hpp"
29 #include "Evolution/DiscontinuousGalerkin/MortarTags.hpp"
30 #include "Evolution/DiscontinuousGalerkin/NormalVectorTags.hpp"
31 #include "Evolution/DiscontinuousGalerkin/ProjectToBoundary.hpp"
32 #include "NumericalAlgorithms/DiscontinuousGalerkin/Formulation.hpp"
33 #include "NumericalAlgorithms/DiscontinuousGalerkin/MetricIdentityJacobian.hpp"
34 #include "NumericalAlgorithms/DiscontinuousGalerkin/MortarHelpers.hpp"
35 #include "NumericalAlgorithms/DiscontinuousGalerkin/Tags.hpp"
36 #include "NumericalAlgorithms/DiscontinuousGalerkin/Tags/Formulation.hpp"
39 #include "NumericalAlgorithms/LinearOperators/WeakDivergence.hpp"
41 #include "NumericalAlgorithms/Spectral/Projection.hpp"
43 #include "ParallelAlgorithms/DiscontinuousGalerkin/FluxCommunication.hpp"
46 #include "Utilities/TypeTraits/CreateHasTypeAlias.hpp"
50 template <
typename...>
58 CREATE_HAS_TYPE_ALIAS_V(boundary_correction)
60 template <
bool HasInverseSpatialMetricTag = false>
61 struct inverse_spatial_metric_tag_impl {
62 template <
typename System>
63 using f = tmpl::list<>;
67 struct inverse_spatial_metric_tag_impl<true> {
68 template <
typename System>
69 using f = tmpl::list<typename System::inverse_spatial_metric_tag>;
72 template <
typename System>
73 using inverse_spatial_metric_tag =
typename inverse_spatial_metric_tag_impl<
74 has_inverse_spatial_metric_tag_v<System>>::template f<System>;
76 template <
bool HasPrimitiveVars = false>
77 struct get_primitive_vars {
78 template <
typename BoundaryCorrection>
79 using f = tmpl::list<>;
83 struct get_primitive_vars<true> {
84 template <
typename BoundaryCorrection>
85 using f =
typename BoundaryCorrection::dg_package_data_primitive_tags;
96 template <
typename System,
typename BoundaryCorrection,
97 typename... PackagedFieldTags,
typename... ProjectedFieldTags,
98 typename... ProjectedFieldTagsForCorrection,
size_t Dim,
99 typename DbTagsList,
typename... VolumeTags>
100 double dg_package_data(
101 const gsl::not_null<Variables<tmpl::list<PackagedFieldTags...>>*>
103 const BoundaryCorrection& boundary_correction,
104 const Variables<tmpl::list<ProjectedFieldTags...>>& projected_fields,
105 const tnsr::i<DataVector, Dim, Frame::Inertial>& unit_normal_covector,
106 const std::optional<tnsr::I<DataVector, Dim, Frame::Inertial>>&
108 const db::DataBox<DbTagsList>& box, tmpl::list<VolumeTags...> ,
109 tmpl::list<ProjectedFieldTagsForCorrection...> ) noexcept {
111 if (mesh_velocity.has_value()) {
112 normal_dot_mesh_velocity =
116 if constexpr (evolution::dg::Actions::detail::
117 has_inverse_spatial_metric_tag_v<System>) {
118 return boundary_correction.dg_package_data(
120 get<ProjectedFieldTagsForCorrection>(projected_fields)...,
121 unit_normal_covector,
122 get<evolution::dg::Actions::detail::NormalVector<Dim>>(
124 mesh_velocity, normal_dot_mesh_velocity, db::get<VolumeTags>(box)...);
126 return boundary_correction.dg_package_data(
128 get<ProjectedFieldTagsForCorrection>(projected_fields)...,
129 unit_normal_covector, mesh_velocity, normal_dot_mesh_velocity,
130 db::get<VolumeTags>(box)...);
352 template <
typename Metavariables>
356 tmpl::list<::dg::FluxesInboxTag<typename Metavariables::boundary_scheme>,
358 Metavariables::volume_dim>>;
359 using const_global_cache_tags = tmpl::conditional_t<
360 detail::has_boundary_correction_v<typename Metavariables::system>,
362 typename Metavariables::system>>,
363 tmpl::list<::dg::Tags::Formulation>>;
365 template <
typename DbTagsList,
typename... InboxTags,
typename ArrayIndex,
366 typename ActionList,
typename ParallelComponent>
368 db::DataBox<DbTagsList>& box,
371 const ArrayIndex& , ActionList ,
372 const ParallelComponent* ) noexcept;
415 template <
size_t Dim,
typename ComputeVolumeTimeDerivatives,
416 typename DbTagsList,
typename... VariablesTags,
417 typename... TimeDerivativeArgumentTags,
418 typename... PartialDerivTags,
typename... FluxVariablesTags,
419 typename... TemporaryTags>
420 static void volume_terms(
422 gsl::not_null<Variables<tmpl::list<FluxVariablesTags...>>*> volume_fluxes,
423 gsl::not_null<Variables<tmpl::list<PartialDerivTags...>>*> partial_derivs,
424 gsl::not_null<Variables<tmpl::list<TemporaryTags...>>*> temporaries,
426 tmpl::list<VariablesTags...> ,
427 tmpl::list<TimeDerivativeArgumentTags...> ) noexcept;
429 template <
size_t Dim,
typename BoundaryCorrection,
typename TemporaryTags,
430 typename DbTagsList,
typename VariablesTags,
431 typename... PackageDataVolumeTags>
432 static void compute_internal_mortar_data(
434 const BoundaryCorrection& boundary_correction,
435 const Variables<VariablesTags>& volume_evolved_vars,
437 ::
Tags::Flux,
typename Metavariables::system::flux_variables,
439 const Variables<TemporaryTags>& volume_temporaries) noexcept;
443 template <
typename... NormalDotFluxTags,
typename... Args>
444 static void apply_flux(
445 gsl::not_null<Variables<tmpl::list<NormalDotFluxTags...>>*> boundary_flux,
446 const Args&... boundary_variables) noexcept {
447 Metavariables::system::normal_dot_fluxes::apply(
449 boundary_variables...);
452 template <
typename DbTagsList>
453 static void boundary_terms_nonconservative_products(
456 template <
size_t VolumeDim,
typename BoundaryScheme,
typename DbTagsList>
457 static void fill_mortar_data_for_internal_boundaries(
460 template <
typename ParallelComponent,
typename DbTagsList>
461 static void send_data_for_fluxes(
463 const db::DataBox<DbTagsList>& box) noexcept;
466 template <
typename Metavariables>
467 template <
typename DbTagsList,
typename... InboxTags,
typename ArrayIndex,
468 typename ActionList,
typename ParallelComponent>
471 db::DataBox<DbTagsList>& box,
474 const ArrayIndex& , ActionList ,
475 const ParallelComponent*
const ) noexcept {
476 static constexpr
size_t volume_dim = Metavariables::volume_dim;
477 using system =
typename Metavariables::system;
478 using variables_tag =
typename system::variables_tag;
479 using variables_tags =
typename variables_tag::tags_list;
480 using partial_derivative_tags =
typename system::gradient_variables;
481 using flux_variables =
typename system::flux_variables;
482 using compute_volume_time_derivative_terms =
483 typename system::compute_volume_time_derivative_terms;
485 const Mesh<volume_dim>& mesh = db::get<::domain::Tags::Mesh<volume_dim>>(box);
496 Variables<typename compute_volume_time_derivative_terms::temporary_tags>
505 volume_terms<volume_dim, compute_volume_time_derivative_terms>(
508 db::get<::dg::Tags::Formulation>(box), variables_tags{},
509 typename compute_volume_time_derivative_terms::argument_tags{});
515 if constexpr (not std::is_same_v<tmpl::list<>, flux_variables>) {
519 tmpl::size_t<Metavariables::volume_dim>,
525 [&volume_fluxes](
const auto fluxes_ptr) noexcept {
526 *fluxes_ptr = volume_fluxes;
529 boundary_terms_nonconservative_products(
make_not_null(&box));
532 if constexpr (detail::has_boundary_correction_v<system>) {
533 const auto& boundary_correction =
534 db::get<evolution::Tags::BoundaryCorrection<system>>(box);
535 using derived_boundary_corrections =
536 typename std::decay_t<decltype(boundary_correction)>::creatable_classes;
540 "All createable classes for boundary corrections must be marked "
542 tmpl::for_each<derived_boundary_corrections>(
543 [&boundary_correction, &box, &temporaries,
544 &volume_fluxes](
auto derived_correction_v) noexcept {
545 using DerivedCorrection =
546 tmpl::type_from<decltype(derived_correction_v)>;
547 if (
typeid(boundary_correction) ==
typeid(DerivedCorrection)) {
551 compute_internal_mortar_data<volume_dim>(
553 dynamic_cast<const DerivedCorrection&
>(boundary_correction),
554 db::get<variables_tag>(box), volume_fluxes, temporaries);
559 fill_mortar_data_for_internal_boundaries<
560 volume_dim,
typename Metavariables::boundary_scheme>(
564 send_data_for_fluxes<ParallelComponent>(
make_not_null(&cache), box);
565 return {std::move(box)};
568 template <
typename Metavariables>
569 template <
size_t Dim,
typename ComputeVolumeTimeDerivatives,
570 typename DbTagsList,
typename... VariablesTags,
571 typename... TimeDerivativeArgumentTags,
typename... PartialDerivTags,
572 typename... FluxVariablesTags,
typename... TemporaryTags>
573 void ComputeTimeDerivative<Metavariables>::volume_terms(
575 const gsl::not_null<Variables<tmpl::list<FluxVariablesTags...>>*>
577 const gsl::not_null<Variables<tmpl::list<PartialDerivTags...>>*>
579 const gsl::not_null<Variables<tmpl::list<TemporaryTags...>>*> temporaries,
582 tmpl::list<VariablesTags...> ,
583 tmpl::list<TimeDerivativeArgumentTags...> ) noexcept {
584 static constexpr
bool has_partial_derivs =
sizeof...(PartialDerivTags) != 0;
585 static constexpr
bool has_fluxes =
sizeof...(FluxVariablesTags) != 0;
587 has_fluxes or has_partial_derivs,
588 "Must have either fluxes or partial derivatives in a "
589 "DG evolution scheme. This means the evolution system struct (usually in "
590 "Evolution/Systems/YourSystem/System.hpp) being used does not specify "
591 "any flux_variables or gradient_variables. Make sure the type aliases "
592 "are defined, and that at least one of them is a non-empty list of "
595 using system =
typename Metavariables::system;
596 using variables_tag =
typename system::variables_tag;
597 using variables_tags =
typename variables_tag::tags_list;
598 using partial_derivative_tags =
typename system::gradient_variables;
599 using flux_variables =
typename system::flux_variables;
601 const Mesh<Dim>& mesh = db::get<::domain::Tags::Mesh<Dim>>(*box);
602 const auto& logical_to_inertial_inverse_jacobian =
db::get<
605 const auto& evolved_vars = db::get<variables_tag>(*box);
608 if constexpr (has_partial_derivs) {
609 partial_derivatives<partial_derivative_tags>(
610 partial_derivs, evolved_vars, mesh,
611 logical_to_inertial_inverse_jacobian);
617 db::mutate<db::add_tag_prefix<::Tags::dt, variables_tag>>(
619 [&mesh, &partial_derivs, &temporaries, &volume_fluxes](
623 const auto&... args) noexcept {
628 (void)partial_derivs;
634 dt_vars_ptr->initialize(mesh.number_of_grid_points(), 0.0);
636 ComputeVolumeTimeDerivatives::apply(
640 get<PartialDerivTags>(*partial_derivs)..., args...);
642 db::get<TimeDerivativeArgumentTags>(*box)...);
645 if (
const auto& mesh_velocity =
647 mesh_velocity.has_value()) {
648 db::mutate<db::add_tag_prefix<::Tags::dt, variables_tag>>(
650 [&evolved_vars, &mesh_velocity, &volume_fluxes](
652 ::Tags::dt,
typename variables_tag::tags_list>>*>
655 div_mesh_velocity) noexcept {
656 tmpl::for_each<flux_variables>([&div_mesh_velocity, &dt_vars_ptr,
657 &evolved_vars, &mesh_velocity,
658 &volume_fluxes](
auto tag_v) noexcept {
660 using var_tag =
typename decltype(tag_v)::type;
664 auto& flux_var = get<flux_var_tag>(*volume_fluxes);
666 for (
size_t flux_var_storage_index = 0;
667 flux_var_storage_index < flux_var.size();
668 ++flux_var_storage_index) {
671 const auto flux_var_tensor_index =
672 flux_var.get_tensor_index(flux_var_storage_index);
675 const auto var_tensor_index =
678 const size_t flux_index =
gsl::at(flux_var_tensor_index, 0);
681 flux_var[flux_var_storage_index] -=
682 get<var_tag>(evolved_vars).get(var_tensor_index) *
683 mesh_velocity->get(flux_index);
687 auto& dt_var = get<::Tags::dt<var_tag>>(*dt_vars_ptr);
688 for (
size_t dt_var_storage_index = 0;
689 dt_var_storage_index < dt_var.size(); ++dt_var_storage_index) {
691 dt_var[dt_var_storage_index] -=
692 get<var_tag>(evolved_vars)[dt_var_storage_index] *
693 get(*div_mesh_velocity);
697 db::get<::domain::Tags::DivMeshVelocity>(*box));
705 using non_flux_tags = tmpl::list_difference<variables_tags, flux_variables>;
707 db::mutate<db::add_tag_prefix<::Tags::dt, variables_tag>>(
708 box, [&mesh_velocity, &partial_derivs](
710 ::Tags::dt,
typename variables_tag::tags_list>>*>
712 tmpl::for_each<non_flux_tags>(
713 [&dt_vars, &mesh_velocity,
714 &partial_derivs](
auto var_tag_v) noexcept {
715 using var_tag =
typename decltype(var_tag_v)::type;
717 using deriv_var_tag =
720 const auto& deriv_var = get<deriv_var_tag>(*partial_derivs);
721 auto& dt_var = get<dt_var_tag>(*dt_vars);
725 for (
size_t deriv_var_storage_index = 0;
726 deriv_var_storage_index < deriv_var.size();
727 ++deriv_var_storage_index) {
730 const auto deriv_var_tensor_index =
731 deriv_var.get_tensor_index(deriv_var_storage_index);
734 const auto dt_var_tensor_index =
737 const size_t deriv_index =
gsl::at(deriv_var_tensor_index, 0);
738 dt_var.get(dt_var_tensor_index) +=
739 mesh_velocity->get(deriv_index) *
740 deriv_var[deriv_var_storage_index];
748 if constexpr (has_fluxes) {
752 Variables<tmpl::list<::Tags::div<FluxVariablesTags>...>> div_fluxes{
753 mesh.number_of_grid_points()};
754 if (dg_formulation == ::dg::Formulation::StrongInertial) {
756 logical_to_inertial_inverse_jacobian);
757 }
else if (dg_formulation == ::dg::Formulation::WeakInertial) {
760 if constexpr (Dim == 1) {
763 const auto& inertial_coords =
764 db::get<domain::Tags::Coordinates<Dim, Frame::Inertial>>(*box);
766 const auto jacobian =
771 InverseJacobian<DataVector, Dim, Frame::Logical, Frame::Inertial>
772 det_jac_times_inverse_jacobian{};
775 inertial_coords, jacobian);
777 det_jac_times_inverse_jacobian);
784 ERROR(
"Unsupported DG formulation: " << dg_formulation);
787 db::mutate<db::add_tag_prefix<::Tags::dt, variables_tag>>(
788 box, [dg_formulation,
790 ::Tags::dt,
typename variables_tag::tags_list>>*>
791 dt_vars_ptr) noexcept {
792 tmpl::for_each<flux_variables>(
793 [&dg_formulation, &dt_vars_ptr,
794 &div_fluxes](
auto var_tag_v) noexcept {
795 using var_tag =
typename decltype(var_tag_v)::type;
796 auto& dt_var = get<::Tags::dt<var_tag>>(*dt_vars_ptr);
800 if (dg_formulation == ::dg::Formulation::StrongInertial) {
801 for (
size_t storage_index = 0; storage_index < dt_var.size();
803 dt_var[storage_index] -= div_flux[storage_index];
806 for (
size_t storage_index = 0; storage_index < dt_var.size();
808 dt_var[storage_index] += div_flux[storage_index];
814 (void)dg_formulation;
818 template <
typename Metavariables>
819 template <
size_t Dim,
typename BoundaryCorrection,
typename TemporaryTags,
820 typename DbTagsList,
typename VariablesTags,
821 typename... PackageDataVolumeTags>
822 void ComputeTimeDerivative<Metavariables>::compute_internal_mortar_data(
824 const BoundaryCorrection& boundary_correction,
825 const Variables<VariablesTags>& volume_evolved_vars,
827 ::
Tags::Flux,
typename Metavariables::system::flux_variables,
829 const Variables<TemporaryTags>& volume_temporaries) noexcept {
830 using system =
typename Metavariables::system;
831 using variables_tags =
typename system::variables_tag::tags_list;
832 using flux_variables =
typename system::flux_variables;
834 tmpl::size_t<Metavariables::volume_dim>,
836 using temporary_tags_for_face =
837 typename BoundaryCorrection::dg_package_data_temporary_tags;
838 using primitive_tags_for_face =
typename detail::get_primitive_vars<
839 system::has_primitive_and_conservative_vars>::
840 template f<BoundaryCorrection>;
841 using mortar_tags_list =
typename BoundaryCorrection::dg_package_field_tags;
843 std::is_same_v<VariablesTags, variables_tags>,
844 "The evolved variables passed in should match the evolved variables of "
847 const Element<Dim>& element = db::get<domain::Tags::Element<Dim>>(*box);
848 const Mesh<Dim>& volume_mesh = db::get<domain::Tags::Mesh<Dim>>(*box);
849 const auto& face_meshes =
850 get<domain::Tags::Interface<domain::Tags::InternalDirections<Dim>,
852 const auto& mortar_meshes = db::get<Tags::MortarMesh<Dim>>(*box);
853 const auto& mortar_sizes = db::get<Tags::MortarSize<Dim>>(*box);
854 const TimeStepId& temporal_id = db::get<::Tags::TimeStepId>(*box);
871 using dg_package_data_projected_tags =
872 tmpl::append<variables_tags, fluxes_tags, temporary_tags_for_face,
873 primitive_tags_for_face>;
875 tmpl::append<dg_package_data_projected_tags,
876 detail::inverse_spatial_metric_tag<system>>,
877 detail::OneOverNormalVectorMagnitude, detail::NormalVector<Dim>>>>
879 for (
const auto& [direction, neighbors_in_direction] : element.
neighbors()) {
880 (void)neighbors_in_direction;
885 if (direction.side() == Side::Upper and
886 element.
neighbors().count(direction.opposite()) != 0) {
890 const auto internal_mortars =
891 [&box, &boundary_correction, &element, &face_mesh_velocities,
892 &fields_on_face, &mortar_meshes, &mortar_sizes, &moving_mesh_map,
893 &temporal_id, &unnormalized_normal_covectors, &volume_evolved_vars,
894 &volume_fluxes, &volume_temporaries,
895 &volume_mesh](
const Mesh<Dim - 1>& face_mesh,
901 (void)volume_temporaries;
922 volume_evolved_vars, volume_mesh,
924 if constexpr (tmpl::size<fluxes_tags>::value != 0) {
926 volume_fluxes, volume_mesh,
929 if constexpr (tmpl::size<tmpl::append<
930 temporary_tags_for_face,
931 detail::inverse_spatial_metric_tag<system>>>::
934 tmpl::append<temporary_tags_for_face,
935 detail::inverse_spatial_metric_tag<system>>>(
936 make_not_null(&fields_on_face), volume_temporaries, volume_mesh,
939 if constexpr (system::has_primitive_and_conservative_vars and
940 tmpl::size<primitive_tags_for_face>::value != 0) {
941 project_tensors_to_boundary<primitive_tags_for_face>(
943 db::get<typename system::primitive_variables_tag>(*box),
944 volume_mesh, local_direction);
953 db::mutate<evolution::dg::Tags::InternalFace::
954 NormalCovectorAndMagnitude<Dim>>(
955 box, [&fields_on_face, &local_direction, &moving_mesh_map,
956 &unnormalized_normal_covectors](
957 const auto normal_covector_and_magnitude_ptr) noexcept {
958 detail::unit_normal_vector_and_covector_and_magnitude<system>(
959 normal_covector_and_magnitude_ptr,
961 unnormalized_normal_covectors, moving_mesh_map);
966 NormalCovectorAndMagnitude<Dim>>(*box)
969 "The magnitude of the normal vector and the unit normal "
970 "covector have not been computed, even though they should "
971 "have been. Direction: "
974 Variables<mortar_tags_list> packaged_data{
975 face_mesh.number_of_grid_points()};
977 const double max_abs_char_speed_on_face =
978 detail::dg_package_data<system>(
983 NormalCovectorAndMagnitude<Dim>>(*box)
984 .
at(local_direction)),
985 face_mesh_velocities.at(local_direction), *box,
986 typename BoundaryCorrection::dg_package_data_volume_tags{},
987 dg_package_data_projected_tags{});
988 (void)max_abs_char_speed_on_face;
991 const auto& neighbors_in_local_direction =
992 element.neighbors().at(local_direction);
993 for (
const auto& neighbor : neighbors_in_local_direction) {
994 const auto mortar_id = std::make_pair(local_direction, neighbor);
995 const auto&
mortar_mesh = mortar_meshes.at(mortar_id);
996 const auto&
mortar_size = mortar_sizes.at(mortar_id);
1003 auto boundary_data_on_mortar =
1008 : std::move(packaged_data);
1020 boundary_data_on_mortar.data(),
1021 boundary_data_on_mortar.data() +
1022 boundary_data_on_mortar.size()};
1023 db::mutate<Tags::MortarData<Dim>>(
1024 box, [&face_mesh, &mortar_id, &temporal_id,
1025 &type_erased_boundary_data_on_mortar](
1026 const auto mortar_data_ptr) noexcept {
1027 mortar_data_ptr->at(mortar_id).insert_local_mortar_data(
1028 temporal_id, face_mesh,
1029 std::move(type_erased_boundary_data_on_mortar));
1034 if (fields_on_face.number_of_grid_points() !=
1035 face_meshes.at(direction).number_of_grid_points()) {
1036 fields_on_face.initialize(
1037 face_meshes.at(direction).number_of_grid_points());
1039 internal_mortars(face_meshes.at(direction), direction);
1041 if (element.neighbors().count(direction.opposite()) != 0) {
1042 if (fields_on_face.number_of_grid_points() !=
1043 face_meshes.at(direction.opposite()).number_of_grid_points()) {
1044 fields_on_face.initialize(
1045 face_meshes.at(direction.opposite()).number_of_grid_points());
1047 internal_mortars(face_meshes.at(direction.opposite()),
1048 direction.opposite());
1053 template <
typename Metavariables>
1054 template <
typename DbTagsList>
1055 void ComputeTimeDerivative<Metavariables>::
1056 boundary_terms_nonconservative_products(
1057 const gsl::not_null<db::DataBox<DbTagsList>*> box) noexcept {
1058 using system =
typename Metavariables::system;
1059 using variables_tag =
typename system::variables_tag;
1060 using DirectionsTag =
1066 using interface_compute_item_argument_tags = tmpl::transform<
1067 typename Metavariables::system::normal_dot_fluxes::argument_tags,
1068 tmpl::bind<domain::Tags::Interface, DirectionsTag, tmpl::_1>>;
1071 tmpl::list<interface_normal_dot_fluxes_tag>,
1072 tmpl::push_front<interface_compute_item_argument_tags, DirectionsTag>>(
1073 [](
const auto boundary_fluxes_ptr,
1075 internal_directions,
1076 const auto&... tensors) noexcept {
1077 for (
const auto& direction : internal_directions) {
1078 apply_flux(
make_not_null(&boundary_fluxes_ptr->at(direction)),
1079 tensors.at(direction)...);
1085 template <
typename Metavariables>
1086 template <
size_t VolumeDim,
typename BoundaryScheme,
typename DbTagsList>
1087 void ComputeTimeDerivative<Metavariables>::
1088 fill_mortar_data_for_internal_boundaries(
1089 const gsl::not_null<db::DataBox<DbTagsList>*> box) noexcept {
1090 using temporal_id_tag =
typename BoundaryScheme::temporal_id_tag;
1091 using all_mortar_data_tag =
1093 using boundary_data_computer =
1094 typename BoundaryScheme::boundary_data_computer;
1097 auto boundary_data_on_interfaces =
1098 interface_apply<domain::Tags::InternalDirections<VolumeDim>,
1099 boundary_data_computer>(*box);
1102 const auto& element = db::get<domain::Tags::Element<VolumeDim>>(*box);
1103 const auto& face_meshes =
1104 get<domain::Tags::Interface<domain::Tags::InternalDirections<VolumeDim>,
1106 const auto& mortar_meshes =
1108 const auto& mortar_sizes =
1110 const auto& temporal_id = get<temporal_id_tag>(*box);
1111 for (
const auto& [direction, neighbors] : element.neighbors()) {
1112 const auto& face_mesh = face_meshes.at(direction);
1113 for (
const auto& neighbor : neighbors) {
1114 const auto mortar_id = std::make_pair(direction, neighbor);
1115 const auto&
mortar_mesh = mortar_meshes.at(mortar_id);
1116 const auto&
mortar_size = mortar_sizes.at(mortar_id);
1123 auto boundary_data_on_mortar =
1125 ? boundary_data_on_interfaces.at(direction).project_to_mortar(
1127 : std::move(boundary_data_on_interfaces.at(direction));
1130 db::mutate<all_mortar_data_tag>(
1131 box, [&mortar_id, &temporal_id, &boundary_data_on_mortar ](
1133 all_mortar_data) noexcept {
1134 all_mortar_data->at(mortar_id).local_insert(
1135 temporal_id, std::move(boundary_data_on_mortar));
1141 template <
typename Metavariables>
1142 template <
typename ParallelComponent,
typename DbTagsList>
1143 void ComputeTimeDerivative<Metavariables>::send_data_for_fluxes(
1145 const db::DataBox<DbTagsList>& box) noexcept {
1146 using system =
typename Metavariables::system;
1147 constexpr
size_t volume_dim = Metavariables::volume_dim;
1148 auto& receiver_proxy =
1149 Parallel::get_parallel_component<ParallelComponent>(*cache);
1150 const auto& element = db::get<domain::Tags::Element<volume_dim>>(box);
1152 if constexpr (detail::has_boundary_correction_v<system>) {
1153 const auto& time_step_id = db::get<::Tags::TimeStepId>(box);
1154 const auto& all_mortar_data =
1155 db::get<evolution::dg::Tags::MortarData<volume_dim>>(box);
1157 for (
const auto& [direction, neighbors] : element.neighbors()) {
1158 const auto& orientation = neighbors.orientation();
1159 const auto direction_from_neighbor = orientation(direction.opposite());
1161 for (
const auto& neighbor : neighbors) {
1162 const std::pair mortar_id{direction, neighbor};
1165 neighbor_boundary_data_on_mortar =
1166 *all_mortar_data.at(mortar_id).local_mortar_data();
1167 ASSERT(time_step_id == all_mortar_data.at(mortar_id).time_step_id(),
1168 "The current time step id of the volume is "
1170 <<
"but the time step id on the mortar with mortar id "
1171 << mortar_id <<
" is "
1172 << all_mortar_data.at(mortar_id).time_step_id());
1175 if (not orientation.is_aligned()) {
1176 ERROR(
"Currently don't support unaligned meshes");
1184 data{neighbor_boundary_data_on_mortar.first,
1186 {std::move(neighbor_boundary_data_on_mortar.second)},
1187 db::get<tmpl::conditional_t<Metavariables::local_time_stepping,
1195 receiver_proxy[neighbor], time_step_id,
1196 std::make_pair(
std::pair{direction_from_neighbor, element.id()},
1201 using BoundaryScheme =
typename Metavariables::boundary_scheme;
1202 using temporal_id_tag =
typename BoundaryScheme::temporal_id_tag;
1203 using receive_temporal_id_tag =
1204 typename BoundaryScheme::receive_temporal_id_tag;
1206 using all_mortar_data_tag =
1209 const auto& all_mortar_data = get<all_mortar_data_tag>(box);
1210 const auto& temporal_id = db::get<temporal_id_tag>(box);
1211 const auto& receive_temporal_id = db::get<receive_temporal_id_tag>(box);
1212 const auto& mortar_meshes =
db::get<
1216 for (
const auto& direction_and_neighbors : element.neighbors()) {
1217 const auto& direction = direction_and_neighbors.first;
1218 const size_t dimension = direction.dimension();
1219 const auto& neighbors_in_direction = direction_and_neighbors.second;
1220 const auto& orientation = neighbors_in_direction.orientation();
1221 const auto direction_from_neighbor = orientation(direction.opposite());
1223 for (
const auto& neighbor : neighbors_in_direction) {
1224 const ::dg::MortarId<volume_dim> mortar_id{direction, neighbor};
1228 ASSERT(all_mortar_data.find(mortar_id) != all_mortar_data.end(),
1229 "Mortar data on mortar "
1231 <<
" not available for sending. Did you forget to collect "
1232 "the data on mortars?");
1233 auto neighbor_boundary_data_on_mortar =
1234 all_mortar_data.at(mortar_id).local_data(temporal_id);
1237 if (not orientation.is_aligned()) {
1238 neighbor_boundary_data_on_mortar.orient_on_slice(
1239 mortar_meshes.at(mortar_id).extents(), dimension, orientation);
1244 Parallel::receive_data<fluxes_inbox_tag>(
1245 receiver_proxy[neighbor], temporal_id,
1249 std::make_pair(receive_temporal_id,
1250 std::move(neighbor_boundary_data_on_mortar))));