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