64#include <boost/mpi/collectives.hpp>
71#include <initializer_list>
86 p.
call_method(
"set_exclusions", {{
"p_ids", exclusions}});
91 auto const bond_list_flat = get_value<std::vector<std::vector<int>>>(bonds);
92 for (
auto const &bond_flat : bond_list_flat) {
93 auto const bond_id = bond_flat[0];
95 std::vector<int>{bond_flat.begin() + 1, bond_flat.end()};
97 {{
"bond_id", bond_id}, {
"part_id", std::move(part_id)}});
107#ifdef COLLISION_DETECTION
116 std::shared_ptr<Accumulators::AutoUpdateAccumulators>
126 std::shared_ptr<Particles::ParticleList>
part;
130 auto const add_parameter =
131 [
this, ptr = m_leaves.get()](std::string key,
auto(
Leaves::*member)) {
134 [
this, ptr, member, key](
Variant const &val) {
135 auto &dst = ptr->*member;
136 if (dst != nullptr) {
137 throw WriteError(key);
139 dst =
get_value<std::remove_reference_t<
decltype(dst)>>(val);
140 dst->bind_system(m_instance);
142 [ptr, member]() {
return ptr->*member; })});
148 context()->parallel_try_catch([&]() {
149 auto const new_value = get_value<Utils::Vector3d>(v);
151 throw std::domain_error(
"Attribute 'box_l' must be > 0");
153 m_instance->veto_boxl_change();
154 m_instance->box_geo->set_length(new_value);
155 m_instance->on_boxl_change();
158 [
this]() {
return m_instance->box_geo->length(); }},
161 auto const periodicity = get_value<Utils::Vector3b>(v);
162 for (
unsigned int i = 0u; i < 3u; ++i) {
163 m_instance->box_geo->set_periodic(i, periodicity[i]);
165 context()->parallel_try_catch(
166 [&]() { m_instance->on_periodicity_change(); });
170 m_instance->box_geo->periodic(1),
171 m_instance->box_geo->periodic(2)};
175 context()->parallel_try_catch([&]() {
176 auto const new_value = get_value<double>(v);
178 throw std::domain_error(
"Attribute 'min_global_cut' must be >= 0");
180 m_instance->set_min_global_cut(new_value);
183 [
this]() {
return m_instance->get_min_global_cut(); }},
186 m_instance->oif_global->max_oif_objects = get_value<int>(v);
188 [
this]() {
return m_instance->oif_global->max_oif_objects; }},
192 add_parameter(
"cell_system", &Leaves::cell_system);
193 add_parameter(
"integrator", &Leaves::integrator);
194 add_parameter(
"thermostat", &Leaves::thermostat);
195 add_parameter(
"analysis", &Leaves::analysis);
196 add_parameter(
"comfixed", &Leaves::comfixed);
197 add_parameter(
"galilei", &Leaves::galilei);
198 add_parameter(
"bonded_inter", &Leaves::bonded_interactions);
199#ifdef COLLISION_DETECTION
200 add_parameter(
"collision_detection", &Leaves::collision_detection);
202 add_parameter(
"bond_breakage", &Leaves::bond_breakage);
203 add_parameter(
"lees_edwards", &Leaves::lees_edwards);
204 add_parameter(
"auto_update_accumulators", &Leaves::auto_update_accumulators);
205 add_parameter(
"constraints", &Leaves::constraints);
206 add_parameter(
"non_bonded_inter", &Leaves::non_bonded_inter);
208 add_parameter(
"electrostatics", &Leaves::electrostatics);
211 add_parameter(
"magnetostatics", &Leaves::magnetostatics);
213 add_parameter(
"part", &Leaves::part);
216template <
typename LeafType>
217void System::do_set_default_parameter(std::string
const &name) {
218 assert(context()->is_head_node());
219 auto const so_name = Utils::demangle<LeafType>().substr(17);
220 set_parameter(name,
Variant{context()->make_shared(so_name, {})});
233 context()->parallel_try_catch([&]() {
234 if (not
params.contains(
"box_l")) {
235 throw std::domain_error(
"Required argument 'box_l' not provided.");
238 throw std::runtime_error(
239 "You can only have one instance of the system class at a time");
247 do_set_parameter(
"box_l",
params.at(
"box_l"));
250 m_instance->lb.bind_system(m_instance);
251 m_instance->ek.bind_system(m_instance);
253 if (
params.contains(
"_regular_constructor")) {
254 std::set<std::string>
const setable_properties = {
255 "box_l",
"min_global_cut",
256 "periodicity",
"time",
257 "time_step",
"force_cap",
258 "max_oif_objects",
"_regular_constructor"};
259 for (
auto const &kv :
params) {
260 if (not setable_properties.contains(kv.first)) {
261 context()->parallel_try_catch([&kv]() {
262 throw std::domain_error(
263 "Property '" + kv.first +
264 "' cannot be set via argument to System class");
268 for (std::string attr :
269 {
"min_global_cut",
"periodicity",
"max_oif_objects"}) {
270 if (
params.contains(attr)) {
271 do_set_parameter(attr,
params.at(attr));
274 if (not context()->is_head_node()) {
277 auto integrator = std::dynamic_pointer_cast<Integrators::IntegratorHandle>(
278 context()->make_shared(
"Integrators::IntegratorHandle", {}));
279 set_parameter(
"integrator", integrator);
280 for (std::string attr : {
"time",
"time_step",
"force_cap"}) {
281 if (
params.contains(attr)) {
282 integrator->set_parameter(attr,
params.at(attr));
287 do_set_default_parameter<CellSystem::CellSystem>(
"cell_system");
288 do_set_default_parameter<Thermostat::Thermostat>(
"thermostat");
289 do_set_default_parameter<Interactions::BondedInteractions>(
"bonded_inter");
290#ifdef COLLISION_DETECTION
291 do_set_default_parameter<CollisionDetection::CollisionDetection>(
292 "collision_detection");
294 do_set_default_parameter<Analysis::Analysis>(
"analysis");
295 do_set_default_parameter<Galilei::ComFixed>(
"comfixed");
296 do_set_default_parameter<Galilei::Galilei>(
"galilei");
297 do_set_default_parameter<BondBreakage::BreakageSpecs>(
"bond_breakage");
298 do_set_default_parameter<LeesEdwards::LeesEdwards>(
"lees_edwards");
299 do_set_default_parameter<Accumulators::AutoUpdateAccumulators>(
300 "auto_update_accumulators");
301 do_set_default_parameter<Constraints::Constraints>(
"constraints");
302 do_set_default_parameter<Interactions::NonBondedInteractions>(
305 do_set_default_parameter<Coulomb::Container>(
"electrostatics");
308 do_set_default_parameter<Dipoles::Container>(
"magnetostatics");
310 do_set_default_parameter<Particles::ParticleList>(
"part");
312 for (
auto const &key : get_parameter_insertion_order()) {
313 if (key !=
"box_l" and
params.contains(key)) {
314 do_set_parameter(key,
params.at(key));
318 if (not context()->is_head_node()) {
321 call_method(
"internal_attach_leaves", {});
325 double theta,
double alpha) {
330 double local_mass = 0.0;
332 for (
auto const &p : particles) {
333 if (not p.is_virtual()) {
334 local_com += p.mass() * p.pos();
335 local_mass += p.mass();
339 auto const total_mass =
340 boost::mpi::all_reduce(
comm_cart, local_mass, std::plus<>());
342 boost::mpi::all_reduce(
comm_cart, local_com, std::plus<>()) / total_mass;
346 axis[0] = std::sin(theta) * std::cos(phi);
347 axis[1] = std::sin(theta) * std::sin(phi);
348 axis[2] = std::cos(theta);
351 for (
auto &p : particles) {
373 p.pos()[dir] *= scale;
380Variant System::do_call_method(std::string
const &name,
382 if (name ==
"lock_system_creation") {
386 if (name ==
"rescale_boxl") {
387 auto &box_geo = *m_instance->box_geo;
388 auto const coord = get_value<int>(parameters,
"coord");
389 auto const length = get_value<double>(parameters,
"length");
391 assert(
coord != 3 or ((box_geo.length()[0] == box_geo.length()[1]) and
392 (box_geo.length()[1] == box_geo.length()[2])));
393 auto const scale = (
coord == 3) ? length * box_geo.length_inv()[0]
394 : length * box_geo.length_inv()[
coord];
395 context()->parallel_try_catch([&]() {
397 throw std::domain_error(
"Parameter 'd_new' must be > 0");
399 m_instance->veto_boxl_change(
true);
405 new_value = box_geo.length();
406 new_value[
static_cast<unsigned>(
coord)] = length;
411 m_instance->on_particle_change();
413 m_instance->box_geo->set_length(new_value);
414 m_instance->on_boxl_change();
417 m_instance->on_particle_change();
421 if (name ==
"setup_type_map") {
422 auto const types = get_value<std::vector<int>>(parameters,
"type_list");
423 for (
auto const type : types) {
428 if (name ==
"number_of_particles") {
429 auto const type = get_value<int>(parameters,
"type");
430 return ::number_of_particles_with_type(type);
432 if (name ==
"velocity_difference") {
433 auto const pos1 = get_value<Utils::Vector3d>(parameters,
"pos1");
434 auto const pos2 = get_value<Utils::Vector3d>(parameters,
"pos2");
435 auto const v1 = get_value<Utils::Vector3d>(parameters,
"v1");
436 auto const v2 = get_value<Utils::Vector3d>(parameters,
"v2");
437 return m_instance->box_geo->velocity_difference(pos2, pos1, v2, v1);
439 if (name ==
"distance_vec") {
440 auto const pos1 = get_value<Utils::Vector3d>(parameters,
"pos1");
441 auto const pos2 = get_value<Utils::Vector3d>(parameters,
"pos2");
442 return m_instance->box_geo->get_mi_vector(pos2, pos1);
444 if (name ==
"rotate_system") {
446 get_value<double>(parameters,
"phi"),
447 get_value<double>(parameters,
"theta"),
448 get_value<double>(parameters,
"alpha"));
449 m_instance->on_particle_change();
450 m_instance->update_dependent_particles();
453 if (name ==
"get_propagation_modes_enum") {
456 if (name ==
"session_shutdown") {
461 assert(m_instance.use_count() == 1l);
466 if (name ==
"internal_attach_leaves") {
467 m_leaves->part->attach(m_leaves->cell_system,
468 m_leaves->bonded_interactions);
469#ifdef COLLISION_DETECTION
470 m_leaves->collision_detection->attach(m_leaves->bonded_interactions);
483std::string System::get_internal_state()
const {
485 std::vector<std::string> object_states(p_ids.size());
487 std::ranges::transform(p_ids, object_states.begin(), [
this](
auto const p_id) {
488 auto p_obj = context()->make_shared(
489 "Particles::ParticleHandle",
490 {{
"id", p_id}, {
"__cell_structure", m_leaves->cell_system}});
492 auto const packed_state = p_handle.
serialize();
494 auto state = Utils::unpack<ObjectState>(packed_state);
495 state.name =
"Particles::ParticleHandle";
496 auto const bonds_view = p_handle.call_method(
"get_bonds_view", {});
497 state.params.emplace_back(std::string{
"bonds"},
pack(bonds_view));
499 auto const exclusions = p_handle.call_method(
"get_exclusions", {});
500 state.params.emplace_back(std::string{
"exclusions"},
pack(exclusions));
502 state.params.emplace_back(std::string{
"__cpt_sentinel"},
pack(
None{}));
509void System::set_internal_state(std::string
const &state) {
510 auto const object_states = Utils::unpack<std::vector<std::string>>(state);
512 std::unordered_map<int, Variant> exclusions = {};
514 std::unordered_map<int, Variant> bonds = {};
516 for (
auto const &packed_object : object_states) {
517 auto state = Utils::unpack<ObjectState>(packed_object);
519 for (
auto const &kv : state.params) {
522 auto const p_id = get_value<int>(
params.at(
"id"));
523 bonds[p_id] =
params.extract(
"bonds").mapped();
525 exclusions[p_id] =
params.extract(
"exclusions").mapped();
527 params[
"__cell_structure"] = get_parameter(
"cell_system");
528 context()->make_shared(
"Particles::ParticleHandle",
params);
532 auto p_obj = context()->make_shared(
533 "Particles::ParticleHandle",
534 {{
"id", p_id}, {
"__cell_structure", m_leaves->cell_system}});
@ 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.
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()
static DEVICE_QUALIFIER constexpr Vector< T, N > broadcast(typename Base::value_type const &value)
Create a vector that has all entries set to the same value.
boost::mpi::communicator comm_cart
The communicator.
This file contains the defaults for ESPResSo.
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
static void rescale_particles(CellStructure &cell_structure, int dir, double scale)
Rescale all particle positions in direction dir by a factor scale.
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)
boost::make_recursive_variant< None, bool, int, std::size_t, double, std::string, ObjectRef, Utils::Vector3b, Utils::Vector3i, Utils::Vector2d, Utils::Vector3d, Utils::Vector4d, std::vector< int >, std::vector< double >, std::vector< boost::recursive_variant_ >, std::unordered_map< int, boost::recursive_variant_ >, std::unordered_map< std::string, boost::recursive_variant_ > >::type Variant
Possible types for parameters.
Variant unpack(const PackedVariant &v, std::unordered_map< ObjectId, ObjectRef > const &objects)
Unpack a PackedVariant.
void set_system(std::shared_ptr< System > new_instance)
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.
Various procedures concerning interactions between particles.
constexpr double INACTIVE_CUTOFF
Cutoff for deactivated interactions.
Routines to calculate the OIF global forces for a particle triple (triangle from mesh).
void init_type_map(int type)
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.
static SteepestDescentParameters params
Currently active steepest descent instance.
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
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< Galilei::Galilei > galilei
std::shared_ptr< Analysis::Analysis > analysis
std::shared_ptr< Particles::ParticleList > part
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