13#include <Kokkos_Core.hpp>
16#include "integrals.hpp"
17#include "periodic_extrapolation_rule.hpp"
22
23
24
25
26
27
28
29
30
31
32
38 class LowerExtrapolationRule,
39 class UpperExtrapolationRule>
44 using exec_space = ExecSpace;
47 using memory_space = MemorySpace;
50 using continuous_dimension_type =
typename BSplines::continuous_dimension_type;
53 using evaluation_discrete_dimension_type = EvaluationDDim;
56 using bsplines_type = BSplines;
59 using evaluation_domain_type =
ddc::
DiscreteDomain<evaluation_discrete_dimension_type>;
62
63
64
65
67 class BatchedInterpolationDDom,
68 class = std::enable_if_t<
ddc::is_discrete_domain_v<BatchedInterpolationDDom>>>
69 using batched_evaluation_domain_type = BatchedInterpolationDDom;
75
76
77
78
79
81 class BatchedInterpolationDDom,
82 class = std::enable_if_t<
ddc::is_discrete_domain_v<BatchedInterpolationDDom>>>
83 using batch_domain_type
84 =
ddc::remove_dims_of_t<BatchedInterpolationDDom, evaluation_discrete_dimension_type>;
87
88
89
90
91
93 class BatchedInterpolationDDom,
94 class = std::enable_if_t<
ddc::is_discrete_domain_v<BatchedInterpolationDDom>>>
95 using batched_spline_domain_type =
ddc::replace_dim_of_t<
96 BatchedInterpolationDDom,
97 evaluation_discrete_dimension_type,
101 using lower_extrapolation_rule_type = LowerExtrapolationRule;
104 using upper_extrapolation_rule_type = UpperExtrapolationRule;
108 LowerExtrapolationRule m_lower_extrap_rule;
110 UpperExtrapolationRule m_upper_extrap_rule;
114 std::is_same_v<LowerExtrapolationRule,
116 == bsplines_type::is_periodic()
118 UpperExtrapolationRule,
120 == bsplines_type::is_periodic(),
121 "PeriodicExtrapolationRule has to be used if and only if dimension is periodic");
123 std::is_invocable_r_v<
125 LowerExtrapolationRule,
126 ddc::Coordinate<continuous_dimension_type>,
130 Kokkos::layout_right,
132 "LowerExtrapolationRule::operator() has to be callable with usual arguments.");
134 std::is_invocable_r_v<
136 UpperExtrapolationRule,
137 ddc::Coordinate<continuous_dimension_type>,
141 Kokkos::layout_right,
143 "UpperExtrapolationRule::operator() has to be callable with usual arguments.");
146
147
148
149
150
151
152
154 LowerExtrapolationRule
const& lower_extrap_rule,
155 UpperExtrapolationRule
const& upper_extrap_rule)
156 : m_lower_extrap_rule(lower_extrap_rule)
157 , m_upper_extrap_rule(upper_extrap_rule)
162
163
164
165
169
170
171
172
179
180
181
182
183
187
188
189
190
191
195
196
197
198
199
200
201
202
205 return m_lower_extrap_rule;
209
210
211
212
213
214
215
216
219 return m_upper_extrap_rule;
223
224
225
226
227
228
229
230
231
232
233
234 template <
class Layout,
class... CoordsDims>
236 ddc::Coordinate<CoordsDims...>
const& coord_eval,
237 ddc::
ChunkSpan<
double const, spline_domain_type, Layout, memory_space>
const
240 return eval(coord_eval, spline_coef);
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
267 class BatchedInterpolationDDom,
270 ddc::
ChunkSpan<
double, BatchedInterpolationDDom, Layout1, memory_space>
const
273 ddc::Coordinate<CoordsDims...>
const,
274 BatchedInterpolationDDom,
276 memory_space>
const coords_eval,
279 batched_spline_domain_type<BatchedInterpolationDDom>,
281 memory_space>
const spline_coef)
const
283 evaluation_domain_type
const evaluation_domain(spline_eval.domain());
284 batch_domain_type<BatchedInterpolationDDom>
const batch_domain(spline_eval.domain());
286 ddc::parallel_for_each(
287 "ddc_splines_evaluate",
291 typename batch_domain_type<
292 BatchedInterpolationDDom>::discrete_element_type
const j) {
293 auto const spline_eval_1D = spline_eval[j];
294 auto const coords_eval_1D = coords_eval[j];
295 auto const spline_coef_1D = spline_coef[j];
296 for (
auto const i : evaluation_domain) {
297 spline_eval_1D(i) = eval(coords_eval_1D(i), spline_coef_1D);
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320 template <
class Layout1,
class Layout2,
class BatchedInterpolationDDom>
322 ddc::
ChunkSpan<
double, BatchedInterpolationDDom, Layout1, memory_space>
const
326 batched_spline_domain_type<BatchedInterpolationDDom>,
328 memory_space>
const spline_coef)
const
330 evaluation_domain_type
const evaluation_domain(spline_eval.domain());
331 batch_domain_type<BatchedInterpolationDDom>
const batch_domain(spline_eval.domain());
333 ddc::parallel_for_each(
334 "ddc_splines_evaluate",
338 typename batch_domain_type<
339 BatchedInterpolationDDom>::discrete_element_type
const j) {
340 auto const spline_eval_1D = spline_eval[j];
341 auto const spline_coef_1D = spline_coef[j];
342 for (
auto const i : evaluation_domain) {
343 ddc::Coordinate<continuous_dimension_type> coord_eval_1D
344 =
ddc::coordinate(i);
345 spline_eval_1D(i) = eval(coord_eval_1D, spline_coef_1D);
350#if defined(DDC_BUILD_DEPRECATED_CODE)
352
353
354
355
356
357
358
359
360
361
362 template <
class Layout,
class... CoordsDims>
363 [[deprecated(
"Use deriv(DiscreteElement<Deriv<Dim>>(1), ...) instead")]] KOKKOS_FUNCTION
double
364 deriv(
ddc::Coordinate<CoordsDims...>
const& coord_eval,
365 ddc::
ChunkSpan<
double const, spline_domain_type, Layout, memory_space>
const spline_coef)
369 ddc::DiscreteElement<
Deriv<continuous_dimension_type>>(1),
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
396 class BatchedInterpolationDDom,
398 [[deprecated(
"Use deriv(DiscreteElement<Deriv<Dim>>(1), ...) instead")]]
void deriv(
399 ddc::
ChunkSpan<
double, BatchedInterpolationDDom, Layout1, memory_space>
const
402 ddc::Coordinate<CoordsDims...>
const,
403 BatchedInterpolationDDom,
405 memory_space>
const coords_eval,
408 batched_spline_domain_type<BatchedInterpolationDDom>,
410 memory_space>
const spline_coef)
const
413 ddc::DiscreteElement<
Deriv<continuous_dimension_type>>(1),
420
421
422
423
424
425
426
427
428
429
430
431
432
433 template <
class Layout1,
class Layout2,
class BatchedInterpolationDDom>
434 [[deprecated(
"Use deriv(DiscreteElement<Deriv<Dim>>(1), ...) instead")]]
void deriv(
435 ddc::
ChunkSpan<
double, BatchedInterpolationDDom, Layout1, memory_space>
const
439 batched_spline_domain_type<BatchedInterpolationDDom>,
441 memory_space>
const spline_coef)
const
444 ddc::DiscreteElement<
Deriv<continuous_dimension_type>>(1),
451
452
453
454
455
456
457
458
459
460
461
462
463 template <
class DElem,
class Layout,
class... CoordsDims>
465 DElem
const& deriv_order,
466 ddc::Coordinate<CoordsDims...>
const& coord_eval,
467 ddc::
ChunkSpan<
double const, spline_domain_type, Layout, memory_space>
const
470 static_assert(is_discrete_element_v<DElem>);
471 return eval_no_bc(deriv_order, coord_eval, spline_coef);
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
499 class BatchedInterpolationDDom,
502 DElem
const& deriv_order,
503 ddc::
ChunkSpan<
double, BatchedInterpolationDDom, Layout1, memory_space>
const
506 ddc::Coordinate<CoordsDims...>
const,
507 BatchedInterpolationDDom,
509 memory_space>
const coords_eval,
512 batched_spline_domain_type<BatchedInterpolationDDom>,
514 memory_space>
const spline_coef)
const
516 static_assert(is_discrete_element_v<DElem>);
518 evaluation_domain_type
const evaluation_domain(spline_eval.domain());
519 batch_domain_type<BatchedInterpolationDDom>
const batch_domain(spline_eval.domain());
521 ddc::parallel_for_each(
522 "ddc_splines_differentiate",
526 typename batch_domain_type<
527 BatchedInterpolationDDom>::discrete_element_type
const j) {
528 auto const spline_eval_1D = spline_eval[j];
529 auto const coords_eval_1D = coords_eval[j];
530 auto const spline_coef_1D = spline_coef[j];
531 for (
auto const i : evaluation_domain) {
533 = eval_no_bc(deriv_order, coords_eval_1D(i), spline_coef_1D);
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553 template <
class DElem,
class Layout1,
class Layout2,
class BatchedInterpolationDDom>
555 DElem
const& deriv_order,
556 ddc::
ChunkSpan<
double, BatchedInterpolationDDom, Layout1, memory_space>
const
560 batched_spline_domain_type<BatchedInterpolationDDom>,
562 memory_space>
const spline_coef)
const
564 static_assert(is_discrete_element_v<DElem>);
566 evaluation_domain_type
const evaluation_domain(spline_eval.domain());
567 batch_domain_type<BatchedInterpolationDDom>
const batch_domain(spline_eval.domain());
569 ddc::parallel_for_each(
570 "ddc_splines_differentiate",
574 typename batch_domain_type<
575 BatchedInterpolationDDom>::discrete_element_type
const j) {
576 auto const spline_eval_1D = spline_eval[j];
577 auto const spline_coef_1D = spline_coef[j];
578 for (
auto const i : evaluation_domain) {
579 ddc::Coordinate<continuous_dimension_type> coord_eval_1D
580 =
ddc::coordinate(i);
581 spline_eval_1D(i) = eval_no_bc(deriv_order, coord_eval_1D, spline_coef_1D);
587
588
589
590
591
592
593
594
595
596
597
598
599 template <
class Layout1,
class Layout2,
class BatchedDDom,
class BatchedSplineDDom>
601 ddc::
ChunkSpan<
double, BatchedDDom, Layout1, memory_space>
const integrals,
602 ddc::
ChunkSpan<
double const, BatchedSplineDDom, Layout2, memory_space>
const
606 ddc::in_tags_v<bsplines_type, to_type_seq_t<BatchedSplineDDom>>,
607 "The spline coefficients domain must contain the bsplines dimension");
608 using batch_domain_type =
ddc::remove_dims_of_t<BatchedSplineDDom, bsplines_type>;
610 std::is_same_v<batch_domain_type, BatchedDDom>,
611 "The integrals domain must only contain the batch dimensions");
613 BatchedDDom
const batch_domain(integrals.domain());
618 ddc::integrals(exec_space(), values);
620 ddc::parallel_for_each(
621 "ddc_splines_integrate",
624 KOKKOS_LAMBDA(
typename BatchedDDom::discrete_element_type
const j) {
626 for (
typename spline_domain_type::discrete_element_type
const i :
628 integrals(j) += spline_coef(i, j) * values(i);
634 template <
class Layout,
class... CoordsDims>
635 KOKKOS_INLINE_FUNCTION
double eval(
636 ddc::Coordinate<CoordsDims...>
const& coord_eval,
637 ddc::
ChunkSpan<
double const, spline_domain_type, Layout, memory_space>
const
640 ddc::Coordinate<continuous_dimension_type> coord_eval_interest(coord_eval);
641 if constexpr (bsplines_type::is_periodic()) {
642 if (coord_eval_interest <
ddc::discrete_space<bsplines_type>().rmin()
643 || coord_eval_interest >
ddc::discrete_space<bsplines_type>().rmax()) {
644 coord_eval_interest -= Kokkos::floor(
646 -
ddc::discrete_space<bsplines_type>().rmin())
647 /
ddc::discrete_space<bsplines_type>().length())
648 *
ddc::discrete_space<bsplines_type>().length();
651 if (coord_eval_interest <
ddc::discrete_space<bsplines_type>().rmin()) {
652 return m_lower_extrap_rule(coord_eval_interest, spline_coef);
654 if (coord_eval_interest >
ddc::discrete_space<bsplines_type>().rmax()) {
655 return m_upper_extrap_rule(coord_eval_interest, spline_coef);
658 return eval_no_bc(
ddc::DiscreteElement
<>(), coord_eval_interest, spline_coef);
661 template <
class... DerivDims,
class Layout,
class... CoordsDims>
662 KOKKOS_INLINE_FUNCTION
double eval_no_bc(
663 ddc::DiscreteElement<DerivDims...>
const& deriv_order,
664 ddc::Coordinate<CoordsDims...>
const& coord_eval,
665 ddc::
ChunkSpan<
double const, spline_domain_type, Layout, memory_space>
const
668 using deriv_dim =
ddc::
Deriv<continuous_dimension_type>;
670 sizeof...(DerivDims) == 0
672 detail::TypeSeq<DerivDims...>,
673 detail::TypeSeq<deriv_dim>>,
674 "The only valid dimension for deriv_order is Deriv<Dim>");
676 ddc::DiscreteElement<bsplines_type> jmin;
677 std::array<
double, bsplines_type::degree() + 1> vals_ptr;
678 Kokkos::mdspan<
double, Kokkos::extents<std::size_t, bsplines_type::degree() + 1>>
const
679 vals(vals_ptr.data());
680 ddc::Coordinate<continuous_dimension_type>
const coord_eval_interest(coord_eval);
682 if constexpr (
sizeof...(DerivDims) == 0) {
683 jmin =
ddc::discrete_space<bsplines_type>().eval_basis(vals, coord_eval_interest);
685 auto const order = deriv_order.uid();
686 KOKKOS_ASSERT(order > 0 && order <= bsplines_type::degree())
688 std::array<
double, (bsplines_type::degree() + 1) * (bsplines_type::degree() + 1)>
694 bsplines_type::degree() + 1,
695 Kokkos::dynamic_extent>>
const derivs(derivs_ptr.data(), order + 1);
697 jmin =
ddc::discrete_space<bsplines_type>()
698 .eval_basis_and_n_derivs(derivs, coord_eval_interest, order);
700 for (std::size_t i = 0; i < bsplines_type::degree() + 1; ++i) {
701 vals[i] = DDC_MDSPAN_ACCESS_OP(derivs, i, order);
706 for (std::size_t i = 0; i < bsplines_type::degree() + 1; ++i) {
707 y += spline_coef(
ddc::DiscreteElement<bsplines_type>(jmin + i)) * vals[i];
friend class DiscreteDomain
KOKKOS_DEFAULTED_FUNCTION constexpr DiscreteElement()=default
A class to evaluate, differentiate or integrate a spline function.
void operator()(ddc::ChunkSpan< double, BatchedInterpolationDDom, Layout1, memory_space > const spline_eval, ddc::ChunkSpan< ddc::Coordinate< CoordsDims... > const, BatchedInterpolationDDom, Layout2, memory_space > const coords_eval, ddc::ChunkSpan< double const, batched_spline_domain_type< BatchedInterpolationDDom >, Layout3, memory_space > const spline_coef) const
Evaluate spline function (described by its spline coefficients) on a mesh.
upper_extrapolation_rule_type upper_extrapolation_rule() const
Get the upper extrapolation rule.
SplineEvaluator & operator=(SplineEvaluator const &x)=default
Copy-assigns.
SplineEvaluator & operator=(SplineEvaluator &&x)=default
Move-assigns.
SplineEvaluator(LowerExtrapolationRule const &lower_extrap_rule, UpperExtrapolationRule const &upper_extrap_rule)
Build a SplineEvaluator acting on batched_spline_domain.
lower_extrapolation_rule_type lower_extrapolation_rule() const
Get the lower extrapolation rule.
void deriv(DElem const &deriv_order, ddc::ChunkSpan< double, BatchedInterpolationDDom, Layout1, memory_space > const spline_eval, ddc::ChunkSpan< double const, batched_spline_domain_type< BatchedInterpolationDDom >, Layout2, memory_space > const spline_coef) const
Differentiate 1D spline function (described by its spline coefficients) on a mesh.
KOKKOS_FUNCTION double operator()(ddc::Coordinate< CoordsDims... > const &coord_eval, ddc::ChunkSpan< double const, spline_domain_type, Layout, memory_space > const spline_coef) const
Evaluate 1D spline function (described by its spline coefficients) at a given coordinate.
KOKKOS_FUNCTION double deriv(DElem const &deriv_order, ddc::Coordinate< CoordsDims... > const &coord_eval, ddc::ChunkSpan< double const, spline_domain_type, Layout, memory_space > const spline_coef) const
Differentiate 1D spline function (described by its spline coefficients) at a given coordinate.
SplineEvaluator(SplineEvaluator const &x)=default
Copy-constructs.
SplineEvaluator(SplineEvaluator &&x)=default
Move-constructs.
void deriv(DElem const &deriv_order, ddc::ChunkSpan< double, BatchedInterpolationDDom, Layout1, memory_space > const spline_eval, ddc::ChunkSpan< ddc::Coordinate< CoordsDims... > const, BatchedInterpolationDDom, Layout2, memory_space > const coords_eval, ddc::ChunkSpan< double const, batched_spline_domain_type< BatchedInterpolationDDom >, Layout3, memory_space > const spline_coef) const
Differentiate 1D spline function (described by its spline coefficients) on a mesh.
void integrate(ddc::ChunkSpan< double, BatchedDDom, Layout1, memory_space > const integrals, ddc::ChunkSpan< double const, BatchedSplineDDom, Layout2, memory_space > const spline_coef) const
Perform batched 1D integrations of a spline function (described by its spline coefficients) along the...
void operator()(ddc::ChunkSpan< double, BatchedInterpolationDDom, Layout1, memory_space > const spline_eval, ddc::ChunkSpan< double const, batched_spline_domain_type< BatchedInterpolationDDom >, Layout2, memory_space > const spline_coef) const
Evaluate a spline function (described by its spline coefficients) on a mesh.
~SplineEvaluator()=default
Destructs.
The top-level namespace of DDC.
A templated struct representing a discrete dimension storing the derivatives of a function along a co...