DUBeat 1.0.1
High-order discontinuous Galerkin methods and applications to cardiac electrophysiology
Loading...
Searching...
No Matches
QGaussLegendreSimplex.hpp
Go to the documentation of this file.
1/********************************************************************************
2 Copyright (C) 2024 by the DUBeat authors.
3
4 This file is part of DUBeat.
5
6 DUBeat is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 DUBeat is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with DUBeat. If not, see <http://www.gnu.org/licenses/>.
18********************************************************************************/
19
27#ifndef QGAUSSLEGENDRESIMPLEX_HPP_
28#define QGAUSSLEGENDRESIMPLEX_HPP_
29
30#include <deal.II/base/config.h>
31
32#include <deal.II/base/quadrature.h>
33
34#include <utility>
35#include <vector>
36
39extern std::pair<std::vector<dealii::Point<1>>, std::vector<double>>
40gauleg(const double left_position,
41 const double right_position,
42 const unsigned int n)
43{
44 AssertThrow(left_position < right_position,
45 dealii::StandardExceptions::ExcMessage(
46 "(a,b) is an interval, hence a must be lower than b."));
47
48 // The following lines follow the definition of Gauss-Legendre nodes on an
49 // interval.
50
51 const double middle_point = 0.5 * (right_position + left_position);
52 const double half_length = 0.5 * (right_position - left_position);
53
54 std::vector<dealii::Point<1>> coords(n);
55 std::vector<double> weights(n);
56
57 double z, z1, p1, p2, p3, pp = 0.0;
58
59 for (unsigned int i = 1; i <= (n + 1) / 2.; ++i)
60 {
61 z = std::cos(M_PI * (i - 0.25) / (n + 0.5));
62 z1 = z + 1.;
63
64 while (!(std::abs(z - z1) < 1e-10))
65 {
66 p1 = 1.0;
67 p2 = 0.0;
68
69 for (unsigned int j = 1; j <= n; ++j)
70 {
71 p3 = p2;
72 p2 = p1;
73 p1 = ((2 * j - 1) * z * p2 - (j - 1) * p3) / j;
74 }
75
76 pp = n * (z * p1 - p2) / (pow(z, 2) - 1);
77 z1 = z;
78 z = z1 - p1 / pp;
79 }
80
81 const dealii::Point<1> P1(middle_point - half_length * z);
82 const dealii::Point<1> P2(middle_point + half_length * z);
83 coords[i - 1] = P1;
84 coords[n - i] = P2;
85 weights[i - 1] = 2.0 * half_length / ((1.0 - z * z) * pp * pp);
86 weights[n - i] = weights[i - 1];
87 }
88
89 return {coords, weights};
90}
91
98template <unsigned int dim>
99class QGaussLegendreSimplex : public dealii::Quadrature<dim>
100{
101public:
103 QGaussLegendreSimplex<dim>(const unsigned int n);
104};
105
107template <>
109 : dealii::Quadrature<1>(n)
110{
111 std::vector<dealii::Point<1>> coords_1D(n);
112 std::vector<double> weights_1D(n);
113 std::tie(coords_1D, weights_1D) = gauleg(0, 1, n);
114
115 this->quadrature_points = coords_1D;
116 this->weights = weights_1D;
117}
118
121template <>
123 : dealii::Quadrature<2>(n)
124{
125 std::vector<dealii::Point<1>> coords_1D(n);
126 std::vector<double> weights_1D(n);
127 std::tie(coords_1D, weights_1D) = gauleg(-1, 1, n);
128
129 std::vector<dealii::Point<2>> coords_2D;
130 std::vector<double> weights_2D;
131
132 for (unsigned int i = 0; i < n; ++i)
133 {
134 for (unsigned int j = 0; j < n; ++j)
135 {
136 const dealii::Point<2> P((1 + coords_1D[i][0]) / 2,
137 (1 - coords_1D[i][0]) *
138 (1 + coords_1D[j][0]) / 4);
139
140 coords_2D.push_back(P);
141 weights_2D.push_back((1 - coords_1D[i][0]) * weights_1D[i] *
142 weights_1D[j] / 8);
143 }
144 }
145
146 this->quadrature_points = coords_2D;
147 this->weights = weights_2D;
148}
149
153template <>
155 : dealii::Quadrature<3>(n)
156{
157 std::vector<dealii::Point<1>> coords_1D(n);
158 std::vector<double> weights_1D(n);
159 std::tie(coords_1D, weights_1D) = gauleg(-1, 1, n);
160
161 std::vector<dealii::Point<3>> coords_3D;
162 std::vector<double> weights_3D;
163
164 for (unsigned int i = 0; i < n; ++i)
165 {
166 for (unsigned int j = 0; j < n; ++j)
167 {
168 for (unsigned int k = 0; k < n; ++k)
169 {
170 const dealii::Point<3> new_coords((coords_1D[i][0] + 1) *
171 (coords_1D[j][0] - 1) *
172 (coords_1D[k][0] - 1) / 8,
173 (1 - coords_1D[k][0]) *
174 (1 + coords_1D[j][0]) / 4,
175 (coords_1D[k][0] + 1) / 2);
176
177 coords_3D.push_back(new_coords);
178 weights_3D.push_back((1 - coords_1D[k][0]) *
179 (1 - coords_1D[k][0]) *
180 (1 - coords_1D[j][0]) * weights_1D[i] *
181 weights_1D[j] * weights_1D[k] / 64);
182 }
183 }
184 }
185
186 this->quadrature_points = coords_3D;
187 this->weights = weights_3D;
188}
189
190#endif /* QGAUSSLEGENDRESIMPLEX_HPP_*/
std::pair< std::vector< dealii::Point< 1 > >, std::vector< double > > gauleg(const double left_position, const double right_position, const unsigned int n)
This routine computes the Gauss-Legendre nodes and weights on a given interval (a,...
Class representing the Gauss-Legendre quadrature formula on simplex elements.
QGaussLegendreSimplex(const unsigned int n)
Constructor.