40#include "accumulators/AutoUpdateAccumulators.hpp"
46#include "collision_detection/CollisionDetection.hpp"
58#include "system/System.hpp"
68#include <boost/mpi/collectives/all_reduce.hpp>
70#ifdef ESPRESSO_CALIPER
74#ifdef ESPRESSO_VALGRIND
89#ifdef ESPRESSO_WALBERLA
90#ifdef ESPRESSO_WALBERLA_STATIC_ASSERT
91#error "waLberla headers should not be visible to the ESPResSo core"
96volatile std::sig_atomic_t
ctrl_C = 0;
107 assert(m_protocol !=
nullptr);
114 auto &
system = get_system();
115 auto &cell_structure = *
system.cell_structure;
116 auto &box_geo = *
system.box_geo;
118 m_protocol = std::move(protocol);
119 update_box_params(box_geo,
system.get_sim_time());
120 system.propagation->recalc_forces =
true;
125 auto &
system = get_system();
126 auto &cell_structure = *
system.cell_structure;
127 auto &box_geo = *
system.box_geo;
128 m_protocol =
nullptr;
130 system.propagation->recalc_forces =
true;
146#ifdef ESPRESSO_ROTATION
151#ifdef ESPRESSO_ROTATION
156#ifdef ESPRESSO_ROTATION
161#ifdef ESPRESSO_ROTATION
175#ifdef ESPRESSO_ROTATION
179#ifdef ESPRESSO_STOKESIAN_DYNAMICS
185 throw std::runtime_error(
"Unknown value for integ_switch");
191 for (
auto &p : cell_structure->local_particles()) {
192 used_propagations |= p.propagation();
195 used_propagations |= propagation->default_propagation;
197 used_propagations = boost::mpi::all_reduce(
::comm_cart, used_propagations,
199 propagation->used_propagations = used_propagations;
200 propagation->recalc_used_propagations =
false;
203void System::System::integrator_sanity_checks()
const {
204 auto const thermo_switch = thermostat->thermo_switch;
205 if (time_step <= 0.) {
211 <<
"The steepest descent integrator is incompatible with thermostats";
217 "currently active combination of thermostats";
229 nptiso->coulomb_dipole_sanity_checks(*
this);
230 }
catch (std::runtime_error
const &
err) {
241#ifdef ESPRESSO_STOKESIAN_DYNAMICS
247 if (lb.is_solver_set()
and (propagation->used_propagations &
250 if (thermostat->lb ==
nullptr) {
254 if (bonded_ias->get_n_thermalized_bonds() >= 1
and
255 (thermostat->thermalized_bond ==
nullptr or
258 <<
"Thermalized bonds require the thermalized_bond thermostat";
260#ifdef ESPRESSO_BOND_CONSTRAINT
261 if (bonded_ias->get_n_rigid_bonds() >= 1) {
262 if (
not propagation->is_inertial()) {
264 <<
"Rigid bonds (RATTLE) require an inertial integrator "
265 "(VV or symplectic Euler); BD and SD are not supported";
270#ifdef ESPRESSO_STOKESIAN_DYNAMICS
274 stokesian_dynamics->sanity_checks(
275 cell_structure->local_particles().filter(
pred));
279#ifdef ESPRESSO_ROTATION
280 for (
auto const &p : cell_structure->local_particles()) {
282 if (p.can_rotate()
and not p.is_virtual()
and
283 (p.propagation() & (SYSTEM_DEFAULT | ROT_EULER | ROT_LANGEVIN |
284 ROT_BROWNIAN | ROT_STOKESIAN)) == 0) {
286 <<
"Rotating particles must have a rotation propagation mode enabled";
292#ifdef ESPRESSO_VIRTUAL_SITES_CENTER_OF_MASS
293#ifdef ESPRESSO_EXTERNAL_FORCES
294 if (propagation->used_propagations &
296 for (
auto const &p : cell_structure->local_particles()) {
298 if ((p.propagation() & TRANS_VS_CENTER_OF_MASS)
and
299 p.has_fixed_coordinates()) {
306#ifdef ESPRESSO_BOND_CONSTRAINT
307 if (bonded_ias->get_n_rigid_bonds()) {
309 for (
auto const &p : cell_structure->local_particles()) {
310 if (p.propagation() & TRANS_VS_CENTER_OF_MASS) {
311 for (
auto const bond : p.bonds()) {
312 if (std::holds_alternative<RigidBond>(
313 *bonded_ias->at(
bond.bond_id()))) {
324#ifdef ESPRESSO_THERMAL_STONER_WOHLFARTH
326 for (
auto const &p : cell_structure->local_particles()) {
327 if (p.stoner_wohlfarth_is_enabled()) {
328 runtimeErrorMsg() <<
"The thermal Stoner-Wohlfarth model requires the "
329 "Langevin thermostat";
337#ifdef ESPRESSO_WALBERLA
340 if (time_step <= 0.) {
344 auto const eps =
static_cast<double>(std::numeric_limits<float>::epsilon());
345 if ((tau - time_step) / (tau + time_step) < -eps)
346 throw std::invalid_argument(
method +
" tau (" + std::to_string(tau) +
347 ") must be >= MD time_step (" +
348 std::to_string(time_step) +
")");
349 auto const factor = tau / time_step;
351 throw std::invalid_argument(
method +
" tau (" + std::to_string(tau) +
352 ") must be an integer multiple of the "
354 std::to_string(time_step) +
"). Factor is " +
368 std::stringstream error_msg;
369 error_msg <<
"waLBerla and ESPResSo disagree about domain decomposition"
371 <<
"left ESPResSo: [" <<
geo_left <<
"], "
374 <<
"right ESPResSo: [" <<
geo_right <<
"], "
376 <<
"\nfor method: " <<
method;
377 throw std::runtime_error(error_msg.str());
383#ifdef ESPRESSO_CALIPER
386 auto &cell_structure = *
system.cell_structure;
388 *
system.box_geo, cell_structure.get_le_pos_offset_at_last_resort());
389 if (cell_structure.check_resort_required(offset)) {
400#ifdef ESPRESSO_CALIPER
405 return system.steepest_descent->propagate(cell_structure);
407 auto const &thermostat = *
system.thermostat;
408 auto const kT = thermostat.kT;
410#ifdef ESPRESSO_VIRTUAL_SITES
421#ifdef ESPRESSO_ROTATION
427#ifdef ESPRESSO_ROTATION
437#ifdef ESPRESSO_ROTATION
443#ifdef ESPRESSO_ROTATION
450#ifdef ESPRESSO_ROTATION
472#ifdef ESPRESSO_STOKESIAN_DYNAMICS
477 *
system.stokesian_dynamics, *thermostat.stokesian,
503 return [&propagation, time_step](
Particle &p) {
504#ifdef ESPRESSO_VIRTUAL_SITES
515#ifdef ESPRESSO_ROTATION
521#ifdef ESPRESSO_ROTATION
531#ifdef ESPRESSO_ROTATION
537#ifdef ESPRESSO_ROTATION
549#ifdef ESPRESSO_CALIPER
588#ifdef ESPRESSO_CALIPER
594 "integrator_step_2_filtered: steepest-descent is ineligible");
598 "integrator_step_2_filtered: NPT propagation is ineligible");
610#ifdef ESPRESSO_CALIPER
613 auto &propagation = *this->propagation;
614#ifdef ESPRESSO_VIRTUAL_SITES_RELATIVE
616 return propagation.used_propagations &
622#ifdef ESPRESSO_VIRTUAL_SITES_CENTER_OF_MASS
624 return propagation.used_propagations &
628#ifdef ESPRESSO_BOND_CONSTRAINT
629 auto const n_rigid_bonds = bonded_ias->get_n_rigid_bonds();
633 propagation.update_default_propagation(thermostat->thermo_switch);
634 update_used_propagations();
635 on_integration_start();
644 propagation.recalc_forces)) {
645#ifdef ESPRESSO_CALIPER
648 thermostat->lb_coupling_deactivate();
650#ifdef ESPRESSO_VIRTUAL_SITES_RELATIVE
655#ifdef ESPRESSO_VIRTUAL_SITES_CENTER_OF_MASS
662 cell_structure->update_ghosts_and_resort_particle(get_global_ghost_flags());
670 if (cell_structure->has_pending_ghost_reduce()) {
671 cell_structure->ghosts_reduce_forces_finish();
675#ifdef ESPRESSO_ROTATION
680#ifdef ESPRESSO_CALIPER
685 thermostat->lb_coupling_activate();
703 ek_active = ek.is_ready_for_propagation();
706 return static_cast<int>(std::round(tau / time_step));
709#ifdef ESPRESSO_VALGRIND
713#ifdef ESPRESSO_CALIPER
718#ifdef ESPRESSO_CALIPER
723#ifdef ESPRESSO_BOND_CONSTRAINT
726 cell_structure->ghost_particles());
729 lees_edwards->update_box_params(*box_geo, sim_time);
735 sim_time += time_step;
738 cell_structure->for_each_local_particle(
739 [&kernel](
Particle &p) { kernel(p); });
743 if (
not has_npt_enabled())
749 thermostat->philox_counter_increment();
751#ifdef ESPRESSO_BOND_CONSTRAINT
758#ifdef ESPRESSO_VIRTUAL_SITES_RELATIVE
761 if (has_npt_enabled()) {
762 cell_structure->update_ghosts_and_resort_particle(
769#ifdef ESPRESSO_VIRTUAL_SITES_CENTER_OF_MASS
772 if (has_npt_enabled()) {
773 cell_structure->update_ghosts_and_resort_particle(
785 cell_structure->update_ghosts_and_resort_particle(get_global_ghost_flags());
787#ifdef ESPRESSO_THERMAL_STONER_WOHLFARTH
788 integrate_magnetodynamics();
793#ifdef ESPRESSO_VIRTUAL_SITES_INERTIALESS_TRACERS
794 if (thermostat->lb
and
798 assert(
not cell_structure->has_pending_ghost_reduce() &&
799 "LB-tracer arm must be inactive on the split-phase path");
804 if (cell_structure->has_pending_ghost_reduce()) {
830 }
guard{cell_structure.get(),
true};
834 cell_structure->ghosts_reduce_forces_finish();
835 guard.active =
false;
846 cell_structure->for_each_local_particle(
847 [&kernel](
Particle &p) { kernel(p); });
849#ifdef ESPRESSO_BOND_CONSTRAINT
864 <<
"LB and EK are active but with different time steps.";
867 assert(lb.is_gpu() == ek.is_gpu());
868 assert(propagation.lb_skipped_md_steps ==
869 propagation.ek_skipped_md_steps);
871 propagation.lb_skipped_md_steps += 1;
872 propagation.ek_skipped_md_steps += 1;
874 propagation.lb_skipped_md_steps = 0;
875 propagation.ek_skipped_md_steps = 0;
876#ifdef ESPRESSO_CALIPER
880 lb.ghost_communication_vel();
881#ifdef ESPRESSO_CALIPER
884#ifdef ESPRESSO_CALIPER
888#ifdef ESPRESSO_CALIPER
894 propagation.lb_skipped_md_steps += 1;
896 propagation.lb_skipped_md_steps = 0;
897#ifdef ESPRESSO_CALIPER
901#ifdef ESPRESSO_CALIPER
907 propagation.ek_skipped_md_steps += 1;
909 propagation.ek_skipped_md_steps = 0;
910#ifdef ESPRESSO_CALIPER
914#ifdef ESPRESSO_CALIPER
921 thermostat->lb->rng_increment();
924#ifdef ESPRESSO_VIRTUAL_SITES_INERTIALESS_TRACERS
925 if (thermostat->lb
and
927#ifdef ESPRESSO_CALIPER
931 lb.ghost_communication_vel();
934#ifdef ESPRESSO_CALIPER
940#ifdef ESPRESSO_COLLISION_DETECTION
941 cell_structure->clear_new_bonds();
942 collision_detection->handle_collisions();
943 cell_structure->rebuild_bond_list();
945 bond_breakage->process_queue(*
this);
963 lb.ghost_communication();
965 lees_edwards->update_box_params(*box_geo, sim_time);
968#ifdef ESPRESSO_VALGRIND
972#ifdef ESPRESSO_VIRTUAL_SITES_RELATIVE
977#ifdef ESPRESSO_VIRTUAL_SITES_CENTER_OF_MASS
987 if (has_npt_enabled()) {
988 synchronize_npt_state();
998 if (boost::mpi::all_reduce(
::comm_cart,
not cell_structure->use_verlet_list,
999 std::logical_or<>())) {
1000 cell_structure->use_verlet_list =
false;
1013 if (
not cell_structure->is_verlet_skin_set()) {
1015 cell_structure->set_verlet_skin_heuristic();
1028 for (
int i = 0; i <
n_steps;) {
1032 std::min((
n_steps - i), auto_update_accumulators->next_update());
1056 propagation->recalc_forces =
true;
1057 lees_edwards->update_box_params(*box_geo, sim_time);
@ INTEG_METHOD_NPT_ISO_AND
@ INTEG_METHOD_STEEPEST_DESCENT
@ INTEG_METHOD_SYMPLECTIC_EULER
@ INTEG_METHOD_NPT_ISO_MTK
Data structures for bonded interactions.
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.
This file contains everything related to the global cell structure / cell system.
void lees_edwards_update(double pos_offset, double shear_velocity)
Update the Lees-Edwards parameters of the box geometry for the current simulation time.
Describes a cell structure / cell system.
void for_each_local_particle(ParticleCallback auto &&f, bool parallel=true) const
Run a kernel on all local particles.
void for_each_interior_particle(ParticleCallback auto &&f) const
Run a kernel on interior (non-boundary) local particles only.
bool has_pending_ghost_reduce() const
True when a split-phase force reduction is in flight.
void for_each_boundary_particle(ParticleCallback auto &&f) const
Run a kernel on boundary local particles only.
void ghosts_reduce_forces_finish()
Complete the split-phase ghost force reduction.
ParticleRange local_particles() const
void update_box_params(BoxGeometry &box_geo, double sim_time)
Update the Lees-Edwards parameters of the box geometry for the current simulation time.
void set_protocol(std::shared_ptr< ActiveProtocol > protocol)
Set a new Lees-Edwards protocol.
void unset_protocol()
Delete the currently active Lees-Edwards protocol.
ParticleRangeFiltered< Predicate > filter(Predicate pred) const
void update_default_propagation(int thermo_switch)
bool should_propagate_with(Particle const &p, int mode) const
RAII guard for signal handling.
void update_used_propagations()
Update the global propagation bitmask.
void set_sim_time(double value)
Set sim_time.
int integrate_with_signal_handler(int n_steps, int reuse_forces, bool update_accumulators)
int integrate(int n_steps, int reuse_forces)
Integrate equations of motion.
void vs_com_update_particles(CellStructure &cell_structure, BoxGeometry const &box_geo)
cudaStream_t stream[1]
CUDA streams for parallel computing on CPU and GPU.
boost::mpi::communicator comm_cart
The communicator.
int this_node
The number of this node.
int check_runtime_errors(boost::mpi::communicator const &comm)
Count runtime errors on all nodes.
This file contains the errorhandling code for severe errors, like a broken bond or illegal parameter ...
#define runtimeErrorMsg()
static auto make_step2_particle_kernel(Propagation const &propagation, double time_step)
Build the per-particle half-kick callable for step_2.
static bool integrator_step_1(CellStructure &cell_structure, Propagation const &propagation, System::System &system, double time_step)
Calls the hook for propagation kernels before the force calculation.
void walberla_tau_sanity_checks(std::string const &method, double tau, double time_step)
static void resort_particles_if_needed(System::System &system)
static void integrator_step_2_filtered(CellStructure &cell_structure, Propagation const &propagation, double time_step, bool interior_pass)
Restricted step_2 for the split-phase ghost-force-reduce overlap.
static void integrator_step_2(CellStructure &cell_structure, Propagation const &propagation, System::System &system, double time_step)
void walberla_agrid_sanity_checks(std::string const &method, Utils::Vector3d const &geo_left, Utils::Vector3d const &geo_right, Utils::Vector3d const &lattice_left, Utils::Vector3d const &lattice_right, double agrid)
Molecular dynamics integrator.
#define INTEG_ERROR_RUNTIME
#define INTEG_ERROR_SIGINT
#define INTEG_REUSE_FORCES_NEVER
recalculate forces unconditionally (mostly used for timing)
#define INTEG_REUSE_FORCES_ALWAYS
do not recalculate forces (mostly when reading checkpoints with forces)
void brownian_dynamics_rotator(BrownianThermostat const &brownian, Particle &p, double time_step, double kT)
void brownian_dynamics_propagator(BrownianThermostat const &brownian, Particle &p, double time_step, double kT)
void lb_tracers_propagate(CellStructure &cell_structure, LB::Solver const &lb, double time_step)
void lb_tracers_add_particle_force_to_fluid(CellStructure &cell_structure, BoxGeometry const &box_geo, LocalBox const &local_box, LB::Solver &lb)
@ DATA_PART_PROPERTIES
Particle::p.
Utils::Vector3d verlet_list_offset(BoxGeometry const &box, double pos_offset_at_last_resort)
double get_shear_velocity(double time, ActiveProtocol const &protocol)
Calculation of current velocity.
double get_pos_offset(double time, ActiveProtocol const &protocol)
@ TRANS_VS_CENTER_OF_MASS
@ TRANS_LB_MOMENTUM_EXCHANGE
volatile std::sig_atomic_t ctrl_C
Various procedures concerning interactions between particles.
Exports for the NpT code.
void correct_velocity_shake(CellStructure &cs, BoxGeometry const &box_geo, BondedInteractionsMap const &bonded_ias)
Correction of current velocities using RATTLE algorithm.
void save_old_position(const ParticleRange &particles, const ParticleRange &ghost_particles)
copy current position
void correct_position_shake(CellStructure &cs, BoxGeometry const &box_geo, BondedInteractionsMap &bonded_ias)
Propagate velocity and position while using SHAKE algorithm for bond constraint.
void vs_relative_update_particles(CellStructure &cell_structure, BoxGeometry const &box_geo)
void convert_initial_torques(const ParticleRange &particles)
Convert torques to the body-fixed frame before the integration loop.
This file contains all subroutines required to process rotational motion.
See for the Stokesian dynamics method used here.
void stokesian_dynamics_step_1(ParticleRangeStokesian const &particles, StokesianDynamics const &integrator, StokesianThermostat const &stokesian, double time_step, double kT)
RAII loop wrapper replacing the CALI_CXX_MARK_LOOP_BEGIN / CALI_CXX_MARK_LOOP_ITERATION / CALI_CXX_MA...
Struct holding all information for one particle.
constexpr auto is_virtual() const
void symplectic_euler_rotator_2(Particle &, double)
void symplectic_euler_rotator_1(Particle &p, double time_step)
void symplectic_euler_propagator_2(Particle &, double)
Final integration step of the Symplectic Euler integrator For symplectic Euler, there is no second st...
void symplectic_euler_propagator_1(Particle &p, double time_step)
Propagate the velocities and positions.
void velocity_verlet_rotator_1(Particle &p, double time_step)
void velocity_verlet_propagator_2(Particle &p, double time_step)
Final integration step of the Velocity Verlet integrator.
void velocity_verlet_propagator_1(Particle &p, double time_step)
Propagate the velocities and positions.
void velocity_verlet_rotator_2(Particle &p, double time_step)
void velocity_verlet_npt_MTK_step_1(ParticleRangeNPT const &particles, IsotropicNptThermostat const &npt_iso, double time_step, System::System &system)
Special propagator for velocity Verlet NpT with the Andersen method.
void velocity_verlet_npt_MTK_step_2(ParticleRangeNPT const &particles, double time_step, System::System &system)
Final integration step of the velocity Verlet NpT integrator with the MTK method.
void velocity_verlet_npt_Andersen_step_1(ParticleRangeNPT const &particles, IsotropicNptThermostat const &npt_iso, double time_step, System::System &system)
Special propagator for velocity Verlet NpT with the Andersen method.
void velocity_verlet_npt_Andersen_step_2(ParticleRangeNPT const &particles, double time_step, System::System &system)
Final integration step of the velocity Verlet NpT integrator with the Andersen method.