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) {
62 auto const max_type = get_max_seen_particle_type();
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++) {
65 auto &ia_params = get_ia_param(type_a, 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
76 Utils::Vector3d const &p1_position, Utils::Vector3d const &p1_velocity,
77 int p1_id, Utils::Vector3d const &p2_position,
78 Utils::Vector3d const &p2_velocity, int p2_id, DPDThermostat const &dpd,
79 BoxGeometry const &box_geo, IA_parameters const &ia_params,
80 Utils::Vector3d const &d, double dist, double dist2) {
81 if (ia_params.dpd.radial.cutoff <= 0.0 && ia_params.dpd.trans.cutoff <= 0.0) {
82 return {};
83 }
84
85 auto const v21 = box_geo.velocity_difference(p1_position, p2_position,
86 p1_velocity, p2_velocity);
87 auto const noise_vec =
88 (ia_params.dpd.radial.pref > 0.0 || ia_params.dpd.trans.pref > 0.0)
89 ? dpd_noise(dpd, p1_id, p2_id)
91
92 auto const f_r = dpd_pair_force(ia_params.dpd.radial, v21, dist, noise_vec);
93 auto const f_t = dpd_pair_force(ia_params.dpd.trans, v21, dist, noise_vec);
94
95 /* Projection operator to radial direction */
96 auto const P = tensor_product(d / dist2, d);
97 /* This is equivalent to P * f_r + (1 - P) * f_t, but with
98 * doing only one matrix-vector multiplication */
99 auto const force = P * (f_r - f_t) + f_t;
100 return force;
101}
102
104 auto const &box_geo = *system.box_geo;
105 auto const &nonbonded_ias = *system.nonbonded_ias;
106 auto &cell_structure = *system.cell_structure;
107 system.on_observable_calc();
108
110 cell_structure.non_bonded_loop([&stress, &box_geo, &nonbonded_ias](
111 Particle const &p1, Particle const &p2,
112 Distance const &d) {
113 auto const v21 =
114 box_geo.velocity_difference(p1.pos(), p2.pos(), p1.v(), p2.v());
115
116 auto const &ia_params = nonbonded_ias.get_ia_param(p1.type(), p2.type());
117 auto const dist = std::sqrt(d.dist2);
118
119 auto const f_r = dpd_pair_force(ia_params.dpd.radial, v21, dist, {});
120 auto const f_t = dpd_pair_force(ia_params.dpd.trans, v21, dist, {});
121
122 /* Projection operator to radial direction */
123 auto const P = tensor_product(d.vec21 / d.dist2, d.vec21);
124 /* This is equivalent to P * f_r + (1 - P) * f_t, but with
125 * doing only one matrix-vector multiplication */
126 auto const f = P * (f_r - f_t) + f_t;
127
128 stress += tensor_product(d.vec21, f);
129 });
130
131 return stress;
132}
133
135 auto const local_stress = dpd_viscous_stress_local(system);
136 return -Utils::flatten(local_stress);
137}
138
139/**
140 * @brief Viscous stress tensor of the DPD interaction.
141 *
142 * This calculates the total viscous stress contribution of the
143 * DPD interaction. It contains only the dissipative contributions
144 * of the interaction without noise. It's calculated as the
145 * sum over all pair virials as
146 * \f[
147 * \sigma^{\nu\mu} = V^{-1}\sum_i \sum_{j < i} r_{i,j}^{\nu} (- \gamma_{i,j}
148 * v_{i,j})^{\mu} \f] where \f$\gamma_{i,j}\f$ is the (in general tensor valued)
149 * DPD friction coefficient for particles i and j, \f$v_{i,j}\f$, \f$r_{i,j}\f$
150 * are their relative velocity and distance and \f$V\f$ is the box volume.
151 *
152 * @return Stress tensor contribution.
153 */
155 boost::mpi::communicator const &comm) {
156 auto const local_stress = dpd_viscous_stress_local(system);
157 std::remove_const_t<decltype(local_stress)> global_stress{};
158
159 boost::mpi::reduce(comm, local_stress, global_stress, std::plus<>(), 0);
160
161 return Utils::flatten(global_stress) / system.box_geo->volume();
162}
163
164#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.
void on_observable_calc()
called before calculating observables, i.e.
std::shared_ptr< CellStructure > cell_structure
std::shared_ptr< BoxGeometry > box_geo
std::shared_ptr< InteractionsNonBonded > nonbonded_ias
static auto dpd_viscous_stress_local(System::System &system)
Definition dpd.cpp:103
Utils::Vector9d dpd_stress(System::System &system, boost::mpi::communicator const &comm)
Viscous stress tensor of the DPD interaction.
Definition dpd.cpp:154
Utils::Vector9d dpd_pressure_local(System::System &system)
Local contribution to the pressure tensor.
Definition dpd.cpp:134
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
Utils::Vector3d dpd_pair_force(Utils::Vector3d const &p1_position, Utils::Vector3d const &p1_velocity, int p1_id, Utils::Vector3d const &p2_position, Utils::Vector3d const &p2_velocity, int 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:75
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
auto const & v() const
Definition Particle.hpp:473
auto const & type() const
Definition Particle.hpp:458
auto const & pos() const
Definition Particle.hpp:471
Matrix representation with static size.
Definition matrix.hpp:65