DDC 0.4.1
Loading...
Searching...
No Matches
bsplines_uniform.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 <memory>
10#include <tuple>
11
12#include <ddc/ddc.hpp>
13
14#include "math_tools.hpp"
15#include "view.hpp"
16
17namespace ddc {
18
19namespace detail {
20
21struct UniformBSplinesBase
22{
23};
24
25template <class ExecSpace, class ODDim, class Layout, class OMemorySpace>
26void uniform_bsplines_integrals(
27 ExecSpace const& execution_space,
28 ddc::ChunkSpan<double, ddc::DiscreteDomain<ODDim>, Layout, OMemorySpace> int_vals);
29
30} // namespace detail
31
32template <class T>
34{
35};
36
37/**
38 * The type of a uniform 1D spline basis (B-spline).
39 *
40 * Knots for uniform B-splines are uniformly distributed (the associated discrete dimension
41 * is a UniformPointSampling).
42 *
43 * @tparam CDim The tag identifying the continuous dimension on which the support of the B-spline functions are defined.
44 * @tparam D The degree of the B-splines.
45 */
46template <class CDim, std::size_t D>
47class UniformBSplines : detail::UniformBSplinesBase
48{
49 static_assert(D > 0, "Parameter `D` must be positive");
50
51public:
52 /// @brief The tag identifying the continuous dimension on which the support of the B-splines are defined.
53 using continuous_dimension_type = CDim;
54
55 /// @brief The discrete dimension representing B-splines.
56 using discrete_dimension_type = UniformBSplines;
57
58 /** @brief The degree of B-splines.
59 *
60 * @return The degree.
61 */
62 static constexpr std::size_t degree() noexcept
63 {
64 return D;
65 }
66
67 /** @brief Indicates if the B-splines are periodic or not.
68 *
69 * @return A boolean indicating if the B-splines are periodic or not.
70 */
71 static constexpr bool is_periodic() noexcept
72 {
73 return CDim::PERIODIC;
74 }
75
76 /** @brief Indicates if the B-splines are uniform or not (this is the case here).
77 *
78 * @return A boolean indicating if the B-splines are uniform or not.
79 */
80 static constexpr bool is_uniform() noexcept
81 {
82 return true;
83 }
84
85 /** @brief Storage class of the static attributes of the discrete dimension.
86 *
87 * @tparam DDim The name of the discrete dimension.
88 * @tparam MemorySpace The Kokkos memory space where the attributes are being stored.
89 */
90 template <class DDim, class MemorySpace>
91 class Impl
92 {
93 template <class ODDim, class OMemorySpace>
94 friend class Impl;
95
96 template <class ExecSpace, class ODDim, class Layout, class OMemorySpace>
97 friend void detail::uniform_bsplines_integrals(
98 ExecSpace const& execution_space,
99 ddc::ChunkSpan<double, ddc::DiscreteDomain<ODDim>, Layout, OMemorySpace> int_vals);
100
101 public:
102 /// @brief The type of the knots defining the B-splines.
103 using knot_discrete_dimension_type = UniformBsplinesKnots<DDim>;
104
105 /// @brief The type of the discrete dimension representing the B-splines.
106 using discrete_dimension_type = UniformBSplines;
107
108 /// @brief The type of a DiscreteDomain whose elements identify the B-splines.
109 using discrete_domain_type = DiscreteDomain<DDim>;
110
111 /// @brief The type of a DiscreteElement identifying a B-spline.
112 using discrete_element_type = DiscreteElement<DDim>;
113
114 /// @brief The type of a DiscreteVector representing an "index displacement" between two B-splines.
115 using discrete_vector_type = DiscreteVector<DDim>;
116
117 private:
118 // In the periodic case, they contain the periodic point twice!!!
119 ddc::DiscreteDomain<knot_discrete_dimension_type> m_knot_domain;
120 ddc::DiscreteDomain<knot_discrete_dimension_type> m_break_point_domain;
121
122 public:
123 Impl() = default;
124
125 /** Constructs a spline basis (B-splines) with n equidistant knots over \f$[a, b]\f$.
126 *
127 * @param rmin The real ddc::coordinate of the first knot.
128 * @param rmax The real ddc::coordinate of the last knot.
129 * @param ncells The number of cells in the range [rmin, rmax].
130 */
131 explicit Impl(ddc::Coordinate<CDim> rmin, ddc::Coordinate<CDim> rmax, std::size_t ncells)
132 {
133 assert(ncells > 0);
134 std::tie(m_break_point_domain, m_knot_domain, std::ignore, std::ignore)
135 = ddc::init_discrete_space<knot_discrete_dimension_type>(
136 knot_discrete_dimension_type::template init_ghosted<
137 knot_discrete_dimension_type>(
138 rmin,
139 rmax,
140 ddc::DiscreteVector<knot_discrete_dimension_type>(ncells + 1),
141 ddc::DiscreteVector<knot_discrete_dimension_type>(degree()),
142 ddc::DiscreteVector<knot_discrete_dimension_type>(degree())));
143 }
144
145 /** @brief Copy-constructs from another Impl with a different Kokkos memory space.
146 *
147 * @param impl A reference to the other Impl.
148 */
149 template <class OriginMemorySpace>
150 explicit Impl(Impl<DDim, OriginMemorySpace> const& impl)
151 : m_knot_domain(impl.m_knot_domain)
152 , m_break_point_domain(impl.m_break_point_domain)
153 {
154 }
155
156 /** @brief Copy-constructs.
157 *
158 * @param x A reference to another Impl.
159 */
160 Impl(Impl const& x) = default;
161
162 /** @brief Move-constructs.
163 *
164 * @param x An rvalue to another Impl.
165 */
166 Impl(Impl&& x) = default;
167
168 /// @brief Destructs.
169 ~Impl() = default;
170
171 /** @brief Copy-assigns.
172 *
173 * @param x A reference to another Impl.
174 * @return A reference to the copied Impl.
175 */
176 Impl& operator=(Impl const& x) = default;
177
178 /** @brief Move-assigns.
179 *
180 * @param x An rvalue to another Impl.
181 * @return A reference to this object.
182 */
183 Impl& operator=(Impl&& x) = default;
184
185 /** @brief Evaluates non-zero B-splines at a given coordinate.
186 *
187 * The values are computed for every B-spline with support at the given coordinate x. There are only (degree+1)
188 * B-splines which are non-zero at any given point. It is these B-splines which are evaluated.
189 * This can be useful to calculate a spline approximation of a function. A spline approximation at coordinate x
190 * is a linear combination of these B-spline evaluations weighted with the spline coefficients of the spline-transformed
191 * initial discrete function.
192 *
193 * @param[out] values The values of the B-splines evaluated at coordinate x. It has to be a 1D mdspan with (degree+1) elements.
194 * @param[in] x The coordinate where B-splines are evaluated. It has to be in the range of break points coordinates.
195 * @return The index of the first B-spline which is evaluated.
196 */
197 KOKKOS_INLINE_FUNCTION discrete_element_type
198 eval_basis(DSpan1D values, ddc::Coordinate<CDim> const& x) const
199 {
200 assert(values.size() == degree() + 1);
201 return eval_basis(values, x, degree());
202 }
203
204 /** @brief Evaluates non-zero B-spline derivatives at a given coordinate
205 *
206 * The derivatives are computed for every B-spline with support at the given coordinate x. There are only (degree+1)
207 * B-splines which are non-zero at any given point. It is these B-splines which are differentiated.
208 * A spline approximation of a derivative at coordinate x is a linear
209 * combination of those B-spline derivatives weighted with the spline coefficients of the spline-transformed
210 * initial discrete function.
211 *
212 * @param[out] derivs The derivatives of the B-splines evaluated at coordinate x. It has to be a 1D mdspan with (degree+1) elements.
213 * @param[in] x The coordinate where B-spline derivatives are evaluated. It has to be in the range of break points coordinates.
214 * @return The index of the first B-spline which is evaluated.
215 */
216 KOKKOS_INLINE_FUNCTION discrete_element_type
217 eval_deriv(DSpan1D derivs, ddc::Coordinate<CDim> const& x) const;
218
219 /** @brief Evaluates non-zero B-spline values and \f$n\f$ derivatives at a given coordinate
220 *
221 * The values and derivatives are computed for every B-spline with support at the given coordinate x. There are only (degree+1)
222 * B-splines which are non-zero at any given point. It is these B-splines which are evaluated and differentiated.
223 * A spline approximation of a derivative at coordinate x is a linear
224 * combination of those B-spline derivatives weighted with spline coefficients of the spline-transformed
225 * initial discrete function.
226 *
227 * @param[out] derivs The values and \f$n\f$ derivatives of the B-splines evaluated at coordinate x. It has to be a 2D mdspan of sizes (degree+1, n+1).
228 * @param[in] x The coordinate where B-spline derivatives are evaluated. It has to be in the range of break points coordinates.
229 * @param[in] n The number of derivatives to evaluate (in addition to the B-spline values themselves).
230 * @return The index of the first B-spline which is evaluated.
231 */
233 ddc::DSpan2D derivs,
234 ddc::Coordinate<CDim> const& x,
235 std::size_t n) const;
236
237 /** @brief Returns the coordinate of the first support knot associated to a DiscreteElement identifying a B-spline.
238 *
239 * Each B-spline has a support defined over (degree+2) knots. For a B-spline identified by the
240 * provided DiscreteElement, this function returns the first knot in the support of the B-spline.
241 * In other words it returns the lower bound of the support.
242 *
243 * @param[in] ix DiscreteElement identifying the B-spline.
244 * @return DiscreteElement of the lower bound of the support of the B-spline.
245 */
246 KOKKOS_INLINE_FUNCTION ddc::DiscreteElement<knot_discrete_dimension_type>
247 get_first_support_knot(discrete_element_type const& ix) const
248 {
249 return ddc::DiscreteElement<knot_discrete_dimension_type>(
250 (ix - discrete_element_type(0)).value());
251 }
252
253 /** @brief Returns the coordinate of the last support knot associated to a DiscreteElement identifying a B-spline.
254 *
255 * Each B-spline has a support defined over (degree+2) knots. For a B-spline identified by the
256 * provided DiscreteElement, this function returns the last knot in the support of the B-spline.
257 * In other words it returns the upper bound of the support.
258 *
259 * @param[in] ix DiscreteElement identifying the B-spline.
260 * @return DiscreteElement of the upper bound of the support of the B-spline.
261 */
262 KOKKOS_INLINE_FUNCTION ddc::DiscreteElement<knot_discrete_dimension_type>
263 get_last_support_knot(discrete_element_type const& ix) const
264 {
266 + ddc::DiscreteVector<knot_discrete_dimension_type>(degree() + 1);
267 }
268
269 /** @brief Returns the coordinate of the lower bound of the domain on which the B-splines are defined.
270 *
271 * @return Coordinate of the lower bound of the domain.
272 */
273 KOKKOS_INLINE_FUNCTION ddc::Coordinate<CDim> rmin() const noexcept
274 {
275 return ddc::coordinate(m_break_point_domain.front());
276 }
277
278 /** @brief Returns the coordinate of the upper bound of the domain on which the B-splines are defined.
279 *
280 * @return Coordinate of the upper bound of the domain.
281 */
282 KOKKOS_INLINE_FUNCTION ddc::Coordinate<CDim> rmax() const noexcept
283 {
284 return ddc::coordinate(m_break_point_domain.back());
285 }
286
287 /** @brief Returns the length of the domain.
288 *
289 * @return The length of the domain.
290 */
291 KOKKOS_INLINE_FUNCTION double length() const noexcept
292 {
293 return rmax() - rmin();
294 }
295
296 /** @brief Returns the number of elements necessary to construct a spline representation of a function.
297 *
298 * For a non-periodic domain the number of elements necessary to construct a spline representation of a function
299 * is equal to the number of basis functions. However in the periodic case it additionally includes degree additional elements
300 * which allow the first B-splines to be evaluated close to rmax (where they also appear due to the periodicity).
301 *
302 * @return The number of elements necessary to construct a spline representation of a function.
303 */
304 KOKKOS_INLINE_FUNCTION std::size_t size() const noexcept
305 {
306 return degree() + ncells();
307 }
308
309 /** @brief Returns the discrete domain including eventual additional B-splines in the periodic case. See size().
310 *
311 * @return The discrete domain including eventual additional B-splines.
312 */
313 KOKKOS_INLINE_FUNCTION discrete_domain_type full_domain() const
314 {
315 return discrete_domain_type(discrete_element_type(0), discrete_vector_type(size()));
316 }
317
318 /** @brief Returns the discrete domain which describes the break points.
319 *
320 * @return The discrete domain describing the break points.
321 */
322 KOKKOS_INLINE_FUNCTION ddc::DiscreteDomain<knot_discrete_dimension_type>
323 break_point_domain() const
324 {
325 return m_break_point_domain;
326 }
327
328 /** @brief Returns the number of basis functions.
329 *
330 * The number of functions in the spline basis.
331 *
332 * @return The number of basis functions.
333 */
334 KOKKOS_INLINE_FUNCTION std::size_t nbasis() const noexcept
335 {
336 return ncells() + !is_periodic() * degree();
337 }
338
339 /** @brief Returns the number of cells over which the B-splines are defined.
340 *
341 * The number of cells over which the B-splines and any spline representation are defined.
342 * In other words the number of polynomials that comprise a spline representation on the domain where the basis is defined.
343 *
344 * @return The number of cells over which the B-splines are defined.
345 */
346 KOKKOS_INLINE_FUNCTION std::size_t ncells() const noexcept
347 {
348 return m_break_point_domain.size() - 1;
349 }
350
351 private:
352 KOKKOS_INLINE_FUNCTION double inv_step() const noexcept
353 {
354 return 1.0 / ddc::step<knot_discrete_dimension_type>();
355 }
356
357 KOKKOS_INLINE_FUNCTION discrete_element_type
358 eval_basis(DSpan1D values, ddc::Coordinate<CDim> const& x, std::size_t degree) const;
359
360 KOKKOS_INLINE_FUNCTION void get_icell_and_offset(
361 int& icell,
362 double& offset,
363 ddc::Coordinate<CDim> const& x) const;
364 };
365};
366
367template <class DDim>
368struct is_uniform_bsplines : public std::is_base_of<detail::UniformBSplinesBase, DDim>::type
369{
370};
371
372/**
373 * @brief Indicates if a tag corresponds to uniform B-splines or not.
374 *
375 * @tparam The presumed uniform B-splines.
376 */
377template <class DDim>
379
380template <class CDim, std::size_t D>
381template <class DDim, class MemorySpace>
382KOKKOS_INLINE_FUNCTION ddc::DiscreteElement<DDim> UniformBSplines<CDim, D>::
383 Impl<DDim, MemorySpace>::eval_basis(
384 DSpan1D values,
385 ddc::Coordinate<CDim> const& x,
386 [[maybe_unused]] std::size_t const degree) const
387{
388 assert(values.size() == degree + 1);
389
390 double offset;
391 int jmin;
392 // 1. Compute cell index 'icell' and x_offset
393 // 2. Compute index range of B-splines with support over cell 'icell'
394 get_icell_and_offset(jmin, offset, x);
395
396 // 3. Compute values of aforementioned B-splines
397 double xx;
398 double temp;
399 double saved;
400 DDC_MDSPAN_ACCESS_OP(values, 0) = 1.0;
401 for (std::size_t j = 1; j < values.size(); ++j) {
402 xx = -offset;
403 saved = 0.0;
404 for (std::size_t r = 0; r < j; ++r) {
405 xx += 1;
406 temp = DDC_MDSPAN_ACCESS_OP(values, r) / j;
407 DDC_MDSPAN_ACCESS_OP(values, r) = saved + xx * temp;
408 saved = (j - xx) * temp;
409 }
410 DDC_MDSPAN_ACCESS_OP(values, j) = saved;
411 }
412
413 return discrete_element_type(jmin);
414}
415
416template <class CDim, std::size_t D>
417template <class DDim, class MemorySpace>
418KOKKOS_INLINE_FUNCTION ddc::DiscreteElement<DDim> UniformBSplines<CDim, D>::
419 Impl<DDim, MemorySpace>::eval_deriv(DSpan1D derivs, ddc::Coordinate<CDim> const& x) const
420{
421 assert(derivs.size() == degree() + 1);
422
423 double offset;
424 int jmin;
425 // 1. Compute cell index 'icell' and x_offset
426 // 2. Compute index range of B-splines with support over cell 'icell'
427 get_icell_and_offset(jmin, offset, x);
428
429 // 3. Compute derivatives of aforementioned B-splines
430 // Derivatives are normalized, hence they should be divided by dx
431 double xx;
432 double temp;
433 double saved;
434 DDC_MDSPAN_ACCESS_OP(derivs, 0) = 1.0 / ddc::step<knot_discrete_dimension_type>();
435 for (std::size_t j = 1; j < degree(); ++j) {
436 xx = -offset;
437 saved = 0.0;
438 for (std::size_t r = 0; r < j; ++r) {
439 xx += 1.0;
440 temp = DDC_MDSPAN_ACCESS_OP(derivs, r) / j;
441 DDC_MDSPAN_ACCESS_OP(derivs, r) = saved + xx * temp;
442 saved = (j - xx) * temp;
443 }
444 DDC_MDSPAN_ACCESS_OP(derivs, j) = saved;
445 }
446
447 // Compute derivatives
448 double bjm1 = derivs[0];
449 double bj = bjm1;
450 DDC_MDSPAN_ACCESS_OP(derivs, 0) = -bjm1;
451 for (std::size_t j = 1; j < degree(); ++j) {
452 bj = DDC_MDSPAN_ACCESS_OP(derivs, j);
453 DDC_MDSPAN_ACCESS_OP(derivs, j) = bjm1 - bj;
454 bjm1 = bj;
455 }
456 DDC_MDSPAN_ACCESS_OP(derivs, degree()) = bj;
457
458 return discrete_element_type(jmin);
459}
460
461template <class CDim, std::size_t D>
462template <class DDim, class MemorySpace>
463KOKKOS_INLINE_FUNCTION ddc::DiscreteElement<DDim> UniformBSplines<CDim, D>::
464 Impl<DDim, MemorySpace>::eval_basis_and_n_derivs(
465 ddc::DSpan2D const derivs,
466 ddc::Coordinate<CDim> const& x,
467 std::size_t const n) const
468{
469 std::array<double, (degree() + 1) * (degree() + 1)> ndu_ptr;
470 Kokkos::mdspan<double, Kokkos::extents<std::size_t, degree() + 1, degree() + 1>> const ndu(
471 ndu_ptr.data());
472 std::array<double, 2 * (degree() + 1)> a_ptr;
473 Kokkos::mdspan<double, Kokkos::extents<std::size_t, degree() + 1, 2>> const a(a_ptr.data());
474 double offset;
475 int jmin;
476
477 assert(x - rmin() >= -length() * 1e-14);
478 assert(rmax() - x >= -length() * 1e-14);
479 // assert(n >= 0); as long as n is unsigned
480 assert(n <= degree());
481 assert(derivs.extent(0) == 1 + degree());
482 assert(derivs.extent(1) == 1 + n);
483
484 // 1. Compute cell index 'icell' and x_offset
485 // 2. Compute index range of B-splines with support over cell 'icell'
486 get_icell_and_offset(jmin, offset, x);
487
488 // 3. Recursively evaluate B-splines (eval_basis)
489 // up to self%degree, and store them all in the upper-right triangle of
490 // ndu
491 double xx;
492 double temp;
493 double saved;
494 DDC_MDSPAN_ACCESS_OP(ndu, 0, 0) = 1.0;
495 for (std::size_t j = 1; j < degree() + 1; ++j) {
496 xx = -offset;
497 saved = 0.0;
498 for (std::size_t r = 0; r < j; ++r) {
499 xx += 1.0;
500 temp = DDC_MDSPAN_ACCESS_OP(ndu, j - 1, r) / j;
501 DDC_MDSPAN_ACCESS_OP(ndu, j, r) = saved + xx * temp;
502 saved = (j - xx) * temp;
503 }
504 DDC_MDSPAN_ACCESS_OP(ndu, j, j) = saved;
505 }
506 for (std::size_t i = 0; i < ndu.extent(1); ++i) {
507 DDC_MDSPAN_ACCESS_OP(derivs, i, 0) = DDC_MDSPAN_ACCESS_OP(ndu, degree(), i);
508 }
509
510 for (int r = 0; r < int(degree() + 1); ++r) {
511 int s1 = 0;
512 int s2 = 1;
513 DDC_MDSPAN_ACCESS_OP(a, 0, 0) = 1.0;
514 for (int k = 1; k < int(n + 1); ++k) {
515 double d = 0.0;
516 int const rk = r - k;
517 int const pk = degree() - k;
518 if (r >= k) {
519 DDC_MDSPAN_ACCESS_OP(a, 0, s2) = DDC_MDSPAN_ACCESS_OP(a, 0, s1) / (pk + 1);
520 d = DDC_MDSPAN_ACCESS_OP(a, 0, s2) * DDC_MDSPAN_ACCESS_OP(ndu, pk, rk);
521 }
522 int const j1 = rk > -1 ? 1 : (-rk);
523 int const j2 = (r - 1) <= pk ? k : (degree() - r + 1);
524 for (int j = j1; j < j2; ++j) {
525 DDC_MDSPAN_ACCESS_OP(a, j, s2)
526 = (DDC_MDSPAN_ACCESS_OP(a, j, s1) - DDC_MDSPAN_ACCESS_OP(a, j - 1, s1))
527 / (pk + 1);
528 d += DDC_MDSPAN_ACCESS_OP(a, j, s2) * DDC_MDSPAN_ACCESS_OP(ndu, pk, rk + j);
529 }
530 if (r <= pk) {
531 DDC_MDSPAN_ACCESS_OP(a, k, s2) = -DDC_MDSPAN_ACCESS_OP(a, k - 1, s1) / (pk + 1);
532 d += DDC_MDSPAN_ACCESS_OP(a, k, s2) * DDC_MDSPAN_ACCESS_OP(ndu, pk, r);
533 }
534 DDC_MDSPAN_ACCESS_OP(derivs, r, k) = d;
535 Kokkos::kokkos_swap(s1, s2);
536 }
537 }
538
539 // Multiply result by correct factors:
540 // degree!/(degree-n)! = degree*(degree-1)*...*(degree-n+1)
541 // k-th derivatives are normalized, hence they should be divided by dx^k
542 double const inv_dx = inv_step();
543 double d = degree() * inv_dx;
544 for (int k = 1; k < int(n + 1); ++k) {
545 for (std::size_t i = 0; i < derivs.extent(0); ++i) {
546 DDC_MDSPAN_ACCESS_OP(derivs, i, k) *= d;
547 }
548 d *= (degree() - k) * inv_dx;
549 }
550
551 return discrete_element_type(jmin);
552}
553
554template <class CDim, std::size_t D>
555template <class DDim, class MemorySpace>
556KOKKOS_INLINE_FUNCTION void UniformBSplines<CDim, D>::Impl<DDim, MemorySpace>::get_icell_and_offset(
557 int& icell,
558 double& offset,
559 ddc::Coordinate<CDim> const& x) const
560{
561 assert(x - rmin() >= -length() * 1e-14);
562 assert(rmax() - x >= -length() * 1e-14);
563
564 double const inv_dx = inv_step();
565 if (x <= rmin()) {
566 icell = 0;
567 offset = 0.0;
568 } else if (x >= rmax()) {
569 icell = ncells() - 1;
570 offset = 1.0;
571 } else {
572 offset = (x - rmin()) * inv_dx;
573 icell = static_cast<int>(offset);
574 offset = offset - icell;
575
576 // When x is very close to xmax, round-off may cause the wrong answer
577 // icell=ncells and x_offset=0, which we convert to the case x=xmax:
578 if (icell == int(ncells()) && offset == 0.0) {
579 icell = ncells() - 1;
580 offset = 1.0;
581 }
582 }
583}
584
585} // namespace ddc
friend class DiscreteDomain
KOKKOS_FUNCTION constexpr bool operator!=(DiscreteVector< OTags... > const &rhs) const noexcept
Storage class of the static attributes of the discrete dimension.
KOKKOS_INLINE_FUNCTION ddc::DiscreteElement< knot_discrete_dimension_type > get_last_support_knot(discrete_element_type const &ix) const
Returns the coordinate of the last support knot associated to a DiscreteElement identifying a B-splin...
Impl(ddc::Coordinate< CDim > rmin, ddc::Coordinate< CDim > rmax, std::size_t ncells)
Constructs a spline basis (B-splines) with n equidistant knots over .
KOKKOS_INLINE_FUNCTION ddc::Coordinate< CDim > rmax() const noexcept
Returns the coordinate of the upper bound of the domain on which the B-splines are defined.
KOKKOS_INLINE_FUNCTION discrete_element_type eval_basis(DSpan1D values, ddc::Coordinate< CDim > const &x) const
Evaluates non-zero B-splines at a given coordinate.
KOKKOS_INLINE_FUNCTION ddc::DiscreteDomain< knot_discrete_dimension_type > break_point_domain() const
Returns the discrete domain which describes the break points.
KOKKOS_INLINE_FUNCTION ddc::Coordinate< CDim > rmin() const noexcept
Returns the coordinate of the lower bound of the domain on which the B-splines are defined.
~Impl()=default
Destructs.
KOKKOS_INLINE_FUNCTION std::size_t nbasis() const noexcept
Returns the number of basis functions.
Impl(Impl const &x)=default
Copy-constructs.
KOKKOS_INLINE_FUNCTION std::size_t size() const noexcept
Returns the number of elements necessary to construct a spline representation of a function.
Impl(Impl &&x)=default
Move-constructs.
KOKKOS_INLINE_FUNCTION discrete_element_type eval_basis_and_n_derivs(ddc::DSpan2D derivs, ddc::Coordinate< CDim > const &x, std::size_t n) const
Evaluates non-zero B-spline values and derivatives at a given coordinate.
KOKKOS_INLINE_FUNCTION ddc::DiscreteElement< knot_discrete_dimension_type > get_first_support_knot(discrete_element_type const &ix) const
Returns the coordinate of the first support knot associated to a DiscreteElement identifying a B-spli...
KOKKOS_INLINE_FUNCTION double length() const noexcept
Returns the length of the domain.
Impl(Impl< DDim, OriginMemorySpace > const &impl)
Copy-constructs from another Impl with a different Kokkos memory space.
KOKKOS_INLINE_FUNCTION std::size_t ncells() const noexcept
Returns the number of cells over which the B-splines are defined.
KOKKOS_INLINE_FUNCTION discrete_element_type eval_deriv(DSpan1D derivs, ddc::Coordinate< CDim > const &x) const
Evaluates non-zero B-spline derivatives at a given coordinate.
Impl & operator=(Impl &&x)=default
Move-assigns.
KOKKOS_INLINE_FUNCTION discrete_domain_type full_domain() const
Returns the discrete domain including eventual additional B-splines in the periodic case.
Impl & operator=(Impl const &x)=default
Copy-assigns.
The type of a uniform 1D spline basis (B-spline).
static constexpr bool is_uniform() noexcept
Indicates if the B-splines are uniform or not (this is the case here).
static constexpr bool is_periodic() noexcept
Indicates if the B-splines are periodic or not.
static constexpr std::size_t degree() noexcept
The degree of B-splines.
UniformPointSampling models a uniform discretization of the provided continuous dimension.
The top-level namespace of DDC.
constexpr bool is_uniform_bsplines_v
Indicates if a tag corresponds to uniform B-splines or not.