DDC 0.10.0
Loading...
Searching...
No Matches
integrals.hpp
1// Copyright (C) The DDC development team, see COPYRIGHT.md file
2//
3// SPDX-License-Identifier: MIT
4
5#pragma once
6
7#include <array>
8#include <cassert>
9#include <cstddef>
10
11#include <ddc/ddc.hpp>
12
13#include <Kokkos_Core.hpp>
14
15#include "bsplines_non_uniform.hpp"
16#include "bsplines_uniform.hpp"
17#include "math_tools.hpp"
18
19namespace ddc {
20
21namespace detail {
22
23/** @brief Compute the integrals of the uniform B-splines.
24 *
25 * The integral of each of the B-splines over their support within the domain on which this basis was defined.
26 *
27 * @param[in] execution_space a Kokkos execution space where the loop will be executed on
28 * @param[out] int_vals The values of the integrals. It has to be a 1D Chunkspan of size (nbasis).
29 */
30template <class ExecSpace, class DDim, class Layout, class MemorySpace>
31void uniform_bsplines_integrals(
32 ExecSpace const& execution_space,
33 ddc::ChunkSpan<double, ddc::DiscreteDomain<DDim>, Layout, MemorySpace> int_vals)
34{
35 static_assert(is_uniform_bsplines_v<DDim>);
36 static_assert(
37 Kokkos::SpaceAccessibility<ExecSpace, MemorySpace>::accessible,
38 "MemorySpace has to be accessible for ExecutionSpace.");
39
40 assert([&]() -> bool {
41 if constexpr (DDim::is_periodic()) {
42 return int_vals.size() == ddc::discrete_space<DDim>().nbasis()
43 || int_vals.size() == ddc::discrete_space<DDim>().size();
44 } else {
45 return int_vals.size() == ddc::discrete_space<DDim>().nbasis();
46 }
47 }());
48
49 ddc::DiscreteDomain<DDim> const full_dom_splines(ddc::discrete_space<DDim>().full_domain());
50
51 if constexpr (DDim::is_periodic()) {
52 ddc::DiscreteDomain<DDim> const dom_bsplines(full_dom_splines.take_first(
53 ddc::DiscreteVector<DDim> {ddc::discrete_space<DDim>().nbasis()}));
54 ddc::parallel_fill(
55 execution_space,
56 int_vals[dom_bsplines],
57 ddc::step<UniformBsplinesKnots<DDim>>());
58 if (int_vals.size() == ddc::discrete_space<DDim>().size()) {
59 ddc::DiscreteDomain<DDim> const dom_bsplines_repeated(
60 full_dom_splines.take_last(ddc::DiscreteVector<DDim> {DDim::degree()}));
61 ddc::parallel_fill(execution_space, int_vals[dom_bsplines_repeated], 0);
62 }
63 } else {
64 ddc::DiscreteDomain<DDim> const dom_bspline_entirely_in_domain
65 = full_dom_splines
66 .remove(ddc::DiscreteVector<DDim>(DDim::degree()),
67 ddc::DiscreteVector<DDim>(DDim::degree()));
68 ddc::parallel_fill(
69 execution_space,
70 int_vals[dom_bspline_entirely_in_domain],
71 ddc::step<UniformBsplinesKnots<DDim>>());
72
73 ddc::DiscreteElement<DDim> const first_bspline = full_dom_splines.front();
74 ddc::DiscreteElement<DDim> const last_bspline = full_dom_splines.back();
75
76 Kokkos::parallel_for(
77 Kokkos::RangePolicy<
78 ExecSpace,
79 Kokkos::IndexType<std::size_t>>(execution_space, 0, DDim::degree()),
80 KOKKOS_LAMBDA(std::size_t i) {
81 std::array<double, DDim::degree() + 2> edge_vals_ptr;
82 Kokkos::mdspan<double, Kokkos::extents<std::size_t, DDim::degree() + 2>> const
83 edge_vals(edge_vals_ptr.data());
84
85 ddc::discrete_space<DDim>().eval_basis(
86 edge_vals,
87 ddc::discrete_space<DDim>().rmin(),
88 DDim::degree() + 1);
89
90 double const d_eval = ddc::detail::sum(edge_vals);
91
92 double const c_eval = ddc::detail::sum(edge_vals, 0, DDim::degree() - i);
93
94 double const edge_value
95 = ddc::step<UniformBsplinesKnots<DDim>>() * (d_eval - c_eval);
96
97 int_vals(first_bspline + i) = edge_value;
98 int_vals(last_bspline - i) = edge_value;
99 });
100 }
101}
102
103/** @brief Compute the integrals of the non uniform B-splines.
104 *
105 * The integral of each of the B-splines over their support within the domain on which this basis was defined.
106 *
107 * @param[in] execution_space a Kokkos execution space where the loop will be executed on
108 * @param[out] int_vals The values of the integrals. It has to be a 1D Chunkspan of size (nbasis).
109 */
110template <class ExecSpace, class DDim, class Layout, class MemorySpace>
111void non_uniform_bsplines_integrals(
112 ExecSpace const& execution_space,
113 ddc::ChunkSpan<double, ddc::DiscreteDomain<DDim>, Layout, MemorySpace> int_vals)
114{
115 static_assert(is_non_uniform_bsplines_v<DDim>);
116 static_assert(
117 Kokkos::SpaceAccessibility<ExecSpace, MemorySpace>::accessible,
118 "MemorySpace has to be accessible for ExecutionSpace.");
119
120 assert([&]() -> bool {
121 if constexpr (DDim::is_periodic()) {
122 return int_vals.size() == ddc::discrete_space<DDim>().nbasis()
123 || int_vals.size() == ddc::discrete_space<DDim>().size();
124 } else {
125 return int_vals.size() == ddc::discrete_space<DDim>().nbasis();
126 }
127 }());
128
129 ddc::DiscreteDomain<DDim> const full_dom_splines(ddc::discrete_space<DDim>().full_domain());
130
131 double const inv_deg = 1.0 / (DDim::degree() + 1);
132
133 ddc::DiscreteDomain<DDim> const dom_bsplines(full_dom_splines.take_first(
134 ddc::DiscreteVector<DDim> {ddc::discrete_space<DDim>().nbasis()}));
135 ddc::parallel_for_each(
136 execution_space,
137 dom_bsplines,
138 KOKKOS_LAMBDA(ddc::DiscreteElement<DDim> ix) {
139 int_vals(ix)
140 = (ddc::coordinate(ddc::discrete_space<DDim>().get_last_support_knot(ix))
141 - ddc::coordinate(
142 ddc::discrete_space<DDim>().get_first_support_knot(ix)))
143 * inv_deg;
144 });
145
146 if constexpr (DDim::is_periodic()) {
147 if (int_vals.size() == ddc::discrete_space<DDim>().size()) {
148 ddc::DiscreteDomain<DDim> const dom_bsplines_wrap(
149 full_dom_splines.take_last(ddc::DiscreteVector<DDim> {DDim::degree()}));
150 ddc::parallel_fill(execution_space, int_vals[dom_bsplines_wrap], 0);
151 }
152 }
153}
154
155} // namespace detail
156
157/** @brief Compute the integrals of the B-splines.
158 *
159 * The integral of each of the B-splines over their support within the domain on which this basis was defined.
160 *
161 * @param[in] execution_space a Kokkos execution space where the loop will be executed on
162 * @param[out] int_vals The values of the integrals. It has to be a 1D Chunkspan of size (nbasis).
163 * @return The values of the integrals.
164 */
165template <class ExecSpace, class DDim, class Layout, class MemorySpace>
166ddc::ChunkSpan<double, ddc::DiscreteDomain<DDim>, Layout, MemorySpace> integrals(
167 ExecSpace const& execution_space,
168 ddc::ChunkSpan<double, ddc::DiscreteDomain<DDim>, Layout, MemorySpace> int_vals)
169{
170 static_assert(is_uniform_bsplines_v<DDim> || is_non_uniform_bsplines_v<DDim>);
171 if constexpr (is_uniform_bsplines_v<DDim>) {
172 uniform_bsplines_integrals(execution_space, int_vals);
173 } else if constexpr (is_non_uniform_bsplines_v<DDim>) {
174 non_uniform_bsplines_integrals(execution_space, int_vals);
175 }
176 return int_vals;
177}
178
179} // namespace ddc
friend class ChunkSpan
friend class DiscreteDomain
KOKKOS_FUNCTION constexpr bool operator!=(DiscreteVector< OTags... > const &rhs) const noexcept
The top-level namespace of DDC.
ddc::ChunkSpan< double, ddc::DiscreteDomain< DDim >, Layout, MemorySpace > integrals(ExecSpace const &execution_space, ddc::ChunkSpan< double, ddc::DiscreteDomain< DDim >, Layout, MemorySpace > int_vals)
Compute the integrals of the B-splines.