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-2026 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#include "ParticleList.hpp"
30
31#include <utils/Vector.hpp>
33
34#include <boost/mpi/collectives/reduce.hpp>
35#include <boost/mpi/communicator.hpp>
36
37#include <algorithm>
38#include <cstddef>
39#include <functional>
40#include <iterator>
41#include <optional>
42#include <set>
43#include <utility>
44
45HybridDecomposition::HybridDecomposition(boost::mpi::communicator comm,
46 double cutoff_regular, double skin,
47 std::function<bool()> get_ghost_flags,
48 BoxGeometry const &box_geo,
49 LocalBox const &local_box,
50 std::set<int> n_square_types)
51 : m_comm(std::move(comm)), m_box(box_geo), m_cutoff_regular(cutoff_regular),
52 m_regular_decomposition(RegularDecomposition(
53 m_comm, cutoff_regular + skin, m_box, local_box, std::nullopt)),
54 m_n_square(AtomDecomposition(m_comm, m_box)),
55 m_n_square_types(std::move(n_square_types)),
56 m_get_global_ghost_flags(std::move(get_ghost_flags)) {
57
58 /* Vector containing cells of both child decompositions */
59 m_local_cells = m_regular_decomposition.get_local_cells();
60 auto local_cells_n_square = m_n_square.get_local_cells();
61 std::ranges::copy(local_cells_n_square, std::back_inserter(m_local_cells));
62
63 /* Vector containing ghost cells of both child decompositions */
64 m_ghost_cells = m_regular_decomposition.get_ghost_cells();
65 auto ghost_cells_n_square = m_n_square.get_ghost_cells();
66 std::ranges::copy(ghost_cells_n_square, std::back_inserter(m_ghost_cells));
67
68 /* Communicators that contain communications of both child decompositions */
69 m_exchange_ghosts_comm = m_regular_decomposition.exchange_ghosts_comm();
71 std::ranges::copy(exchange_ghosts_comm_n_square.communications,
72 std::back_inserter(m_exchange_ghosts_comm.communications));
73
74 m_collect_ghost_force_comm =
75 m_regular_decomposition.collect_ghost_force_comm();
77 m_n_square.collect_ghost_force_comm();
78 std::ranges::copy(
80 std::back_inserter(m_collect_ghost_force_comm.communications));
81
82 /* coupling between the child decompositions via neighborship relation */
83 std::vector<Cell *> additional_reds = m_n_square.get_local_cells();
84 std::ranges::copy(ghost_cells_n_square, std::back_inserter(additional_reds));
85 for (auto &local_cell : m_regular_decomposition.local_cells()) {
86 std::vector<Cell *> red_neighbors(local_cell->m_neighbors.red().begin(),
87 local_cell->m_neighbors.red().end());
88 std::vector<Cell *> black_neighbors(local_cell->m_neighbors.black().begin(),
89 local_cell->m_neighbors.black().end());
90 std::ranges::copy(additional_reds, std::back_inserter(red_neighbors));
92 }
93}
94
96 std::vector<ParticleChange> &diff) {
98
99 /* Check for n_square type particles in regular decomposition */
100 for (auto &cell_rd : m_regular_decomposition.local_cells()) {
101 for (auto it = cell_rd->particles().begin();
102 it != cell_rd->particles().end();) {
103 /* Particle is in the right decomposition, i.e. has no n_square type */
104 if (not is_n_square_type(it->type())) {
105 std::advance(it, 1);
106 continue;
107 }
108
109 /* else remove from current cell ... */
110 auto p = std::move(*it);
111 it = cell_rd->particles().erase(it);
112 diff.emplace_back(ModifiedList{cell_rd->particles()});
113 diff.emplace_back(RemovedParticle{p.id()});
114
115 /* ... and insert into a n_square cell */
116 auto const first_local_cell = m_n_square.get_local_cells()[0];
117 first_local_cell->particles().insert(std::move(p));
118 diff.emplace_back(ModifiedList{first_local_cell->particles()});
119 }
120
121 /* Now check for regular decomposition type particles in n_square */
122 for (auto &cell_ns : m_n_square.local_cells()) {
123 for (auto it = cell_ns->particles().begin();
124 it != cell_ns->particles().end();) {
125 /* Particle is of n_square type */
126 if (is_n_square_type(it->type())) {
127 std::advance(it, 1);
128 continue;
129 }
130
131 /* else remove from current cell ... */
132 auto p = std::move(*it);
133 it = cell_ns->particles().erase(it);
134 diff.emplace_back(ModifiedList{cell_ns->particles()});
135 diff.emplace_back(RemovedParticle{p.id()});
136
137 /* ... and insert in regular decomposition */
138 auto const target_cell = particle_to_cell(p);
139 /* if particle belongs to this node insert it into correct cell */
140 if (target_cell != nullptr) {
141 target_cell->particles().insert(std::move(p));
142 diff.emplace_back(ModifiedList{target_cell->particles()});
143 }
144 /* otherwise just put into regular decomposition */
145 else {
146 auto first_local_cell = m_regular_decomposition.get_local_cells()[0];
147 first_local_cell->particles().insert(std::move(p));
148 diff.emplace_back(ModifiedList{first_local_cell->particles()});
149 }
150 }
151 }
152 }
153
154 /* now resort into correct cells within the respective decompositions */
155 m_regular_decomposition.resort(global, diff);
156 m_n_square.resort(global, diff);
157
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)
cudaStream_t stream[1]
CUDA streams for parallel computing on CPU and GPU.
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:443
@ GHOSTTRANS_PARTNUM
resize the receiver particle arrays to the size of the senders
Definition ghosts.hpp:140
STL namespace.
std::vector< GhostCommunication > communications
List of ghost communications.
Definition ghosts.hpp:168
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