194 auto const &unique_particles = system.
cell_structure->get_unique_particles();
195 auto const &local_force = system.
cell_structure->get_local_force();
196#ifdef ESPRESSO_ROTATION
197 auto const &local_torque = system.
cell_structure->get_local_torque();
200 auto const &local_virial = system.
cell_structure->get_local_virial();
203 using execution_space = Kokkos::DefaultExecutionSpace;
204 int num_threads = execution_space().concurrency();
205 Kokkos::RangePolicy<execution_space> policy(std::size_t{0},
206 unique_particles.size());
207 Kokkos::parallel_for(
"reduction", policy,
209#ifdef ESPRESSO_ROTATION
212 &unique_particles, num_threads](std::size_t
const i) {
214#ifdef ESPRESSO_ROTATION
217 for (
int tid = 0; tid < num_threads; ++tid) {
218 force[0] += local_force(i, tid, 0);
219 force[1] += local_force(i, tid, 1);
220 force[2] += local_force(i, tid, 2);
221#ifdef ESPRESSO_ROTATION
222 torque[0] += local_torque(i, tid, 0);
223 torque[1] += local_torque(i, tid, 1);
224 torque[2] += local_torque(i, tid, 2);
227 unique_particles.at(i)->force() += force;
228#ifdef ESPRESSO_ROTATION
229 unique_particles.at(i)->torque() += torque;
236 for (
int tid = 0; tid < num_threads; ++tid) {
237 (*virial)[0] += local_virial(tid, 0);
238 (*virial)[1] += local_virial(tid, 1);
239 (*virial)[2] += local_virial(tid, 2);
247#ifdef ESPRESSO_CALIPER
248 CALI_CXX_MARK_FUNCTION;
252#ifdef ESPRESSO_CALIPER
253 CALI_MARK_BEGIN(
"copy_particles_to_GPU");
256#ifdef ESPRESSO_CALIPER
257 CALI_MARK_END(
"copy_particles_to_GPU");
262#ifdef ESPRESSO_COLLISION_DETECTION
263 collision_detection->clear_queue();
264 auto const collision_detection_cutoff = collision_detection->cutoff();
268 bond_breakage->clear_queue();
269 auto particles = cell_structure->local_particles();
276#ifdef ESPRESSO_DIPOLE_FIELD_TRACKING
283 auto const elc_kernel = coulomb.pair_force_elc_kernel();
284 auto const coulomb_kernel = coulomb.pair_force_kernel();
285 auto const dipoles_kernel = dipoles.pair_force_kernel();
286 auto const coulomb_u_kernel = coulomb.pair_energy_kernel();
287 auto *
const virial = get_npt_virial();
290 auto bond_kernel = [coulomb_kernel_ptr =
get_ptr(coulomb_kernel),
291 &bonded_ias = *bonded_ias,
292 &bond_breakage = *bond_breakage, virial,
293 &box_geo = *box_geo](
Particle &p1,
int bond_id,
294 std::span<Particle *> partners) {
296 box_geo, virial, coulomb_kernel_ptr);
300 cell_structure->get_verlet_skin(),
301 get_interaction_range(),
304 collision_detection_cutoff};
306#ifdef ESPRESSO_SHARED_MEMORY_PARALLELISM
308 get_interaction_range(), propagation->integ_switch);
310#ifdef ESPRESSO_ELECTROSTATICS
311 if (coulomb.impl->extension) {
312 update_icc_particles();
316#ifdef ESPRESSO_CALIPER
317 CALI_MARK_BEGIN(
"calc_long_range_forces");
319#ifdef ESPRESSO_ELECTROSTATICS
320 coulomb.calc_long_range_force();
322#ifdef ESPRESSO_DIPOLES
323 dipoles.calc_long_range_force();
325#ifdef ESPRESSO_CALIPER
326 CALI_MARK_END(
"calc_long_range_forces");
329#ifdef ESPRESSO_SHARED_MEMORY_PARALLELISM
330#ifdef ESPRESSO_CALIPER
331 CALI_MARK_BEGIN(
"cabana_short_range");
334 auto first_neighbor_kernel =
336 dipoles_kernel, coulomb_u_kernel);
339 get_interaction_range(), bonded_ias->maximal_cutoff(),
340 verlet_criterion, propagation->integ_switch);
345#ifdef ESPRESSO_COLLISION_DETECTION
346 auto collision_kernel = [&collision_detection = *collision_detection](
349 collision_detection.detect_collision(p1, p2, d.dist2);
351 if (not collision_detection->is_off()) {
352 cell_structure->non_bonded_loop(collision_kernel, verlet_criterion);
356#ifdef ESPRESSO_CALIPER
357 CALI_MARK_END(
"cabana_short_range");
362#ifdef ESPRESSO_CALIPER
363 CALI_MARK_BEGIN(
"serial_short_range");
366 auto pair_kernel = [coulomb_kernel_ptr =
get_ptr(coulomb_kernel),
367 dipoles_kernel_ptr =
get_ptr(dipoles_kernel),
368 elc_kernel_ptr =
get_ptr(elc_kernel),
369 coulomb_u_kernel_ptr =
get_ptr(coulomb_u_kernel),
370 &nonbonded_ias = *nonbonded_ias,
371 &thermostat = *thermostat, &bonded_ias = *bonded_ias,
373#ifdef ESPRESSO_COLLISION_DETECTION
374 &collision_detection = *collision_detection,
377 system_max_cutoff2 =
Utils::sqr(maximal_cutoff())](
379 if (d.dist2 > system_max_cutoff2)
381 auto const &ia_params = nonbonded_ias.get_ia_param(p1.type(), p2.type());
383 p1, p2, d.vec21, sqrt(d.dist2), d.dist2, p1.q() * p2.q(), ia_params,
384 thermostat, box_geo, bonded_ias, virial, coulomb_kernel_ptr,
385 dipoles_kernel_ptr, elc_kernel_ptr, coulomb_u_kernel_ptr);
386#ifdef ESPRESSO_COLLISION_DETECTION
387 if (not collision_detection.is_off()) {
388 collision_detection.detect_collision(p1, p2, d.dist2);
393 short_range_loop(bond_kernel, pair_kernel, *cell_structure, maximal_cutoff(),
394 bonded_ias->maximal_cutoff(), verlet_criterion);
396#ifdef ESPRESSO_CALIPER
397 CALI_MARK_END(
"serial_short_range");
402 constraints->add_forces(particles, get_sim_time());
403 oif_global->calculate_forces();
406 immersed_boundaries->volume_conservation(*cell_structure);
408 if (thermostat->lb and (propagation->used_propagations &
410#ifdef ESPRESSO_CALIPER
411 CALI_MARK_BEGIN(
"lb_particle_coupling");
413 lb_couple_particles();
414#ifdef ESPRESSO_CALIPER
415 CALI_MARK_END(
"lb_particle_coupling");
421#ifdef ESPRESSO_CALIPER
422 CALI_MARK_BEGIN(
"copy_forces_from_GPU");
424 gpu.copy_forces_to_host(particles,
this_node);
426#ifdef ESPRESSO_DIPOLE_FIELD_TRACKING
427 gpu.copy_dip_fld_to_host(particles,
this_node);
430#ifdef ESPRESSO_CALIPER
431 CALI_MARK_END(
"copy_forces_from_GPU");
436#ifdef ESPRESSO_VIRTUAL_SITES_RELATIVE
437 if (propagation->used_propagations &
443#ifdef ESPRESSO_VIRTUAL_SITES_CENTER_OF_MASS
444 if (propagation->used_propagations &
451 cell_structure->ghosts_reduce_forces();
454 comfixed->apply(particles);
460 propagation->recalc_forces =
false;
void add_non_bonded_pair_force(Particle &p1, Particle &p2, Utils::Vector3d const &d, double dist, double dist2, double q1q2, IA_parameters const &ia_params, Thermostat::Thermostat const &thermostat, BoxGeometry const &box_geo, BondedInteractionsMap const &bonded_ias, Utils::Vector3d *const virial, Coulomb::ShortRangeForceKernel::kernel_type const *coulomb_kernel, Dipoles::ShortRangeForceKernel::kernel_type const *dipoles_kernel, Coulomb::ShortRangeForceCorrectionsKernel::kernel_type const *elc_kernel, Coulomb::ShortRangeEnergyKernel::kernel_type const *coulomb_u_kernel)
Calculate non-bonded forces between a pair of particles and update their forces and torques.
Force information on a particle.
Struct holding all information for one particle.