13#include <Kokkos_Core.hpp>
15#include "bsplines_non_uniform.hpp"
16#include "bsplines_uniform.hpp"
17#include "spline_boundary_conditions.hpp"
22
23
24
25
26
27
31 using continuous_dimension_type =
typename BSplines::continuous_dimension_type;
33 template <
class Sampling>
34 struct IntermediateUniformSampling
39 template <
class Sampling>
40 struct IntermediateNonUniformSampling
45 template <
class Sampling,
typename U = BSplines,
class = std::enable_if_t<U::is_uniform()>>
46 static auto uniform_greville_points()
48 using SamplingImpl =
typename Sampling::
template Impl<Sampling, Kokkos::HostSpace>;
50 double constexpr shift = (BSplines::degree() % 2 == 0) ? 0.5 : 0.0;
52 = (
ddc::discrete_space<BSplines>().rmax() -
ddc::discrete_space<BSplines>().rmin())
53 /
ddc::discrete_space<BSplines>().ncells();
55 ddc::Coordinate<continuous_dimension_type>(
56 ddc::discrete_space<BSplines>().rmin() + shift * dx),
57 ddc::Coordinate<continuous_dimension_type>(dx));
60 template <
class Sampling,
typename U = BSplines,
class = std::enable_if_t<!U::is_uniform()>>
61 static auto non_uniform_greville_points()
63 using SamplingImpl =
typename Sampling::
template Impl<Sampling, Kokkos::HostSpace>;
65 int n_greville_points = 0;
66 if constexpr (U::is_periodic()) {
67 n_greville_points =
ddc::discrete_space<BSplines>().nbasis() + 1;
69 n_greville_points =
ddc::discrete_space<BSplines>().nbasis();
72 std::vector<
double> greville_points(n_greville_points);
74 =
ddc::discrete_space<BSplines>().full_domain().take_first(
80 ddc::DiscreteElement<BSplines> ib0(bspline_domain.front());
82 ddc::host_for_each(bspline_domain, [&](
ddc::DiscreteElement<BSplines> ib) {
84 greville_points[ib - ib0] = 0.0;
86 ddc::discrete_space<BSplines>().get_first_support_knot(ib) + 1,
88 ddc::host_for_each(sub_domain, [&](
auto ik) {
89 greville_points[ib - ib0] +=
ddc::coordinate(ik);
91 greville_points[ib - ib0] /= n_points_in_average.value();
95 if constexpr (U::is_periodic()) {
96 std::vector<
double> temp_knots(BSplines::degree());
99 while (greville_points[npoints] <
ddc::discrete_space<BSplines>().rmin()) {
101 = greville_points[npoints] +
ddc::discrete_space<BSplines>().length();
105 for (std::size_t i = 0; i <
ddc::discrete_space<BSplines>().nbasis() - npoints; ++i) {
106 greville_points[i] = greville_points[i + npoints];
108 for (
int i = 0; i < npoints; ++i) {
109 greville_points[
ddc::discrete_space<BSplines>().nbasis() - npoints + i]
114 greville_points[n_greville_points - 1]
115 = greville_points[0] +
ddc::discrete_space<BSplines>().length();
118 return SamplingImpl(greville_points);
121 static constexpr int N_BE_MIN = n_boundary_equations(BcLower, BSplines::degree());
122 static constexpr int N_BE_MAX = n_boundary_equations(BcUpper, BSplines::degree());
124 static constexpr bool is_uniform_discrete_dimension_v
125 = U::is_uniform() && ((N_BE_MIN != 0 && N_BE_MAX != 0) || U::is_periodic());
129
130
131
132
133
134
135
136
137
138
141 typename U = BSplines,
143 is_uniform_discrete_dimension_v<U>,
148 return uniform_greville_points<Sampling>();
152
153
154
155
156
157
160 typename U = BSplines,
162 !is_uniform_discrete_dimension_v<U>,
167 using SamplingImpl =
typename Sampling::
template Impl<Sampling, Kokkos::HostSpace>;
168 if constexpr (U::is_uniform()) {
169 using IntermediateSampling = IntermediateUniformSampling<Sampling>;
170 auto points_wo_bcs = uniform_greville_points<IntermediateSampling>();
171 int const n_break_points =
ddc::discrete_space<BSplines>().ncells() + 1;
172 int const npoints =
ddc::discrete_space<BSplines>().nbasis() - N_BE_MIN - N_BE_MAX;
173 std::vector<
double> points_with_bcs(npoints);
177 for (std::size_t i(0); i < BSplines::degree() / 2 + 1; ++i) {
179 = (BSplines::degree() - i) *
ddc::discrete_space<BSplines>().rmin();
180 ddc::DiscreteElement<BSplines>
const spline_idx(i);
183 ddc::discrete_space<BSplines>().get_last_support_knot(spline_idx)
189 points_with_bcs[i] +=
ddc::coordinate(ik);
191 points_with_bcs[i] /= BSplines::degree();
195 = points_wo_bcs.coordinate(
ddc::DiscreteElement<IntermediateSampling>(0));
200 int const domain_size = n_break_points - 2;
201 ddc::DiscreteElement<IntermediateSampling> domain_start(1);
206 ddc::host_for_each(domain, [&](
auto ip) {
207 points_with_bcs[ip - domain_start + n_start] = points_wo_bcs.coordinate(ip);
212 for (std::size_t i(0); i < BSplines::degree() / 2 + 1; ++i) {
213 points_with_bcs[npoints - 1 - i]
214 = (BSplines::degree() - i) *
ddc::discrete_space<BSplines>().rmax();
215 ddc::DiscreteElement<BSplines>
const spline_idx(
216 ddc::discrete_space<BSplines>().nbasis() - 1 - i);
219 ddc::discrete_space<BSplines>().get_first_support_knot(spline_idx) + 1,
224 points_with_bcs[npoints - 1 - i] +=
ddc::coordinate(ik);
226 points_with_bcs[npoints - 1 - i] /= BSplines::degree();
229 points_with_bcs[npoints - 1] = points_wo_bcs.coordinate(
230 ddc::DiscreteElement<IntermediateSampling>(
231 ddc::discrete_space<BSplines>().ncells() - 1
232 + BSplines::degree() % 2));
234 return SamplingImpl(points_with_bcs);
236 using IntermediateSampling = IntermediateNonUniformSampling<Sampling>;
237 if constexpr (N_BE_MIN == 0 && N_BE_MAX == 0) {
238 return non_uniform_greville_points<Sampling>();
240 auto points_wo_bcs = non_uniform_greville_points<IntermediateSampling>();
242 std::vector<
double> points_with_bcs(points_wo_bcs.size() - N_BE_MIN - N_BE_MAX);
243 int constexpr n_start = N_BE_MIN;
247 ddc::DiscreteElement<IntermediateSampling> domain_start(n_start);
249 domain(domain_start, length(points_with_bcs.size()));
251 points_with_bcs[0] = points_wo_bcs.coordinate(domain.front());
252 ddc::host_for_each(domain.remove(length(1), length(1)), [&](
auto ip) {
253 points_with_bcs[ip - domain_start] = points_wo_bcs.coordinate(ip);
255 points_with_bcs[points_with_bcs.size() - 1]
256 = points_wo_bcs.coordinate(domain.back());
258 return SamplingImpl(points_with_bcs);
264
265
266
267
268 using interpolation_discrete_dimension_type = std::conditional_t<
269 is_uniform_discrete_dimension_v<BSplines>,
274
275
276
277
278
279
280 template <
class Sampling>
283 int const npoints =
ddc::discrete_space<BSplines>().nbasis() - N_BE_MIN - N_BE_MAX;
285 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.
static auto get_sampling()
Get the UniformPointSampling defining the Greville points.
The top-level namespace of DDC.
BoundCond
An enum representing a spline boundary condition.
@ GREVILLE
Use Greville points instead of conditions on derivative for B-Spline interpolation.