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 <cstdint> 8 : #include <iosfwd> 9 : #include <string> 10 : 11 : #include "Utilities/MakeArray.hpp" 12 : 13 : /// \cond 14 : namespace Options { 15 : class Option; 16 : template <typename T> 17 : struct create_from_yaml; 18 : } // namespace Options 19 : /// \endcond 20 : 21 : namespace Spectral { 22 : /*! 23 : * \brief Either the choice of quadrature method to compute integration weights 24 : * for a spectral or discontinuous Galerkin (DG) method, or the locations of 25 : * grid points when a finite difference method is used 26 : * 27 : * \details The particular choices of Basis and Quadrature determine 28 : * where the collocation points of a Mesh are located in an Element. For a 29 : * spectral or DG method, integrals using \f$N\f$ collocation points with Gauss 30 : * quadrature are exact to polynomial order \f$p=2N-1\f$. Gauss-Lobatto 31 : * quadrature is exact only to polynomial order \f$p=2N-3\f$, but includes 32 : * collocation points at the Element boundary. Gauss-Radau 33 : * quadrature is exact only to polynomial order \f$p=2N-2\f$, but includes a 34 : * collocation points at the lower or upper boundary of the Element. For a 35 : * finite difference method, one needs to choose the order of the scheme (and 36 : * hence the weights, differentiation matrix, integration weights, and 37 : * interpolant) locally in space and time to handle discontinuous 38 : * solutions. 39 : * 40 : * \note Choose `Gauss` or `GaussLobatto` when using Basis::Legendre or 41 : * Basis::Chebyshev. 42 : * 43 : * \note Choose `CellCentered` or `FaceCentered` when using 44 : * Basis::FiniteDifference. 45 : * 46 : * \note Choose `Equiangular` when using Basis::Fourier. 47 : * 48 : * \note When using Basis::SphericalHarmonic in consecutive dimensions, choose 49 : * `Gauss` for the first dimension and `Equiangular` in the second dimension. 50 : * 51 : * \note When using Basis::ZernikeB2 in consecutive dimensions, choose 52 : * `GaussRadauUpper` for the first dimension and `Equiangular` in the second 53 : * dimension. 54 : * 55 : * \note When using Basis::ZernikeB3 in consecutive dimensions, choose 56 : * `GaussRadauUpper` for the first dimension, `Gauss` for the second dimension, 57 : * and `Equiangular` in the third dimension. 58 : * 59 : * \remark We store these effectively as a 4-bit integer using the lowest 4 60 : * bits of a uint8_t. Unlike Basis, this does not need a bitshift. We cannot 61 : * have more than 16 quadratures to fit into the 4 bits, including the 62 : * `Uninitialized` value. 63 : */ 64 0 : enum class Quadrature : uint8_t { 65 : Uninitialized = 0, 66 : Gauss, 67 : GaussLobatto, 68 : CellCentered, 69 : FaceCentered, 70 : Equiangular, 71 : GaussRadauLower, 72 : GaussRadauUpper, 73 : AxialSymmetry, 74 : SphericalSymmetry 75 : }; 76 : 77 : /// All possible values of Quadrature 78 1 : std::array<Quadrature, 10> all_quadratures(); 79 : 80 : /// Convert a string to a Quadrature enum. 81 1 : Quadrature to_quadrature(const std::string& quadrature); 82 : 83 : /// Output operator for a Quadrature. 84 1 : std::ostream& operator<<(std::ostream& os, const Quadrature& quadrature); 85 : 86 : /// Shortcuts for common Quadrature products where the default value of 87 : /// I1Quadrature is Quadrature::GaussLobatto 88 1 : namespace quadratures { 89 : template <size_t VolumeDim, Quadrature I1Quadrature = Quadrature::GaussLobatto> 90 0 : static constexpr auto hypercube = make_array<VolumeDim>(I1Quadrature); 91 : 92 : template <size_t VolumeDim> 93 0 : static constexpr auto hypertorus = 94 : make_array<VolumeDim>(Quadrature::Equiangular); 95 : 96 : template <Quadrature I1Quadrature = Quadrature::GaussLobatto> 97 0 : static constexpr auto annulus = 98 : std::array{I1Quadrature, Quadrature::Equiangular}; 99 : 100 0 : static constexpr auto spherical_surface = 101 : std::array{Quadrature::Gauss, Quadrature::Equiangular}; 102 : 103 0 : static constexpr auto disk = 104 : std::array{Quadrature::GaussRadauUpper, Quadrature::Equiangular}; 105 : 106 : template <Quadrature I1Quadrature = Quadrature::GaussLobatto> 107 0 : static constexpr auto spherical_shell = 108 : std::array{I1Quadrature, Quadrature::Gauss, Quadrature::Equiangular}; 109 : 110 : template <Quadrature I1Quadrature = Quadrature::GaussLobatto> 111 0 : static constexpr auto cylindrical_shell = 112 : std::array{I1Quadrature, Quadrature::Equiangular, I1Quadrature}; 113 : 114 : template <Quadrature I1Quadrature = Quadrature::GaussLobatto> 115 0 : static constexpr auto full_cylinder = std::array{ 116 : Quadrature::GaussRadauUpper, Quadrature::Equiangular, I1Quadrature}; 117 : 118 0 : static constexpr auto full_sphere = std::array{ 119 : Quadrature::GaussRadauUpper, Quadrature::Gauss, Quadrature::Equiangular}; 120 : 121 : template <Quadrature I1Quadrature = Quadrature::GaussLobatto> 122 0 : static constexpr auto cartoon_sphere = std::array{ 123 : I1Quadrature, Quadrature::SphericalSymmetry, Quadrature::SphericalSymmetry}; 124 : 125 0 : static constexpr auto cartoon_sphere_inner = 126 : std::array{Quadrature::GaussRadauUpper, Quadrature::SphericalSymmetry, 127 : Quadrature::SphericalSymmetry}; 128 : 129 : template <Quadrature I1Quadrature = Quadrature::GaussLobatto> 130 0 : static constexpr auto cartoon_cylinder = 131 : std::array{I1Quadrature, I1Quadrature, Quadrature::AxialSymmetry}; 132 : 133 : template <Quadrature I1Quadrature = Quadrature::GaussLobatto> 134 0 : static constexpr auto cartoon_cylinder_inner = std::array{ 135 : Quadrature::GaussRadauUpper, I1Quadrature, Quadrature::AxialSymmetry}; 136 : } // namespace quadratures 137 : } // namespace Spectral 138 : 139 : template <> 140 0 : struct Options::create_from_yaml<Spectral::Quadrature> { 141 : template <typename Metavariables> 142 0 : static Spectral::Quadrature create(const Options::Option& options) { 143 : return create<void>(options); 144 : } 145 : }; 146 : 147 : template <> 148 0 : Spectral::Quadrature 149 : Options::create_from_yaml<Spectral::Quadrature>::create<void>( 150 : const Options::Option& options);