ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
dpd.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/** \file
22 * Implementation of dpd.hpp.
23 */
24#include <config/config.hpp>
25
26#ifdef ESPRESSO_DPD
27
28#include "dpd.hpp"
29
30#include "BoxGeometry.hpp"
33#include "random.hpp"
34#include "system/System.hpp"
35#include "thermostat.hpp"
36
37#include <utils/Vector.hpp>
39#include <utils/matrix.hpp>
40
41#include <boost/mpi/collectives/reduce.hpp>
42
43#include <cmath>
44#include <functional>
45#include <type_traits>
46
47/** Return a random uniform 3D vector with the Philox thermostat.
48 * Random numbers depend on
49 * 1. dpd_rng_counter (initialized by seed) which is increased on integration
50 * 2. Salt (decorrelates different counters)
51 * 3. Two particle IDs (order-independent, decorrelates particles, gets rid of
52 * seed-per-node)
53 */
54static Utils::Vector3d dpd_noise(DPDThermostat const &dpd, int pid1, int pid2) {
55 auto const pref = (pid1 < pid2) ? 1.0 : -1.0;
56 return pref * Random::noise_uniform<RNGSalt::SALT_DPD>(
57 dpd.rng_counter(), dpd.rng_seed(),
58 (pid1 < pid2) ? pid2 : pid1, (pid1 < pid2) ? pid1 : pid2);
59}
60
61void InteractionsNonBonded::dpd_init(double kT, double time_step) {
63 for (int type_a = 0; type_a <= max_type; type_a++) {
64 for (int type_b = type_a; type_b <= max_type; type_b++) {
66
67 ia_params.dpd.radial.pref =
68 sqrt(24.0 * kT * ia_params.dpd.radial.gamma / time_step);
69 ia_params.dpd.trans.pref =
70 sqrt(24.0 * kT * ia_params.dpd.trans.gamma / time_step);
71 }
72 }
73}
74
77 Utils::Vector3d const &p1_velocity, int const &p1_id,
79 Utils::Vector3d const &p2_velocity, int const &p2_id,
80 DPDThermostat const &dpd, BoxGeometry const &box_geo,
82 double dist, double dist2) {
83 if (ia_params.dpd.radial.cutoff <= 0.0 && ia_params.dpd.trans.cutoff <= 0.0) {
84 return {};
85 }
86
87 auto const v21 = box_geo.velocity_difference(p1_position, p2_position,
89 auto const noise_vec =
90 (ia_params.dpd.radial.pref > 0.0 || ia_params.dpd.trans.pref > 0.0)
91 ? dpd_noise(dpd, p1_id, p2_id)
93
94 auto const f_r = dpd_pair_force(ia_params.dpd.radial, v21, dist, noise_vec);
95 auto const f_t = dpd_pair_force(ia_params.dpd.trans, v21, dist, noise_vec);
96
97 /* Projection operator to radial direction */
98 auto const P = tensor_product(d / dist2, d);
99 /* This is equivalent to P * f_r + (1 - P) * f_t, but with
100 * doing only one matrix-vector multiplication */
101 auto const force = P * (f_r - f_t) + f_t;
102 return force;
103}
104
106 auto const &box_geo = *system.box_geo;
107 auto const &nonbonded_ias = *system.nonbonded_ias;
108 auto &cell_structure = *system.cell_structure;
109 system.on_observable_calc();
110
112 cell_structure.non_bonded_loop([&stress, &box_geo, &nonbonded_ias](
113 Particle const &p1, Particle const &p2,
114 Distance const &d) {
115 auto const v21 =
116 box_geo.velocity_difference(p1.pos(), p2.pos(), p1.v(), p2.v());
117
118 auto const &ia_params = nonbonded_ias.get_ia_param(p1.type(), p2.type());
119 auto const dist = std::sqrt(d.dist2);
120
121 auto const f_r = dpd_pair_force(ia_params.dpd.radial, v21, dist, {});
122 auto const f_t = dpd_pair_force(ia_params.dpd.trans, v21, dist, {});
123
124 /* Projection operator to radial direction */
125 auto const P = tensor_product(d.vec21 / d.dist2, d.vec21);
126 /* This is equivalent to P * f_r + (1 - P) * f_t, but with
127 * doing only one matrix-vector multiplication */
128 auto const f = P * (f_r - f_t) + f_t;
129
130 stress += tensor_product(d.vec21, f);
131 });
132
133 return stress;
134}
135
140
141/**
142 * @brief Viscous stress tensor of the DPD interaction.
143 *
144 * This calculates the total viscous stress contribution of the
145 * DPD interaction. It contains only the dissipative contributions
146 * of the interaction without noise. It's calculated as the
147 * sum over all pair virials as
148 * \f[
149 * \sigma^{\nu\mu} = V^{-1}\sum_i \sum_{j < i} r_{i,j}^{\nu} (- \gamma_{i,j}
150 * v_{i,j})^{\mu} \f] where \f$\gamma_{i,j}\f$ is the (in general tensor valued)
151 * DPD friction coefficient for particles i and j, \f$v_{i,j}\f$, \f$r_{i,j}\f$
152 * are their relative velocity and distance and \f$V\f$ is the box volume.
153 *
154 * @return Stress tensor contribution.
155 */
157 boost::mpi::communicator const &comm) {
159 std::remove_const_t<decltype(local_stress)> global_stress{};
160
161 boost::mpi::reduce(comm, local_stress, global_stress, std::plus<>(), 0);
162
163 return Utils::flatten(global_stress) / system.box_geo->volume();
164}
165
166#endif // ESPRESSO_DPD
Vector implementation and trait types for boost qvm interoperability.
Utils::Vector3d velocity_difference(Utils::Vector3d const &x, Utils::Vector3d const &y, Utils::Vector3d const &u, Utils::Vector3d const &v) const
Calculate the velocity difference including the Lees-Edwards velocity.
void dpd_init(double kT, double time_step)
Definition dpd.cpp:61
auto & get_ia_param(int i, int j)
Get interaction parameters between particle types i and j.
Main system class.
cudaStream_t stream[1]
CUDA streams for parallel computing on CPU and GPU.
static auto dpd_viscous_stress_local(System::System &system)
Definition dpd.cpp:105
Utils::Vector9d dpd_stress(System::System &system, boost::mpi::communicator const &comm)
Viscous stress tensor of the DPD interaction.
Definition dpd.cpp:156
Utils::Vector3d dpd_pair_force(Utils::Vector3d const &p1_position, Utils::Vector3d const &p1_velocity, int const &p1_id, Utils::Vector3d const &p2_position, Utils::Vector3d const &p2_velocity, int const &p2_id, DPDThermostat const &dpd, BoxGeometry const &box_geo, IA_parameters const &ia_params, Utils::Vector3d const &d, double dist, double dist2)
Definition dpd.cpp:76
Utils::Vector9d dpd_pressure_local(System::System &system)
Local contribution to the pressure tensor.
Definition dpd.cpp:136
static Utils::Vector3d dpd_noise(DPDThermostat const &dpd, int pid1, int pid2)
Return a random uniform 3D vector with the Philox thermostat.
Definition dpd.cpp:54
Routines to use DPD as thermostat or pair force .
Matrix implementation and trait types for boost qvm interoperability.
void flatten(Range const &v, OutputIterator out)
Flatten a range of ranges.
Definition flatten.hpp:56
Various procedures concerning interactions between particles.
Random number generation using Philox.
uint64_t rng_counter() const
Get current value of the RNG.
uint32_t rng_seed() const
Thermostat for dissipative particle dynamics.
Distance vector and length handed to pair kernels.
Utils::Vector3d vec21
Parameters for non-bonded interactions.
Struct holding all information for one particle.
Definition Particle.hpp:435
Matrix representation with static size.
Definition matrix.hpp:65