265 [[maybe_unused]]
auto const &elc_kernel,
auto const &coulomb_kernel,
266 [[maybe_unused]]
auto const &dipoles_kernel) {
270 if (virial !=
nullptr)
273#ifdef ESPRESSO_DIPOLES
274 if (
get_ptr(dipoles_kernel) !=
nullptr)
277#ifdef ESPRESSO_ELECTROSTATICS
278 if (
get_ptr(elc_kernel) !=
nullptr)
287 if ((nonbonded_ias.combined_active_pair_mask() &
292 if (nonbonded_ias.any_thole_configured())
296 auto const &aosoa = cell_structure.get_aosoa();
297#ifdef ESPRESSO_EXCLUSIONS
302 if (aosoa.has_any_exclusion())
306 auto scatter_force = cell_structure.get_scatter_force();
307 auto const minimum_image = system.
box_geo->cuboid_minimum_image();
310#ifdef ESPRESSO_ELECTROSTATICS
311 if (
auto const *coulomb_ptr =
get_ptr(coulomb_kernel);
312 coulomb_ptr !=
nullptr) {
313 return make_specialized_verlet_pair_loop<true>(
314 nonbonded_ias, aosoa, scatter_force, minimum_image, max_cutoff_sq,
323 static_cast<void>(coulomb_kernel);
326 return make_specialized_verlet_pair_loop<false>(
327 nonbonded_ias, aosoa, scatter_force, minimum_image, max_cutoff_sq);
332#ifdef ESPRESSO_CALIPER
336 auto const &unique_particles = system.
cell_structure->get_unique_particles();
339 Kokkos::Experimental::contribute(local_force, scatter_force);
340#ifdef ESPRESSO_ROTATION
344 auto const reduce_torque = system.
cell_structure->torque_replicas_dirty();
347 auto scatter_torque = system.
cell_structure->get_scatter_torque();
348 Kokkos::Experimental::contribute(local_torque, scatter_torque);
351#ifdef ESPRESSO_DIPOLE_FIELD_TRACKING
352 auto const reduce_dip_fld = system.
cell_structure->dip_fld_replicas_dirty();
354 if (reduce_dip_fld) {
355 auto scatter_dip_fld = system.
cell_structure->get_scatter_dip_fld();
356 Kokkos::Experimental::contribute(local_dip_fld, scatter_dip_fld);
362 auto scatter_virial = system.
cell_structure->get_scatter_virial();
363 Kokkos::Experimental::contribute(local_virial, scatter_virial);
367 using execution_space = Kokkos::DefaultHostExecutionSpace;
368 Kokkos::RangePolicy<execution_space> policy(std::size_t{0},
369 unique_particles.size());
370 Kokkos::parallel_for(
"reduction", policy,
372#ifdef ESPRESSO_ROTATION
373 &local_torque, reduce_torque,
375#ifdef ESPRESSO_DIPOLE_FIELD_TRACKING
376 &local_dip_fld, reduce_dip_fld,
378 &unique_particles](std::size_t
const i) {
380 force[0] += local_force(i, 0);
381 force[1] += local_force(i, 1);
382 force[2] += local_force(i, 2);
383 unique_particles.at(i)->force() += force;
384#ifdef ESPRESSO_ROTATION
387 torque[0] += local_torque(i, 0);
388 torque[1] += local_torque(i, 1);
389 torque[2] += local_torque(i, 2);
390 unique_particles.at(i)->torque() += torque;
393#ifdef ESPRESSO_DIPOLE_FIELD_TRACKING
394 if (reduce_dip_fld) {
396 dip_fld[0] += local_dip_fld(i, 0);
397 dip_fld[1] += local_dip_fld(i, 1);
398 dip_fld[2] += local_dip_fld(i, 2);
399 unique_particles.at(i)->dip_fld() += dip_fld;
407 (*virial)[0] += local_virial(0);
408 (*virial)[1] += local_virial(1);
409 (*virial)[2] += local_virial(2);
415#ifdef ESPRESSO_CALIPER
420#ifdef ESPRESSO_CALIPER
424#ifdef ESPRESSO_CALIPER
430#ifdef ESPRESSO_COLLISION_DETECTION
431 collision_detection->clear_queue();
432 auto const collision_detection_cutoff = collision_detection->cutoff();
436 bond_breakage->clear_queue();
437 auto particles = cell_structure->local_particles();
444#ifdef ESPRESSO_DIPOLE_FIELD_TRACKING
445 if (dipoles.impl->solver.has_value()) {
452 auto const elc_kernel = coulomb.pair_force_elc_kernel();
453 auto const coulomb_kernel = coulomb.pair_force_kernel();
454 auto const dipoles_kernel = dipoles.pair_force_kernel();
455 auto const coulomb_u_kernel = coulomb.pair_energy_kernel();
456 auto *
const virial = get_npt_virial();
461 auto const make_verlet_criterion = [&] {
463 cell_structure->get_verlet_skin(),
464 get_interaction_range(),
467 collision_detection_cutoff};
471#ifdef ESPRESSO_ELECTROSTATICS
472 if (coulomb.impl->extension) {
473 update_icc_particles();
477#ifdef ESPRESSO_CALIPER
480#ifdef ESPRESSO_ELECTROSTATICS
481 coulomb.calc_long_range_force();
483#ifdef ESPRESSO_DIPOLES
484 dipoles.calc_long_range_force();
486#ifdef ESPRESSO_CALIPER
490#ifdef ESPRESSO_CALIPER
493 auto &bs = cell_structure->bond_state();
496 bonds_kernel_data, bs.pair_list, bs.pair_ids,
get_ptr(coulomb_kernel)};
497 auto angle_bonds_kernel =
499 auto dihedral_bonds_kernel =
502 auto first_neighbor_kernel =
504 dipoles_kernel, coulomb_u_kernel);
507 *
this, virial, elc_kernel, coulomb_kernel, dipoles_kernel);
517 [[maybe_unused]]
auto const generic_pair_path =
518 get_interaction_range() > 0. and
519 (not specialized_pair_loop or
521 not cell_structure->use_verlet_list);
522#ifdef ESPRESSO_ROTATION
527 auto const dipolar_pair_kernel_active =
528#ifdef ESPRESSO_DIPOLES
529 get_ptr(dipoles_kernel) !=
nullptr;
533 if (generic_pair_path and (
gay_berne_active or dipolar_pair_kernel_active)) {
534 cell_structure->mark_torque_replicas_dirty();
535#ifdef ESPRESSO_DIPOLE_FIELD_TRACKING
536 cell_structure->mark_dip_fld_replicas_dirty();
545 auto const have_bonds = cell_structure->get_local_pair_bond_numbers() > 0 or
546 cell_structure->get_local_angle_bond_numbers() > 0 or
547 cell_structure->get_local_dihedral_bond_numbers() > 0;
548 if (generic_pair_path or
549 (bonded_ias->maximal_cutoff() >= 0. and have_bonds)) {
550 cell_structure->mark_virial_replicas_dirty();
555 dihedral_bonds_kernel, first_neighbor_kernel,
556 *cell_structure, get_interaction_range(),
557 bonded_ias->maximal_cutoff(), make_verlet_criterion,
558 propagation->integ_switch, specialized_pair_loop);
563#ifdef ESPRESSO_COLLISION_DETECTION
564 auto collision_kernel = [&collision_detection = *collision_detection](
567 collision_detection.detect_collision(p1, p2, d.dist2);
569 if (not collision_detection->is_off()) {
570 auto const verlet_criterion = make_verlet_criterion();
571 cell_structure->non_bonded_loop(collision_kernel, verlet_criterion);
575#ifdef ESPRESSO_CALIPER
579 constraints->add_forces(particles, get_sim_time());
580 oif_global->calculate_forces();
583 immersed_boundaries->volume_conservation(*cell_structure);
585 if (thermostat->lb and (propagation->used_propagations &
587#ifdef ESPRESSO_CALIPER
590 lb_couple_particles();
591#ifdef ESPRESSO_CALIPER
598#ifdef ESPRESSO_CALIPER
601 gpu->copy_forces_to_host(particles,
this_node);
603#ifdef ESPRESSO_DIPOLE_FIELD_TRACKING
604 gpu->copy_dip_fld_to_host(particles,
this_node);
607#ifdef ESPRESSO_CALIPER
613#ifdef ESPRESSO_VIRTUAL_SITES_RELATIVE
614 if (propagation->used_propagations &
620#ifdef ESPRESSO_VIRTUAL_SITES_CENTER_OF_MASS
621 if (propagation->used_propagations &
632 assert(comfixed->get_fixed_types().empty() &&
633 "ghost_reduce_overlap: comfixed must be inactive on the eligible "
635 assert(force_cap == 0. &&
636 "ghost_reduce_overlap: force_cap must be 0 on the eligible path");
637 cell_structure->ghosts_reduce_forces_start();
640 cell_structure->ghosts_reduce_forces();
641#ifdef ESPRESSO_DIPOLE_FIELD_TRACKING
642 if (dipoles.impl->solver.has_value()) {
643 cell_structure->ghosts_reduce_dipole_field();
648 comfixed->apply(particles);
655 propagation->recalc_forces =
false;
Struct holding all information for one particle.
constexpr auto const & dip_fld() const
constexpr auto const & force() const