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