ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
aosoa_pack.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
25
27
28#include <Kokkos_Core.hpp>
29
30#include <omp.h>
31
32#include <atomic>
33#include <cstdint>
34#include <span>
35
38 Kokkos::View<double *[3], Kokkos::LayoutRight, Kokkos::HostSpace>;
40 Kokkos::View<double *[3], Kokkos::LayoutRight, Kokkos::HostSpace>;
42 Kokkos::View<double *[3], Kokkos::LayoutRight, Kokkos::HostSpace>;
44 Kokkos::View<int *[3], Kokkos::LayoutRight, Kokkos::HostSpace>;
45 using ChargeViewType = Kokkos::View<double *, Kokkos::HostSpace>;
46 using DipmViewType = Kokkos::View<double *, Kokkos::HostSpace>;
47 using IdViewType = Kokkos::View<int *, Kokkos::HostSpace>;
48 using TypeViewType = Kokkos::View<int *, Kokkos::HostSpace>;
49 using MassViewType = Kokkos::View<double *, Kokkos::HostSpace>;
50 using FlagsViewType = Kokkos::View<uint8_t *, Kokkos::HostSpace>;
51
62
63 AoSoA_pack() = default;
64
66
68 void resize(std::size_t num_particles) {
69 if (position.extent(0) == 0) {
70 // First allocation
73#ifdef ESPRESSO_ELECTROSTATICS
75#endif
76 id = IdViewType("id", num_particles);
78#ifdef ESPRESSO_MASS
80#endif
83#if defined(ESPRESSO_GAY_BERNE) or defined(ESPRESSO_DIPOLES)
85#endif
86#ifdef ESPRESSO_DIPOLES
88#endif
89 } else {
90 // Reallocation
91 Kokkos::realloc(position, num_particles);
92 Kokkos::realloc(image, num_particles);
93#ifdef ESPRESSO_ELECTROSTATICS
94 Kokkos::realloc(charge, num_particles);
95#endif
96 Kokkos::realloc(id, num_particles);
97 Kokkos::realloc(type, num_particles);
98#ifdef ESPRESSO_MASS
99 Kokkos::realloc(mass, num_particles);
100#endif
101 Kokkos::realloc(flags, num_particles);
102 Kokkos::realloc(velocity, num_particles);
103#if defined(ESPRESSO_GAY_BERNE) or defined(ESPRESSO_DIPOLES)
104 Kokkos::realloc(director, num_particles);
105#endif
106#ifdef ESPRESSO_DIPOLES
107 Kokkos::realloc(dipm, num_particles);
108#endif
109 }
110 }
111
112 template <typename array_layout, typename T, std::size_t N>
113 DEVICE_QUALIFIER std::span<T, N>
114 get_span_at(Kokkos::View<T *[N], array_layout, Kokkos::HostSpace> const &view,
115 std::size_t i) const {
116 return std::span<T, N>(const_cast<T *>(&view(i, 0)), N);
117 }
118
119 template <typename array_layout, typename T, std::size_t N>
121 Kokkos::View<T *[N], array_layout, Kokkos::HostSpace> const &view,
122 std::size_t i) const {
123 Utils::Vector<T, N> result;
124 auto const data = result.data();
125#if !defined(__NVCOMPILER) && !defined(__CUDACC__)
126#if defined(__clang__)
127#pragma omp unroll
128#elif defined(__GNUC__) or defined(__GNUG__)
129#pragma GCC unroll 8
130#endif
131#endif
132 for (std::size_t j = 0ul; j < N; j += 1ul) {
133 data[j] = view(i, j);
134 }
135 return result;
136 }
137
138 template <typename array_layout, typename T, std::size_t N>
140 set_vector_at(Kokkos::View<T *[N], array_layout, Kokkos::HostSpace> &view,
141 std::size_t i, Utils::Vector<T, N> const &value) {
142#if !defined(__NVCOMPILER) && !defined(__CUDACC__)
143#if defined(__clang__)
144#pragma omp unroll
145#elif defined(__GNUC__) or defined(__GNUG__)
146#pragma GCC unroll 8
147#endif
148#endif
149 for (std::size_t j = 0ul; j < N; j += 1ul) {
150 view(i, j) = value[j];
151 }
152 }
153
154 // Aggregate of the per-particle exclusion flag over the whole pack (local +
155 // ghost). It lets the specialized-kernel dispatch decide in O(1) whether any
156 // packed particle carries an exclusion, instead of sweeping every flag on
157 // every force call. It is only ever transitioned false->true during a commit
158 // sweep (which runs under Kokkos::parallel_for on the host execution space),
159 // so a relaxed atomic store suffices; reads happen after the sweep's
160 // Kokkos::fence() and are therefore race-free. The atomic member makes
161 // AoSoA_pack non-copyable and non-movable, which is fine: it is only ever
162 // default-constructed via std::make_unique and accessed by reference (see
163 // CellStructure::m_aosoa).
164 std::atomic<bool> any_exclusion{false};
165
167 any_exclusion.store(false, std::memory_order_relaxed);
168 }
169
170 bool has_any_exclusion() const {
171 return any_exclusion.load(std::memory_order_relaxed);
172 }
173
174 // Host-only: record that some particle carries an exclusion. Kept out of the
175 // device-qualified set_has_exclusion so the atomic never appears in device
176 // code; commit_particle calls this from the host commit sweep. Test before
177 // setting: after the first write the flag's cache line stays shared, so
178 // exclusion-heavy sweeps don't ping-pong it across threads.
180 if (not any_exclusion.load(std::memory_order_relaxed)) {
181 any_exclusion.store(true, std::memory_order_relaxed);
182 }
183 }
184
185 DEVICE_QUALIFIER void set_has_exclusion(std::size_t i, bool value) {
186 flags(i) = value ? uint8_t{1} : uint8_t{0};
187 }
188
189 DEVICE_QUALIFIER bool has_exclusion(std::size_t i) const {
190 return flags(i) == uint8_t{1};
191 }
192};
DEVICE_QUALIFIER constexpr pointer data() noexcept
Definition Array.hpp:132
cudaStream_t stream[1]
CUDA streams for parallel computing on CPU and GPU.
#define HOST_ONLY_QUALIFIER
#define DEVICE_QUALIFIER
DEVICE_QUALIFIER void set_has_exclusion(std::size_t i, bool value)
Kokkos::View< int *[3], Kokkos::LayoutRight, Kokkos::HostSpace > ImageViewType
Kokkos::View< double *, Kokkos::HostSpace > ChargeViewType
DEVICE_QUALIFIER std::span< T, N > get_span_at(Kokkos::View< T *[N], array_layout, Kokkos::HostSpace > const &view, std::size_t i) const
std::atomic< bool > any_exclusion
Kokkos::View< uint8_t *, Kokkos::HostSpace > FlagsViewType
Kokkos::View< double *, Kokkos::HostSpace > DipmViewType
Kokkos::View< double *[3], Kokkos::LayoutRight, Kokkos::HostSpace > DirectorViewType
DEVICE_QUALIFIER bool has_exclusion(std::size_t i) const
PositionViewType position
AoSoA_pack(std::size_t num_particles)
DEVICE_QUALIFIER void set_vector_at(Kokkos::View< T *[N], array_layout, Kokkos::HostSpace > &view, std::size_t i, Utils::Vector< T, N > const &value)
Kokkos::View< int *, Kokkos::HostSpace > TypeViewType
Kokkos::View< double *[3], Kokkos::LayoutRight, Kokkos::HostSpace > PositionViewType
DEVICE_QUALIFIER Utils::Vector< T, N > get_vector_at(Kokkos::View< T *[N], array_layout, Kokkos::HostSpace > const &view, std::size_t i) const
DirectorViewType director
Kokkos::View< double *[3], Kokkos::LayoutRight, Kokkos::HostSpace > VelocityViewType
HOST_ONLY_QUALIFIER void resize(std::size_t num_particles)
Kokkos::View< double *, Kokkos::HostSpace > MassViewType
Kokkos::View< int *, Kokkos::HostSpace > IdViewType
VelocityViewType velocity