ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
sd_interface.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2010-2025 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#include <config/config.hpp>
21
22#ifdef ESPRESSO_STOKESIAN_DYNAMICS
23
24#include "sd_interface.hpp"
25
26#include "stokesian_dynamics/sd_cpu.hpp"
27
28#include "BoxGeometry.hpp"
29#include "Particle.hpp"
30#include "communication.hpp"
31#include "system/System.hpp"
32#include "thermostat.hpp"
33
34#include <utils/Vector.hpp>
37
38#include <boost/serialization/is_bitwise_serializable.hpp>
39
40#include <algorithm>
41#include <cmath>
42#include <cstddef>
43#include <iterator>
44#include <stdexcept>
45#include <string>
46#include <utility>
47#include <vector>
48
49/* type for particle data transfer between nodes */
51 SD_particle_data() = default;
52 explicit SD_particle_data(Particle const &p)
53 : type(p.type()), pos(p.pos()), ext_force(p.force_and_torque()) {}
54
55 int type = 0;
56
57 /* particle position */
58 Utils::Vector3d pos = {0., 0., 0.};
59
60 /* external force */
62
63 template <class Archive> void serialize(Archive &ar, long int /* version */) {
64 ar & type;
65 ar & pos;
66 ar & ext_force;
67 }
68};
69
70BOOST_IS_BITWISE_SERIALIZABLE(SD_particle_data)
71
72/** Update translational and rotational velocities of all particles. */
73template <typename ParticleIterable>
74static void sd_update_locally(ParticleIterable const &parts,
75 std::vector<double> const &v_sd) {
76 std::size_t i = 0;
77
78 // Even though on the head node, the v_sd vector is larger than
79 // the (local) parts vector, this should still work. Because the local
80 // particles correspond to the first 6*n entries in the head node's v_sd
81 // (which holds the velocities of ALL particles).
82
83 for (auto &p : parts) {
84 // Copy velocities
85 p.v()[0] = v_sd[6 * i + 0];
86 p.v()[1] = v_sd[6 * i + 1];
87 p.v()[2] = v_sd[6 * i + 2];
88
89 p.omega()[0] = v_sd[6 * i + 3];
90 p.omega()[1] = v_sd[6 * i + 4];
91 p.omega()[2] = v_sd[6 * i + 5];
92
93 ++i;
94 }
95}
96
98 std::unordered_map<int, double> radii,
99 int flags)
100 : viscosity{viscosity}, radii{radii}, flags{flags} {
101 if (viscosity < 0.) {
102 throw std::domain_error("Viscosity has an invalid value: " +
103 std::to_string(viscosity));
104 }
105 /* Check that radii are positive */
106 for (auto const &[p_type, radius] : radii) {
107 if (radius < 0.) {
108 throw std::domain_error(
109 "Particle radius for type " + std::to_string(p_type) +
110 " has an invalid value: " + std::to_string(radius));
111 }
112 }
113}
114
116 ParticleRangeStokesian const &particles,
117 StokesianThermostat const &stokesian, double const time_step,
118 double const kT) const {
119
120 std::vector<SD_particle_data> parts_buffer{};
121 parts_buffer.reserve(particles.size());
122
123 std::ranges::transform(particles, std::back_inserter(parts_buffer),
124 [](auto const &p) { return SD_particle_data(p); });
125 Utils::Mpi::gather_buffer(parts_buffer, ::comm_cart, 0);
126
127 /* Buffer that holds local particle data, and all particles on the head
128 * node used for sending particle data to head node. */
129 if (::comm_cart.rank() == 0) {
130 std::size_t n_part = parts_buffer.size();
131
132 x_host.resize(6 * n_part);
133 f_host.resize(6 * n_part);
134 a_host.resize(n_part);
135
136 std::size_t i = 0;
137 for (auto const &p : parts_buffer) {
138 x_host[6 * i + 0] = p.pos[0];
139 x_host[6 * i + 1] = p.pos[1];
140 x_host[6 * i + 2] = p.pos[2];
141 // Actual orientation is not needed, just need default.
142 x_host[6 * i + 3] = 1;
143 x_host[6 * i + 4] = 0;
144 x_host[6 * i + 5] = 0;
145
146 f_host[6 * i + 0] = p.ext_force.f[0];
147 f_host[6 * i + 1] = p.ext_force.f[1];
148 f_host[6 * i + 2] = p.ext_force.f[2];
149
150 f_host[6 * i + 3] = p.ext_force.torque[0];
151 f_host[6 * i + 4] = p.ext_force.torque[1];
152 f_host[6 * i + 5] = p.ext_force.torque[2];
153
154 a_host[i] = radii.at(p.type);
155
156 ++i;
157 }
158
159 v_sd = sd_cpu(x_host, f_host, a_host, n_part, viscosity,
160 std::sqrt(kT / time_step),
161 static_cast<std::size_t>(stokesian.rng_counter()),
162 static_cast<std::size_t>(stokesian.rng_seed()), flags);
163 } else { // if (this_node == 0)
164 v_sd.resize(particles.size() * 6);
165 } // if (this_node == 0) {...} else
166
168 v_sd.data(), static_cast<int>(particles.size() * 6), ::comm_cart, 0);
169 sd_update_locally(particles, v_sd);
170}
171
172#endif // ESPRESSO_STOKESIAN_DYNAMICS
Vector implementation and trait types for boost qvm interoperability.
base_type::size_type size() const
boost::mpi::communicator comm_cart
The communicator.
void gather_buffer(std::vector< T, Allocator > &buffer, boost::mpi::communicator const &comm, int root=0)
Gather buffer with different size on each node.
void scatter_buffer(T *buffer, int n_elem, boost::mpi::communicator comm, int root=0)
Scatter buffer with different size on each node.
static void sd_update_locally(ParticleIterable const &parts, std::vector< double > const &v_sd)
Update translational and rotational velocities of all particles.
See for the Stokesian dynamics method used here.
uint64_t rng_counter() const
Get current value of the RNG.
uint32_t rng_seed() const
Force information on a particle.
Definition Particle.hpp:345
Struct holding all information for one particle.
Definition Particle.hpp:450
SD_particle_data()=default
SD_particle_data(Particle const &p)
Utils::Vector3d pos
void serialize(Archive &ar, long int)
ParticleForce ext_force
StokesianDynamics()=default
void propagate_vel_pos(ParticleRangeStokesian const &particles, StokesianThermostat const &stokesian, double time_step, double kT) const
Take the forces and torques on all particles and compute velocities.
std::unordered_map< int, double > radii
Thermostat for Stokesian dynamics.