ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
bond_forces_kokkos.hpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 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 "aosoa_pack.hpp"
26#include "forces_inline.hpp"
27
28#include <utils/Vector.hpp>
29
30#include <Kokkos_Core.hpp>
31#include <Kokkos_ScatterView.hpp>
32
33#include <cstddef>
34#include <optional>
35#include <variant>
36
48
54
59 : data(std::move(data_)), bond_list(std::move(bond_list_)),
60 bond_ids(std::move(bond_ids_)), coulomb_kernel(coulomb_kernel_) {}
61
62 ESPRESSO_ATTR_ALWAYS_INLINE KOKKOS_INLINE_FUNCTION void
63 operator()(std::size_t idx) const {
64 auto const &bonded_ias = data.bonded_ias;
65 auto const &box_geo = data.box_geo;
66 auto local_force = data.local_force.access();
67 auto const &aosoa = data.aosoa;
68 auto &bond_breakage = data.bond_breakage;
69#ifdef ESPRESSO_NPT
70 auto local_virial = data.local_virial.access();
71#endif
72 auto const has_breakage_specs = data.has_breakage_specs;
73 auto const bond_id = bond_ids(idx);
74
75 auto const i = bond_list(idx, 0);
76 auto const j = bond_list(idx, 1);
77 auto const &iaparams = *bonded_ias.at(bond_id);
78
79 auto const dx =
80 box_geo.get_mi_vector(aosoa.get_vector_at(aosoa.position, i),
81 aosoa.get_vector_at(aosoa.position, j));
82 // Consider for bond breakage
83 if (has_breakage_specs &&
84 bond_breakage.check_and_handle_breakage(
85 aosoa.id(i), {{aosoa.id(j), std::nullopt}}, bond_id, dx.norm())) {
86 return;
87 }
88
89 if (auto const *iap = std::get_if<ThermalizedBond>(&iaparams)) {
90 auto const result = iap->forces(
91#ifdef ESPRESSO_MASS
92 aosoa.mass(i), aosoa.mass(j),
93#else
94 1.0, 1.0,
95#endif
96 aosoa.get_vector_at(aosoa.velocity, i),
97 aosoa.get_vector_at(aosoa.velocity, j), aosoa.id(i), aosoa.id(j), dx);
98 if (result) {
99 auto const &forces = result.value();
100
101 local_force(i, 0) += std::get<0>(forces)[0];
102 local_force(i, 1) += std::get<0>(forces)[1];
103 local_force(i, 2) += std::get<0>(forces)[2];
104 local_force(j, 0) += std::get<1>(forces)[0];
105 local_force(j, 1) += std::get<1>(forces)[1];
106 local_force(j, 2) += std::get<1>(forces)[2];
107 } else {
108 auto partner_id = aosoa.id(j);
109 bond_broken_error(aosoa.id(i), {&partner_id, 1});
110 }
111 return;
112 }
113
114 auto const result =
115 calc_bond_pair_force(iaparams, dx,
116#ifdef ESPRESSO_ELECTROSTATICS
117 aosoa.charge(i) * aosoa.charge(j), coulomb_kernel
118#else
119 0.0, nullptr
120#endif
121 );
122
123 if (result) {
124 auto const f = result.value();
125 local_force(i, 0) += f[0];
126 local_force(i, 1) += f[1];
127 local_force(i, 2) += f[2];
128 local_force(j, 0) -= f[0];
129 local_force(j, 1) -= f[1];
130 local_force(j, 2) -= f[2];
131#ifdef ESPRESSO_NPT
132 auto const virial = hadamard_product(f, dx);
133 local_virial(0) += virial[0];
134 local_virial(1) += virial[1];
135 local_virial(2) += virial[2];
136#endif
137 } else {
138 auto partner_id = aosoa.id(j);
139 bond_broken_error(aosoa.id(i), {&partner_id, 1});
140 }
141 }
142};
143
148
152 : data(std::move(data_)), bond_list(std::move(bond_list_)),
153 bond_ids(std::move(bond_ids_)) {}
154
155 ESPRESSO_ATTR_ALWAYS_INLINE KOKKOS_INLINE_FUNCTION void
156 operator()(std::size_t idx) const {
157 auto const &bonded_ias = data.bonded_ias;
158 auto const &box_geo = data.box_geo;
159 auto local_force = data.local_force.access();
160 auto const &aosoa = data.aosoa;
161 auto &bond_breakage = data.bond_breakage;
162 auto const has_breakage_specs = data.has_breakage_specs;
163 auto const bond_id = bond_ids(idx);
164
165 auto const i = bond_list(idx, 0);
166 auto const j = bond_list(idx, 1);
167 auto const k = bond_list(idx, 2);
168 auto const &iaparams = *bonded_ias.at(bond_id);
169
170 auto const pos1 = aosoa.get_vector_at(aosoa.position, i);
171 auto const pos2 = aosoa.get_vector_at(aosoa.position, j);
172 auto const pos3 = aosoa.get_vector_at(aosoa.position, k);
173 auto const vec1 = box_geo.get_mi_vector(pos2, pos1);
174 auto const vec2 = box_geo.get_mi_vector(pos3, pos1);
175
176 // Consider for bond breakage
177 if (has_breakage_specs &&
178 bond_breakage.check_and_handle_breakage(
179 aosoa.id(i), {{aosoa.id(j), aosoa.id(k)}}, bond_id,
180 box_geo.get_mi_vector(pos2, pos3).norm())) {
181 return;
182 }
183 if (std::get_if<OifGlobalForcesBond>(&iaparams)) {
184 return;
185 }
186
187 auto const result = calc_bonded_three_body_force(iaparams, vec1, vec2);
188
189 if (result) {
190 auto const &forces = result.value();
191
192 local_force(i, 0) += std::get<0>(forces)[0];
193 local_force(i, 1) += std::get<0>(forces)[1];
194 local_force(i, 2) += std::get<0>(forces)[2];
195 local_force(j, 0) += std::get<1>(forces)[0];
196 local_force(j, 1) += std::get<1>(forces)[1];
197 local_force(j, 2) += std::get<1>(forces)[2];
198 local_force(k, 0) += std::get<2>(forces)[0];
199 local_force(k, 1) += std::get<2>(forces)[1];
200 local_force(k, 2) += std::get<2>(forces)[2];
201 } else {
202 std::array<int, 2> pids = {aosoa.id(j), aosoa.id(k)};
203 bond_broken_error(aosoa.id(i), {pids.data(), 2});
204 }
205 }
206};
207
212
216 : data(std::move(data_)), bond_list(std::move(bond_list_)),
217 bond_ids(std::move(bond_ids_)) {}
218
219 ESPRESSO_ATTR_ALWAYS_INLINE KOKKOS_INLINE_FUNCTION void
220 operator()(std::size_t idx) const {
221 auto const &bonded_ias = data.bonded_ias;
222 auto const &box_geo = data.box_geo;
223 auto local_force = data.local_force.access();
224 auto const &aosoa = data.aosoa;
225 auto const bond_id = bond_ids(idx);
226
227 auto const i = bond_list(idx, 0);
228 auto const j = bond_list(idx, 1);
229 auto const k = bond_list(idx, 2);
230 auto const m = bond_list(idx, 3);
231 auto const &iaparams = *bonded_ias.at(bond_id);
232
233 auto const pos1 = aosoa.get_vector_at(aosoa.position, i);
234 auto const pos2 = aosoa.get_vector_at(aosoa.position, j);
235 auto const pos3 = aosoa.get_vector_at(aosoa.position, k);
236 auto const pos4 = aosoa.get_vector_at(aosoa.position, m);
237 auto const vel1 = aosoa.get_vector_at(aosoa.velocity, i);
238 auto const vel3 = aosoa.get_vector_at(aosoa.velocity, k);
239 auto const image1 = aosoa.get_vector_at(aosoa.image, i);
240
241 auto const result = calc_bonded_four_body_force(
242 iaparams, box_geo, pos1, pos2, pos3, pos4, vel1, vel3, image1);
243
244 if (result) {
245 auto const &forces = result.value();
246
247 local_force(i, 0) += std::get<0>(forces)[0];
248 local_force(i, 1) += std::get<0>(forces)[1];
249 local_force(i, 2) += std::get<0>(forces)[2];
250 local_force(j, 0) += std::get<1>(forces)[0];
251 local_force(j, 1) += std::get<1>(forces)[1];
252 local_force(j, 2) += std::get<1>(forces)[2];
253 local_force(k, 0) += std::get<2>(forces)[0];
254 local_force(k, 1) += std::get<2>(forces)[1];
255 local_force(k, 2) += std::get<2>(forces)[2];
256 local_force(m, 0) += std::get<3>(forces)[0];
257 local_force(m, 1) += std::get<3>(forces)[1];
258 local_force(m, 2) += std::get<3>(forces)[2];
259 } else {
260 std::array<int, 3> pids = {aosoa.id(j), aosoa.id(k), aosoa.id(m)};
261 bond_broken_error(aosoa.id(i), {pids.data(), 3});
262 }
263 }
264};
Vector implementation and trait types for boost qvm interoperability.
#define ESPRESSO_ATTR_ALWAYS_INLINE
void bond_broken_error(int id, std::span< const int > partner_ids)
container for bonded interactions.
Kokkos::Experimental::ScatterView< double[3], Kokkos::LayoutRight > ScatterVirial
Kokkos::Experimental::ScatterView< double *[3], Kokkos::LayoutRight > ScatterForce
Force calculation.
ESPRESSO_ATTR_ALWAYS_INLINE std::optional< Utils::Vector3d > calc_bond_pair_force(Bonded_IA_Parameters const &iaparams, Utils::Vector3d const &dx, double const q1q2, Coulomb::ShortRangeForceKernel::kernel_type const *kernel)
Compute the bonded interaction force between particle pairs.
ESPRESSO_ATTR_ALWAYS_INLINE std::optional< std::tuple< Utils::Vector3d, Utils::Vector3d, Utils::Vector3d, Utils::Vector3d > > calc_bonded_four_body_force(Bonded_IA_Parameters const &iaparams, BoxGeometry const &box_geo, Utils::Vector3d const &pos1, Utils::Vector3d const &pos2, Utils::Vector3d const &pos3, Utils::Vector3d const &pos4, Utils::Vector3d const &vel1, Utils::Vector3d const &vel3, Utils::Vector3i const &image1)
ESPRESSO_ATTR_ALWAYS_INLINE std::optional< std::tuple< Utils::Vector3d, Utils::Vector3d, Utils::Vector3d > > calc_bonded_three_body_force(Bonded_IA_Parameters const &iaparams, Utils::Vector3d const &vec1, Utils::Vector3d const &vec2)
auto hadamard_product(Vector< T, N > const &a, Vector< U, N > const &b)
Definition Vector.hpp:377
STL namespace.
ESPRESSO_ATTR_ALWAYS_INLINE KOKKOS_INLINE_FUNCTION void operator()(std::size_t idx) const
LocalBondState::AngleBondIDType bond_ids
AngleBondsKernel(BondsKernelData data_, LocalBondState::AngleBondlistType bond_list_, LocalBondState::AngleBondIDType bond_ids_)
LocalBondState::AngleBondlistType bond_list
CellStructure::AoSoA_pack const & aosoa
bool const has_breakage_specs
BondBreakage::BondBreakage & bond_breakage
CellStructure::ScatterForce local_force
BondedInteractionsMap const & bonded_ias
BoxGeometry const & box_geo
CellStructure::ScatterVirial local_virial
Solver::ShortRangeForceKernel kernel_type
ESPRESSO_ATTR_ALWAYS_INLINE KOKKOS_INLINE_FUNCTION void operator()(std::size_t idx) const
DihedralBondsKernel(BondsKernelData data_, LocalBondState::DihedralBondlistType bond_list_, LocalBondState::DihedralBondIDType bond_ids_)
LocalBondState::DihedralBondIDType bond_ids
LocalBondState::DihedralBondlistType bond_list
Kokkos::View< int *[4], Kokkos::LayoutRight > DihedralBondlistType
Kokkos::View< int *[2], Kokkos::LayoutRight > PairBondlistType
Kokkos::View< int *, Kokkos::LayoutRight > DihedralBondIDType
Kokkos::View< int *[3], Kokkos::LayoutRight > AngleBondlistType
Kokkos::View< int *, Kokkos::LayoutRight > PairBondIDType
Kokkos::View< int *, Kokkos::LayoutRight > AngleBondIDType
PairBondsKernel(BondsKernelData data_, LocalBondState::PairBondlistType bond_list_, LocalBondState::PairBondIDType bond_ids_, Coulomb::ShortRangeForceKernel::kernel_type const *coulomb_kernel_)
LocalBondState::PairBondIDType bond_ids
ESPRESSO_ATTR_ALWAYS_INLINE KOKKOS_INLINE_FUNCTION void operator()(std::size_t idx) const
Coulomb::ShortRangeForceKernel::kernel_type const *const coulomb_kernel
LocalBondState::PairBondlistType bond_list
BondsKernelData data