Line data Source code
1 0 : // Distributed under the MIT License. 2 : // See LICENSE.txt for details. 3 : 4 : #pragma once 5 : 6 : #include <cstddef> 7 : #include <iosfwd> 8 : #include <optional> 9 : #include <pup.h> 10 : #include <string> 11 : #include <utility> 12 : 13 : #include "DataStructures/DataVector.hpp" 14 : #include "DataStructures/Tensor/TypeAliases.hpp" 15 : #include "NumericalAlgorithms/Spectral/Mesh.hpp" 16 : #include "Time/TimeStepId.hpp" 17 : #include "Utilities/Gsl.hpp" 18 : #include "Utilities/Serialization/PupStlCpp17.hpp" 19 : 20 : namespace evolution::dg { 21 : /*! 22 : * \brief Data on the mortar used to compute the boundary correction for the 23 : * DG scheme. 24 : * 25 : * The class holds the local data that has been projected to the mortar as well 26 : * as the neighbor data that has been projected to the mortar. The local and 27 : * neighbor data is later used to compute the same unique boundary correction on 28 : * the mortar for both elements. That is, the final boundary correction 29 : * computation is done twice: once on each element touching the mortar. However, 30 : * the computation is done in such a way that the results agree. 31 : * 32 : * In addition to the (type-erased) fields on both sides of the mortar, the face 33 : * (not mortar!) mesh of the neighbor is stored. The mesh will be necessary 34 : * when hybridizing DG with finite difference or finite volume schemes 35 : * (DG-subcell). 36 : * 37 : * If the element and its neighbor have unaligned logical coordinate systems 38 : * then the data is stored in the local logical coordinate's orientation 39 : * (\f$\xi\f$ varies fastest). This means the action sending the data is 40 : * responsible for reorienting the data on the mortar so it matches the 41 : * neighbor's orientation. 42 : * 43 : * \tparam Dim the volume dimension of the mesh 44 : */ 45 : template <size_t Dim> 46 1 : class MortarData { 47 0 : using MortarType = std::optional<std::pair<Mesh<Dim - 1>, DataVector>>; 48 : 49 : public: 50 0 : MortarData(size_t number_of_buffers = 1); 51 : 52 : /*! 53 : * \brief Insert data onto the mortar. 54 : * 55 : * Exactly one local and neighbor insert call must be made between calls to 56 : * `extract()`. 57 : * 58 : * The insert functions require that: 59 : * - the data is inserted only once 60 : * - the `TimeStepId` of the local and neighbor data are the same (this is 61 : * only checked if the local/neighbor data was already inserted) 62 : * 63 : * \note it is not required that the number of grid points between the local 64 : * and neighbor data be the same since one may be using FD/FV instead of DG 65 : * and this switch is done locally in space and time in such a way that 66 : * neighboring elements have no a priori knowledge about what well be 67 : * received. 68 : */ 69 : /// @{ 70 1 : void insert_local_mortar_data(TimeStepId time_step_id, 71 : Mesh<Dim - 1> local_interface_mesh, 72 : DataVector local_mortar_vars); 73 1 : void insert_neighbor_mortar_data(TimeStepId time_step_id, 74 : Mesh<Dim - 1> neighbor_interface_mesh, 75 : DataVector neighbor_mortar_vars); 76 : /// @} 77 : 78 : /*! 79 : * \brief Insert the magnitude of the local face normal, the determinant 80 : * of the volume inverse Jacobian, and the determinant of the face Jacobian. 81 : * Used for local time stepping with Gauss points. 82 : * 83 : * The magnitude of the face normal is given by: 84 : * 85 : * \f{align*}{ 86 : * \sqrt{ 87 : * \frac{\partial\xi}{\partial x^i} \gamma^{ij} 88 : * \frac{\partial\xi}{\partial x^j}} 89 : * \f} 90 : * 91 : * for a face in the \f$\xi\f$-direction, with inverse spatial metric 92 : * \f$\gamma^{ij}\f$. 93 : */ 94 1 : void insert_local_geometric_quantities( 95 : const Scalar<DataVector>& local_volume_det_inv_jacobian, 96 : const Scalar<DataVector>& local_face_det_jacobian, 97 : const Scalar<DataVector>& local_face_normal_magnitude); 98 : 99 : /*! 100 : * \brief Insert the magnitude of the local face normal. Used for local time 101 : * stepping with Gauss-Lobatto points. 102 : * 103 : * The magnitude of the face normal is given by: 104 : * 105 : * \f{align*}{ 106 : * \sqrt{ 107 : * \frac{\partial\xi}{\partial x^i} \gamma^{ij} 108 : * \frac{\partial\xi}{\partial x^j}} 109 : * \f} 110 : * 111 : * for a face in the \f$\xi\f$-direction, with inverse spatial metric 112 : * \f$\gamma^{ij}\f$. 113 : */ 114 1 : void insert_local_face_normal_magnitude( 115 : const Scalar<DataVector>& local_face_normal_magnitude); 116 : 117 : /*! 118 : * \brief Sets the `local_volume_det_inv_jacobian` by setting the DataVector 119 : * to point into the `MortarData`'s internal storage. 120 : * 121 : * \warning The result should never be changed. 122 : */ 123 1 : void get_local_volume_det_inv_jacobian( 124 : gsl::not_null<Scalar<DataVector>*> local_volume_det_inv_jacobian) const; 125 : 126 : /*! 127 : * \brief Sets the `local_face_det_jacobian` by setting the DataVector to 128 : * point into the `MortarData`'s internal storage. 129 : * 130 : * \warning The result should never be changed. 131 : */ 132 1 : void get_local_face_det_jacobian( 133 : gsl::not_null<Scalar<DataVector>*> local_face_det_jacobian) const; 134 : 135 : /*! 136 : * \brief Sets the `local_face_normal_magnitude` by setting the DataVector to 137 : * point into the `MortarData`'s internal storage. 138 : * 139 : * \warning The result should never be changed. 140 : */ 141 1 : void get_local_face_normal_magnitude( 142 : gsl::not_null<Scalar<DataVector>*> local_face_normal_magnitude) const; 143 : 144 : /// Return the inserted data and reset the state to empty. 145 : /// 146 : /// The first element is the local data while the second element is the 147 : /// neighbor data. 148 1 : auto extract() -> std::pair<std::pair<Mesh<Dim - 1>, DataVector>, 149 : std::pair<Mesh<Dim - 1>, DataVector>>; 150 : 151 : /// Move to the next internal mortar buffer 152 1 : void next_buffer(); 153 : 154 : /// Return the current internal mortar index 155 1 : size_t current_buffer_index() const; 156 : 157 : /// Return the total number of buffers that this MortarData was constructed 158 : /// with 159 1 : size_t total_number_of_buffers() const; 160 : 161 0 : const TimeStepId& time_step_id() const { 162 : return time_step_id_[mortar_index_]; 163 : } 164 : 165 0 : TimeStepId& time_step_id() { return time_step_id_[mortar_index_]; } 166 : 167 0 : auto local_mortar_data() const 168 : -> const std::optional<std::pair<Mesh<Dim - 1>, DataVector>>& { 169 : return local_mortar_data_[mortar_index_]; 170 : } 171 : 172 0 : auto neighbor_mortar_data() const 173 : -> const std::optional<std::pair<Mesh<Dim - 1>, DataVector>>& { 174 : return neighbor_mortar_data_[mortar_index_]; 175 : } 176 : 177 0 : auto local_mortar_data() 178 : -> std::optional<std::pair<Mesh<Dim - 1>, DataVector>>& { 179 : return local_mortar_data_[mortar_index_]; 180 : } 181 : 182 0 : auto neighbor_mortar_data() 183 : -> std::optional<std::pair<Mesh<Dim - 1>, DataVector>>& { 184 : return neighbor_mortar_data_[mortar_index_]; 185 : } 186 : 187 : // NOLINTNEXTLINE(google-runtime-references) 188 0 : void pup(PUP::er& p); 189 : 190 0 : std::string pretty_print_current_buffer_no_data(size_t padding_size) const; 191 : 192 : private: 193 : template <size_t LocalDim> 194 : // NOLINTNEXTLINE 195 0 : friend bool operator==(const MortarData<LocalDim>& lhs, 196 : const MortarData<LocalDim>& rhs); 197 : 198 0 : size_t number_of_buffers_{1}; 199 0 : std::vector<TimeStepId> time_step_id_{}; 200 0 : std::vector<MortarType> local_mortar_data_{}; 201 0 : std::vector<MortarType> neighbor_mortar_data_{}; 202 0 : size_t mortar_index_{0}; 203 0 : DataVector local_geometric_quantities_{}; 204 0 : bool using_volume_and_face_jacobians_{false}; 205 0 : bool using_only_face_normal_magnitude_{false}; 206 : }; 207 : 208 : template <size_t Dim> 209 0 : bool operator!=(const MortarData<Dim>& lhs, const MortarData<Dim>& rhs); 210 : 211 : template <size_t Dim> 212 0 : std::ostream& operator<<(std::ostream& os, const MortarData<Dim>& mortar_data); 213 : } // namespace evolution::dg