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();
57 ddc::Coordinate<continuous_dimension_type>(
58 ddc::discrete_space<BSplines>().rmin() + shift * dx),
59 ddc::Coordinate<continuous_dimension_type>(dx));
62 template <
class Sampling>
63 static auto non_uniform_greville_points()
64 requires(!BSplines::is_uniform())
66 using SamplingImpl = Sampling::
template Impl<Sampling, Kokkos::HostSpace>;
68 std::size_t n_greville_points = 0;
69 if constexpr (BSplines::is_periodic()) {
70 n_greville_points =
ddc::discrete_space<BSplines>().nbasis() + 1;
72 n_greville_points =
ddc::discrete_space<BSplines>().nbasis();
75 std::vector<
double> greville_points(n_greville_points);
77 =
ddc::discrete_space<BSplines>().full_domain().take_first(
83 ddc::DiscreteElement<BSplines> ib0(bspline_domain.front());
85 ddc::host_for_each(bspline_domain, [&](
ddc::DiscreteElement<BSplines> ib) {
87 greville_points[ib - ib0] = 0.0;
89 ddc::discrete_space<BSplines>().get_first_support_knot(ib) + 1,
91 ddc::host_for_each(sub_domain, [&](
auto ik) {
92 greville_points[ib - ib0] +=
ddc::coordinate(ik);
94 greville_points[ib - ib0] /= n_points_in_average.value();
98 if constexpr (BSplines::is_periodic()) {
99 std::vector<
double> temp_knots(BSplines::degree());
100 std::size_t npoints = 0;
102 while (greville_points[npoints] <
ddc::discrete_space<BSplines>().rmin()) {
103 assert(npoints < BSplines::degree());
105 = greville_points[npoints] +
ddc::discrete_space<BSplines>().length();
109 for (std::size_t i = 0; i <
ddc::discrete_space<BSplines>().nbasis() - npoints; ++i) {
110 greville_points[i] = greville_points[i + npoints];
112 for (std::size_t i = 0; i < npoints; ++i) {
113 greville_points[
ddc::discrete_space<BSplines>().nbasis() - npoints + i]
118 greville_points[n_greville_points - 1]
119 = greville_points[0] +
ddc::discrete_space<BSplines>().length();
122 return SamplingImpl(greville_points);
125 static constexpr std::size_t N_BE_MIN = n_boundary_equations(BcLower, BSplines::degree());
126 static constexpr std::size_t N_BE_MAX = n_boundary_equations(BcUpper, BSplines::degree());
127 static constexpr std::size_t N_BE = N_BE_MIN + N_BE_MAX;
129 static constexpr bool is_uniform_discrete_dimension_v
130 = U::is_uniform() && ((N_BE_MIN != 0 && N_BE_MAX != 0) || U::is_periodic());
134
135
136
137
138
139
140
141
142
143
144 template <
class Sampling>
145 static auto get_sampling()
146 requires(is_uniform_discrete_dimension_v<BSplines>)
148 return uniform_greville_points<Sampling>();
152
153
154
155
156
157
158 template <
class Sampling>
159 static auto get_sampling()
160 requires(!is_uniform_discrete_dimension_v<BSplines>)
162 using SamplingImpl = Sampling::
template Impl<Sampling, Kokkos::HostSpace>;
163 if constexpr (BSplines::is_uniform()) {
164 using IntermediateSampling = IntermediateUniformSampling<Sampling>;
165 auto points_wo_bcs = uniform_greville_points<IntermediateSampling>();
166 std::size_t
const n_break_points =
ddc::discrete_space<BSplines>().ncells() + 1;
167 if constexpr (N_BE > 0) {
168 assert(
ddc::discrete_space<BSplines>().nbasis() >= N_BE);
170 std::size_t
const npoints =
ddc::discrete_space<BSplines>().nbasis() - N_BE;
171 std::vector<
double> points_with_bcs(npoints);
175 for (std::size_t i(0); i < BSplines::degree() / 2 + 1; ++i) {
177 = (BSplines::degree() - i) *
ddc::discrete_space<BSplines>().rmin();
178 ddc::DiscreteElement<BSplines>
const spline_idx(i);
181 ddc::discrete_space<BSplines>().get_last_support_knot(spline_idx)
187 points_with_bcs[i] +=
ddc::coordinate(ik);
189 points_with_bcs[i] /= BSplines::degree();
193 = points_wo_bcs.coordinate(
ddc::DiscreteElement<IntermediateSampling>(0));
196 std::size_t
const n_start
198 std::size_t
const domain_size = n_break_points - 2;
199 ddc::DiscreteElement<IntermediateSampling> domain_start(1);
204 ddc::host_for_each(domain, [&](
auto ip) {
205 points_with_bcs[ip - domain_start + n_start] = points_wo_bcs.coordinate(ip);
210 for (std::size_t i(0); i < BSplines::degree() / 2 + 1; ++i) {
211 points_with_bcs[npoints - 1 - i]
212 = (BSplines::degree() - i) *
ddc::discrete_space<BSplines>().rmax();
213 ddc::DiscreteElement<BSplines>
const spline_idx(
214 ddc::discrete_space<BSplines>().nbasis() - 1 - i);
217 ddc::discrete_space<BSplines>().get_first_support_knot(spline_idx) + 1,
222 points_with_bcs[npoints - 1 - i] +=
ddc::coordinate(ik);
224 points_with_bcs[npoints - 1 - i] /= BSplines::degree();
227 points_with_bcs[npoints - 1] = points_wo_bcs.coordinate(
228 ddc::DiscreteElement<IntermediateSampling>(
229 ddc::discrete_space<BSplines>().ncells() - 1
230 + BSplines::degree() % 2));
232 return SamplingImpl(points_with_bcs);
234 using IntermediateSampling = IntermediateNonUniformSampling<Sampling>;
235 if constexpr (N_BE == 0) {
236 return non_uniform_greville_points<Sampling>();
238 auto points_wo_bcs = non_uniform_greville_points<IntermediateSampling>();
240 std::vector<
double> points_with_bcs(points_wo_bcs.size() - N_BE);
241 std::size_t
constexpr n_start = N_BE_MIN;
245 ddc::DiscreteElement<IntermediateSampling> domain_start(n_start);
247 domain(domain_start, length(points_with_bcs.size()));
249 points_with_bcs[0] = points_wo_bcs.coordinate(domain.front());
250 ddc::host_for_each(domain.remove(length(1), length(1)), [&](
auto ip) {
251 points_with_bcs[ip - domain_start] = points_wo_bcs.coordinate(ip);
253 points_with_bcs[points_with_bcs.size() - 1]
254 = points_wo_bcs.coordinate(domain.back());
256 return SamplingImpl(points_with_bcs);
262
263
264
265
266 using interpolation_discrete_dimension_type = std::conditional_t<
267 is_uniform_discrete_dimension_v<BSplines>,
272
273
274
275
276
277
278 template <
class Sampling>
281 std::size_t
const npoints =
ddc::discrete_space<BSplines>().nbasis() - N_BE;
283 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...