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);
|