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