Gyselalib++
 
Loading...
Searching...
No Matches
simpson_quadrature.hpp
1// SPDX-License-Identifier: MIT
2
3#pragma once
4#include <ddc/ddc.hpp>
5
6#include "ddc_aliases.hpp"
7#include "geometry_descriptors.hpp"
10
22template <class ExecSpace, class Grid1D>
23void fill_simpson_quadrature_coefficients_1d(
24 DField<IdxRange<Grid1D>, typename ExecSpace::memory_space> coefficients)
25{
26 IdxRange<Grid1D> idx_range = get_idx_range(coefficients);
27 if constexpr (Grid1D::continuous_dimension_type::PERIODIC) {
28 if (idx_range.size() % 2 != 0) {
29 throw std::runtime_error(
30 "Simpson quadrature requires 2n quadrature points for a periodic direction.");
31 }
32 } else {
33 if (idx_range.size() % 2 == 0) {
34 throw std::runtime_error("Simpson quadrature requires 2n+1 quadrature points for a "
35 "non-periodic direction.");
36 }
37 }
38
39 Kokkos::parallel_for(
40 "centre_left",
41 Kokkos::RangePolicy<ExecSpace>(
42 0,
43 idx_range.size() / 2 - int(Grid1D::continuous_dimension_type::PERIODIC)),
44 KOKKOS_LAMBDA(const int i) {
45 Idx<Grid1D> idx_c = idx_range.front() + i * 2 + 1;
46 double const dx_l = distance_at_left(idx_c);
47 double const dx_r = distance_at_right(idx_c);
48 double const dx_sum = dx_l + dx_r;
49 coefficients(idx_c - 1) = dx_sum * (2. * dx_l - dx_r) / (6. * dx_l);
50 coefficients(idx_c) = dx_sum * dx_sum * dx_sum / (6. * dx_l * dx_r);
51 });
52
53 // The incrementation is done in a separate loop to avoid race conditions
54 Kokkos::parallel_for(
55 "overlap_increment",
56 Kokkos::RangePolicy<ExecSpace>(
57 0,
58 idx_range.size() / 2 - int(Grid1D::continuous_dimension_type::PERIODIC) - 1),
59 KOKKOS_LAMBDA(const int i) {
60 Idx<Grid1D> idx_c = idx_range.front() + i * 2 + 1;
61 double const dx_l = distance_at_left(idx_c);
62 double const dx_r = distance_at_right(idx_c);
63 double const dx_sum = dx_l + dx_r;
64 coefficients(idx_c + 1) += dx_sum * (2. * dx_r - dx_l) / (6. * dx_r);
65 });
66
67 Kokkos::parallel_for(
68 "bounds",
69 Kokkos::RangePolicy<ExecSpace>(0, 1),
70 KOKKOS_LAMBDA(const int i) {
71 Idx<Grid1D> idx_c
72 = idx_range.back() - 1 - int(Grid1D::continuous_dimension_type::PERIODIC);
73 double const dx_l = distance_at_left(idx_c);
74 double const dx_r = distance_at_right(idx_c);
75 double const dx_sum = dx_l + dx_r;
76 coefficients(idx_c + 1) = dx_sum * (2. * dx_r - dx_l) / (6. * dx_r);
77 });
78
79 if constexpr (Grid1D::continuous_dimension_type::PERIODIC) {
80 Kokkos::parallel_for(
81 "bounds",
82 Kokkos::RangePolicy<ExecSpace>(0, 1),
83 KOKKOS_LAMBDA(const int i) {
84 Idx<Grid1D> idx_c = idx_range.back();
85 double const dx_l = distance_at_left(idx_c);
86 double const dx_r = distance_at_right(idx_c);
87 double const dx_sum = dx_l + dx_r;
88 coefficients(idx_c - 1) += dx_sum * (2. * dx_l - dx_r) / (6. * dx_l);
89 coefficients(idx_c) = dx_sum * dx_sum * dx_sum / (6. * dx_l * dx_r);
90 coefficients(idx_range.front()) += dx_sum * (2. * dx_r - dx_l) / (6. * dx_r);
91 });
92 }
93}
94
108template <class ExecSpace, class Grid1D>
109DFieldMem<IdxRange<Grid1D>, typename ExecSpace::memory_space> simpson_quadrature_coefficients_1d(
110 IdxRange<Grid1D> const& idx_range)
111{
112 DFieldMem<IdxRange<Grid1D>, typename ExecSpace::memory_space> coefficients_alloc(idx_range);
113 fill_simpson_quadrature_coefficients_1d<ExecSpace>(get_field(coefficients_alloc));
114 return coefficients_alloc;
115}
116
130template <class ExecSpace, class Grid1D>
131DFieldMem<IdxRange<Grid1D>, typename ExecSpace::memory_space>
132simpson_trapezoid_quadrature_coefficients_1d(
133 IdxRange<Grid1D> const& idx_range,
134 Extremity trapezoid_extremity)
135{
136 static_assert(
137 !Grid1D::continuous_dimension_type::PERIODIC,
138 "The extremity is non-sensical in a Periodic dimension");
139 try {
140 return simpson_quadrature_coefficients_1d<ExecSpace>(idx_range);
141 } catch (const std::runtime_error& error) {
142 DFieldMem<IdxRange<Grid1D>, typename ExecSpace::memory_space> coefficients_alloc(idx_range);
143 DField<IdxRange<Grid1D>, typename ExecSpace::memory_space> coefficients(
144 get_field(coefficients_alloc));
145 IdxStep<Grid1D> npts_to_remove(1);
146 if (trapezoid_extremity == Extremity::FRONT) {
147 fill_simpson_quadrature_coefficients_1d<ExecSpace>(
148 coefficients_alloc[idx_range.remove_first(npts_to_remove)]);
149 Kokkos::parallel_for(
150 "trapezoid_region",
151 Kokkos::RangePolicy<ExecSpace>(0, 1),
152 KOKKOS_LAMBDA(const int i) {
153 Idx<Grid1D> idx_l = idx_range.front();
154 double dx_cell = 0.5 * distance_at_right(idx_l);
155 coefficients(idx_l) = dx_cell;
156 coefficients(idx_l + 1) += dx_cell;
157 });
158 } else {
159 fill_simpson_quadrature_coefficients_1d<ExecSpace>(
160 coefficients_alloc[idx_range.remove_last(npts_to_remove)]);
161 Kokkos::parallel_for(
162 "trapezoid_region",
163 Kokkos::RangePolicy<ExecSpace>(0, 1),
164 KOKKOS_LAMBDA(const int i) {
165 Idx<Grid1D> idx_r = idx_range.back();
166 double dx_cell = 0.5 * distance_at_left(idx_r);
167 coefficients(idx_r) = dx_cell;
168 coefficients(idx_r - 1) += dx_cell;
169 });
170 }
171 return coefficients_alloc;
172 }
173}
174
188template <class ExecSpace, class... ODims>
189DFieldMem<IdxRange<ODims...>, typename ExecSpace::memory_space> simpson_quadrature_coefficients(
190 IdxRange<ODims...> const& idx_range)
191{
192 return quadrature_coeffs_nd<ExecSpace, ODims...>(
193 idx_range,
194 (std::function<DFieldMem<IdxRange<ODims>, typename ExecSpace::memory_space>(
195 IdxRange<ODims>)>(simpson_quadrature_coefficients_1d<ExecSpace, ODims>))...);
196}
File providing helper functions for defining multi-dimensional quadrature methods.
DFieldMem< IdxRange< DDims... >, typename ExecSpace::memory_space > quadrature_coeffs_nd(IdxRange< DDims... > const &idx_range, std::function< DFieldMem< IdxRange< DDims >, typename ExecSpace::memory_space >(IdxRange< DDims >)>... funcs)
Helper function which creates ND dimensions from N 1D quadrature coefficient functions.
Definition quadrature_coeffs_nd.hpp:31
File providing quadrature coefficients via the trapezoidal method.