68#include <boost/mpi/collectives.hpp>
75#include <initializer_list>
88#ifdef ESPRESSO_EXCLUSIONS
91 p.
call_method(
"set_exclusions", {{
"p_ids", exclusions}});
102 {{
"bond_id", bond_id}, {
"part_id", std::move(
part_id)}});
112#ifdef ESPRESSO_COLLISION_DETECTION
121 std::shared_ptr<Accumulators::AutoUpdateAccumulators>
125#ifdef ESPRESSO_ELECTROSTATICS
128#ifdef ESPRESSO_DIPOLES
131 std::shared_ptr<LB::Container>
lb;
132 std::shared_ptr<EK::Container>
ek;
133 std::shared_ptr<Particles::ParticleList>
part;
155 auto &dst = ptr->*member;
156 if (dst != nullptr) {
157 throw WriteError(key);
159 dst =
get_value<std::remove_reference_t<
decltype(dst)>>(
val);
160 dst->bind_system(m_instance);
168 context()->parallel_try_catch([&]() {
171 throw std::domain_error(
"Attribute 'box_l' must be > 0");
173 m_instance->veto_boxl_change();
174 m_instance->box_geo->set_length(
new_value);
175 m_instance->on_boxl_change();
178 [
this]() {
return m_instance->box_geo->length(); }},
182 for (
unsigned int i = 0
u; i < 3u; ++i) {
183 m_instance->box_geo->set_periodic(i,
periodicity[i]);
185 context()->parallel_try_catch(
186 [&]() { m_instance->on_periodicity_change(); });
190 m_instance->box_geo->periodic(1),
191 m_instance->box_geo->periodic(2)};
195 context()->parallel_try_catch([&]() {
198 throw std::domain_error(
"Attribute 'min_global_cut' must be >= 0");
200 m_instance->set_min_global_cut(
new_value);
203 [
this]() {
return m_instance->get_min_global_cut(); }},
208 [
this]() {
return m_instance->oif_global->max_oif_objects; }},
220#ifdef ESPRESSO_COLLISION_DETECTION
221 add_parameter(
"collision_detection", &Leaves::collision_detection);
225 add_parameter(
"auto_update_accumulators", &Leaves::auto_update_accumulators);
227 add_parameter(
"non_bonded_inter", &Leaves::non_bonded_inter);
228#ifdef ESPRESSO_ELECTROSTATICS
231#ifdef ESPRESSO_DIPOLES
239 m_leaves->ek->do_call_method(
"deactivate", {});
240 if (
not context()->is_head_node()) {
243 set_parameter(
"ekcontainer",
244 context()->make_shared(
"EK::Container", {}));
246 auto const detach_solver = [
this]() {
247 auto &solver = m_leaves->ek;
249 solver->do_call_method(
"deactivate", {});
250 solver->detach_system();
254 auto const bind_solver = [
this]() {
255 auto &solver = m_leaves->ek;
257 solver->bind_system(m_instance);
258 solver->do_call_method(
"activate", {});
261 auto &solver = m_leaves->ek;
267 context()->parallel_try_catch([&]() { bind_solver(); });
276 [
this]() {
return m_leaves->ek; }},
281template <
typename LeafType>
282void System::do_set_default_parameter(std::string
const &name) {
283 assert(context()->is_head_node());
284 auto const so_name = Utils::demangle<LeafType>().substr(17);
285 set_parameter(name,
Variant{context()->make_shared(
so_name, {})});
298 context()->parallel_try_catch([&]() {
299 if (
not params.contains(
"box_l")) {
300 throw std::domain_error(
"Required argument 'box_l' not provided.");
303 throw std::runtime_error(
304 "You can only have one instance of the system class at a time");
312 do_set_parameter(
"box_l", params.at(
"box_l"));
315 m_instance->lb.bind_system(m_instance);
316 m_instance->ek.bind_system(m_instance);
318 if (params.contains(
"_regular_constructor")) {
320 "box_l",
"min_global_cut",
321 "periodicity",
"time",
322 "time_step",
"force_cap",
323 "max_oif_objects",
"_regular_constructor"};
324 for (
auto const &name : std::views::elements<0>(params)) {
326 context()->parallel_try_catch([&name]() {
327 throw std::domain_error(
328 "Property '" + name +
329 "' cannot be set via argument to System class");
333 for (std::string
attr :
334 {
"min_global_cut",
"periodicity",
"max_oif_objects"}) {
335 if (params.contains(
attr)) {
336 do_set_parameter(
attr, params.at(
attr));
339 if (
not context()->is_head_node()) {
342 auto integrator = std::dynamic_pointer_cast<Integrators::IntegratorHandle>(
343 context()->make_shared(
"Integrators::IntegratorHandle", {}));
344 set_parameter(
"integrator", integrator);
345 for (std::string
attr : {
"time",
"time_step",
"force_cap"}) {
346 if (params.contains(
attr)) {
347 integrator->set_parameter(
attr, params.at(
attr));
355#ifdef ESPRESSO_COLLISION_DETECTION
357 "collision_detection");
365 "auto_update_accumulators");
369#ifdef ESPRESSO_ELECTROSTATICS
372#ifdef ESPRESSO_DIPOLES
379 for (
auto const &
key : get_parameter_insertion_order()) {
380 if (
key !=
"box_l" and params.contains(
key)) {
381 do_set_parameter(
key, params.at(
key));
385 if (
not context()->is_head_node()) {
388 call_method(
"internal_attach_leaves", {});
392 double theta,
double alpha) {
399 for (
auto const &p : particles) {
400 if (
not p.is_virtual()) {
406 auto const total_mass =
413 axis[0] = std::sin(
theta) * std::cos(
phi);
414 axis[1] = std::sin(
theta) * std::sin(
phi);
415 axis[2] = std::cos(
theta);
418 for (
auto &p : particles) {
421#ifdef ESPRESSO_ROTATION
431Variant System::do_call_method(std::string
const &name,
433 if (name ==
"lock_system_creation") {
437 if (name ==
"rescale_boxl") {
439 for (
auto &p : m_instance->cell_structure->local_particles()) {
440 p.pos()[dir] *= scale;
443 auto const &box_geo = *m_instance->box_geo;
447 context()->parallel_try_catch([&]() {
449 throw std::domain_error(
"Parameter 'd_new' must be > 0");
451 m_instance->veto_boxl_change(
true);
458 for (
auto axis = 0
u; axis < 3u; ++axis) {
459 if (rescale[axis] <= 1.) {
463 m_instance->on_particle_change();
464 m_instance->box_geo->set_length(
new_value);
465 m_instance->on_boxl_change();
467 for (
auto axis = 0
u; axis < 3u; ++axis) {
468 if (rescale[axis] > 1.) {
472 m_instance->on_particle_change();
474 auto const axis =
static_cast<unsigned>(
coord);
475 auto const scale = length * box_geo.length_inv()[axis];
481 m_instance->on_particle_change();
483 m_instance->box_geo->set_length(
new_value);
484 m_instance->on_boxl_change();
488 m_instance->on_particle_change();
493 if (name ==
"reaction_get_maximal_particle_id") {
494 return ::get_maximal_particle_id();
496 if (name ==
"get_pids_of_type") {
498 std::vector<int>
pids;
499 for (
auto const &p : get_system().
cell_structure->local_particles()) {
500 if (p.type() == type) {
501 pids.emplace_back(p.id());
507 if (name ==
"number_of_particles") {
511 for (
auto const &p : get_system().
cell_structure->local_particles()) {
512 if (p.type() == type) {
520 if (name ==
"velocity_difference") {
525 return m_instance->box_geo->velocity_difference(pos2, pos1,
v2,
v1);
527 if (name ==
"distance_vec") {
530 return m_instance->box_geo->get_mi_vector(pos2, pos1);
532 if (name ==
"rotate_system") {
537 m_instance->on_particle_change();
538 m_instance->update_dependent_particles();
541 if (name ==
"get_propagation_modes_enum") {
544 if (name ==
"session_shutdown") {
549 assert(m_instance.use_count() == 1l);
555 if (name ==
"internal_attach_leaves") {
556 m_leaves->part->attach(m_leaves->cell_system,
557 m_leaves->bonded_interactions);
558#ifdef ESPRESSO_COLLISION_DETECTION
559 m_leaves->collision_detection->attach(m_leaves->bonded_interactions);
572std::string System::get_internal_state()
const {
577 auto p_obj = context()->make_shared(
578 "Particles::ParticleHandle",
579 {{
"id", p_id}, {
"__cell_structure", m_leaves->cell_system}});
584 state.name =
"Particles::ParticleHandle";
587#ifdef ESPRESSO_EXCLUSIONS
588 auto const exclusions =
p_handle.call_method(
"get_exclusions", {});
589 state.params.emplace_back(std::string{
"exclusions"},
pack(exclusions));
591 state.params.emplace_back(std::string{
"__cpt_sentinel"},
pack(
None{}));
598void System::set_internal_state(std::string
const &state) {
599 auto const object_states = Utils::unpack<std::vector<std::string>>(state);
600#ifdef ESPRESSO_EXCLUSIONS
601 std::unordered_map<int, Variant> exclusions = {};
603 std::unordered_map<int, Variant> bonds = {};
605 for (
auto const &packed_object : object_states) {
606 auto state = Utils::unpack<ObjectState>(packed_object);
608 for (
auto const &[name, packed_value] : state.params) {
609 params[name] =
unpack(packed_value, {});
611 auto const p_id = get_value<int>(params.at(
"id"));
612 bonds[p_id] = params.extract(
"bonds").mapped();
613#ifdef ESPRESSO_EXCLUSIONS
614 exclusions[p_id] = params.extract(
"exclusions").mapped();
616 params[
"__cell_structure"] = get_parameter(
"cell_system");
617 context()->make_shared(
"Particles::ParticleHandle", params);
621 auto p_obj = context()->make_shared(
622 "Particles::ParticleHandle",
623 {{
"id", p_id}, {
"__cell_structure", m_leaves->cell_system}});
626#ifdef ESPRESSO_EXCLUSIONS
@ NSQUARE
Atom decomposition (N-square).
@ REGULAR
Regular decomposition.
static int coord(std::string const &s)
Vector implementation and trait types for boost qvm interoperability.
This file contains everything related to the global cell structure / cell system.
Describes a cell structure / cell system.
void update_ghosts_and_resort_particle(unsigned data_parts)
Update ghost particles, with particle resort if needed.
void set_resort_particles(Cells::Resort level)
Increase the local resort level at least to level.
ParticleRange local_particles() const
void add_parameters(std::vector< AutoParameter > &¶ms)
Type to indicate no value in Variant.
std::string serialize() const
Variant call_method(const std::string &name, const VariantMap ¶ms)
Call a method on the object.
static std::shared_ptr< System > create()
std::shared_ptr< CellStructure > cell_structure
static DEVICE_QUALIFIER constexpr Vector< T, N > broadcast(typename Base::value_type const &value) noexcept
Create a vector that has all entries set to the same value.
boost::mpi::communicator comm_cart
The communicator.
constexpr double inactive_cutoff
Special cutoff value for an inactive interaction.
This file contains the asynchronous MPI communication.
@ DATA_PART_PROPERTIES
Particle::p.
@ DATA_PART_POSITION
Particle::r.
static void set_bonds(Particles::ParticleHandle &p, Variant const &bonds)
static void set_exclusions(Particles::ParticleHandle &p, Variant const &exclusions)
static void rotate_system(CellStructure &cell_structure, double phi, double theta, double alpha)
static bool system_created
constexpr bool is_none(Variant const &v)
PackedVariant pack(const Variant &v)
Transform a Variant to a PackedVariant.
T get_value(Variant const &v)
Extract value of specific type T from a Variant.
std::unordered_map< std::string, Variant > VariantMap
auto make_unordered_map_of_variants(std::unordered_map< K, V > const &v)
Variant unpack(const PackedVariant &v, std::unordered_map< ObjectId, ObjectRef > const &objects)
Unpack a PackedVariant.
make_recursive_variant< ObjectRef > Variant
Possible types for parameters.
bool is_same_system(System const *const system)
void set_system(std::shared_ptr< System > new_instance)
void gather_buffer(std::vector< T, Allocator > &buffer, boost::mpi::communicator const &comm, int root=0)
Gather buffer with different size on each node.
Vector3d vec_rotate(const Vector3d &axis, double angle, const Vector3d &vector)
Rotate a vector around an axis.
std::string pack(T const &v)
Pack a serialize type into a string.
auto hadamard_product(Vector< T, N > const &a, Vector< U, N > const &b)
Various procedures concerning interactions between particles.
Exports for the NpT code.
Routines to calculate the OIF global forces for a particle triple (triangle from mesh).
std::vector< int > get_particle_ids()
Get all particle ids.
Particles creation and deletion.
std::unordered_map< std::string, int > propagation_flags_map()
Convert PropagationMode::PropagationMode to name/value pairs.
This file contains all subroutines required to process rotational motion.
void local_rotate_particle(Particle &p, const Utils::Vector3d &axis_space_frame, const double phi)
Rotate the particle p around the NORMALIZED axis aSpaceFrame by amount phi.
Description and getter/setter for a parameter.
Container for leaves of the system class.
std::shared_ptr< Thermostat::Thermostat > thermostat
std::shared_ptr< Integrators::IntegratorHandle > integrator
std::shared_ptr< Dipoles::Container > magnetostatics
std::shared_ptr< CellSystem::CellSystem > cell_system
std::shared_ptr< LB::Container > lb
std::shared_ptr< Galilei::Galilei > galilei
std::shared_ptr< Analysis::Analysis > analysis
std::shared_ptr< Particles::ParticleList > part
std::shared_ptr< EK::Container > ek
std::shared_ptr< BondBreakage::BreakageSpecs > bond_breakage
std::shared_ptr< Constraints::Constraints > constraints
std::shared_ptr< Interactions::BondedInteractions > bonded_interactions
std::shared_ptr< CollisionDetection::CollisionDetection > collision_detection
std::shared_ptr< Interactions::NonBondedInteractions > non_bonded_inter
std::shared_ptr< Coulomb::Container > electrostatics
std::shared_ptr< Galilei::ComFixed > comfixed
std::shared_ptr< Accumulators::AutoUpdateAccumulators > auto_update_accumulators
std::shared_ptr< LeesEdwards::LeesEdwards > lees_edwards
Recursive variant implementation.