ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
core/galilei/ComFixed.hpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2017-2022 The ESPResSo project
3 *
4 * This file is part of ESPResSo.
5 *
6 * ESPResSo is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * ESPResSo is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#pragma once
21
22#include "ParticleRange.hpp"
23#include "communication.hpp"
24
25#include <utils/Vector.hpp>
26
27#include <boost/mpi/collectives/all_reduce.hpp>
28#include <boost/mpi/communicator.hpp>
29
30#include <algorithm>
31#include <functional>
32#include <ranges>
33#include <unordered_map>
34#include <vector>
35
36class ComFixed {
37private:
38 std::unordered_map<int, int> m_type_index;
39
40 std::vector<Utils::Vector3d>
41 local_type_forces(ParticleRange const &particles) const {
42 std::vector<Utils::Vector3d> ret(m_type_index.size(), Utils::Vector3d{});
43
44 for (auto const &p : particles) {
45 /* Check if type is of interest */
46 auto it = m_type_index.find(p.type());
47 if (it != m_type_index.end()) {
48 ret[it->second] += p.force();
49 }
50 }
51
52 return ret;
53 }
54
55 std::vector<double> local_type_masses(ParticleRange const &particles) const {
56 std::vector<double> ret(m_type_index.size(), 0.);
57
58 for (auto const &p : particles) {
59 /* Check if type is of interest */
60 auto it = m_type_index.find(p.type());
61 if (it != m_type_index.end()) {
62 ret[it->second] += p.mass();
63 }
64 }
65
66 return ret;
67 }
68
69public:
70 ComFixed() = default;
71
72 void set_fixed_types(std::vector<int> const &p_types) {
73 m_type_index.clear();
74
75 int i = 0;
76 for (auto const &p_type : p_types) {
77 m_type_index[p_type] = i++;
78 }
79 }
80
81 std::vector<int> get_fixed_types() const {
82 std::vector<int> res{};
83 std::ranges::copy(std::views::keys(m_type_index), std::back_inserter(res));
84 return res;
85 }
86
87 void apply(ParticleRange const &particles) const {
88 /* Bail out early if there is nothing to do. */
89 if (m_type_index.empty())
90 return;
91
92 auto const local_forces = local_type_forces(particles);
93 auto const local_masses = local_type_masses(particles);
94
95 /* Total forces and masses of the types. */
96 std::vector<Utils::Vector3d> forces(m_type_index.size(), Utils::Vector3d{});
97 std::vector<double> masses(m_type_index.size(), 0.0);
98
99 /* Add contributions from all nodes and redistribute them to all. */
100 boost::mpi::all_reduce(::comm_cart, local_forces.data(),
101 static_cast<int>(local_forces.size()), forces.data(),
102 std::plus<Utils::Vector3d>{});
103 boost::mpi::all_reduce(::comm_cart, local_masses.data(),
104 static_cast<int>(local_masses.size()), masses.data(),
105 std::plus<double>{});
106
107 for (auto &p : particles) {
108 /* Check if type is of interest */
109 auto it = m_type_index.find(p.type());
110 if (it != m_type_index.end()) {
111 auto const mass_frac = p.mass() / masses[it->second];
112 auto const &type_force = forces[it->second];
113 for (unsigned int i = 0u; i < 3u; i++) {
114 p.force()[i] -= mass_frac * type_force[i];
115 }
116 }
117 }
118 }
119};
Vector implementation and trait types for boost qvm interoperability.
ComFixed()=default
std::vector< int > get_fixed_types() const
void apply(ParticleRange const &particles) const
void set_fixed_types(std::vector< int > const &p_types)
A range of particles.
boost::mpi::communicator comm_cart
The communicator.