13#include <Kokkos_Macros.hpp>
14#include <Kokkos_MathematicalFunctions.hpp>
16#include "integrals.hpp"
17#include "periodic_extrapolation_rule.hpp"
22
23
24
25
26
27
28
29
30
31
32
33
39 class LowerExtrapolationRule,
40 class UpperExtrapolationRule,
46
47
53
54
55 struct eval_deriv_type
61 using exec_space = ExecSpace;
64 using memory_space = MemorySpace;
67 using continuous_dimension_type =
typename BSplines::continuous_dimension_type;
70 using evaluation_discrete_dimension_type = EvaluationDDim;
73 using bsplines_type = BSplines;
76 using evaluation_domain_type =
ddc::
DiscreteDomain<evaluation_discrete_dimension_type>;
85
86
87
88 using batch_domain_type =
ddc::
89 remove_dims_of_t<batched_evaluation_domain_type, evaluation_discrete_dimension_type>;
92
93
94
95 using batched_spline_domain_type =
ddc::replace_dim_of_t<
96 batched_evaluation_domain_type,
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
263 template <
class Layout1,
class Layout2,
class Layout3,
class... CoordsDims>
265 ddc::
ChunkSpan<
double, batched_evaluation_domain_type, Layout1, memory_space>
const
268 ddc::Coordinate<CoordsDims...>
const,
269 batched_evaluation_domain_type,
271 memory_space>
const coords_eval,
272 ddc::
ChunkSpan<
double const, batched_spline_domain_type, Layout3, memory_space>
const
275 evaluation_domain_type
const evaluation_domain(spline_eval.domain());
276 batch_domain_type
const batch_domain(spline_eval.domain());
278 ddc::parallel_for_each(
279 "ddc_splines_evaluate",
282 KOKKOS_CLASS_LAMBDA(
typename batch_domain_type::discrete_element_type
const j) {
283 const auto spline_eval_1D = spline_eval[j];
284 const auto coords_eval_1D = coords_eval[j];
285 const auto spline_coef_1D = spline_coef[j];
286 for (
auto const i : evaluation_domain) {
287 spline_eval_1D(i) = eval(coords_eval_1D(i), spline_coef_1D);
293
294
295
296
297
298
299
300
301
302
303 template <
class Layout,
class... CoordsDims>
305 ddc::Coordinate<CoordsDims...>
const& coord_eval,
306 ddc::
ChunkSpan<
double const, spline_domain_type, Layout, memory_space>
const
309 return eval_no_bc<eval_deriv_type>(coord_eval, spline_coef);
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330 template <
class Layout1,
class Layout2,
class Layout3,
class... CoordsDims>
332 ddc::
ChunkSpan<
double, batched_evaluation_domain_type, Layout1, memory_space>
const
335 ddc::Coordinate<CoordsDims...>
const,
336 batched_evaluation_domain_type,
338 memory_space>
const coords_eval,
339 ddc::
ChunkSpan<
double const, batched_spline_domain_type, Layout3, memory_space>
const
342 evaluation_domain_type
const evaluation_domain(spline_eval.domain());
343 batch_domain_type
const batch_domain(spline_eval.domain());
345 ddc::parallel_for_each(
346 "ddc_splines_differentiate",
349 KOKKOS_CLASS_LAMBDA(
typename batch_domain_type::discrete_element_type
const j) {
350 const auto spline_eval_1D = spline_eval[j];
351 const auto coords_eval_1D = coords_eval[j];
352 const auto spline_coef_1D = spline_coef[j];
353 for (
auto const i : evaluation_domain) {
355 = eval_no_bc<eval_deriv_type>(coords_eval_1D(i), spline_coef_1D);
361
362
363
364
365
366
367
368
369
370
371
372
373 template <
class Layout1,
class Layout2>
375 ddc::
ChunkSpan<
double, batch_domain_type, Layout1, memory_space>
const integrals,
376 ddc::
ChunkSpan<
double const, batched_spline_domain_type, Layout2, memory_space>
const
379 batch_domain_type
const batch_domain(integrals.domain());
384 ddc::integrals(exec_space(), values);
386 ddc::parallel_for_each(
387 "ddc_splines_integrate",
390 KOKKOS_LAMBDA(
typename batch_domain_type::discrete_element_type
const j) {
392 for (
typename spline_domain_type::discrete_element_type
const i :
394 integrals(j) += spline_coef(i, j) * values(i);
400 template <
class Layout,
class... CoordsDims>
401 KOKKOS_INLINE_FUNCTION
double eval(
402 ddc::Coordinate<CoordsDims...>
const& coord_eval,
403 ddc::
ChunkSpan<
double const, spline_domain_type, Layout, memory_space>
const
406 ddc::Coordinate<continuous_dimension_type> coord_eval_interest
407 =
ddc::select<continuous_dimension_type>(coord_eval);
408 if constexpr (bsplines_type::is_periodic()) {
409 if (coord_eval_interest <
ddc::discrete_space<bsplines_type>().rmin()
410 || coord_eval_interest >
ddc::discrete_space<bsplines_type>().rmax()) {
411 coord_eval_interest -= Kokkos::floor(
413 -
ddc::discrete_space<bsplines_type>().rmin())
414 /
ddc::discrete_space<bsplines_type>().length())
415 *
ddc::discrete_space<bsplines_type>().length();
418 if (coord_eval_interest <
ddc::discrete_space<bsplines_type>().rmin()) {
419 return m_lower_extrap_rule(coord_eval_interest, spline_coef);
421 if (coord_eval_interest >
ddc::discrete_space<bsplines_type>().rmax()) {
422 return m_upper_extrap_rule(coord_eval_interest, spline_coef);
425 return eval_no_bc<eval_type>(coord_eval_interest, spline_coef);
428 template <
class EvalType,
class Layout,
class... CoordsDims>
429 KOKKOS_INLINE_FUNCTION
double eval_no_bc(
430 ddc::Coordinate<CoordsDims...>
const& coord_eval,
431 ddc::
ChunkSpan<
double const, spline_domain_type, Layout, memory_space>
const
435 std::is_same_v<EvalType, eval_type> || std::is_same_v<EvalType, eval_deriv_type>);
436 ddc::DiscreteElement<bsplines_type> jmin;
437 std::array<
double, bsplines_type::degree() + 1> vals_ptr;
438 Kokkos::mdspan<
double, Kokkos::extents<std::size_t, bsplines_type::degree() + 1>>
const
439 vals(vals_ptr.data());
440 ddc::Coordinate<continuous_dimension_type>
const coord_eval_interest
441 =
ddc::select<continuous_dimension_type>(coord_eval);
442 if constexpr (std::is_same_v<EvalType, eval_type>) {
443 jmin =
ddc::discrete_space<bsplines_type>().eval_basis(vals, coord_eval_interest);
444 }
else if constexpr (std::is_same_v<EvalType, eval_deriv_type>) {
445 jmin =
ddc::discrete_space<bsplines_type>().eval_deriv(vals, coord_eval_interest);
448 for (std::size_t i = 0; i < bsplines_type::degree() + 1; ++i) {
449 y += spline_coef(
ddc::DiscreteElement<bsplines_type>(jmin + i)) * vals[i];
friend class DiscreteDomain
A class to evaluate, differentiate or integrate a spline function.
void deriv(ddc::ChunkSpan< double, batched_evaluation_domain_type, Layout1, memory_space > const spline_eval, ddc::ChunkSpan< ddc::Coordinate< CoordsDims... > const, batched_evaluation_domain_type, Layout2, memory_space > const coords_eval, ddc::ChunkSpan< double const, batched_spline_domain_type, Layout3, memory_space > const spline_coef) const
Differentiate spline function (described by its spline coefficients) on a mesh.
KOKKOS_FUNCTION double deriv(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.
lower_extrapolation_rule_type lower_extrapolation_rule() const
Get the lower extrapolation rule.
SplineEvaluator(LowerExtrapolationRule const &lower_extrap_rule, UpperExtrapolationRule const &upper_extrap_rule)
Build a SplineEvaluator acting on batched_spline_domain.
SplineEvaluator(SplineEvaluator &&x)=default
Move-constructs.
SplineEvaluator & operator=(SplineEvaluator &&x)=default
Move-assigns.
SplineEvaluator(SplineEvaluator const &x)=default
Copy-constructs.
~SplineEvaluator()=default
Destructs.
void integrate(ddc::ChunkSpan< double, batch_domain_type, Layout1, memory_space > const integrals, ddc::ChunkSpan< double const, batched_spline_domain_type, 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, batched_evaluation_domain_type, Layout1, memory_space > const spline_eval, ddc::ChunkSpan< ddc::Coordinate< CoordsDims... > const, batched_evaluation_domain_type, Layout2, memory_space > const coords_eval, ddc::ChunkSpan< double const, batched_spline_domain_type, Layout3, memory_space > const spline_coef) const
Evaluate spline function (described by its spline coefficients) on a mesh.
SplineEvaluator & operator=(SplineEvaluator const &x)=default
Copy-assigns.
upper_extrapolation_rule_type upper_extrapolation_rule() const
Get the upper extrapolation rule.
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.
The top-level namespace of DDC.