Line data Source code
1 0 : // Distributed under the MIT License. 2 : // See LICENSE.txt for details. 3 : 4 : #pragma once 5 : 6 : #include <array> 7 : #include <cstddef> 8 : #include <optional> 9 : #include <unordered_map> 10 : #include <utility> 11 : #include <vector> 12 : 13 : #include "Domain/Block.hpp" 14 : #include "Domain/Creators/Tags/Domain.hpp" 15 : #include "Domain/Creators/Tags/InitialExtents.hpp" 16 : #include "Domain/Creators/Tags/InitialRefinementLevels.hpp" 17 : #include "Domain/Domain.hpp" 18 : #include "Domain/ElementMap.hpp" 19 : #include "Domain/ExcisionSphere.hpp" 20 : #include "Domain/InterfaceLogicalCoordinates.hpp" 21 : #include "Domain/Structure/CreateInitialMesh.hpp" 22 : #include "Domain/Structure/ElementId.hpp" 23 : #include "Domain/Structure/InitialElementIds.hpp" 24 : #include "Evolution/DiscontinuousGalerkin/Initialization/QuadratureTag.hpp" 25 : #include "Evolution/Systems/CurvedScalarWave/Worldtube/Tags.hpp" 26 : #include "NumericalAlgorithms/Spectral/Basis.hpp" 27 : #include "NumericalAlgorithms/Spectral/Mesh.hpp" 28 : #include "NumericalAlgorithms/Spectral/Quadrature.hpp" 29 : #include "Utilities/Gsl.hpp" 30 : #include "Utilities/TMPL.hpp" 31 : 32 : namespace CurvedScalarWave::Worldtube::Initialization { 33 : 34 : /*! 35 : * \brief Initializes a map of the grid coordinates centered on the worldtube of 36 : * all faces that abut the worldtube with corresponding ElementIds. 37 : * 38 : * \details The worldtube singleton computes an internal solution in the grid 39 : * frame and uses this map to evaluate compute it at the grid coordinates of 40 : * each element face abutting the worldtube each time step. This data is sent to 41 : * the corresponding element where it is used to apply pointwise boundary 42 : * conditions. The `ElementFacesGridCoordinates` holds a map of all the element 43 : * ids abutting the worldtube with the corresonding grid coordinates. 44 : * 45 : * \warning This currently assumes that initial domain remains the same and 46 : * there is no AMR. To support this, the worldtube could send the 47 : * coefficients of its internal solution to each element which can evaluate 48 : * it on their current grid in the boundary conditions. 49 : * 50 : * DataBox changes: 51 : * - Adds: nothing 52 : * - Removes: nothing 53 : * - Modifies: Tags::ElementFacesCoordinatesMap<Dim> 54 : */ 55 : template <size_t Dim> 56 1 : struct InitializeElementFacesGridCoordinates { 57 0 : using return_tags = tmpl::list<Tags::ElementFacesGridCoordinates<Dim>>; 58 0 : using simple_tags = tmpl::list<Tags::ElementFacesGridCoordinates<Dim>>; 59 0 : using compute_tags = tmpl::list<>; 60 0 : using simple_tags_from_options = 61 : tmpl::list<::domain::Tags::InitialExtents<Dim>, 62 : ::domain::Tags::InitialRefinementLevels<Dim>, 63 : evolution::dg::Tags::Quadrature>; 64 0 : using const_global_cache_tags = tmpl::list<>; 65 0 : using mutable_global_cache_tags = tmpl::list<>; 66 0 : using argument_tags = tmpl::flatten< 67 : tmpl::list<simple_tags_from_options, ::domain::Tags::Domain<Dim>, 68 : Tags::ExcisionSphere<Dim>>>; 69 0 : static void apply( 70 : const gsl::not_null<std::unordered_map< 71 : ElementId<Dim>, tnsr::I<DataVector, Dim, Frame::Grid>>*> 72 : element_faces_grid_coords, 73 : const std::vector<std::array<size_t, Dim>>& initial_extents, 74 : const std::vector<std::array<size_t, Dim>>& initial_refinement, 75 : const Spectral::Quadrature& i1_quadrature, const Domain<Dim>& domain, 76 : const ::ExcisionSphere<Dim>& excision_sphere) { 77 : const Spectral::Basis i1_basis{Spectral::Basis::Legendre}; 78 : const auto& blocks = domain.blocks(); 79 : const auto& worldtube_grid_coords = excision_sphere.center(); 80 : const auto& neighboring_blocks = excision_sphere.abutting_directions(); 81 : for (const auto& [block_id, _] : neighboring_blocks) { 82 : const auto element_ids = 83 : initial_element_ids(block_id, initial_refinement.at(block_id)); 84 : for (const auto element_id : element_ids) { 85 : const auto direction = excision_sphere.abutting_direction(element_id); 86 : if (direction.has_value()) { 87 : const auto& current_block = blocks.at(block_id); 88 : const auto mesh = ::domain::create_initial_mesh( 89 : initial_extents, current_block, element_id, i1_basis, 90 : i1_quadrature); 91 : const auto face_mesh = mesh.slice_away(direction.value().dimension()); 92 : const ElementMap<Dim, Frame::Grid> element_map{ 93 : element_id, 94 : current_block.is_time_dependent() 95 : ? current_block.moving_mesh_logical_to_grid_map().get_clone() 96 : : current_block.stationary_map().get_to_grid_frame()}; 97 : const auto face_logical_coords = 98 : interface_logical_coordinates(face_mesh, direction.value()); 99 : auto faces_grid_coords = element_map(face_logical_coords); 100 : for (size_t i = 0; i < 3; ++i) { 101 : faces_grid_coords.get(i) -= worldtube_grid_coords.get(i); 102 : } 103 : element_faces_grid_coords->operator[](element_id) = 104 : std::move(faces_grid_coords); 105 : } 106 : } 107 : } 108 : } 109 : }; 110 : } // namespace CurvedScalarWave::Worldtube::Initialization