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::copy(local_cells_n_square.begin(), local_cells_n_square.end(),
61 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::copy(ghost_cells_n_square.begin(), ghost_cells_n_square.end(),
67 std::back_inserter(m_ghost_cells));
68
69 /* Communicators that contain communications of both child decompositions */
70 m_exchange_ghosts_comm = m_regular_decomposition.exchange_ghosts_comm();
71 auto exchange_ghosts_comm_n_square = m_n_square.exchange_ghosts_comm();
72 std::copy(exchange_ghosts_comm_n_square.communications.begin(),
73 exchange_ghosts_comm_n_square.communications.end(),
74 std::back_inserter(m_exchange_ghosts_comm.communications));
75
76 m_collect_ghost_force_comm =
77 m_regular_decomposition.collect_ghost_force_comm();
78 auto collect_ghost_force_comm_n_square =
79 m_n_square.collect_ghost_force_comm();
80 std::copy(collect_ghost_force_comm_n_square.communications.begin(),
81 collect_ghost_force_comm_n_square.communications.end(),
82 std::back_inserter(m_collect_ghost_force_comm.communications));
83
84 /* coupling between the child decompositions via neighborship relation */
85 std::vector<Cell *> additional_reds = m_n_square.get_local_cells();
86 std::copy(ghost_cells_n_square.begin(), ghost_cells_n_square.end(),
87 std::back_inserter(additional_reds));
88 for (auto &local_cell : m_regular_decomposition.local_cells()) {
89 std::vector<Cell *> red_neighbors(local_cell->m_neighbors.red().begin(),
90 local_cell->m_neighbors.red().end());
91 std::vector<Cell *> black_neighbors(local_cell->m_neighbors.black().begin(),
92 local_cell->m_neighbors.black().end());
93 std::copy(additional_reds.begin(), additional_reds.end(),
94 std::back_inserter(red_neighbors));
95 local_cell->m_neighbors = Neighbors<Cell *>(red_neighbors, black_neighbors);
96 }
97}
98
100 std::vector<ParticleChange> &diff) {
101 ParticleList displaced_parts;
102
103 /* Check for n_square type particles in regular decomposition */
104 for (auto &c : m_regular_decomposition.local_cells()) {
105 for (auto it = c->particles().begin(); it != c->particles().end();) {
106 /* Particle is in the right decomposition, i.e. has no n_square type */
107 if (not is_n_square_type(it->type())) {
108 std::advance(it, 1);
109 continue;
110 }
111
112 /* else remove from current cell ... */
113 auto p = std::move(*it);
114 it = c->particles().erase(it);
115 diff.emplace_back(ModifiedList{c->particles()});
116 diff.emplace_back(RemovedParticle{p.id()});
117
118 /* ... and insert into a n_square cell */
119 auto const first_local_cell = m_n_square.get_local_cells()[0];
120 first_local_cell->particles().insert(std::move(p));
121 diff.emplace_back(ModifiedList{first_local_cell->particles()});
122 }
123
124 /* Now check for regular decomposition type particles in n_square */
125 for (auto &c : m_n_square.local_cells()) {
126 for (auto it = c->particles().begin(); it != c->particles().end();) {
127 /* Particle is of n_square type */
128 if (is_n_square_type(it->type())) {
129 std::advance(it, 1);
130 continue;
131 }
132
133 /* else remove from current cell ... */
134 auto p = std::move(*it);
135 it = c->particles().erase(it);
136 diff.emplace_back(ModifiedList{c->particles()});
137 diff.emplace_back(RemovedParticle{p.id()});
138
139 /* ... and insert in regular decomposition */
140 auto const target_cell = particle_to_cell(p);
141 /* if particle belongs to this node insert it into correct cell */
142 if (target_cell != nullptr) {
143 target_cell->particles().insert(std::move(p));
144 diff.emplace_back(ModifiedList{target_cell->particles()});
145 }
146 /* otherwise just put into regular decomposition */
147 else {
148 auto first_local_cell = m_regular_decomposition.get_local_cells()[0];
149 first_local_cell->particles().insert(std::move(p));
150 diff.emplace_back(ModifiedList{first_local_cell->particles()});
151 }
152 }
153 }
154 }
155
156 /* now resort into correct cells within the respective decompositions */
157 m_regular_decomposition.resort(global, diff);
158 m_n_square.resort(global, diff);
159
160 /* basically do CellStructure::ghost_count() */
162
163 /* basically do CellStructure::ghost_update(unsigned data_parts) */
165 map_data_parts(m_get_global_ghost_flags()));
166}
167
168std::size_t HybridDecomposition::count_particles(
169 std::vector<Cell *> const &local_cells) const {
170 std::size_t count_local = 0;
171 std::size_t count_global = 0;
172 for (auto const &cell : local_cells) {
173 count_local += cell->particles().size();
174 }
175 boost::mpi::reduce(m_comm, count_local, count_global, std::plus<>{}, 0);
176 return count_global;
177}
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