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