58 int const n_bonds_max) {
60 std::unordered_map<int, std::vector<std::pair<int, int>>> partners;
61 std::vector<int> bonded_pairs;
64 auto &cell_structure = *system.cell_structure;
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];
73 bonded_pairs.emplace_back(pid1);
74 bonded_pairs.emplace_back(pid2);
82 if (comm.rank() == 0) {
83 auto const add_partner = [&partners](
int pid1,
int pid2,
int n_bonds) {
86 for (
auto const &partner : partners[pid1])
87 if (partner.first == pid2)
89 partners[pid1].emplace_back(pid2, n_bonds);
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);
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);
103 for (
auto const pid1 : pids) {
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)
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)
117 add_partner(pid1, pid3, dist31);
118 add_partner(pid3, pid1, dist31);
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)) {
134 if (
auto p2 = cell_structure.get_local_particle(pid2)) {
139 system.on_particle_change();
143Variant ParticleList::do_call_method(std::string
const &name,
146 if (
name ==
"auto_exclusions") {
147 auto const distance = get_value<int>(
params,
"distance");
152 if (
name ==
"get_highest_particle_id") {
155 if (
name ==
"clear") {
159 if (not
context()->is_head_node()) {
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()}}));
169 if (
name ==
"by_ids") {
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()}});
176 if (
name ==
"get_n_part") {
179 if (
name ==
"get_particle_ids") {
182 if (
name ==
"particle_exists") {
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));
193 if (
params.count(
"exclusions")) {
194 so->call_method(
"set_exclusions", {{
"p_ids",
params.at(
"exclusions")}});
197 return so->get_parameter(
"id");
virtual std::shared_ptr< ObjectHandle > make_shared(std::string const &name, const VariantMap ¶meters)=0
Get a new reference counted instance of a script interface by name.
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...
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.
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.
bool particle_exists(int p_id)
Check if particle exists.
Particles creation and deletion.