Skip to content

Conversation

@tretre91
Copy link
Member

This PR adds the ability to compute derivatives higher than the first order using the SplineEvaluator classes.
The deriv, deriv_dim_1, deriv_1_and_2, deriv_1_2_3, etc. methods are deprecated in favor of a deriv method taking as first argument a DiscreteElement defined on the dimensions of interest whose components are the desired orders of derivation along each of the dimension.

For example, for a 3D evaluator with continuous_dimension_types I1, I2 and I3

spline_evaluator.deriv(ddc::DiscreteElement<ddc::Deriv<I1>, ddc::Deriv<I3>>(2, 1), ...)

will use the second derivative on the first dimension, the first derivative on the third dimension, and the values (no derivation) on the second dimension because the DiscreteElement does not contain a component in Deriv<I2>.

For practical reasons, the 1D evaluator can go up to the first derivative, the 2D evaluator up to the second derivative and the 3D evaluator up to the third derivative.

Note that I still need to create some tests for the higher order derivatives, the current tests only go up to cross-differentiation with the first derivative on all dimensions.

This should resolve #926

@codecov
Copy link

codecov bot commented Nov 19, 2025

Codecov Report

❌ Patch coverage is 85.00000% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 91.63%. Comparing base (36f25f1) to head (ac4cd66).
⚠️ Report is 8 commits behind head on main.

Files with missing lines Patch % Lines
...nclude/ddc/kernels/splines/spline_evaluator_2d.hpp 77.77% 2 Missing ⚠️
...nclude/ddc/kernels/splines/spline_evaluator_3d.hpp 66.66% 1 Missing ⚠️

❌ Your patch check has failed because the patch coverage (85.00%) is below the target coverage (100.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #973      +/-   ##
==========================================
- Coverage   91.76%   91.63%   -0.13%     
==========================================
  Files          57       57              
  Lines        2756     2643     -113     
  Branches      924      865      -59     
==========================================
- Hits         2529     2422     -107     
+ Misses        136      130       -6     
  Partials       91       91              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment on lines 247 to 259
template <class... DDims>
double error_bound(
ddc::DiscreteElement<DDims...> const& orders,
std::array<double, sizeof...(DDims)> const& cell_width,
std::array<int, sizeof...(DDims)> const& degrees) const
{
using ddims = ddc::detail::TypeSeq<DDims...>;
return (tikhomirov_error_bound(
cell_width[ddc::type_seq_rank_v<DDims, ddims>],
degrees[ddc::type_seq_rank_v<DDims, ddims>] - orders.template uid<DDims>(),
max_norm<DDims>(orders, degrees))
+ ...);
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is outside the scope of this PR, but in the future all the other error_bound_on* functions in this file could be removed in favor of this generic implementation

@tretre91 tretre91 marked this pull request as ready for review December 1, 2025 14:32
Copy link
Member

@tpadioleau tpadioleau left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok looks pretty good, just a few comments/questions.

Comment on lines 1384 to 1401
if (order1 == 0) {
jmin1 = ddc::discrete_space<bsplines_type1>()
.eval_basis(vals1, coord_eval_interest1);
} else if (order1 == 1) {
jmin1 = ddc::discrete_space<bsplines_type1>()
.eval_deriv(vals1, coord_eval_interest1);
} else {
std::array<double, 3 * (bsplines_type1::degree() + 1)> derivs1_ptr;
Kokkos::mdspan<
double,
Kokkos::extents<std::size_t, bsplines_type1::degree() + 1, 3>> const
derivs1(derivs1_ptr.data());

jmin1 = ddc::discrete_space<bsplines_type1>()
.eval_basis_and_n_derivs(derivs1, coord_eval_interest1, order1);

for (std::size_t i = 0; i < bsplines_type1::degree() + 1; ++i) {
vals1[i] = DDC_MDSPAN_ACCESS_OP(derivs1, i, order1);
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would be in favor of only keeping the cases order1 > 0 && order1 < 3. The case order1 == 0, can be represented by not adding the dimension in the discrete element. I wonder if the case order1 == 1 is necessary, I guess we can consider it an optimization path ?

@EmilyBourne Any opinion ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would be in favor of only keeping the cases order1 > 0 && order1 < 3.

I agree with order1 > 0 as it seems counter-intuitive to use a derivs function to get the values. But I don't see any reason to restrict to <3. Unless you meant <degree()?

I would agree with restricting to order1<degree()+1 as the (d+1)-th derivative of a d-th order polynomial is 0.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I guess we got confused between the degree and dimensionality. We will fix that.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if the case order1 == 1 is necessary, I guess we can consider it an optimization path ?

We could only have a case order > 0, the only advantages I see for order == 1 are that it does a few less operations, and it uses less stack memory (2 arrays in eval_basis_and_n_derivs vs 0 in eval_deriv)

@tretre91 tretre91 force-pushed the nth_order_derivatives branch from 3490048 to 96349fb Compare December 2, 2025 11:17
- Use the degree of the spline instead of the Evaluator's dimension as
  the upper limit for the derivation order
- Update the tests
- Don't split the 3D test into multiple executables anymore
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add the possibility to compute 2nd derivatives or higher with the spline evaluators

3 participants