Loading [MathJax]/extensions/TeX/AMSmath.js
ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages Concepts
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