15#include <Kokkos_Core.hpp>
21struct UniformBSplinesBase
25template <
class ExecSpace,
class ODDim,
class Layout,
class OMemorySpace>
26void uniform_bsplines_integrals(
27 ExecSpace
const& execution_space,
38
39
40
41
42
43
44
45
46template <
class CDim, std::size_t D,
bool Periodic = CDim::PERIODIC>
49 static_assert(D > 0,
"Parameter `D` must be positive");
53 using continuous_dimension_type = CDim;
59
60
61
62 static constexpr std::size_t
degree()
noexcept
68
69
70
77
78
79
86
87
88
89
90 template <
class DDim,
class MemorySpace>
93 template <
class ODDim,
class OMemorySpace>
96 template <
class ExecSpace,
class ODDim,
class Layout,
class OMemorySpace>
97 friend void detail::uniform_bsplines_integrals(
98 ExecSpace
const& execution_space,
112 using discrete_element_type = DiscreteElement<DDim>;
122 ddc::DiscreteElement<DDim> m_reference;
128
129
130
131
132
133 explicit Impl(
ddc::Coordinate<CDim> rmin,
ddc::Coordinate<CDim> rmax, std::size_t ncells)
134 : m_reference(
ddc::create_reference_discrete_element<DDim>())
137 std::tie(m_break_point_domain, m_knot_domain, std::ignore, std::ignore)
138 =
ddc::init_discrete_space<knot_discrete_dimension_type>(
139 knot_discrete_dimension_type::
template init_ghosted<
140 knot_discrete_dimension_type>(
149
150
151
152 template <
class OriginMemorySpace>
153 explicit Impl(
Impl<DDim, OriginMemorySpace>
const& impl)
154 : m_knot_domain(impl.m_knot_domain)
155 , m_break_point_domain(impl.m_break_point_domain)
156 , m_reference(impl.m_reference)
161
162
163
167
168
169
176
177
178
179
183
184
185
186
190
191
192
193
194
195
196
197
198
199
200
201 KOKKOS_INLINE_FUNCTION discrete_element_type
eval_basis(
202 Kokkos::mdspan<
double, Kokkos::dextents<std::size_t, 1>> values,
203 ddc::Coordinate<CDim>
const& x)
const
205 KOKKOS_ASSERT(values.size() ==
degree() + 1)
206 return eval_basis(values, x,
degree());
210
211
212
213
214
215
216
217
218
219
220
221 KOKKOS_INLINE_FUNCTION discrete_element_type
eval_deriv(
222 Kokkos::mdspan<
double, Kokkos::dextents<std::size_t, 1>> derivs,
223 ddc::Coordinate<CDim>
const& x)
const;
226
227
228
229
230
231
232
233
234
235
236
237
239 Kokkos::mdspan<
double, Kokkos::dextents<std::size_t, 2>> derivs,
240 ddc::Coordinate<CDim>
const& x,
241 std::size_t n)
const;
244
245
246
247
248
249
250
251
252 KOKKOS_INLINE_FUNCTION
ddc::DiscreteElement<knot_discrete_dimension_type>
255 return m_knot_domain.front() + (ix - m_reference).value();
259
260
261
262
263
264
265
266
267 KOKKOS_INLINE_FUNCTION
ddc::DiscreteElement<knot_discrete_dimension_type>
275
276
277
278 KOKKOS_INLINE_FUNCTION
ddc::Coordinate<CDim>
rmin()
const noexcept
280 return ddc::coordinate(m_break_point_domain.front());
284
285
286
287 KOKKOS_INLINE_FUNCTION
ddc::Coordinate<CDim>
rmax()
const noexcept
289 return ddc::coordinate(m_break_point_domain.back());
293
294
295
296 KOKKOS_INLINE_FUNCTION
double length()
const noexcept
302
303
304
305
306
307
308
309 KOKKOS_INLINE_FUNCTION std::size_t
size()
const noexcept
315
316
317
318 KOKKOS_INLINE_FUNCTION discrete_domain_type
full_domain()
const
320 return discrete_domain_type(m_reference, discrete_vector_type(
size()));
324
325
326
330 return m_break_point_domain;
334
335
336
337
338
339 KOKKOS_INLINE_FUNCTION std::size_t
nbasis()
const noexcept
345
346
347
348
349
350
351 KOKKOS_INLINE_FUNCTION std::size_t
ncells()
const noexcept
353 return m_break_point_domain.size() - 1;
357 KOKKOS_INLINE_FUNCTION
double inv_step()
const noexcept
359 return 1.0 /
ddc::step<knot_discrete_dimension_type>();
362 KOKKOS_INLINE_FUNCTION discrete_element_type eval_basis(
363 Kokkos::mdspan<
double, Kokkos::dextents<std::size_t, 1>> values,
364 ddc::Coordinate<CDim>
const& x,
365 std::size_t degree)
const;
367 KOKKOS_INLINE_FUNCTION
void get_icell_and_offset(
370 ddc::Coordinate<CDim>
const& x)
const;
375struct is_uniform_bsplines :
public std::is_base_of<detail::UniformBSplinesBase, DDim>::type
380
381
382
383
390concept uniform_bsplines = is_uniform_bsplines_v<DDim>;
394template <
class CDim, std::size_t D,
bool Periodic>
395template <
class DDim,
class MemorySpace>
397 Impl<DDim, MemorySpace>::eval_basis(
398 Kokkos::mdspan<
double, Kokkos::dextents<std::size_t, 1>> values,
399 ddc::Coordinate<CDim>
const& x,
400 [[maybe_unused]] std::size_t
const degree)
const
402 KOKKOS_ASSERT(values.size() == degree + 1)
408 get_icell_and_offset(jmin, offset, x);
414 DDC_MDSPAN_ACCESS_OP(values, 0) = 1.0;
415 for (std::size_t j = 1; j < values.size(); ++j) {
418 for (std::size_t r = 0; r < j; ++r) {
420 temp = DDC_MDSPAN_ACCESS_OP(values, r) / j;
421 DDC_MDSPAN_ACCESS_OP(values, r) = saved + xx * temp;
422 saved = (j - xx) * temp;
424 DDC_MDSPAN_ACCESS_OP(values, j) = saved;
427 return m_reference + jmin;
430template <
class CDim, std::size_t D,
bool Periodic>
431template <
class DDim,
class MemorySpace>
434 Kokkos::mdspan<
double, Kokkos::dextents<std::size_t, 1>> derivs,
435 ddc::Coordinate<CDim>
const& x)
const
437 KOKKOS_ASSERT(derivs.size() ==
degree() + 1)
443 get_icell_and_offset(jmin, offset, x);
450 DDC_MDSPAN_ACCESS_OP(derivs, 0) = 1.0 /
ddc::step<knot_discrete_dimension_type>();
451 for (std::size_t j = 1; j <
degree(); ++j) {
454 for (std::size_t r = 0; r < j; ++r) {
456 temp = DDC_MDSPAN_ACCESS_OP(derivs, r) / j;
457 DDC_MDSPAN_ACCESS_OP(derivs, r) = saved + xx * temp;
458 saved = (j - xx) * temp;
460 DDC_MDSPAN_ACCESS_OP(derivs, j) = saved;
464 double bjm1 = derivs[0];
466 DDC_MDSPAN_ACCESS_OP(derivs, 0) = -bjm1;
467 for (std::size_t j = 1; j <
degree(); ++j) {
468 bj = DDC_MDSPAN_ACCESS_OP(derivs, j);
469 DDC_MDSPAN_ACCESS_OP(derivs, j) = bjm1 - bj;
472 DDC_MDSPAN_ACCESS_OP(derivs, degree()) = bj;
474 return m_reference + jmin;
477template <
class CDim, std::size_t D,
bool Periodic>
478template <
class DDim,
class MemorySpace>
480 Impl<DDim, MemorySpace>::eval_basis_and_n_derivs(
481 Kokkos::mdspan<
double, Kokkos::dextents<std::size_t, 2>>
const derivs,
482 ddc::Coordinate<CDim>
const& x,
483 std::size_t
const n)
const
486 Kokkos::mdspan<
double, Kokkos::extents<std::size_t,
degree() + 1,
degree() + 1>>
const ndu(
488 std::array<
double, 2 * (
degree() + 1)> a_ptr;
489 Kokkos::mdspan<
double, Kokkos::extents<std::size_t,
degree() + 1, 2>>
const a(a_ptr.data());
497 KOKKOS_ASSERT(derivs.extent(0) == 1 +
degree())
498 KOKKOS_ASSERT(derivs.extent(1) == 1 + n)
502 get_icell_and_offset(jmin, offset, x);
510 DDC_MDSPAN_ACCESS_OP(ndu, 0, 0) = 1.0;
511 for (std::size_t j = 1; j <
degree() + 1; ++j) {
514 for (std::size_t r = 0; r < j; ++r) {
516 temp = DDC_MDSPAN_ACCESS_OP(ndu, j - 1, r) / j;
517 DDC_MDSPAN_ACCESS_OP(ndu, j, r) = saved + xx * temp;
518 saved = (j - xx) * temp;
520 DDC_MDSPAN_ACCESS_OP(ndu, j, j) = saved;
522 for (std::size_t i = 0; i < ndu.extent(1); ++i) {
523 DDC_MDSPAN_ACCESS_OP(derivs, i, 0) = DDC_MDSPAN_ACCESS_OP(ndu,
degree(), i);
526 for (
int r = 0; r <
static_cast<
int>(
degree() + 1); ++r) {
529 DDC_MDSPAN_ACCESS_OP(a, 0, 0) = 1.0;
530 for (
int k = 1; k <
static_cast<
int>(n + 1); ++k) {
532 int const rk = r - k;
535 DDC_MDSPAN_ACCESS_OP(a, 0, s2) = DDC_MDSPAN_ACCESS_OP(a, 0, s1) / (pk + 1);
536 d = DDC_MDSPAN_ACCESS_OP(a, 0, s2) * DDC_MDSPAN_ACCESS_OP(ndu, pk, rk);
538 int const j1 = rk > -1 ? 1 : (-rk);
539 int const j2 = (r - 1) <= pk ? k : (
degree() - r + 1);
540 for (
int j = j1; j < j2; ++j) {
541 DDC_MDSPAN_ACCESS_OP(a, j, s2)
542 = (DDC_MDSPAN_ACCESS_OP(a, j, s1) - DDC_MDSPAN_ACCESS_OP(a, j - 1, s1))
544 d += DDC_MDSPAN_ACCESS_OP(a, j, s2) * DDC_MDSPAN_ACCESS_OP(ndu, pk, rk + j);
547 DDC_MDSPAN_ACCESS_OP(a, k, s2) = -DDC_MDSPAN_ACCESS_OP(a, k - 1, s1) / (pk + 1);
548 d += DDC_MDSPAN_ACCESS_OP(a, k, s2) * DDC_MDSPAN_ACCESS_OP(ndu, pk, r);
550 DDC_MDSPAN_ACCESS_OP(derivs, r, k) = d;
551 Kokkos::kokkos_swap(s1, s2);
558 double const inv_dx = inv_step();
560 for (
int k = 1; k <
static_cast<
int>(n + 1); ++k) {
561 for (std::size_t i = 0; i < derivs.extent(0); ++i) {
562 DDC_MDSPAN_ACCESS_OP(derivs, i, k) *= d;
567 return m_reference + jmin;
570template <
class CDim, std::size_t D,
bool Periodic>
571template <
class DDim,
class MemorySpace>
573 get_icell_and_offset(
int& icell,
double& offset,
ddc::Coordinate<CDim>
const& x)
const
578 double const inv_dx = inv_step();
586 offset = (x -
rmin()) * inv_dx;
587 icell =
static_cast<
int>(offset);
588 offset = offset - icell;
592 if (icell ==
static_cast<
int>(
ncells()) && offset == 0.0) {
friend class DiscreteDomain
KOKKOS_FUNCTION constexpr bool operator!=(DiscreteVector< OTags... > const &rhs) const noexcept
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.