Loading [MathJax]/extensions/TeX/AMSmath.js
ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages Concepts
ParticleList.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2022 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 "ParticleList.hpp"
21#include "ParticleHandle.hpp"
22#include "ParticleSlice.hpp"
23
27
29#include "core/exclusions.hpp"
32
33#include <utils/Vector.hpp>
36
37#include <boost/mpi/collectives.hpp>
38#include <boost/mpi/communicator.hpp>
39
40#include <algorithm>
41#include <cstddef>
42#include <memory>
43#include <stdexcept>
44#include <string>
45#include <unordered_map>
46#include <utility>
47#include <vector>
48
49namespace ScriptInterface {
50namespace Particles {
51
52#ifdef EXCLUSIONS
53/**
54 * @brief Use the bond topology to automatically add exclusions between
55 * particles that are up to @c n_bonds_max bonds apart in a chain.
56 */
57static void auto_exclusions(boost::mpi::communicator const &comm,
58 int const n_bonds_max) {
59 // bookkeeping of particle exclusions, with their n-bond distance
60 std::unordered_map<int, std::vector<std::pair<int, int>>> partners;
61 std::vector<int> bonded_pairs;
62
64 auto &cell_structure = *system.cell_structure;
65
66 // determine initial connectivity
67 for (auto const &p : cell_structure.local_particles()) {
68 auto const pid1 = p.id();
69 for (auto const bond : p.bonds()) {
70 if (bond.partner_ids().size() == 1u) {
71 auto const pid2 = bond.partner_ids()[0];
72 if (pid1 != pid2) {
73 bonded_pairs.emplace_back(pid1);
74 bonded_pairs.emplace_back(pid2);
75 }
76 }
77 }
78 }
79
81
82 if (comm.rank() == 0) {
83 auto const add_partner = [&partners](int pid1, int pid2, int n_bonds) {
84 if (pid2 == pid1)
85 return;
86 for (auto const &partner : partners[pid1])
87 if (partner.first == pid2)
88 return;
89 partners[pid1].emplace_back(pid2, n_bonds);
90 };
91
92 for (auto it = bonded_pairs.begin(); it != bonded_pairs.end(); it += 2) {
93 add_partner(it[0], it[1], 1);
94 add_partner(it[1], it[0], 1);
95 }
96
97 // determine transient connectivity
98 for (int iteration = 1; iteration < n_bonds_max; iteration++) {
99 std::vector<int> pids;
100 for (auto const &kv : partners) {
101 pids.emplace_back(kv.first);
102 }
103 for (auto const pid1 : pids) {
104 // loop over partners (counter-based loops due to iterator invalidation)
105 // NOLINTNEXTLINE(modernize-loop-convert)
106 for (std::size_t i = 0u; i < partners[pid1].size(); ++i) {
107 auto const [pid2, dist21] = partners[pid1][i];
108 if (dist21 > n_bonds_max)
109 continue;
110 // loop over all partners of the partner
111 // NOLINTNEXTLINE(modernize-loop-convert)
112 for (std::size_t j = 0u; j < partners[pid2].size(); ++j) {
113 auto const [pid3, dist32] = partners[pid2][j];
114 auto const dist31 = dist32 + dist21;
115 if (dist31 > n_bonds_max)
116 continue;
119 }
120 }
121 }
122 }
123 }
124
125 boost::mpi::broadcast(comm, partners, 0);
126 for (auto const &kv : partners) {
127 auto const pid1 = kv.first;
128 auto const &partner_list = kv.second;
129 for (auto const &partner : partner_list) {
130 auto const pid2 = partner.first;
131 if (auto p1 = cell_structure.get_local_particle(pid1)) {
133 }
134 if (auto p2 = cell_structure.get_local_particle(pid2)) {
136 }
137 }
138 }
139 system.on_particle_change();
140}
141#endif // EXCLUSIONS
142
143Variant ParticleList::do_call_method(std::string const &name,
144 VariantMap const &params) {
145#ifdef EXCLUSIONS
146 if (name == "auto_exclusions") {
147 auto const distance = get_value<int>(params, "distance");
148 auto_exclusions(context()->get_comm(), distance);
149 return {};
150 }
151#endif // EXCLUSIONS
152 if (name == "get_highest_particle_id") {
154 }
155 if (name == "clear") {
157 return {};
158 }
159 if (not context()->is_head_node()) {
160 return {};
161 }
162 if (name == "by_id") {
163 return std::dynamic_pointer_cast<ParticleHandle>(
164 context()->make_shared("Particles::ParticleHandle",
165 {{"id", get_value<int>(params, "p_id")},
166 {"__cell_structure", m_cell_structure.lock()},
167 {"__bonded_ias", m_bonded_ias.lock()}}));
168 }
169 if (name == "by_ids") {
170 return context()->make_shared(
171 "Particles::ParticleSlice",
172 {{"id_selection", get_value<std::vector<int>>(params, "id_selection")},
173 {"__cell_structure", m_cell_structure.lock()},
174 {"__bonded_ias", m_bonded_ias.lock()}});
175 }
176 if (name == "get_n_part") {
177 return get_n_part();
178 }
179 if (name == "get_particle_ids") {
180 return get_particle_ids();
181 }
182 if (name == "particle_exists") {
183 return particle_exists(get_value<int>(params, "p_id"));
184 }
185 if (name == "add_particle") {
186 assert(not params.contains("bonds"));
188 local_params["__cell_structure"] = m_cell_structure.lock();
189 local_params["__bonded_ias"] = m_bonded_ias.lock();
190 auto so = std::dynamic_pointer_cast<ParticleHandle>(
191 context()->make_shared("Particles::ParticleHandle", local_params));
192#ifdef EXCLUSIONS
193 if (params.count("exclusions")) {
194 so->call_method("set_exclusions", {{"p_ids", params.at("exclusions")}});
195 }
196#endif // EXCLUSIONS
197 return so;
198 }
199 return {};
200}
201
202} // namespace Particles
203} // namespace ScriptInterface
Vector implementation and trait types for boost qvm interoperability.
virtual std::shared_ptr< ObjectHandle > make_shared(std::string const &name, const VariantMap &parameters)=0
Get a new reference counted instance of a script interface by name.
boost::string_ref name() const
Context * context() const
Responsible context.
void add_exclusion(Particle &p, int p_id)
Insert an exclusion if not already set.
static void auto_exclusions(boost::mpi::communicator const &comm, int const n_bonds_max)
Use the bond topology to automatically add exclusions between particles that are up to n_bonds_max bo...
T get_value(Variant const &v)
Extract value of specific type T from a Variant.
std::unordered_map< std::string, Variant > VariantMap
Definition Variant.hpp:69
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.
Definition Variant.hpp:67
System & get_system()
void gather_buffer(std::vector< T, Allocator > &buffer, boost::mpi::communicator const &comm, int root=0)
Gather buffer with different size on each node.
void remove_all_particles()
Remove all particles.
int get_maximal_particle_id()
Get maximal particle id.
std::vector< int > get_particle_ids()
Get all particle ids.
int get_n_part()
Get number of particles.
bool particle_exists(int p_id)
Check if particle exists.
Particles creation and deletion.
static SteepestDescentParameters params
Currently active steepest descent instance.