13#include <Kokkos_Macros.hpp>
14#include <Kokkos_MathematicalFunctions.hpp>
17#include "integrals.hpp"
18#include "periodic_extrapolation_rule.hpp"
23
24
25
26
27
28
29
30
31
32
33
39 class LowerExtrapolationRule,
40 class UpperExtrapolationRule>
45 using exec_space = ExecSpace;
48 using memory_space = MemorySpace;
51 using continuous_dimension_type =
typename BSplines::continuous_dimension_type;
54 using evaluation_discrete_dimension_type = EvaluationDDim;
57 using bsplines_type = BSplines;
60 using evaluation_domain_type =
ddc::
DiscreteDomain<evaluation_discrete_dimension_type>;
63
64
65
66
68 class BatchedInterpolationDDom,
69 class = std::enable_if_t<
ddc::is_discrete_domain_v<BatchedInterpolationDDom>>>
70 using batched_evaluation_domain_type = BatchedInterpolationDDom;
76
77
78
79
80
82 class BatchedInterpolationDDom,
83 class = std::enable_if_t<
ddc::is_discrete_domain_v<BatchedInterpolationDDom>>>
84 using batch_domain_type
85 =
ddc::remove_dims_of_t<BatchedInterpolationDDom, evaluation_discrete_dimension_type>;
88
89
90
91
92
94 class BatchedInterpolationDDom,
95 class = std::enable_if_t<
ddc::is_discrete_domain_v<BatchedInterpolationDDom>>>
96 using batched_spline_domain_type =
ddc::replace_dim_of_t<
97 BatchedInterpolationDDom,
98 evaluation_discrete_dimension_type,
102 using lower_extrapolation_rule_type = LowerExtrapolationRule;
105 using upper_extrapolation_rule_type = UpperExtrapolationRule;
109 LowerExtrapolationRule m_lower_extrap_rule;
111 UpperExtrapolationRule m_upper_extrap_rule;
115 std::is_same_v<LowerExtrapolationRule,
117 == bsplines_type::is_periodic()
119 UpperExtrapolationRule,
121 == bsplines_type::is_periodic(),
122 "PeriodicExtrapolationRule has to be used if and only if dimension is periodic");
124 std::is_invocable_r_v<
126 LowerExtrapolationRule,
127 ddc::Coordinate<continuous_dimension_type>,
131 Kokkos::layout_right,
133 "LowerExtrapolationRule::operator() has to be callable with usual arguments.");
135 std::is_invocable_r_v<
137 UpperExtrapolationRule,
138 ddc::Coordinate<continuous_dimension_type>,
142 Kokkos::layout_right,
144 "UpperExtrapolationRule::operator() has to be callable with usual arguments.");
147
148
149
150
151
152
153
155 LowerExtrapolationRule
const& lower_extrap_rule,
156 UpperExtrapolationRule
const& upper_extrap_rule)
157 : m_lower_extrap_rule(lower_extrap_rule)
158 , m_upper_extrap_rule(upper_extrap_rule)
163
164
165
166
170
171
172
173
180
181
182
183
184
188
189
190
191
192
196
197
198
199
200
201
202
203
206 return m_lower_extrap_rule;
210
211
212
213
214
215
216
217
220 return m_upper_extrap_rule;
224
225
226
227
228
229
230
231
232
233
234
235 template <
class Layout,
class... CoordsDims>
237 ddc::Coordinate<CoordsDims...>
const& coord_eval,
238 ddc::
ChunkSpan<
double const, spline_domain_type, Layout, memory_space>
const
241 return eval(coord_eval, spline_coef);
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
268 class BatchedInterpolationDDom,
271 ddc::
ChunkSpan<
double, BatchedInterpolationDDom, Layout1, memory_space>
const
274 ddc::Coordinate<CoordsDims...>
const,
275 BatchedInterpolationDDom,
277 memory_space>
const coords_eval,
280 batched_spline_domain_type<BatchedInterpolationDDom>,
282 memory_space>
const spline_coef)
const
284 evaluation_domain_type
const evaluation_domain(spline_eval.domain());
285 batch_domain_type<BatchedInterpolationDDom>
const batch_domain(spline_eval.domain());
287 ddc::parallel_for_each(
288 "ddc_splines_evaluate",
292 typename batch_domain_type<
293 BatchedInterpolationDDom>::discrete_element_type
const j) {
294 auto const spline_eval_1D = spline_eval[j];
295 auto const coords_eval_1D = coords_eval[j];
296 auto const spline_coef_1D = spline_coef[j];
297 for (
auto const i : evaluation_domain) {
298 spline_eval_1D(i) = eval(coords_eval_1D(i), spline_coef_1D);
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321 template <
class Layout1,
class Layout2,
class BatchedInterpolationDDom>
323 ddc::
ChunkSpan<
double, BatchedInterpolationDDom, Layout1, memory_space>
const
327 batched_spline_domain_type<BatchedInterpolationDDom>,
329 memory_space>
const spline_coef)
const
331 evaluation_domain_type
const evaluation_domain(spline_eval.domain());
332 batch_domain_type<BatchedInterpolationDDom>
const batch_domain(spline_eval.domain());
334 ddc::parallel_for_each(
335 "ddc_splines_evaluate",
339 typename batch_domain_type<
340 BatchedInterpolationDDom>::discrete_element_type
const j) {
341 auto const spline_eval_1D = spline_eval[j];
342 auto const spline_coef_1D = spline_coef[j];
343 for (
auto const i : evaluation_domain) {
344 ddc::Coordinate<continuous_dimension_type> coord_eval_1D
345 =
ddc::coordinate(i);
346 spline_eval_1D(i) = eval(coord_eval_1D, spline_coef_1D);
351#if defined(DDC_BUILD_DEPRECATED_CODE)
353
354
355
356
357
358
359
360
361
362
363 template <
class Layout,
class... CoordsDims>
364 [[deprecated(
"Use deriv(DiscreteElement<Deriv<Dim>>(1), ...) instead")]] KOKKOS_FUNCTION
double
365 deriv(
ddc::Coordinate<CoordsDims...>
const& coord_eval,
366 ddc::
ChunkSpan<
double const, spline_domain_type, Layout, memory_space>
const spline_coef)
370 ddc::DiscreteElement<
Deriv<continuous_dimension_type>>(1),
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
397 class BatchedInterpolationDDom,
399 [[deprecated(
"Use deriv(DiscreteElement<Deriv<Dim>>(1), ...) instead")]]
void deriv(
400 ddc::
ChunkSpan<
double, BatchedInterpolationDDom, Layout1, memory_space>
const
403 ddc::Coordinate<CoordsDims...>
const,
404 BatchedInterpolationDDom,
406 memory_space>
const coords_eval,
409 batched_spline_domain_type<BatchedInterpolationDDom>,
411 memory_space>
const spline_coef)
const
414 ddc::DiscreteElement<
Deriv<continuous_dimension_type>>(1),
421
422
423
424
425
426
427
428
429
430
431
432
433
434 template <
class Layout1,
class Layout2,
class BatchedInterpolationDDom>
435 [[deprecated(
"Use deriv(DiscreteElement<Deriv<Dim>>(1), ...) instead")]]
void deriv(
436 ddc::
ChunkSpan<
double, BatchedInterpolationDDom, Layout1, memory_space>
const
440 batched_spline_domain_type<BatchedInterpolationDDom>,
442 memory_space>
const spline_coef)
const
445 ddc::DiscreteElement<
Deriv<continuous_dimension_type>>(1),
452
453
454
455
456
457
458
459
460
461
462
463
464 template <
class DElem,
class Layout,
class... CoordsDims>
466 DElem
const& deriv_order,
467 ddc::Coordinate<CoordsDims...>
const& coord_eval,
468 ddc::
ChunkSpan<
double const, spline_domain_type, Layout, memory_space>
const
471 static_assert(is_discrete_element_v<DElem>);
472 return eval_no_bc(deriv_order, coord_eval, spline_coef);
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
500 class BatchedInterpolationDDom,
503 DElem
const& deriv_order,
504 ddc::
ChunkSpan<
double, BatchedInterpolationDDom, Layout1, memory_space>
const
507 ddc::Coordinate<CoordsDims...>
const,
508 BatchedInterpolationDDom,
510 memory_space>
const coords_eval,
513 batched_spline_domain_type<BatchedInterpolationDDom>,
515 memory_space>
const spline_coef)
const
517 static_assert(is_discrete_element_v<DElem>);
519 evaluation_domain_type
const evaluation_domain(spline_eval.domain());
520 batch_domain_type<BatchedInterpolationDDom>
const batch_domain(spline_eval.domain());
522 ddc::parallel_for_each(
523 "ddc_splines_differentiate",
527 typename batch_domain_type<
528 BatchedInterpolationDDom>::discrete_element_type
const j) {
529 auto const spline_eval_1D = spline_eval[j];
530 auto const coords_eval_1D = coords_eval[j];
531 auto const spline_coef_1D = spline_coef[j];
532 for (
auto const i : evaluation_domain) {
534 = eval_no_bc(deriv_order, coords_eval_1D(i), spline_coef_1D);
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554 template <
class DElem,
class Layout1,
class Layout2,
class BatchedInterpolationDDom>
556 DElem
const& deriv_order,
557 ddc::
ChunkSpan<
double, BatchedInterpolationDDom, Layout1, memory_space>
const
561 batched_spline_domain_type<BatchedInterpolationDDom>,
563 memory_space>
const spline_coef)
const
565 static_assert(is_discrete_element_v<DElem>);
567 evaluation_domain_type
const evaluation_domain(spline_eval.domain());
568 batch_domain_type<BatchedInterpolationDDom>
const batch_domain(spline_eval.domain());
570 ddc::parallel_for_each(
571 "ddc_splines_differentiate",
575 typename batch_domain_type<
576 BatchedInterpolationDDom>::discrete_element_type
const j) {
577 auto const spline_eval_1D = spline_eval[j];
578 auto const spline_coef_1D = spline_coef[j];
579 for (
auto const i : evaluation_domain) {
580 ddc::Coordinate<continuous_dimension_type> coord_eval_1D
581 =
ddc::coordinate(i);
582 spline_eval_1D(i) = eval_no_bc(deriv_order, coord_eval_1D, spline_coef_1D);
588
589
590
591
592
593
594
595
596
597
598
599
600 template <
class Layout1,
class Layout2,
class BatchedDDom,
class BatchedSplineDDom>
602 ddc::
ChunkSpan<
double, BatchedDDom, Layout1, memory_space>
const integrals,
603 ddc::
ChunkSpan<
double const, BatchedSplineDDom, Layout2, memory_space>
const
607 ddc::in_tags_v<bsplines_type, to_type_seq_t<BatchedSplineDDom>>,
608 "The spline coefficients domain must contain the bsplines dimension");
609 using batch_domain_type =
ddc::remove_dims_of_t<BatchedSplineDDom, bsplines_type>;
611 std::is_same_v<batch_domain_type, BatchedDDom>,
612 "The integrals domain must only contain the batch dimensions");
614 BatchedDDom
const batch_domain(integrals.domain());
619 ddc::integrals(exec_space(), values);
621 ddc::parallel_for_each(
622 "ddc_splines_integrate",
625 KOKKOS_LAMBDA(
typename BatchedDDom::discrete_element_type
const j) {
627 for (
typename spline_domain_type::discrete_element_type
const i :
629 integrals(j) += spline_coef(i, j) * values(i);
635 template <
class Layout,
class... CoordsDims>
636 KOKKOS_INLINE_FUNCTION
double eval(
637 ddc::Coordinate<CoordsDims...>
const& coord_eval,
638 ddc::
ChunkSpan<
double const, spline_domain_type, Layout, memory_space>
const
641 ddc::Coordinate<continuous_dimension_type> coord_eval_interest(coord_eval);
642 if constexpr (bsplines_type::is_periodic()) {
643 if (coord_eval_interest <
ddc::discrete_space<bsplines_type>().rmin()
644 || coord_eval_interest >
ddc::discrete_space<bsplines_type>().rmax()) {
645 coord_eval_interest -= Kokkos::floor(
647 -
ddc::discrete_space<bsplines_type>().rmin())
648 /
ddc::discrete_space<bsplines_type>().length())
649 *
ddc::discrete_space<bsplines_type>().length();
652 if (coord_eval_interest <
ddc::discrete_space<bsplines_type>().rmin()) {
653 return m_lower_extrap_rule(coord_eval_interest, spline_coef);
655 if (coord_eval_interest >
ddc::discrete_space<bsplines_type>().rmax()) {
656 return m_upper_extrap_rule(coord_eval_interest, spline_coef);
659 return eval_no_bc(
ddc::DiscreteElement
<>(), coord_eval_interest, spline_coef);
662 template <
class... DerivDims,
class Layout,
class... CoordsDims>
663 KOKKOS_INLINE_FUNCTION
double eval_no_bc(
664 ddc::DiscreteElement<DerivDims...>
const& deriv_order,
665 ddc::Coordinate<CoordsDims...>
const& coord_eval,
666 ddc::
ChunkSpan<
double const, spline_domain_type, Layout, memory_space>
const
669 using deriv_dim =
ddc::
Deriv<continuous_dimension_type>;
671 sizeof...(DerivDims) == 0
673 detail::TypeSeq<DerivDims...>,
674 detail::TypeSeq<deriv_dim>>,
675 "The only valid dimension for deriv_order is Deriv<Dim>");
677 ddc::DiscreteElement<bsplines_type> jmin;
678 std::array<
double, bsplines_type::degree() + 1> vals_ptr;
679 Kokkos::mdspan<
double, Kokkos::extents<std::size_t, bsplines_type::degree() + 1>>
const
680 vals(vals_ptr.data());
681 ddc::Coordinate<continuous_dimension_type>
const coord_eval_interest(coord_eval);
683 if constexpr (
sizeof...(DerivDims) == 0) {
684 jmin =
ddc::discrete_space<bsplines_type>().eval_basis(vals, coord_eval_interest);
686 auto const order = deriv_order.uid();
687 KOKKOS_ASSERT(order > 0 && order <= bsplines_type::degree())
689 std::array<
double, (bsplines_type::degree() + 1) * (bsplines_type::degree() + 1)>
695 bsplines_type::degree() + 1,
696 Kokkos::dynamic_extent>>
const derivs(derivs_ptr.data(), order + 1);
698 jmin =
ddc::discrete_space<bsplines_type>()
699 .eval_basis_and_n_derivs(derivs, coord_eval_interest, order);
701 for (std::size_t i = 0; i < bsplines_type::degree() + 1; ++i) {
702 vals[i] = DDC_MDSPAN_ACCESS_OP(derivs, i, order);
707 for (std::size_t i = 0; i < bsplines_type::degree() + 1; ++i) {
708 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...