ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
particle_reduction.hpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2025-2026 The ESPResSo project
3 *
4 * This file is part of ESPResSo.
5 *
6 * ESPResSo is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * ESPResSo is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#pragma once
21
22#include <config/config.hpp>
23
24#include "Particle.hpp"
26
27#include <Kokkos_Core.hpp>
28
29#include <concepts>
30#include <functional>
31#include <utility>
32
33namespace Reduction {
34
35/** @brief Kernel that adds the result from a single particle to a reduction */
36template <typename ResultType>
38 std::function<void(ResultType &, Particle const &)>;
39
40/** @brief Join two partial reduction results */
41template <typename ResultType>
42using ReductionOp = std::function<void(ResultType &, ResultType const &)>;
43
44/** @brief Custom reduction in the form required by Kokkos */
45template <typename ResultType, typename Kernel> class KokkosReducer {
46public:
47 // Kokkos reduction functors need the value_type typedef.
48 // This is the type of the result of the reduction.
49 using value_type = ResultType;
50
51 // Just like with parallel_for functors, you may specify
52 // an execution_space typedef. If not provided, Kokkos
53 // will use the default execution space by default.
54
55 // kernels to wrap
57 Kernel kernel;
61 : reduction_op(other.reduction_op), kernel(other.kernel) {}
62
63 KOKKOS_INLINE_FUNCTION void operator()(std::integral auto const i,
64 value_type &update) const {
65 kernel(i, update);
66 }
67
68 // "Join" intermediate results from different threads.
69 // This should normally implement the same reduction
70 // operation as operator() above.
71 KOKKOS_INLINE_FUNCTION void join(value_type &dst,
72 value_type const &src) const {
73 reduction_op(dst, src);
74 }
75};
76
77template <typename ResultType, typename Kernel>
78KokkosReducer<ResultType, Kernel>
80 return KokkosReducer<ResultType, Kernel>(k, reduce_op);
81}
82
83} // namespace Reduction
84
85/** @brief performs a reduction over all particles
86 *
87 * @param cs cell structure to iterate over
88 * @param add_partial is a function that adds a reduction result from a single
89 * particle
90 * @param reduce_op is a function that joins two reduction results
91 *
92 * both functions have to implement the same reduction.
93 */
94template <typename ResultType>
96 CellStructure const &cs,
98 [[maybe_unused]] Reduction::ReductionOp<ResultType> reduce_op) {
99
100 ResultType result{};
101
102 auto const &cells = cs.decomposition().local_cells();
103 if (cells.size() > 1) { // parallel loop over cells
104 auto reducer = Reduction::make_kokkos_reducer<ResultType>(
105 [&cells, add_partial](std::size_t const c_index, ResultType &res) {
106 for (auto const &p : cells[c_index]->particles()) {
107 add_partial(res, p);
108 }
109 },
110 reduce_op);
111 Kokkos::parallel_reduce( // loop over cells
112 "reduce_on_local_particle", cells.size(), reducer, result);
113 return result;
114 }
115 // single cell case
116 auto const &particles = cells.front()->particles();
117 auto reducer = Reduction::make_kokkos_reducer<ResultType>(
118 [&particles, add_partial](std::size_t const p_index, ResultType &res) {
119 add_partial(res, std::as_const(*(particles.begin() + p_index)));
120 },
121 reduce_op);
122 Kokkos::parallel_reduce( // loop over particles
123 "reduce_on_local_particle", particles.size(), reducer, result);
124 return result;
125}
Describes a cell structure / cell system.
ParticleDecomposition const & decomposition() const
Get the underlying particle decomposition.
virtual std::span< Cell *const > local_cells() const =0
Get pointer to local cells.
base_type::size_type size() const
Custom reduction in the form required by Kokkos.
KokkosReducer(Kernel kernel, ReductionOp< ResultType > reduction_op)
ReductionOp< ResultType > reduction_op
KOKKOS_INLINE_FUNCTION void join(value_type &dst, value_type const &src) const
KokkosReducer(KokkosReducer const &other)
KOKKOS_INLINE_FUNCTION void operator()(std::integral auto const i, value_type &update) const
std::function< void(ResultType &, ResultType const &)> ReductionOp
Join two partial reduction results.
KokkosReducer< ResultType, Kernel > make_kokkos_reducer(Kernel k, ReductionOp< ResultType > reduce_op)
std::function< void(ResultType &, Particle const &)> AddPartialResultKernel
Kernel that adds the result from a single particle to a reduction.
STL namespace.
ResultType reduce_over_local_particles(CellStructure const &cs, Reduction::AddPartialResultKernel< ResultType > add_partial, Reduction::ReductionOp< ResultType > reduce_op)
performs a reduction over all particles
Struct holding all information for one particle.
Definition Particle.hpp:435