ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
core/system/System.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2014-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#include <config/config.hpp>
21
22#include "System.hpp"
23#include "System.impl.hpp"
24
25#include "BoxGeometry.hpp"
26#include "GpuParticleData.hpp"
27#include "LocalBox.hpp"
28#include "Observable_stat.hpp"
29#include "PropagationMode.hpp"
30#include "accumulators/AutoUpdateAccumulators.hpp"
36#include "collision_detection/CollisionDetection.hpp"
37#include "communication.hpp"
39#include "errorhandling.hpp"
40#include "ghosts.hpp"
43#include "npt.hpp"
44#include "particle_node.hpp"
48#include "thermostat.hpp"
49#include "virtual_sites/com.hpp"
51
52#include <utils/Vector.hpp>
54
55#include <boost/mpi/collectives/all_reduce.hpp>
56
57#include <algorithm>
58#include <cassert>
59#include <cstddef>
60#include <functional>
61#include <memory>
62#include <stdexcept>
63#include <utility>
64
65namespace System {
66
67static std::shared_ptr<System> instance = System::create();
68
69std::shared_ptr<System> System::create() {
70 auto handle = std::make_shared<System>(Private());
71 handle->initialize();
72 return handle;
73}
74
76 box_geo = std::make_shared<BoxGeometry>();
77 local_geo = std::make_shared<LocalBox>();
78 cell_structure = std::make_shared<CellStructure>(*box_geo);
79 cell_structure->set_kokkos_handle(::kokkos_handle);
80#ifdef ESPRESSO_CUDA
81 gpu = std::make_shared<GpuParticleData>();
82#endif
83 propagation = std::make_shared<Propagation>();
84 bonded_ias = std::make_shared<BondedInteractionsMap>();
85 thermostat = std::make_shared<Thermostat::Thermostat>();
86 nonbonded_ias = std::make_shared<InteractionsNonBonded>();
87 comfixed = std::make_shared<ComFixed>();
88 galilei = std::make_shared<Galilei>();
89 oif_global = std::make_shared<OifGlobal>();
90 immersed_boundaries = std::make_shared<ImmersedBoundaries>();
91#ifdef ESPRESSO_COLLISION_DETECTION
92 collision_detection =
93 std::make_shared<CollisionDetection::CollisionDetection>();
94#endif
95 bond_breakage = std::make_shared<BondBreakage::BondBreakage>();
96 lees_edwards = std::make_shared<LeesEdwards::LeesEdwards>();
97 auto_update_accumulators =
98 std::make_shared<Accumulators::AutoUpdateAccumulators>();
99 constraints = std::make_shared<Constraints::Constraints>();
100 steepest_descent = std::make_shared<SteepestDescent>();
101#ifdef ESPRESSO_STOKESIAN_DYNAMICS
102 stokesian_dynamics = std::make_shared<StokesianDynamics>();
103#endif
104#ifdef ESPRESSO_NPT
105 nptiso = std::make_shared<NptIsoParameters>();
106 npt_inst_pressure = std::make_shared<InstantaneousPressure>();
107#endif
108 reinit_thermo = true;
109 time_step = -1.;
110 sim_time = 0.;
111 force_cap = 0.;
112 min_global_cut = inactive_cutoff;
113}
114
115void System::initialize() {
116 auto handle = shared_from_this();
117 cell_structure->bind_system(handle);
118 lees_edwards->bind_system(handle);
119 bonded_ias->bind_system(handle);
120 thermostat->bind_system(handle);
121 nonbonded_ias->bind_system(handle);
122 oif_global->bind_system(handle);
123 immersed_boundaries->bind_system(handle);
124#ifdef ESPRESSO_COLLISION_DETECTION
125 collision_detection->bind_system(handle);
126#endif
127 auto_update_accumulators->bind_system(handle);
128 constraints->bind_system(handle);
129#ifdef ESPRESSO_CUDA
130 gpu->bind_system(handle);
131 gpu->initialize();
132#endif
133 lb.bind_system(handle);
134 ek.bind_system(handle);
135}
136
137void reset_system() { instance.reset(); }
138
139void set_system(std::shared_ptr<System> new_instance) {
140 instance = new_instance;
141}
142
144
145bool is_same_system(System const *const system) {
146 assert(system != nullptr);
147 return system == instance.get();
148}
149
150void System::set_time_step(double value) {
151 if (value <= 0.)
152 throw std::domain_error("time_step must be > 0.");
153 if (lb.is_solver_set()) {
154 lb.veto_time_step(value);
155 }
156 if (ek.is_solver_set()) {
157 ek.veto_time_step(value);
158 }
159 time_step = value;
160 on_timestep_change();
161}
162
163void System::check_kT(double value) const {
164 if (lb.is_solver_set()) {
165 lb.veto_kT(value);
166 }
167 if (ek.is_solver_set()) {
168 ek.veto_kT(value);
169 }
170}
171
172void System::set_force_cap(double value) {
173 force_cap = value;
174 propagation->recalc_forces = true;
175}
176
177void System::set_min_global_cut(double value) {
178 min_global_cut = value;
179 on_verlet_skin_change();
180}
181
183 if (topology == CellStructureType::REGULAR) {
184 if (cell_structure->decomposition_type() == CellStructureType::REGULAR) {
185 // get fully connected info from existing regular decomposition
186 auto &old_regular_decomposition =
187 dynamic_cast<RegularDecomposition const &>(
188 std::as_const(*cell_structure).decomposition());
189 cell_structure->set_regular_decomposition(
190 get_interaction_range(),
191 old_regular_decomposition.fully_connected_boundary());
192 } else { // prev. decomposition is not a regular decomposition
193 cell_structure->set_regular_decomposition(get_interaction_range(), {});
194 }
195 } else if (topology == CellStructureType::NSQUARE) {
196 cell_structure->set_atom_decomposition();
197 } else {
198 assert(topology == CellStructureType::HYBRID);
199 /* Get current HybridDecomposition to extract n_square_types */
200 auto &old_hybrid_decomposition = dynamic_cast<HybridDecomposition const &>(
201 std::as_const(*cell_structure).decomposition());
202 cell_structure->set_hybrid_decomposition(
203 old_hybrid_decomposition.get_cutoff_regular(),
204 old_hybrid_decomposition.get_n_square_types());
205 }
206}
207
209 set_cell_structure_topology(cell_structure->decomposition_type());
210}
211
212void System::on_boxl_change(bool skip_method_adaption) {
213 update_local_geo();
214 rebuild_cell_structure();
215
216 /* Now give methods a chance to react to the change in box length */
217 if (not skip_method_adaption) {
218 lb.on_boxl_change();
219 ek.on_boxl_change();
220#ifdef ESPRESSO_ELECTROSTATICS
221 coulomb.on_boxl_change();
222#endif
223#ifdef ESPRESSO_DIPOLES
224 dipoles.on_boxl_change();
225#endif
226 }
227 constraints->on_boxl_change();
228}
229
230void System::veto_boxl_change(bool skip_particle_checks) const {
231 if (not skip_particle_checks) {
232 auto const n_part = boost::mpi::all_reduce(
233 ::comm_cart, cell_structure->local_particles().size(), std::plus<>());
234 if (n_part > 0ul) {
235 throw std::runtime_error(
236 "Cannot reset the box length when particles are present");
237 }
238 }
239 constraints->veto_boxl_change();
240 lb.veto_boxl_change();
241 ek.veto_boxl_change();
242}
243
245 update_local_geo();
246 lb.on_node_grid_change();
247 ek.on_node_grid_change();
248#ifdef ESPRESSO_ELECTROSTATICS
249 coulomb.on_node_grid_change();
250#endif
251#ifdef ESPRESSO_DIPOLES
252 dipoles.on_node_grid_change();
253#endif
254 rebuild_cell_structure();
255}
256
258#ifdef ESPRESSO_ELECTROSTATICS
259 coulomb.on_periodicity_change();
260#endif
261
262#ifdef ESPRESSO_DIPOLES
263 dipoles.on_periodicity_change();
264#endif
265
266#ifdef ESPRESSO_STOKESIAN_DYNAMICS
267 if (propagation->integ_switch == INTEG_METHOD_SD) {
268 if (box_geo->periodic(0u) or box_geo->periodic(1u) or box_geo->periodic(2u))
269 runtimeErrorMsg() << "Stokesian Dynamics requires periodicity "
270 << "(False, False, False)\n";
271 }
272#endif
273 on_verlet_skin_change();
274}
275
278 lb.on_cell_structure_change();
279 ek.on_cell_structure_change();
280#ifdef ESPRESSO_ELECTROSTATICS
281 coulomb.on_cell_structure_change();
282#endif
283#ifdef ESPRESSO_DIPOLES
284 dipoles.on_cell_structure_change();
285#endif
286}
287
288void System::on_thermostat_param_change() { reinit_thermo = true; }
289
291 rebuild_cell_structure();
292#ifdef ESPRESSO_ELECTROSTATICS
293 coulomb.on_coulomb_change();
294#endif
295#ifdef ESPRESSO_DIPOLES
296 dipoles.on_dipoles_change();
297#endif
298 on_short_range_ia_change();
299}
300
302 lb.on_temperature_change();
303 ek.on_temperature_change();
304}
305
307 lb.on_timestep_change();
308 ek.on_timestep_change();
309 on_thermostat_param_change();
310}
311
313 rebuild_cell_structure();
314 propagation->recalc_forces = true;
315}
316
318 nonbonded_ias->recalc_maximal_cutoffs();
319 rebuild_cell_structure();
320 on_thermostat_param_change();
321 propagation->recalc_forces = true;
322}
323
325#ifdef ESPRESSO_ELECTROSTATICS
326 coulomb.on_coulomb_change();
327#endif
328 on_short_range_ia_change();
329}
330
332#ifdef ESPRESSO_DIPOLES
333 dipoles.on_dipoles_change();
334#endif
335 on_short_range_ia_change();
336}
337
338void System::on_constraint_change() { propagation->recalc_forces = true; }
339
341 propagation->recalc_forces = true;
342}
343
345 cell_structure->update_ghosts_and_resort_particle(get_global_ghost_flags());
346 propagation->recalc_forces = true;
347 propagation->recalc_used_propagations = true;
348}
349
351 if (cell_structure->decomposition_type() == CellStructureType::HYBRID) {
352 cell_structure->set_resort_particles(Cells::RESORT_GLOBAL);
353 } else {
354 cell_structure->set_resort_particles(Cells::RESORT_LOCAL);
355 }
356#ifdef ESPRESSO_ELECTROSTATICS
357 coulomb.on_particle_change();
358#endif
359#ifdef ESPRESSO_DIPOLES
360 dipoles.on_particle_change();
361#endif
362 propagation->recalc_forces = true;
363 propagation->recalc_used_propagations = true;
364
365 /* the particle information is no longer valid */
367 cell_structure->clear_local_properties();
368}
369
371#ifdef ESPRESSO_ELECTROSTATICS
372 coulomb.on_particle_change();
373#endif
374}
375
377#ifdef ESPRESSO_VIRTUAL_SITES
378 if (propagation->recalc_used_propagations) {
379 update_used_propagations();
380 }
381#ifdef ESPRESSO_VIRTUAL_SITES_RELATIVE
382 if (propagation->used_propagations &
385 vs_relative_update_particles(*cell_structure, *box_geo);
386 }
387#endif
388#ifdef ESPRESSO_VIRTUAL_SITES_CENTER_OF_MASS
389 if (propagation->used_propagations &
391 vs_com_update_particles(*cell_structure, *box_geo);
392 }
393#endif
394 cell_structure->update_ghosts_and_resort_particle(get_global_ghost_flags());
395#endif
396
397#ifdef ESPRESSO_ELECTROSTATICS
398 if (has_icc_enabled()) {
399 rebuild_aosoa();
400 update_icc_particles();
401 }
402#endif
403
404 // Here we initialize volume conservation
405 // This function checks if the reference volumes have been set and if
406 // necessary calculates them
407 immersed_boundaries->init_volume_conservation(*cell_structure);
408}
409
411 /* Prepare particle structure: Communication step: number of ghosts and ghost
412 * information */
413 cell_structure->update_ghosts_and_resort_particle(get_global_ghost_flags());
414 update_dependent_particles();
415
416#ifdef ESPRESSO_ELECTROSTATICS
417 coulomb.on_observable_calc();
418#endif
419
420#ifdef ESPRESSO_DIPOLES
421 dipoles.on_observable_calc();
422#endif
423
425 rebuild_aosoa();
426}
427
429#ifdef ESPRESSO_COLLISION_DETECTION
430 auto const collision_detection_cutoff = collision_detection->cutoff();
431#else
432 auto const collision_detection_cutoff = inactive_cutoff;
433#endif
434
435 update_verlet_state(*this, collision_detection_cutoff);
436}
437
438void System::on_lees_edwards_change() { lb.on_lees_edwards_change(); }
439
445
447 auto max_cut = inactive_cutoff;
448 max_cut = std::max(max_cut, get_min_global_cut());
449 max_cut = std::max(max_cut, coulomb.cutoff());
450 max_cut = std::max(max_cut, dipoles.cutoff());
451 if (::communicator.size > 1) {
452 // If there is just one node, the bonded cutoff can be omitted
453 // because bond partners are always on the local node.
454 max_cut = std::max(max_cut, bonded_ias->maximal_cutoff());
455 }
456 max_cut = std::max(max_cut, nonbonded_ias->maximal_cutoff());
457
458#ifdef ESPRESSO_COLLISION_DETECTION
459 max_cut = std::max(max_cut, collision_detection->cutoff());
460#endif
461 return max_cut;
462}
463
465 try {
466#ifdef ESPRESSO_ELECTROSTATICS
467 coulomb.sanity_checks();
468#endif
469#ifdef ESPRESSO_DIPOLES
470 dipoles.sanity_checks();
471#endif
472 } catch (std::runtime_error const &err) {
473 runtimeErrorMsg() << err.what();
474 return true;
475 }
476 return false;
477}
478
480 auto const max_cut = maximal_cutoff();
481 auto const verlet_skin = cell_structure->get_verlet_skin();
482 /* Consider skin only if there are actually interactions */
483 return (max_cut > 0.) ? max_cut + verlet_skin : inactive_cutoff;
484}
485
487 box_geo->set_length(box_l);
488 on_boxl_change();
489}
490
492 // sanity checks
493 integrator_sanity_checks();
494 long_range_interactions_sanity_checks();
495 lb.sanity_checks();
496 ek.sanity_checks();
497
498#ifdef ESPRESSO_NPT
499 if (propagation->integ_switch == INTEG_METHOD_NPT_ISO_AND ||
500 propagation->integ_switch == INTEG_METHOD_NPT_ISO_MTK) {
501 npt_ensemble_init(propagation->recalc_forces);
502 }
503#endif
504
505 /* Prepare the thermostat */
506 if (reinit_thermo) {
507 thermostat->recalc_prefactors(time_step);
508 reinit_thermo = false;
509 propagation->recalc_forces = true;
510 }
511
513 cell_structure->clear_local_properties();
514
515#ifdef ESPRESSO_ADDITIONAL_CHECKS
516 if (!Utils::Mpi::all_compare(::comm_cart, cell_structure->use_verlet_list)) {
517 runtimeErrorMsg() << "Nodes disagree about use of verlet lists.";
518 }
519#ifdef ESPRESSO_ELECTROSTATICS
520 {
521 auto const &actor = coulomb.impl->solver;
522 if (not Utils::Mpi::all_compare(::comm_cart, static_cast<bool>(actor)) or
523 (actor and not Utils::Mpi::all_compare(::comm_cart, (*actor).index())))
524 runtimeErrorMsg() << "Nodes disagree about Coulomb long-range method";
525 }
526#endif
527#ifdef ESPRESSO_DIPOLES
528 {
529 auto const &actor = dipoles.impl->solver;
530 if (not Utils::Mpi::all_compare(::comm_cart, static_cast<bool>(actor)) or
531 (actor and not Utils::Mpi::all_compare(::comm_cart, (*actor).index())))
532 runtimeErrorMsg() << "Nodes disagree about dipolar long-range method";
533 }
534#endif
535#endif /* ESPRESSO_ADDITIONAL_CHECKS */
536
537 on_observable_calc();
538}
539
540/**
541 * @brief Return true when any active physics requires orientation of ghost
542 * particles. Used by both @c get_global_ghost_flags (QUAT push) and
543 * @c get_force_reduce_ghost_flags (TORQUE reduce).
544 *
545 * Conservative: include a reader when in doubt. Non-rotating plain LJ
546 * must yield false so that both bits stay OFF for that common case.
547 *
548 * Readers of ghost particle quat / director / calc_dip:
549 * - short_range_cabana commit_particle: quat -> director for Gay-Berne /
550 * Dipoles pair kernels (ghost particles in AoSoA)
551 * - vs_relative_update_particles: p_ref.quat() where p_ref may be a ghost
552 * - LB particle coupling (swimmer): p.calc_director() on ghost particles
553 * when ESPRESSO_ENGINE and LB are both active
554 * - HomogeneousMagneticField constraint: p.calc_dip() (local particles only,
555 * does NOT read ghosts; included conservatively via dipole check)
556 * - dipolar solvers (dp3m, dds, dlc, scafacos): p.calc_dip() on
557 * unique_particles which includes ghost particles that have no local
558 * counterpart (see @ref CellStructure::set_index_map); covered by
559 * the dipolar-solver-set condition
560 * - ShapeBasedConstraint / calc_non_central_force: reads p.quat() on LOCAL
561 * particles only (Constraints iterate local_particles); safe without the
562 * bit
563 * - Stoner-Wohlfarth integrate_magnetodynamics: calls p_ref->calc_director()
564 * where p_ref comes from get_reference_particle / get_local_particle, which
565 * CAN return a ghost; covered by the explicit #ifdef below
566 * - rotational integrators: operate on local particles only (OK)
567 * - ICC blocking reduce: resets force_and_torque on local particles and may
568 * carry a zero-valued TORQUE payload on the wire when orientation physics is
569 * concurrently active — harmless (bytes only, value is zero)
570 */
571#ifdef ESPRESSO_ROTATION
572static bool orientation_ghosts_needed(System const &sys) {
573 // Rotational propagation active: ghost quat needed for vs_relative position
574 // update and for any kernel that uses the director of a ghost particle.
575 if (sys.propagation->used_propagations &
580 return true;
581 }
582
583 // Virtual sites relative uses p_ref.quat() where p_ref may be a ghost.
584 if (sys.propagation->used_propagations &
587 return true;
588 }
589
590#ifdef ESPRESSO_DIPOLES
591 // Dipolar solver set: particles have a dipole moment derived from quat;
592 // short_range_cabana reads quat -> director for dipole pair kernels on ghosts
593 if (sys.dipoles.impl && sys.dipoles.impl->solver) {
594 return true;
595 }
596#endif
597
598#ifdef ESPRESSO_GAY_BERNE
599 // Gay-Berne anisotropic nonbonded interaction configured: short_range_cabana
600 // commits ghost quat -> director for the Cabana pair kernel.
601 if (sys.nonbonded_ias->pair_potential_active(PairPotential::GayBerne)) {
602 return true;
603 }
604#endif
605
606#ifdef ESPRESSO_ENGINE
607 // LB active with ENGINE compiled in: coupling loop includes ghost particles
608 // and calls p.calc_director() for swimmer_force_on_fluid particles.
609 if (sys.lb.is_solver_set()) {
610 return true;
611 }
612#endif
613
614#ifdef ESPRESSO_THERMAL_STONER_WOHLFARTH
615 // Stoner-Wohlfarth integrate_magnetodynamics calls
616 // get_reference_particle / get_local_particle which can return a ghost, then
617 // reads p_ref->calc_director() on it. SW requires the Langevin thermostat
618 // (enforced in integrate.cpp integrator_sanity_checks); use that as the
619 // cheapest reliable system-level runtime signal.
620 if (sys.thermostat->thermo_switch & THERMO_LANGEVIN) {
621 return true;
622 }
623#endif
624
625 return false;
626}
627#endif // ESPRESSO_ROTATION
628
629/**
630 * @brief Returns the ghost flags required for running pair
631 * kernels for the global state, e.g. the force calculation.
632 * @return Required data parts;
633 */
635 /* Position and Properties are always requested. */
637
638 if (lb.is_solver_set())
639 data_parts |= Cells::DATA_PART_MOMENTUM;
640
641 if (thermostat->thermo_switch & THERMO_DPD)
642 data_parts |= Cells::DATA_PART_MOMENTUM;
643
644 if (thermostat->thermo_switch & THERMO_BOND) {
645 data_parts |= Cells::DATA_PART_MOMENTUM;
646 data_parts |= Cells::DATA_PART_BONDS;
647 }
648
649#ifdef ESPRESSO_COLLISION_DETECTION
650 if (not collision_detection->is_off()) {
651 data_parts |= Cells::DATA_PART_BONDS;
652 }
653#endif
654
655#ifdef ESPRESSO_ROTATION
656 if (orientation_ghosts_needed(*this)) {
657 data_parts |= Cells::DATA_PART_QUAT;
658 }
659#endif
660
661 return data_parts;
662}
663
665 unsigned flags = GHOSTTRANS_FORCE;
666#ifdef ESPRESSO_ROTATION
667 if (orientation_ghosts_needed(*this)) {
668 flags |= GHOSTTRANS_TORQUE;
669 }
670#endif
671 return flags;
672}
673
674#ifdef ESPRESSO_NPT
676 return (propagation->integ_switch == INTEG_METHOD_NPT_ISO_AND) or
677 (propagation->integ_switch == INTEG_METHOD_NPT_ISO_MTK);
678}
679#endif
680
682#ifdef ESPRESSO_NPT
683 if (has_npt_enabled()) {
684 return &npt_inst_pressure->p_vir;
685 }
686#endif
687 return nullptr;
688}
689
690#ifdef ESPRESSO_COLLISION_DETECTION
692 return not collision_detection->is_off();
693}
694#endif
695
696} // namespace System
CellStructureType
Cell structure topology.
@ NSQUARE
Atom decomposition (N-square).
@ HYBRID
Hybrid decomposition.
@ REGULAR
Regular decomposition.
@ INTEG_METHOD_NPT_ISO_AND
@ INTEG_METHOD_SD
@ INTEG_METHOD_NPT_ISO_MTK
@ THERMO_BOND
@ THERMO_LANGEVIN
@ THERMO_DPD
Vector implementation and trait types for boost qvm interoperability.
Data structures for bonded interactions.
Hybrid decomposition cell system.
static LocalBox make_regular_decomposition(Utils::Vector3d const &box_l, Utils::Vector3i const &node_index, Utils::Vector3i const &node_grid)
Definition LocalBox.hpp:72
Main system class.
double get_interaction_range() const
Get the interaction range.
double maximal_cutoff() const
Calculate the maximal cutoff of all interactions.
void on_constraint_change()
Called every time a constraint is changed.
unsigned get_global_ghost_flags() const
Returns the ghost flags required for running pair kernels for the global state, e....
void on_boxl_change(bool skip_method_adaption=false)
Called when the box length has changed.
void set_box_l(Utils::Vector3d const &box_l)
Change the box dimensions.
void set_force_cap(double value)
Set force_cap.
void update_dependent_particles()
Update particles with properties depending on other particles, namely virtual sites and ICC charges.
void on_lb_boundary_conditions_change()
Called when the LB boundary conditions change (geometry, slip velocity, or both).
void veto_boxl_change(bool skip_particle_checks=false) const
void set_time_step(double value)
Set time_step.
void on_particle_change()
Called every time a particle property changes.
bool long_range_interactions_sanity_checks() const
Check electrostatic and magnetostatic methods are properly initialized.
void on_particle_charge_change()
Called every time a particle charge changes.
void on_particle_local_change()
Called every time a particle local property changes.
void on_observable_calc()
called before calculating observables, i.e.
void check_kT(double value) const
Veto temperature change.
static std::shared_ptr< System > create()
Utils::Vector3d * get_npt_virial() const
unsigned get_force_reduce_ghost_flags() const
Returns the ghost flags for the force-reduce step.
void set_min_global_cut(double value)
Set min_global_cut.
bool has_npt_enabled() const
void set_cell_structure_topology(CellStructureType topology)
Change cell structure topology.
void rebuild_cell_structure()
Rebuild cell lists.
bool has_collision_detection_enabled() const
void vs_com_update_particles(CellStructure &cell_structure, BoxGeometry const &box_geo)
Definition com.cpp:131
std::shared_ptr< KokkosHandle > kokkos_handle
Communicator communicator
boost::mpi::communicator comm_cart
The communicator.
constexpr double inactive_cutoff
Special cutoff value for an inactive interaction.
Definition config.hpp:53
This file contains the errorhandling code for severe errors, like a broken bond or illegal parameter ...
#define runtimeErrorMsg()
Ghost particles and particle exchange.
@ GHOSTTRANS_FORCE
transfer ParticleForce
Definition ghosts.hpp:43
@ GHOSTTRANS_TORQUE
transfer torque (reduced with force; runtime-conditional)
Definition ghosts.hpp:56
ICC is a method that allows to take into account the influence of arbitrarily shaped dielectric inter...
@ DATA_PART_MOMENTUM
Particle::m.
@ DATA_PART_PROPERTIES
Particle::p.
@ DATA_PART_BONDS
Particle::bonds.
@ DATA_PART_QUAT
orientation quaternion (pushed with position)
@ DATA_PART_POSITION
Particle::r.
System & get_system()
static std::shared_ptr< System > instance
bool is_same_system(System const *const system)
void set_system(std::shared_ptr< System > new_instance)
static bool orientation_ghosts_needed(System const &sys)
Return true when any active physics requires orientation of ghost particles.
bool all_compare(boost::mpi::communicator const &comm, T const &value)
Compare values on all nodes.
Exports for the NpT code.
void invalidate_fetch_cache()
Invalidate the fetch cache for get_particle_data.
void clear_particle_node()
Invalidate particle_node.
Particles creation and deletion.
void vs_relative_update_particles(CellStructure &cell_structure, BoxGeometry const &box_geo)
Definition relative.cpp:121
See for the Stokesian dynamics method used here.
void update_verlet_state(System::System const &system, double const collision_cut)
Utils::Vector3i calc_node_index() const
Calculate the node index in the Cartesian topology.
Utils::Vector3i node_grid
Regular decomposition cell system.
Routines to thermalize the center of mass and distance of a particle pair.