32#include <Cabana_Core.hpp>
33#include <Cabana_NeighborList.hpp>
35#ifdef ESPRESSO_CALIPER
49#ifdef ESPRESSO_ELECTROSTATICS
53#if defined(ESPRESSO_GAY_BERNE) or defined(ESPRESSO_DIPOLES)
57#ifdef ESPRESSO_DIPOLES
63 aosoa.
id(index) = p.
id();
72#ifdef ESPRESSO_EXCLUSIONS
73 bool const has_exclusion = not p.
exclusions().empty();
82 aosoa.
flags(index) = 0;
87 std::span<Cell *const> cells,
BoxGeometry const &box_geo,
88 auto const &verlet_criterion,
89 Kokkos::View<int *, Kokkos::DefaultHostExecutionSpace>
const &id_to_index,
90 int const max_id,
auto const &intra_operator,
auto const &inter_operator) {
102 auto const minimum_image_dist2 =
103 [&box_geo, has_lees_edwards, cuboid_minimum_image](
106 : cuboid_minimum_image.dist2(a, b);
109 auto intra_kernel = [&cells, minimum_image_dist2, &verlet_criterion,
110 &id_to_index, &intra_operator, max_id](
const int i) {
111 auto &local_particles = cells[i]->particles();
112 for (
auto it = local_particles.begin(); it != local_particles.end(); ++it) {
113 auto const &p1 = *it;
114 if (p1.id() <= max_id) {
115 auto const ii = id_to_index(p1.id());
118 for (
auto jt = std::next(it); jt != local_particles.end(); ++jt) {
119 if ((*jt).id() <= max_id) {
120 if (verlet_criterion(p1, *jt,
121 minimum_image_dist2(p1.pos(), jt->pos()))) {
122 auto const jj = id_to_index((*jt).id());
124 intra_operator(ii, jj);
134 auto inter_kernel = [&cells, minimum_image_dist2, &verlet_criterion,
135 &id_to_index, &inter_operator, max_id](
const int i) {
136 auto &local_particles = cells[i]->particles();
137 for (
auto const &p1 : local_particles) {
138 if (p1.id() <= max_id) {
139 auto const ii = id_to_index(p1.id());
142 for (
auto &neighbor : cells[i]->neighbors().red()) {
143 for (
auto const &p2 : neighbor->particles()) {
144 if (p2.id() <= max_id) {
145 if (verlet_criterion(p1, p2,
146 minimum_image_dist2(p1.pos(), p2.pos()))) {
147 auto const jj = id_to_index(p2.id());
149 inter_operator(ii, jj);
160 kokkos_parallel_range_for<Kokkos::DefaultHostExecutionSpace>(
161 "intra", std::size_t{0}, cells.size(), intra_kernel);
164 kokkos_parallel_range_for<Kokkos::DefaultHostExecutionSpace>(
165 "inter", std::size_t{0}, cells.size(), inter_kernel);
172template <
class execution_space = Kokkos::DefaultHostExecutionSpace>
175 auto const &make_verlet_criterion,
double const pair_cutoff,
176 auto const integ_switch) {
177#ifdef ESPRESSO_CALIPER
182 auto const n_part = unique_particles.size();
184 auto &aosoa = cell_structure.
get_aosoa();
192#ifdef ESPRESSO_CALIPER
197 int dihedral_count = 0;
198#ifdef ESPRESSO_EXCLUSIONS
201 aosoa.reset_any_exclusion();
203 kokkos_parallel_range_for<execution_space>(
204 "AoSoA write", std::size_t{0}, n_part,
205 [&unique_particles, &aosoa, &id_to_index, &cell_structure, &pair_count,
206 &angle_count, &dihedral_count](
int const index) {
207 auto const &p = *unique_particles.at(index);
209 id_to_index(p.id()) = index;
210 if (not p.is_ghost()) {
211 cell_structure.update_bond_storage(pair_count, angle_count,
216 using host_space = Kokkos::DefaultHostExecutionSpace;
217 auto &bs = cell_structure.bond_state();
219 auto &pair_bond_list = bs.pair_list;
220 kokkos_parallel_range_for<host_space>(
221 "resolve_pair_bond_indices", std::size_t{0}, pair_count,
222 [&pair_bond_list, &id_to_index](
int idx) {
223 for (
int col = 0; col < 2; ++col) {
224 pair_bond_list(idx, col) = id_to_index(pair_bond_list(idx, col));
229 auto &angle_bond_list = bs.angle_list;
230 kokkos_parallel_range_for<host_space>(
231 "resolve_angle_bond_indices", std::size_t{0}, angle_count,
232 [&angle_bond_list, &id_to_index](
int idx) {
233 for (
int col = 0; col < 3; ++col) {
234 angle_bond_list(idx, col) =
235 id_to_index(angle_bond_list(idx, col));
239 if (dihedral_count) {
240 auto &dihedral_bond_list = bs.dihedral_list;
241 kokkos_parallel_range_for<host_space>(
242 "resolve_dihedral_bond_indices", std::size_t{0}, dihedral_count,
243 [&dihedral_bond_list, &id_to_index](
int idx) {
244 for (
int col = 0; col < 4; ++col) {
245 dihedral_bond_list(idx, col) =
246 id_to_index(dihedral_bond_list(idx, col));
250 if (pair_count != 0 or angle_count != 0 or dihedral_count != 0) {
253#ifdef ESPRESSO_CALIPER
261 cell_structure.use_verlet_list);
262#ifdef ESPRESSO_CALIPER
265 cell_structure.rebuild_verlet_list_cabana(
266 [&](std::span<Cell *const> cells,
BoxGeometry const &box,
268 auto const verlet_criterion = make_verlet_criterion();
270 std::move(cells), box, verlet_criterion, id_to_index, max_id,
271 [&](
const int i,
const int j) {
275 [&](
const int i,
const int j) {
281 cell_structure.use_verlet_list =
false;
283 <<
"Verlet list overflow detected: neighbor count exceeded "
284 "max_counts. Falling back to the link cell algorithm. "
286 << Cabana::NeighborList<CellStructure::ListType>::maxNeighbor(
291#ifdef ESPRESSO_CALIPER
298#ifdef ESPRESSO_CALIPER
301#ifdef ESPRESSO_EXCLUSIONS
304 aosoa.reset_any_exclusion();
306 kokkos_parallel_range_for<execution_space>(
307 "AoSoA write", std::size_t{0}, n_part,
308 [&unique_particles, &aosoa](
int const index) {
309 auto const &p = *unique_particles.at(index);
313#ifdef ESPRESSO_CALIPER
319#ifdef ESPRESSO_ELECTROSTATICS
320template <
class execution_space = Kokkos::DefaultHostExecutionSpace>
324 auto const n_part = unique_particles.size();
325 auto &aosoa = cell_structure.
get_aosoa();
327 kokkos_parallel_range_for<execution_space>(
328 "Views update charges", std::size_t{0}, n_part,
329 [&unique_particles, &aosoa](std::size_t
const index) {
330 aosoa.charge(index) = unique_particles.at(index)->q();
347template <
class execution_space = Kokkos::DefaultHostExecutionSpace>
349 auto const &angle_bonds_kernel,
350 auto const &dihedral_bonds_kernel,
351 auto const &nonbonded_kernel,
353 double bond_cutoff,
auto const &make_verlet_criterion,
354 auto const integ_switch,
358 if (bond_cutoff >= 0.) {
359#ifdef ESPRESSO_CALIPER
362 using host_space = Kokkos::DefaultHostExecutionSpace;
365 auto const n_dihedral_bonds =
367 if (n_pair_bonds > 0) {
368 kokkos_parallel_range_for<host_space>(
"for_each_local_pair_bonds",
369 std::size_t{0}, n_pair_bonds,
372 if (n_angle_bonds > 0) {
373 kokkos_parallel_range_for<host_space>(
"for_each_local_angle_bonds",
374 std::size_t{0}, n_angle_bonds,
377 if (n_dihedral_bonds > 0) {
378 kokkos_parallel_range_for<host_space>(
"for_each_local_dihedral_bonds",
379 std::size_t{0}, n_dihedral_bonds,
380 dihedral_bonds_kernel);
382 if (n_pair_bonds != 0 or n_angle_bonds != 0 or n_dihedral_bonds != 0) {
385#ifdef ESPRESSO_CALIPER
391 if (pair_cutoff > 0.) {
392#ifdef ESPRESSO_CALIPER
399 if (verlet_pair_loop) {
400 verlet_pair_loop(verlet_list, n_particles);
401 }
else if (Kokkos::num_threads() == 1) {
402 using NL = Cabana::NeighborList<CellStructure::ListType>;
403 for (std::size_t i = 0; i < n_particles; ++i) {
404 auto const nn = NL::numNeighbor(verlet_list, i);
405 for (std::size_t n = 0; n < nn; ++n) {
406 nonbonded_kernel(i, NL::getNeighbor(verlet_list, i, n));
410 Kokkos::RangePolicy<execution_space> policy(std::size_t{0},
412 Cabana::neighbor_parallel_for(policy, nonbonded_kernel, verlet_list,
413 Cabana::FirstNeighborsTag(),
414 Cabana::SerialOpTag());
418 [&](std::span<Cell *const> cells,
BoxGeometry const &box) {
419 auto const verlet_criterion = make_verlet_criterion();
421 std::move(cells), box, verlet_criterion,
424 [&](
const int i,
const int j) {
426 nonbonded_kernel(i, j);
428 [&](
const int i,
const int j) {
430 nonbonded_kernel(i, j);
435#ifdef ESPRESSO_CALIPER
@ INTEG_METHOD_STEEPEST_DESCENT
#define ESPRESSO_ATTR_ALWAYS_INLINE
Zero-overhead Caliper guards for the inactive (no CALI_CONFIG) case.
#define ESPRESSO_CALI_MARK_END(name)
Guarded CALI_MARK_END — no-op when inactive.
#define ESPRESSO_CALI_MARK_BEGIN(name)
Guarded CALI_MARK_BEGIN — no-op when inactive.
#define ESPRESSO_CALI_MARK_FUNCTION
Guarded drop-in replacement for CALI_CXX_MARK_FUNCTION.
ESPRESSO_ATTR_ALWAYS_INLINE T get_mi_dist2(Utils::Vector3< T > const &a, Utils::Vector3< T > const &b) const noexcept
Get the squared minimum-image distance between two coordinates.
auto cuboid_minimum_image() const
Cuboid minimum-image fold parameters for hoisting into kernels.
Describes a cell structure / cell system.
int get_local_angle_bond_numbers() const
int get_local_pair_bond_numbers() const
auto prepare_verlet_list_cabana(double cutoff)
Reset local properties of the Verlet list.
int get_local_dihedral_bond_numbers() const
int get_cached_max_local_particle_id() const
auto const & get_unique_particles() const
unsigned get_resort_particles() const
Get the currently scheduled resort level.
void cell_list_loop(auto &&kernel)
auto const & get_verlet_list_cabana() const
KOKKOS_INLINE_FUNCTION void addNeighborLB(int pid, int nid)
KOKKOS_INLINE_FUNCTION void addNeighbor(int pid, int nid)
KOKKOS_INLINE_FUNCTION bool hasOverflow() const
#define runtimeWarningMsg()
constexpr Vector< T, 3 > convert_quaternion_to_director(Quaternion< T > const &quat)
Convert quaternion to director.
ESPRESSO_ATTR_ALWAYS_INLINE void link_cell_kokkos(std::span< Cell *const > cells, BoxGeometry const &box_geo, auto const &verlet_criterion, Kokkos::View< int *, Kokkos::DefaultHostExecutionSpace > const &id_to_index, int const max_id, auto const &intra_operator, auto const &inter_operator)
void cabana_short_range(auto const &pair_bonds_kernel, auto const &angle_bonds_kernel, auto const &dihedral_bonds_kernel, auto const &nonbonded_kernel, CellStructure &cell_structure, double pair_cutoff, double bond_cutoff, auto const &make_verlet_criterion, auto const integ_switch, ShortRangeVerletPairLoop const &verlet_pair_loop={})
ESPRESSO_ATTR_ALWAYS_INLINE void commit_particle(Particle const &p, auto const index, CellStructure::AoSoA_pack &aosoa, bool const rebuild)
ESPRESSO_ATTR_ALWAYS_INLINE void update_cabana_state(CellStructure &cell_structure, auto const &make_verlet_criterion, double const pair_cutoff, auto const integ_switch)
std::function< void(CellStructure::ListType const &, std::size_t)> ShortRangeVerletPairLoop
ESPRESSO_ATTR_ALWAYS_INLINE void update_aosoa_charges(CellStructure &cell_structure)
DEVICE_QUALIFIER void set_has_exclusion(std::size_t i, bool value)
PositionViewType position
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)
void mark_any_exclusion()
DirectorViewType director
VelocityViewType velocity
Struct holding all information for one particle.
constexpr auto const & quat() const
constexpr auto const & pos() const
constexpr auto const & mass() const
constexpr auto const & dipm() const
Utils::compact_vector< int > & exclusions()
constexpr auto const & type() const
constexpr auto const & image_box() const
constexpr auto const & id() const
constexpr auto const & q() const
constexpr auto const & v() const