Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include "DataStructures/DataBox/DataBox.hpp"
7 : #include "DataStructures/DataBox/MetavariablesTag.hpp"
8 : #include "DataStructures/DataVector.hpp"
9 : #include "DataStructures/Variables.hpp"
10 : #include "Domain/BoundaryConditions/BoundaryCondition.hpp"
11 : #include "Domain/BoundaryConditions/None.hpp"
12 : #include "Domain/BoundaryConditions/Periodic.hpp"
13 : #include "Domain/Creators/Tags/ExternalBoundaryConditions.hpp"
14 : #include "Domain/Domain.hpp"
15 : #include "Domain/Structure/Direction.hpp"
16 : #include "Domain/Structure/Element.hpp"
17 : #include "Domain/Structure/ElementId.hpp"
18 : #include "Domain/Tags.hpp"
19 : #include "Evolution/BoundaryConditions/Type.hpp"
20 : #include "Evolution/DgSubcell/Tags/GhostDataForReconstruction.hpp"
21 : #include "Evolution/DgSubcell/Tags/Mesh.hpp"
22 : #include "Evolution/Systems/Ccz4/BoundaryConditions/BoundaryCondition.hpp"
23 : #include "Evolution/Systems/Ccz4/BoundaryConditions/Factory.hpp"
24 : #include "Evolution/Systems/Ccz4/FiniteDifference/Reconstructor.hpp"
25 : #include "Evolution/Systems/Ccz4/FiniteDifference/System.hpp"
26 : #include "Evolution/Systems/Ccz4/Tags.hpp"
27 : #include "PointwiseFunctions/GeneralRelativity/Tags.hpp"
28 : #include "Utilities/CallWithDynamicType.hpp"
29 : #include "Utilities/ErrorHandling/Assert.hpp"
30 : #include "Utilities/Gsl.hpp"
31 : #include "Utilities/PrettyType.hpp"
32 : #include "Utilities/TMPL.hpp"
33 :
34 : namespace Ccz4::fd {
35 : /*!
36 : * \brief Computes finite difference ghost data for external boundary
37 : * conditions.
38 : *
39 : * If the element is at the external boundary, computes FD ghost data with a
40 : * given boundary condition and stores it into neighbor data with {direction,
41 : * ElementId::external_boundary_id()} as the mortar_id key.
42 : *
43 : * \note Subcell needs to be enabled for boundary elements. Otherwise this
44 : * function would be never called.
45 : *
46 : */
47 1 : struct BoundaryConditionGhostData {
48 : template <typename DbTagsList>
49 0 : static void apply(gsl::not_null<db::DataBox<DbTagsList>*> box,
50 : const Element<3>& element,
51 : const Reconstructor& reconstructor);
52 :
53 : private:
54 : template <typename FdBoundaryConditionHelper, typename DbTagsList,
55 : typename... FdBoundaryConditionArgsTags>
56 : // A helper function for calling fd_ghost() of BoundaryCondition subclasses
57 0 : static void apply_subcell_boundary_condition_impl(
58 : FdBoundaryConditionHelper& fd_boundary_condition_helper,
59 : const gsl::not_null<db::DataBox<DbTagsList>*>& box,
60 : tmpl::list<FdBoundaryConditionArgsTags...> /*unused*/) {
61 : return fd_boundary_condition_helper(
62 : db::get<FdBoundaryConditionArgsTags>(*box)...);
63 : }
64 : };
65 :
66 : template <typename DbTagsList>
67 0 : void BoundaryConditionGhostData::apply(
68 : const gsl::not_null<db::DataBox<DbTagsList>*> box,
69 : const Element<3>& element, const Reconstructor& reconstructor) {
70 : const auto& external_boundary_condition =
71 : db::get<domain::Tags::ExternalBoundaryConditions<3>>(*box).at(
72 : element.id().block_id());
73 :
74 : // Check if the element is on the external boundary. If not, the caller is
75 : // doing something wrong (e.g. trying to compute FD ghost data with boundary
76 : // conditions at an element which is not on the external boundary).
77 : ASSERT(not element.external_boundaries().empty(),
78 : "The element (ID : " << element.id()
79 : << ") is not on external boundaries");
80 :
81 : const Mesh<3> subcell_mesh =
82 : db::get<evolution::dg::subcell::Tags::Mesh<3>>(*box);
83 :
84 : const size_t ghost_zone_size{reconstructor.ghost_zone_size()};
85 :
86 : // Tags and tags list for FD reconstruction
87 : using variables_for_reconstruction = typename System::variables_tag_list;
88 :
89 : size_t num_evolved_tensor_components = 0;
90 : tmpl::for_each<variables_for_reconstruction>(
91 : [&num_evolved_tensor_components]<typename Tag>
92 : (const tmpl::type_<Tag> /*meta*/) {
93 : num_evolved_tensor_components += Tag::type::size();
94 : });
95 :
96 : for (const auto& direction : element.external_boundaries()) {
97 : const auto& boundary_condition_at_direction =
98 : *external_boundary_condition.at(direction);
99 :
100 : const size_t num_face_pts{
101 : subcell_mesh.extents().slice_away(direction.dimension()).product()};
102 :
103 : // Allocate a vector to store the computed FD ghost data and assign a
104 : // non-owning Variables on it.
105 : const size_t evolved_vars_size =
106 : num_evolved_tensor_components * ghost_zone_size * num_face_pts;
107 : const size_t fluxes_size = 0; // CCZ4 doesn't use flux variables
108 :
109 : auto& all_ghost_data = db::get_mutable_reference<
110 : evolution::dg::subcell::Tags::GhostDataForReconstruction<3>>(box);
111 : // Put the computed ghost data into neighbor data with {direction,
112 : // ElementId::external_boundary_id()} as the mortar_id key
113 : const DirectionalId<3> mortar_id{direction,
114 : ElementId<3>::external_boundary_id()};
115 :
116 : all_ghost_data[mortar_id] = evolution::dg::subcell::GhostData{1};
117 : DataVector& boundary_ghost_data =
118 : all_ghost_data.at(mortar_id).neighbor_ghost_data_for_reconstruction();
119 : boundary_ghost_data.destructive_resize(evolved_vars_size + fluxes_size);
120 : Variables<variables_for_reconstruction> ghost_data_vars{
121 : boundary_ghost_data.data(), evolved_vars_size};
122 :
123 : // We don't need to care about boundary ghost data when using the periodic
124 : // condition, so exclude it from the type list
125 : using factory_classes =
126 : typename std::decay_t<decltype(db::get<Parallel::Tags::Metavariables>(
127 : *box))>::factory_creation::factory_classes;
128 : using derived_boundary_conditions_for_subcell = tmpl::remove_if<
129 : tmpl::at<factory_classes, BoundaryConditions::BoundaryCondition>,
130 : tmpl::or_<
131 : std::is_base_of<domain::BoundaryConditions::MarkAsPeriodic,
132 : tmpl::_1>,
133 : std::is_base_of<domain::BoundaryConditions::MarkAsNone, tmpl::_1>>>;
134 :
135 : // Now apply subcell boundary conditions
136 : call_with_dynamic_type<void, derived_boundary_conditions_for_subcell>(
137 : &boundary_condition_at_direction,
138 : [&box, &direction, &ghost_data_vars](const auto* boundary_condition) {
139 : using BoundaryCondition = std::decay_t<decltype(*boundary_condition)>;
140 : using bcondition_interior_evolved_vars_tags =
141 : typename BoundaryCondition::fd_interior_evolved_variables_tags;
142 : using bcondition_interior_temporary_tags =
143 : typename BoundaryCondition::fd_interior_temporary_tags;
144 : using bcondition_interior_primitive_vars_tags =
145 : typename BoundaryCondition::fd_interior_primitive_variables_tags;
146 : using bcondition_gridless_tags =
147 : typename BoundaryCondition::fd_gridless_tags;
148 :
149 : using bcondition_interior_tags =
150 : tmpl::append<bcondition_interior_evolved_vars_tags,
151 : bcondition_interior_temporary_tags,
152 : bcondition_interior_primitive_vars_tags,
153 : bcondition_gridless_tags>;
154 :
155 : if constexpr (BoundaryCondition::bc_type ==
156 : evolution::BoundaryConditions::Type::Ghost) {
157 : const auto apply_fd_ghost =
158 : [&boundary_condition, &direction,
159 : &ghost_data_vars](const auto&... boundary_ghost_data_args) {
160 : (*boundary_condition)
161 : .fd_ghost(
162 : make_not_null(
163 : &get<
164 : ::Ccz4::Tags::ConformalMetric<DataVector, 3>>(
165 : ghost_data_vars)),
166 : make_not_null(&get<gr::Tags::Lapse<DataVector>>(
167 : ghost_data_vars)),
168 : make_not_null(&get<gr::Tags::Shift<DataVector, 3>>(
169 : ghost_data_vars)),
170 : make_not_null(
171 : &get<::Ccz4::Tags::ConformalFactor<DataVector>>(
172 : ghost_data_vars)),
173 : make_not_null(
174 : &get<::Ccz4::Tags::ATilde<DataVector, 3>>(
175 : ghost_data_vars)),
176 : make_not_null(&get<gr::Tags::TraceExtrinsicCurvature<
177 : DataVector>>(ghost_data_vars)),
178 : make_not_null(&get<::Ccz4::Tags::Theta<DataVector>>(
179 : ghost_data_vars)),
180 : make_not_null(
181 : &get<::Ccz4::Tags::GammaHat<DataVector, 3>>(
182 : ghost_data_vars)),
183 : make_not_null(
184 : &get<
185 : ::Ccz4::Tags::AuxiliaryShiftB<DataVector, 3>>(
186 : ghost_data_vars)),
187 : direction, boundary_ghost_data_args...);
188 : };
189 : apply_subcell_boundary_condition_impl(apply_fd_ghost, box,
190 : bcondition_interior_tags{});
191 : } else {
192 : ERROR("Unsupported boundary condition "
193 : << pretty_type::short_name<BoundaryCondition>()
194 : << " when using finite-difference");
195 : }
196 : });
197 : }
198 : }
199 : } // namespace Ccz4::fd
|