14#include <Kokkos_Core.hpp>
23
24
25
26
27
28
32 using continuous_dimension_type = BSplines::continuous_dimension_type;
34 template <
class Sampling>
35 struct IntermediateUniformSampling
40 template <
class Sampling>
41 struct IntermediateNonUniformSampling
46 template <
class Sampling>
47 static auto uniform_greville_points()
48 requires(BSplines::is_uniform())
50 using SamplingImpl = Sampling::
template Impl<Sampling, Kokkos::HostSpace>;
52 double constexpr shift = (BSplines::degree() % 2 == 0) ? 0.5 : 0.0;
54 = (
ddc::discrete_space<BSplines>().rmax() -
ddc::discrete_space<BSplines>().rmin())
55 /
ddc::discrete_space<BSplines>().ncells();
56 if constexpr (
ddc::is_uniform_point_sampling_v<Sampling>) {
58 ddc::Coordinate<continuous_dimension_type>(
59 ddc::discrete_space<BSplines>().rmin() + shift * dx),
60 ddc::Coordinate<continuous_dimension_type>(dx));
62 std::size_t
const npoints =
ddc::discrete_space<BSplines>().nbasis() - N_BE;
63 std::vector<
ddc::Coordinate<continuous_dimension_type>> grid_points(npoints);
64 for (std::size_t i(0); i < npoints; ++i) {
65 grid_points[i] =
ddc::discrete_space<BSplines>().rmin() + (shift + i) * dx;
67 return SamplingImpl(grid_points);
71 template <
class Sampling>
72 static auto non_uniform_greville_points()
73 requires(!BSplines::is_uniform())
75 using SamplingImpl = Sampling::
template Impl<Sampling, Kokkos::HostSpace>;
77 std::size_t n_greville_points = 0;
78 if constexpr (BSplines::is_periodic()) {
79 n_greville_points =
ddc::discrete_space<BSplines>().nbasis() + 1;
81 n_greville_points =
ddc::discrete_space<BSplines>().nbasis();
84 std::vector<
double> greville_points(n_greville_points);
86 =
ddc::discrete_space<BSplines>().full_domain().take_first(
92 ddc::DiscreteElement<BSplines> ib0(bspline_domain.front());
94 ddc::host_for_each(bspline_domain, [&](
ddc::DiscreteElement<BSplines> ib) {
96 greville_points[ib - ib0] = 0.0;
98 ddc::discrete_space<BSplines>().get_first_support_knot(ib) + 1,
100 ddc::host_for_each(sub_domain, [&](
auto ik) {
101 greville_points[ib - ib0] +=
ddc::coordinate(ik);
103 greville_points[ib - ib0] /= n_points_in_average.value();
107 if constexpr (BSplines::is_periodic()) {
108 std::vector<
double> temp_knots(BSplines::degree());
109 std::size_t npoints = 0;
111 while (greville_points[npoints] <
ddc::discrete_space<BSplines>().rmin()) {
112 assert(npoints < BSplines::degree());
114 = greville_points[npoints] +
ddc::discrete_space<BSplines>().length();
118 for (std::size_t i = 0; i <
ddc::discrete_space<BSplines>().nbasis() - npoints; ++i) {
119 greville_points[i] = greville_points[i + npoints];
121 for (std::size_t i = 0; i < npoints; ++i) {
122 greville_points[
ddc::discrete_space<BSplines>().nbasis() - npoints + i]
127 greville_points[n_greville_points - 1]
128 = greville_points[0] +
ddc::discrete_space<BSplines>().length();
131 return SamplingImpl(greville_points);
134 static constexpr std::size_t N_BE_MIN = n_boundary_equations(BcLower, BSplines::degree());
135 static constexpr std::size_t N_BE_MAX = n_boundary_equations(BcUpper, BSplines::degree());
136 static constexpr std::size_t N_BE = N_BE_MIN + N_BE_MAX;
138 static constexpr bool is_uniform_discrete_dimension_v
139 = U::is_uniform() && ((N_BE_MIN != 0 && N_BE_MAX != 0) || U::is_periodic());
143
144
145
146
147
148
149
150
151
152
153 template <
class Sampling>
154 static auto get_sampling()
155 requires(is_uniform_discrete_dimension_v<BSplines>)
157 return uniform_greville_points<Sampling>();
161
162
163
164
165
166
167 template <
class Sampling>
168 static auto get_sampling()
169 requires(!is_uniform_discrete_dimension_v<BSplines>)
171 using SamplingImpl = Sampling::
template Impl<Sampling, Kokkos::HostSpace>;
172 if constexpr (BSplines::is_uniform()) {
173 using IntermediateSampling = IntermediateUniformSampling<Sampling>;
174 auto points_wo_bcs = uniform_greville_points<IntermediateSampling>();
175 std::size_t
const n_break_points =
ddc::discrete_space<BSplines>().ncells() + 1;
176 if constexpr (N_BE > 0) {
177 assert(
ddc::discrete_space<BSplines>().nbasis() >= N_BE);
179 std::size_t
const npoints =
ddc::discrete_space<BSplines>().nbasis() - N_BE;
180 std::vector<
double> points_with_bcs(npoints);
184 for (std::size_t i(0); i < BSplines::degree() / 2 + 1; ++i) {
186 = (BSplines::degree() - i) *
ddc::discrete_space<BSplines>().rmin();
187 ddc::DiscreteElement<BSplines>
const spline_idx(i);
190 ddc::discrete_space<BSplines>().get_last_support_knot(spline_idx)
196 points_with_bcs[i] +=
ddc::coordinate(ik);
198 points_with_bcs[i] /= BSplines::degree();
202 = points_wo_bcs.coordinate(
ddc::DiscreteElement<IntermediateSampling>(0));
205 std::size_t
const n_start
207 std::size_t
const domain_size = n_break_points - 2;
208 ddc::DiscreteElement<IntermediateSampling> domain_start(1);
213 ddc::host_for_each(domain, [&](
auto ip) {
214 points_with_bcs[ip - domain_start + n_start] = points_wo_bcs.coordinate(ip);
219 for (std::size_t i(0); i < BSplines::degree() / 2 + 1; ++i) {
220 points_with_bcs[npoints - 1 - i]
221 = (BSplines::degree() - i) *
ddc::discrete_space<BSplines>().rmax();
222 ddc::DiscreteElement<BSplines>
const spline_idx(
223 ddc::discrete_space<BSplines>().nbasis() - 1 - i);
226 ddc::discrete_space<BSplines>().get_first_support_knot(spline_idx) + 1,
231 points_with_bcs[npoints - 1 - i] +=
ddc::coordinate(ik);
233 points_with_bcs[npoints - 1 - i] /= BSplines::degree();
236 points_with_bcs[npoints - 1] = points_wo_bcs.coordinate(
237 ddc::DiscreteElement<IntermediateSampling>(
238 ddc::discrete_space<BSplines>().ncells() - 1
239 + BSplines::degree() % 2));
241 return SamplingImpl(points_with_bcs);
243 using IntermediateSampling = IntermediateNonUniformSampling<Sampling>;
244 if constexpr (N_BE == 0) {
245 return non_uniform_greville_points<Sampling>();
247 auto points_wo_bcs = non_uniform_greville_points<IntermediateSampling>();
249 std::vector<
double> points_with_bcs(points_wo_bcs.size() - N_BE);
250 std::size_t
constexpr n_start = N_BE_MIN;
254 ddc::DiscreteElement<IntermediateSampling> domain_start(n_start);
256 domain(domain_start, length(points_with_bcs.size()));
258 points_with_bcs[0] = points_wo_bcs.coordinate(domain.front());
259 ddc::host_for_each(domain.remove(length(1), length(1)), [&](
auto ip) {
260 points_with_bcs[ip - domain_start] = points_wo_bcs.coordinate(ip);
262 points_with_bcs[points_with_bcs.size() - 1]
263 = points_wo_bcs.coordinate(domain.back());
265 return SamplingImpl(points_with_bcs);
271
272
273
274
275 using interpolation_discrete_dimension_type = std::conditional_t<
276 is_uniform_discrete_dimension_v<BSplines>,
281
282
283
284
285
286
287 template <
class Sampling>
290 std::size_t
const npoints =
ddc::discrete_space<BSplines>().nbasis() - N_BE;
292 ddc::DiscreteElement<Sampling>(0),
friend class DiscreteDomain
KOKKOS_FUNCTION constexpr bool operator!=(DiscreteVector< OTags... > const &rhs) const noexcept
A class which provides helper functions to initialise the Greville points from a B-Spline definition.
static ddc::DiscreteDomain< Sampling > get_domain()
Get the domain which gives us access to all of the Greville points.
The top-level namespace of DDC.
constexpr bool is_uniform_bsplines_v
Indicates if a tag corresponds to uniform B-splines or not.
BoundCond
An enum representing a spline boundary condition.
@ GREVILLE
Use Greville points instead of conditions on derivative for B-Spline interpolation.
constexpr bool is_non_uniform_bsplines_v
Indicates if a tag corresponds to non-uniform B-splines or not.
A templated struct representing a discrete dimension storing the derivatives of a function along a co...