Skip to content

Commit

Permalink
Make integrals a host function (#620)
Browse files Browse the repository at this point in the history
  • Loading branch information
tpadioleau authored Sep 5, 2024
1 parent 263508f commit 75bcbeb
Show file tree
Hide file tree
Showing 7 changed files with 193 additions and 17 deletions.
1 change: 1 addition & 0 deletions include/ddc/kernels/splines.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "splines/constant_extrapolation_rule.hpp"
#include "splines/deriv.hpp"
#include "splines/greville_interpolation_points.hpp"
#include "splines/integrals.hpp"
#include "splines/knot_discrete_dimension_type.hpp"
#include "splines/knots_as_interpolation_points.hpp"
#include "splines/math_tools.hpp"
Expand Down
4 changes: 3 additions & 1 deletion include/ddc/kernels/splines/bsplines_non_uniform.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -247,11 +247,13 @@ class NonUniformBSplines : detail::NonUniformBSplinesBase
*
* The integral of each of the B-splines over their support within the domain on which this basis was defined.
*
* @deprecated Use @ref integrals instead.
*
* @param[out] int_vals The values of the integrals. It has to be a 1D Chunkspan of size (nbasis).
* @return The values of the integrals.
*/
template <class Layout, class MemorySpace2>
KOKKOS_INLINE_FUNCTION ddc::
[[deprecated("Use `integrals` instead")]] KOKKOS_INLINE_FUNCTION ddc::
ChunkSpan<double, ddc::DiscreteDomain<DDim>, Layout, MemorySpace2>
integrals(ddc::ChunkSpan<double, discrete_domain_type, Layout, MemorySpace2>
int_vals) const;
Expand Down
14 changes: 13 additions & 1 deletion include/ddc/kernels/splines/bsplines_uniform.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ struct UniformBSplinesBase
{
};

template <class ExecSpace, class ODDim, class Layout, class OMemorySpace>
void uniform_bsplines_integrals(
ExecSpace const& execution_space,
ddc::ChunkSpan<double, ddc::DiscreteDomain<ODDim>, Layout, OMemorySpace> int_vals);

} // namespace detail

template <class T>
Expand Down Expand Up @@ -87,6 +92,11 @@ class UniformBSplines : detail::UniformBSplinesBase
template <class ODDim, class OMemorySpace>
friend class Impl;

template <class ExecSpace, class ODDim, class Layout, class OMemorySpace>
friend void detail::uniform_bsplines_integrals(
ExecSpace const& execution_space,
ddc::ChunkSpan<double, ddc::DiscreteDomain<ODDim>, Layout, OMemorySpace> int_vals);

public:
/// @brief The type of the knots defining the B-splines.
using knot_discrete_dimension_type = UniformBsplinesKnots<DDim>;
Expand Down Expand Up @@ -229,11 +239,13 @@ class UniformBSplines : detail::UniformBSplinesBase
*
* The integral of each of the B-splines over their support within the domain on which this basis was defined.
*
* @deprecated Use @ref integrals instead.
*
* @param[out] int_vals The values of the integrals. It has to be a 1D Chunkspan of size (nbasis).
* @return The values of the integrals.
*/
template <class Layout, class MemorySpace2>
KOKKOS_INLINE_FUNCTION ddc::
[[deprecated("Use `integrals` instead")]] KOKKOS_INLINE_FUNCTION ddc::
ChunkSpan<double, ddc::DiscreteDomain<DDim>, Layout, MemorySpace2>
integrals(ddc::ChunkSpan<double, discrete_domain_type, Layout, MemorySpace2>
int_vals) const;
Expand Down
168 changes: 168 additions & 0 deletions include/ddc/kernels/splines/integrals.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
// Copyright (C) The DDC development team, see COPYRIGHT.md file
//
// SPDX-License-Identifier: MIT

#pragma once

#include <ddc/ddc.hpp>

#include "bsplines_non_uniform.hpp"
#include "bsplines_uniform.hpp"

namespace ddc {

namespace detail {

/** @brief Compute the integrals of the uniform B-splines.
*
* The integral of each of the B-splines over their support within the domain on which this basis was defined.
*
* @param[in] execution_space a Kokkos execution space where the loop will be executed on
* @param[out] int_vals The values of the integrals. It has to be a 1D Chunkspan of size (nbasis).
*/
template <class ExecSpace, class DDim, class Layout, class MemorySpace>
void uniform_bsplines_integrals(
ExecSpace const& execution_space,
ddc::ChunkSpan<double, ddc::DiscreteDomain<DDim>, Layout, MemorySpace> int_vals)
{
static_assert(is_uniform_bsplines_v<DDim>);
static_assert(
Kokkos::SpaceAccessibility<ExecSpace, MemorySpace>::accessible,
"MemorySpace has to be accessible for ExecutionSpace.");

if constexpr (DDim::is_periodic()) {
assert(int_vals.size() == ddc::discrete_space<DDim>().nbasis()
|| int_vals.size() == ddc::discrete_space<DDim>().size());
} else {
assert(int_vals.size() == ddc::discrete_space<DDim>().nbasis());
}
ddc::DiscreteDomain<DDim> const full_dom_splines(ddc::discrete_space<DDim>().full_domain());

if constexpr (DDim::is_periodic()) {
ddc::DiscreteDomain<DDim> const dom_bsplines(full_dom_splines.take_first(
ddc::DiscreteVector<DDim> {ddc::discrete_space<DDim>().nbasis()}));
ddc::parallel_fill(
execution_space,
int_vals[dom_bsplines],
ddc::step<UniformBsplinesKnots<DDim>>());
if (int_vals.size() == ddc::discrete_space<DDim>().size()) {
ddc::DiscreteDomain<DDim> const dom_bsplines_repeated(
full_dom_splines.take_last(ddc::DiscreteVector<DDim> {DDim::degree()}));
ddc::parallel_fill(execution_space, int_vals[dom_bsplines_repeated], 0);
}
} else {
ddc::DiscreteDomain<DDim> const dom_bspline_entirely_in_domain
= full_dom_splines
.remove(ddc::DiscreteVector<DDim>(DDim::degree()),
ddc::DiscreteVector<DDim>(DDim::degree()));
ddc::parallel_fill(
execution_space,
int_vals[dom_bspline_entirely_in_domain],
ddc::step<UniformBsplinesKnots<DDim>>());

ddc::DiscreteElement<DDim> const first_bspline = full_dom_splines.front();
ddc::DiscreteElement<DDim> const last_bspline = full_dom_splines.back();

Kokkos::parallel_for(
Kokkos::RangePolicy<
ExecSpace,
Kokkos::IndexType<std::size_t>>(execution_space, 0, DDim::degree()),
KOKKOS_LAMBDA(std::size_t i) {
std::array<double, DDim::degree() + 2> edge_vals_ptr;
std::experimental::mdspan<
double,
std::experimental::extents<std::size_t, DDim::degree() + 2>> const
edge_vals(edge_vals_ptr.data());

ddc::discrete_space<DDim>().eval_basis(
edge_vals,
ddc::discrete_space<DDim>().rmin(),
DDim::degree() + 1);

double const d_eval = ddc::detail::sum(edge_vals);

double const c_eval = ddc::detail::sum(edge_vals, 0, DDim::degree() - i);

double const edge_value
= ddc::step<UniformBsplinesKnots<DDim>>() * (d_eval - c_eval);

int_vals(first_bspline + i) = edge_value;
int_vals(last_bspline - i) = edge_value;
});
}
}

/** @brief Compute the integrals of the non uniform B-splines.
*
* The integral of each of the B-splines over their support within the domain on which this basis was defined.
*
* @param[in] execution_space a Kokkos execution space where the loop will be executed on
* @param[out] int_vals The values of the integrals. It has to be a 1D Chunkspan of size (nbasis).
*/
template <class ExecSpace, class DDim, class Layout, class MemorySpace>
void non_uniform_bsplines_integrals(
ExecSpace const& execution_space,
ddc::ChunkSpan<double, ddc::DiscreteDomain<DDim>, Layout, MemorySpace> int_vals)
{
static_assert(is_non_uniform_bsplines_v<DDim>);
static_assert(
Kokkos::SpaceAccessibility<ExecSpace, MemorySpace>::accessible,
"MemorySpace has to be accessible for ExecutionSpace.");

if constexpr (DDim::is_periodic()) {
assert(int_vals.size() == ddc::discrete_space<DDim>().nbasis()
|| int_vals.size() == ddc::discrete_space<DDim>().size());
} else {
assert(int_vals.size() == ddc::discrete_space<DDim>().nbasis());
}
ddc::DiscreteDomain<DDim> const full_dom_splines(ddc::discrete_space<DDim>().full_domain());

double const inv_deg = 1.0 / (DDim::degree() + 1);

ddc::DiscreteDomain<DDim> const dom_bsplines(full_dom_splines.take_first(
ddc::DiscreteVector<DDim> {ddc::discrete_space<DDim>().nbasis()}));
ddc::parallel_for_each(
execution_space,
dom_bsplines,
KOKKOS_LAMBDA(ddc::DiscreteElement<DDim> ix) {
int_vals(ix)
= (ddc::coordinate(ddc::discrete_space<DDim>().get_last_support_knot(ix))
- ddc::coordinate(
ddc::discrete_space<DDim>().get_first_support_knot(ix)))
* inv_deg;
});

if constexpr (DDim::is_periodic()) {
if (int_vals.size() == ddc::discrete_space<DDim>().size()) {
ddc::DiscreteDomain<DDim> const dom_bsplines_wrap(
full_dom_splines.take_last(ddc::DiscreteVector<DDim> {DDim::degree()}));
ddc::parallel_fill(execution_space, int_vals[dom_bsplines_wrap], 0);
}
}
}

} // namespace detail

/** @brief Compute the integrals of the B-splines.
*
* The integral of each of the B-splines over their support within the domain on which this basis was defined.
*
* @param[in] execution_space a Kokkos execution space where the loop will be executed on
* @param[out] int_vals The values of the integrals. It has to be a 1D Chunkspan of size (nbasis).
* @return The values of the integrals.
*/
template <class ExecSpace, class DDim, class Layout, class MemorySpace>
ddc::ChunkSpan<double, ddc::DiscreteDomain<DDim>, Layout, MemorySpace> integrals(
ExecSpace const& execution_space,
ddc::ChunkSpan<double, ddc::DiscreteDomain<DDim>, Layout, MemorySpace> int_vals)
{
static_assert(is_uniform_bsplines_v<DDim> || is_non_uniform_bsplines_v<DDim>);
if constexpr (is_uniform_bsplines_v<DDim>) {
uniform_bsplines_integrals(execution_space, int_vals);
} else if constexpr (is_non_uniform_bsplines_v<DDim>) {
non_uniform_bsplines_integrals(execution_space, int_vals);
}
return int_vals;
}

} // namespace ddc
7 changes: 3 additions & 4 deletions include/ddc/kernels/splines/spline_builder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "ddc/kokkos_allocator.hpp"

#include "deriv.hpp"
#include "integrals.hpp"
#include "math_tools.hpp"
#include "spline_boundary_conditions.hpp"
#include "splines_linear_problem_maker.hpp"
Expand Down Expand Up @@ -976,10 +977,8 @@ SplineBuilder<
IDimX...>::quadrature_coefficients() const
{
// Compute integrals of bsplines
ddc::Chunk integral_bsplines_host(spline_domain(), ddc::HostAllocator<double>());
ddc::discrete_space<bsplines_type>().integrals(integral_bsplines_host.span_view());
auto integral_bsplines
= ddc::create_mirror_view_and_copy(MemorySpace(), integral_bsplines_host.span_view());
ddc::Chunk integral_bsplines(spline_domain(), ddc::KokkosAllocator<double, MemorySpace>());
ddc::integrals(ExecSpace(), integral_bsplines.span_view());

// Remove additional B-splines in the periodic case (cf. UniformBSplines::full_domain() documentation)
ddc::ChunkSpan integral_bsplines_without_periodic_additional_bsplines
Expand Down
6 changes: 2 additions & 4 deletions include/ddc/kernels/splines/spline_evaluator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <ddc/ddc.hpp>

#include "Kokkos_Macros.hpp"
#include "integrals.hpp"
#include "periodic_extrapolation_rule.hpp"
#include "spline_boundary_conditions.hpp"
#include "view.hpp"
Expand Down Expand Up @@ -378,10 +379,7 @@ class SplineEvaluator
ddc::DiscreteDomain<bsplines_type>(spline_coef.domain()),
ddc::KokkosAllocator<double, memory_space>());
ddc::ChunkSpan values = values_alloc.span_view();
Kokkos::parallel_for(
"ddc_splines_integrate_bsplines",
Kokkos::RangePolicy<exec_space>(0, 1),
KOKKOS_LAMBDA(int) { ddc::discrete_space<bsplines_type>().integrals(values); });
ddc::integrals(exec_space(), values);

ddc::parallel_for_each(
"ddc_splines_integrate",
Expand Down
10 changes: 3 additions & 7 deletions include/ddc/kernels/splines/spline_evaluator_2d.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <ddc/ddc.hpp>

#include "Kokkos_Macros.hpp"
#include "integrals.hpp"
#include "periodic_extrapolation_rule.hpp"
#include "spline_boundary_conditions.hpp"
#include "view.hpp"
Expand Down Expand Up @@ -812,17 +813,12 @@ class SplineEvaluator2D
ddc::DiscreteDomain<bsplines_type1>(spline_coef.domain()),
ddc::KokkosAllocator<double, memory_space>());
ddc::ChunkSpan values1 = values1_alloc.span_view();
ddc::integrals(exec_space(), values1);
ddc::Chunk values2_alloc(
ddc::DiscreteDomain<bsplines_type2>(spline_coef.domain()),
ddc::KokkosAllocator<double, memory_space>());
ddc::ChunkSpan values2 = values2_alloc.span_view();
Kokkos::parallel_for(
"ddc_splines_integrate_bsplines_2d",
Kokkos::RangePolicy<exec_space>(0, 1),
KOKKOS_LAMBDA(int) {
ddc::discrete_space<bsplines_type1>().integrals(values1);
ddc::discrete_space<bsplines_type2>().integrals(values2);
});
ddc::integrals(exec_space(), values2);

ddc::parallel_for_each(
"ddc_splines_integrate_bsplines",
Expand Down

0 comments on commit 75bcbeb

Please sign in to comment.