ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
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 <ranges>
44#include <stdexcept>
45#include <string>
46#include <unordered_map>
47#include <utility>
48#include <vector>
49
50namespace ScriptInterface {
51namespace Particles {
52
53#ifdef ESPRESSO_EXCLUSIONS
54/**
55 * @brief Use the bond topology to automatically add exclusions between
56 * particles that are up to @c n_bonds_max bonds apart in a chain.
57 */
58static void auto_exclusions(boost::mpi::communicator const &comm,
59 int const n_bonds_max) {
60 // bookkeeping of particle exclusions, with their n-bond distance
61 std::unordered_map<int, std::vector<std::pair<int, int>>> partners;
62 std::vector<int> bonded_pairs;
63
65 auto &cell_structure = *system.cell_structure;
66
67 // determine initial connectivity
68 for (auto const &p : cell_structure.local_particles()) {
69 auto const pid1 = p.id();
70 for (auto const bond : p.bonds()) {
71 if (bond.partner_ids().size() == 1u) {
72 auto const pid2 = bond.partner_ids()[0];
73 if (pid1 != pid2) {
74 bonded_pairs.emplace_back(pid1);
75 bonded_pairs.emplace_back(pid2);
76 }
77 }
78 }
79 }
80
82
83 if (comm.rank() == 0) {
84 auto const add_partner = [&partners](int pid1, int pid2, int n_bonds) {
85 if (pid2 == pid1)
86 return;
87 for (auto const &partner_pid : std::views::elements<0>(partners[pid1]))
88 if (partner_pid == pid2)
89 return;
90 partners[pid1].emplace_back(pid2, n_bonds);
91 };
92
93 for (auto it = bonded_pairs.begin(); it != bonded_pairs.end(); it += 2) {
94 add_partner(it[0], it[1], 1);
95 add_partner(it[1], it[0], 1);
96 }
97
98 // determine transient connectivity
99 for (int iteration = 1; iteration < n_bonds_max; iteration++) {
100 for (auto const pid1 : std::views::elements<0>(partners)) {
101 // loop over partners (counter-based loops due to iterator invalidation)
102 // NOLINTNEXTLINE(modernize-loop-convert)
103 for (std::size_t i = 0u; i < partners[pid1].size(); ++i) {
104 auto const [pid2, dist21] = partners[pid1][i];
106 // loop over all partners of the partner
107 // NOLINTNEXTLINE(modernize-loop-convert)
108 for (std::size_t j = 0u; j < partners[pid2].size(); ++j) {
109 auto const [pid3, dist32] = partners[pid2][j];
110 auto const dist31 = dist32 + dist21;
111 if (dist31 <= n_bonds_max) {
114 }
115 }
116 }
117 }
118 }
119 }
120
121 boost::mpi::broadcast(comm, partners, 0);
122 for (auto const &[pid1, partner_list] : partners) {
123 for (auto const &pid2 : std::views::elements<0>(partner_list)) {
124 if (auto p1 = cell_structure.get_local_particle(pid1)) {
126 }
127 if (auto p2 = cell_structure.get_local_particle(pid2)) {
129 }
130 }
131 }
132 system.on_particle_change();
133}
134#endif // ESPRESSO_EXCLUSIONS
135
136Variant ParticleList::do_call_method(std::string const &name,
137 VariantMap const &params) {
138#ifdef ESPRESSO_EXCLUSIONS
139 if (name == "auto_exclusions") {
140 auto const distance = get_value<int>(params, "distance");
141 auto_exclusions(context()->get_comm(), distance);
142 return {};
143 }
144#endif // ESPRESSO_EXCLUSIONS
145 if (name == "get_highest_particle_id") {
147 }
148 if (name == "clear") {
150 return {};
151 }
152 if (not context()->is_head_node()) {
153 return {};
154 }
155 if (name == "by_id") {
156 return std::dynamic_pointer_cast<ParticleHandle>(
157 context()->make_shared("Particles::ParticleHandle",
158 {{"id", get_value<int>(params, "p_id")},
159 {"__cell_structure", m_cell_structure.lock()},
160 {"__bonded_ias", m_bonded_ias.lock()}}));
161 }
162 if (name == "by_ids") {
163 return context()->make_shared(
164 "Particles::ParticleSlice",
165 {{"id_selection", get_value<std::vector<int>>(params, "id_selection")},
166 {"__cell_structure", m_cell_structure.lock()},
167 {"__bonded_ias", m_bonded_ias.lock()}});
168 }
169 if (name == "get_n_part") {
170 return get_n_part();
171 }
172 if (name == "get_particle_ids") {
173 return get_particle_ids();
174 }
175 if (name == "particle_exists") {
176 return particle_exists(get_value<int>(params, "p_id"));
177 }
178 if (name == "add_particle") {
179 assert(not params.contains("bonds"));
181 local_params["__cell_structure"] = m_cell_structure.lock();
182 local_params["__bonded_ias"] = m_bonded_ias.lock();
183 auto so = std::dynamic_pointer_cast<ParticleHandle>(
184 context()->make_shared("Particles::ParticleHandle", local_params));
185#ifdef ESPRESSO_EXCLUSIONS
186 if (params.contains("exclusions")) {
187 so->call_method("set_exclusions", {{"p_ids", params.at("exclusions")}});
188 }
189#endif // ESPRESSO_EXCLUSIONS
190 return so;
191 }
192 return {};
193}
194
195} // namespace Particles
196} // 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.
Context * context() const
Responsible context.
std::string_view name() const
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:133
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.
Recursive variant implementation.
Definition Variant.hpp:84