ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
HybridDecomposition.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2010-2022 The ESPResSo project
3 * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010
4 * Max-Planck-Institute for Polymer Research, Theory Group
5 *
6 * This file is part of ESPResSo.
7 *
8 * ESPResSo is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * ESPResSo is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
23
24#include "cell_system/Cell.hpp"
26
27#include "BoxGeometry.hpp"
28#include "LocalBox.hpp"
29
30#include <utils/Vector.hpp>
32
33#include <boost/mpi/collectives/reduce.hpp>
34#include <boost/mpi/communicator.hpp>
35
36#include <algorithm>
37#include <cstddef>
38#include <functional>
39#include <iterator>
40#include <optional>
41#include <set>
42#include <utility>
43
44HybridDecomposition::HybridDecomposition(boost::mpi::communicator comm,
45 double cutoff_regular, double skin,
46 std::function<bool()> get_ghost_flags,
47 BoxGeometry const &box_geo,
48 LocalBox const &local_box,
49 std::set<int> n_square_types)
50 : m_comm(std::move(comm)), m_box(box_geo), m_cutoff_regular(cutoff_regular),
51 m_regular_decomposition(RegularDecomposition(
52 m_comm, cutoff_regular + skin, m_box, local_box, std::nullopt)),
53 m_n_square(AtomDecomposition(m_comm, m_box)),
54 m_n_square_types(std::move(n_square_types)),
55 m_get_global_ghost_flags(std::move(get_ghost_flags)) {
56
57 /* Vector containing cells of both child decompositions */
58 m_local_cells = m_regular_decomposition.get_local_cells();
59 auto local_cells_n_square = m_n_square.get_local_cells();
60 std::ranges::copy(local_cells_n_square, std::back_inserter(m_local_cells));
61
62 /* Vector containing ghost cells of both child decompositions */
63 m_ghost_cells = m_regular_decomposition.get_ghost_cells();
64 auto ghost_cells_n_square = m_n_square.get_ghost_cells();
65 std::ranges::copy(ghost_cells_n_square, std::back_inserter(m_ghost_cells));
66
67 /* Communicators that contain communications of both child decompositions */
68 m_exchange_ghosts_comm = m_regular_decomposition.exchange_ghosts_comm();
69 auto exchange_ghosts_comm_n_square = m_n_square.exchange_ghosts_comm();
70 std::ranges::copy(exchange_ghosts_comm_n_square.communications,
71 std::back_inserter(m_exchange_ghosts_comm.communications));
72
73 m_collect_ghost_force_comm =
74 m_regular_decomposition.collect_ghost_force_comm();
75 auto collect_ghost_force_comm_n_square =
76 m_n_square.collect_ghost_force_comm();
77 std::ranges::copy(
78 collect_ghost_force_comm_n_square.communications,
79 std::back_inserter(m_collect_ghost_force_comm.communications));
80
81 /* coupling between the child decompositions via neighborship relation */
82 std::vector<Cell *> additional_reds = m_n_square.get_local_cells();
83 std::ranges::copy(ghost_cells_n_square, std::back_inserter(additional_reds));
84 for (auto &local_cell : m_regular_decomposition.local_cells()) {
85 std::vector<Cell *> red_neighbors(local_cell->m_neighbors.red().begin(),
86 local_cell->m_neighbors.red().end());
87 std::vector<Cell *> black_neighbors(local_cell->m_neighbors.black().begin(),
88 local_cell->m_neighbors.black().end());
89 std::ranges::copy(additional_reds, std::back_inserter(red_neighbors));
90 local_cell->m_neighbors = Neighbors<Cell *>(red_neighbors, black_neighbors);
91 }
92}
93
95 std::vector<ParticleChange> &diff) {
96 ParticleList displaced_parts;
97
98 /* Check for n_square type particles in regular decomposition */
99 for (auto &c : m_regular_decomposition.local_cells()) {
100 for (auto it = c->particles().begin(); it != c->particles().end();) {
101 /* Particle is in the right decomposition, i.e. has no n_square type */
102 if (not is_n_square_type(it->type())) {
103 std::advance(it, 1);
104 continue;
105 }
106
107 /* else remove from current cell ... */
108 auto p = std::move(*it);
109 it = c->particles().erase(it);
110 diff.emplace_back(ModifiedList{c->particles()});
111 diff.emplace_back(RemovedParticle{p.id()});
112
113 /* ... and insert into a n_square cell */
114 auto const first_local_cell = m_n_square.get_local_cells()[0];
115 first_local_cell->particles().insert(std::move(p));
116 diff.emplace_back(ModifiedList{first_local_cell->particles()});
117 }
118
119 /* Now check for regular decomposition type particles in n_square */
120 for (auto &c : m_n_square.local_cells()) {
121 for (auto it = c->particles().begin(); it != c->particles().end();) {
122 /* Particle is of n_square type */
123 if (is_n_square_type(it->type())) {
124 std::advance(it, 1);
125 continue;
126 }
127
128 /* else remove from current cell ... */
129 auto p = std::move(*it);
130 it = c->particles().erase(it);
131 diff.emplace_back(ModifiedList{c->particles()});
132 diff.emplace_back(RemovedParticle{p.id()});
133
134 /* ... and insert in regular decomposition */
135 auto const target_cell = particle_to_cell(p);
136 /* if particle belongs to this node insert it into correct cell */
137 if (target_cell != nullptr) {
138 target_cell->particles().insert(std::move(p));
139 diff.emplace_back(ModifiedList{target_cell->particles()});
140 }
141 /* otherwise just put into regular decomposition */
142 else {
143 auto first_local_cell = m_regular_decomposition.get_local_cells()[0];
144 first_local_cell->particles().insert(std::move(p));
145 diff.emplace_back(ModifiedList{first_local_cell->particles()});
146 }
147 }
148 }
149 }
150
151 /* now resort into correct cells within the respective decompositions */
152 m_regular_decomposition.resort(global, diff);
153 m_n_square.resort(global, diff);
154
155 /* basically do CellStructure::ghost_count() */
157
158 /* basically do CellStructure::ghost_update(unsigned data_parts) */
160 map_data_parts(m_get_global_ghost_flags()));
161}
162
163std::size_t HybridDecomposition::count_particles(
164 std::vector<Cell *> const &local_cells) const {
165 std::size_t count_local = 0;
166 std::size_t count_global = 0;
167 for (auto const &cell : local_cells) {
168 count_local += cell->particles().size();
169 }
170 boost::mpi::reduce(m_comm, count_local, count_global, std::plus<>{}, 0);
171 return count_global;
172}
unsigned map_data_parts(unsigned data_parts)
Map the data parts flags from cells to those used internally by the ghost communication.
Vector implementation and trait types for boost qvm interoperability.
Atom decomposition cell system.
GhostCommunicator const & collect_ghost_force_comm() const override
GhostCommunicator const & exchange_ghosts_comm() const override
auto const & get_local_cells() const
auto const & get_ghost_cells() const
void resort(bool global_flag, std::vector< ParticleChange > &diff) override
std::span< Cell *const > local_cells() const override
std::span< Cell *const > local_cells() const override
GhostCommunicator const & exchange_ghosts_comm() const override
Cell * particle_to_cell(Particle const &p) override
void resort(bool global, std::vector< ParticleChange > &diff) override
HybridDecomposition(boost::mpi::communicator comm, double cutoff_regular, double skin, std::function< bool()> get_ghost_flags, BoxGeometry const &box_geo, LocalBox const &local_box, std::set< int > n_square_types)
void ghost_communicator(GhostCommunicator const &gcr, BoxGeometry const &box_geo, unsigned int data_parts)
Do a ghost communication with the specified data parts.
Definition ghosts.cpp:442
@ GHOSTTRANS_PARTNUM
resize the receiver particle arrays to the size of the senders
Definition ghosts.hpp:138
std::vector< GhostCommunication > communications
List of ghost communications.
Definition ghosts.hpp:166
Regular decomposition cell system.
void resort(bool global, std::vector< ParticleChange > &diff) override
GhostCommunicator const & collect_ghost_force_comm() const override
std::span< Cell *const > local_cells() const override
auto const & get_local_cells() const
GhostCommunicator const & exchange_ghosts_comm() const override
auto const & get_ghost_cells() const