Gyselalib++
 
Loading...
Searching...
No Matches
gauss_legendre_integration.hpp
1#pragma once
2
3#include <array>
4#include <cassert>
5#include <cmath>
6#include <stdexcept>
7#include <utility>
8#include <vector>
9
10#include <ddc/ddc.hpp>
11
12#include "sll/view.hpp"
13
15{
16 static constexpr std::size_t max_order = 10u;
17
18 static constexpr std::size_t nb_coefficients = max_order * (max_order + 1) / 2;
19
20 static std::array<long double, nb_coefficients> weight;
21
22 static std::array<long double, nb_coefficients> pos;
23};
24
25template <class Dim>
27{
29
30public:
31 static std::size_t max_order()
32 {
33 return glc::max_order;
34 }
35
36 explicit GaussLegendre(std::size_t n)
37 {
38 assert(n > 0);
39 assert(n <= glc::max_order);
40
41 std::size_t const offset = n * (n - 1) / 2;
42 m_wx.resize(n);
43 for (std::size_t i = 0; i < n; ++i) {
44 m_wx[i].first = static_cast<double>(glc::weight[offset + i]);
45 m_wx[i].second = static_cast<ddc::Coordinate<Dim>>(glc::pos[offset + i]);
46 }
47 }
48
49 GaussLegendre(GaussLegendre const& x) = default;
50
51 GaussLegendre(GaussLegendre&& x) = default;
52
53 ~GaussLegendre() = default;
54
55 GaussLegendre& operator=(GaussLegendre const& x) = default;
56
57 GaussLegendre& operator=(GaussLegendre&& x) = default;
58
59 std::size_t order() const
60 {
61 return m_wx.size();
62 }
63
64 template <class F>
65 double integrate(F&& f, double x0, double x1) const
66 {
67 static_assert(std::is_invocable_r_v<double, F, double>, "Functor F not handled");
68 assert(x0 <= x1);
69 double const l = 0.5 * (x1 - x0);
70 double const c = 0.5 * (x0 + x1);
71 double integral = 0;
72 for (std::pair<double, ddc::Coordinate<Dim>> const& wx : m_wx) {
73 integral += wx.first * f(l * wx.second + c);
74 }
75 return l * integral;
76 }
77
78 template <class Domain>
79 void compute_points(ddc::ChunkSpan<ddc::Coordinate<Dim>, Domain> points, double x0, double x1)
80 const
81 {
82 assert(x0 <= x1);
83 assert(points.size() == m_wx.size());
84 // map the interval [-1,1] into the interval [a,b].
85 double const l = 0.5 * (x1 - x0);
86 double const c = 0.5 * (x0 + x1);
87 int const dom_start = points.domain().front().uid();
88 for (auto i : points.domain()) {
89 points(i) = ddc::Coordinate<Dim>(l * m_wx[i.uid() - dom_start].second + c);
90 }
91 }
92
93 template <class Domain>
94 void compute_points_and_weights(
95 ddc::ChunkSpan<ddc::Coordinate<Dim>, Domain> points,
96 ddc::ChunkSpan<double, Domain> weights,
97 ddc::Coordinate<Dim> const& x0,
98 ddc::Coordinate<Dim> const& x1) const
99 {
100 assert(x0 <= x1);
101 assert(points.size() == m_wx.size());
102 // map the interval [-1,1] into the interval [a,b].
103 double const l = 0.5 * (ddc::get<Dim>(x1) - ddc::get<Dim>(x0));
104 ddc::Coordinate<Dim> const c(0.5 * (x0 + x1));
105 int const dom_start = points.domain().front().uid();
106 for (auto i : points.domain()) {
107 weights(i) = l * m_wx[i.uid() - dom_start].first;
108 points(i) = ddc::Coordinate<Dim>(l * m_wx[i.uid() - dom_start].second + c);
109 }
110 }
111
112 template <class Domain1, class Domain2>
113 void compute_points_and_weights_on_mesh(
114 ddc::ChunkSpan<ddc::Coordinate<Dim>, Domain1> points,
115 ddc::ChunkSpan<double, Domain1> weights,
116 ddc::ChunkSpan<const ddc::Coordinate<Dim>, Domain2> mesh_edges) const
117 {
118 [[maybe_unused]] int const nbcells = mesh_edges.size() - 1;
119 int const npts_gauss = m_wx.size();
120 assert(points.size() == m_wx.size() * nbcells);
121 assert(weights.size() == m_wx.size() * nbcells);
122
123 typename Domain1::discrete_element_type start = weights.domain().front();
124 typename Domain1::discrete_vector_type step(npts_gauss);
125 typename Domain1::discrete_element_type local_domain_start = start;
126 ddc::for_each(
127 mesh_edges.domain().remove_last(typename Domain2::discrete_vector_type(1)),
128 [&](auto icell) {
129 ddc::Coordinate<Dim> const x0 = mesh_edges(icell);
130 ddc::Coordinate<Dim> const x1 = mesh_edges(icell + 1);
131
132 Domain1 local_domain(local_domain_start, step);
133 local_domain_start += step;
134
135 compute_points_and_weights(points[local_domain], weights[local_domain], x0, x1);
136 });
137 }
138
139private:
140 std::vector<std::pair<double, ddc::Coordinate<Dim>>> m_wx;
141};
Definition gauss_legendre_integration.hpp:27
Definition gauss_legendre_integration.hpp:15