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-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/** \file
22 * Implementation of dpd.hpp.
23 */
24#include "config/config.hpp"
25
26#ifdef DPD
27
28#include "dpd.hpp"
29
30#include "BoxGeometry.hpp"
32#include "cells.hpp"
34#include "random.hpp"
35#include "system/System.hpp"
36#include "thermostat.hpp"
37
38#include <utils/Vector.hpp>
39#include <utils/constants.hpp>
40#include <utils/math/sqr.hpp>
42#include <utils/matrix.hpp>
43
44#include <boost/mpi/collectives/reduce.hpp>
45
46#include <algorithm>
47#include <cmath>
48#include <cstdint>
49#include <functional>
50
51/** Return a random uniform 3D vector with the Philox thermostat.
52 * Random numbers depend on
53 * 1. dpd_rng_counter (initialized by seed) which is increased on integration
54 * 2. Salt (decorrelates different counters)
55 * 3. Two particle IDs (order-independent, decorrelates particles, gets rid of
56 * seed-per-node)
57 */
58Utils::Vector3d dpd_noise(DPDThermostat const &dpd, int pid1, int pid2) {
59 return Random::noise_uniform<RNGSalt::SALT_DPD>(
60 dpd.rng_counter(), dpd.rng_seed(), (pid1 < pid2) ? pid2 : pid1,
61 (pid1 < pid2) ? pid1 : pid2);
62}
63
64void dpd_init(double kT, double time_step) {
65 auto &nonbonded_ias = *System::get_system().nonbonded_ias;
66 auto const max_type = nonbonded_ias.get_max_seen_particle_type();
67 for (int type_a = 0; type_a <= max_type; type_a++) {
68 for (int type_b = type_a; type_b <= max_type; type_b++) {
69 auto &ia_params = nonbonded_ias.get_ia_param(type_a, type_b);
70
71 ia_params.dpd.radial.pref =
72 sqrt(24.0 * kT * ia_params.dpd.radial.gamma / time_step);
73 ia_params.dpd.trans.pref =
74 sqrt(24.0 * kT * ia_params.dpd.trans.gamma / time_step);
75 }
76 }
77}
78
79static double weight(int type, double r_cut, double k, double r) {
80 if (type == 0) {
81 return 1.;
82 }
83 return 1. - pow((r / r_cut), k);
84}
85
87 Utils::Vector3d const &v, double dist,
88 Utils::Vector3d const &noise) {
89 if (dist < params.cutoff) {
90 auto const omega = weight(params.wf, params.cutoff, params.k, dist);
91 auto const omega2 = Utils::sqr(omega);
92
93 auto const f_d = params.gamma * omega2 * v;
94 auto const f_r = params.pref * omega * noise;
95
96 return f_r - f_d;
97 }
98
99 return {};
100}
101
103dpd_pair_force(Particle const &p1, Particle const &p2, DPDThermostat const &dpd,
104 BoxGeometry const &box_geo, IA_parameters const &ia_params,
105 Utils::Vector3d const &d, double dist, double dist2) {
106 if (ia_params.dpd.radial.cutoff <= 0.0 && ia_params.dpd.trans.cutoff <= 0.0) {
107 return {};
108 }
109
110 auto const v21 =
111 box_geo.velocity_difference(p1.pos(), p2.pos(), p1.v(), p2.v());
112 auto const noise_vec =
113 (ia_params.dpd.radial.pref > 0.0 || ia_params.dpd.trans.pref > 0.0)
114 ? dpd_noise(dpd, p1.id(), p2.id())
115 : Utils::Vector3d{};
116
117 auto const f_r = dpd_pair_force(ia_params.dpd.radial, v21, dist, noise_vec);
118 auto const f_t = dpd_pair_force(ia_params.dpd.trans, v21, dist, noise_vec);
119
120 /* Projection operator to radial direction */
121 auto const P = tensor_product(d / dist2, d);
122 /* This is equivalent to P * f_r + (1 - P) * f_t, but with
123 * doing only one matrix-vector multiplication */
124 auto const force = P * (f_r - f_t) + f_t;
125 return force;
126}
127
129 auto &system = System::get_system();
130 auto const &box_geo = *system.box_geo;
131 auto const &nonbonded_ias = *system.nonbonded_ias;
132 auto &cell_structure = *system.cell_structure;
133 system.on_observable_calc();
134
136 cell_structure.non_bonded_loop([&stress, &box_geo, &nonbonded_ias](
137 Particle const &p1, Particle const &p2,
138 Distance const &d) {
139 auto const v21 =
140 box_geo.velocity_difference(p1.pos(), p2.pos(), p1.v(), p2.v());
141
142 auto const &ia_params = nonbonded_ias.get_ia_param(p1.type(), p2.type());
143 auto const dist = std::sqrt(d.dist2);
144
145 auto const f_r = dpd_pair_force(ia_params.dpd.radial, v21, dist, {});
146 auto const f_t = dpd_pair_force(ia_params.dpd.trans, v21, dist, {});
147
148 /* Projection operator to radial direction */
149 auto const P = tensor_product(d.vec21 / d.dist2, d.vec21);
150 /* This is equivalent to P * f_r + (1 - P) * f_t, but with
151 * doing only one matrix-vector multiplication */
152 auto const f = P * (f_r - f_t) + f_t;
153
154 stress += tensor_product(d.vec21, f);
155 });
156
157 return stress;
158}
159
160/**
161 * @brief Viscous stress tensor of the DPD interaction.
162 *
163 * This calculates the total viscous stress contribution of the
164 * DPD interaction. It contains only the dissipative contributions
165 * of the interaction without noise. It's calculated as the
166 * sum over all pair virials as
167 * \f[
168 * \sigma^{\nu\mu} = V^{-1}\sum_i \sum_{j < i} r_{i,j}^{\nu} (- \gamma_{i,j}
169 * v_{i,j})^{\mu} \f] where \f$\gamma_{i,j}\f$ is the (in general tensor valued)
170 * DPD friction coefficient for particles i and j, \f$v_{i,j}\f$, \f$r_{i,j}\f$
171 * are their relative velocity and distance and \f$V\f$ is the box volume.
172 *
173 * @return Stress tensor contribution.
174 */
175Utils::Vector9d dpd_stress(boost::mpi::communicator const &comm) {
176 auto const &box_geo = *System::get_system().box_geo;
177 auto const local_stress = dpd_viscous_stress_local();
178 std::remove_const_t<decltype(local_stress)> global_stress;
179
180 boost::mpi::reduce(comm, local_stress, global_stress, std::plus<>(), 0);
181
182 return Utils::flatten(global_stress) / box_geo.volume();
183}
184
185#endif // DPD
Vector implementation and trait types for boost qvm interoperability.
float f[3]
__global__ float * force
This file contains everything related to the global cell structure / cell system.
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.
std::shared_ptr< BoxGeometry > box_geo
std::shared_ptr< InteractionsNonBonded > nonbonded_ias
This file contains the defaults for ESPResSo.
Utils::Vector3d dpd_pair_force(DPDParameters const &params, Utils::Vector3d const &v, double dist, Utils::Vector3d const &noise)
Definition dpd.cpp:86
static auto dpd_viscous_stress_local()
Definition dpd.cpp:128
void dpd_init(double kT, double time_step)
Definition dpd.cpp:64
static double weight(int type, double r_cut, double k, double r)
Definition dpd.cpp:79
Utils::Vector9d dpd_stress(boost::mpi::communicator const &comm)
Viscous stress tensor of the DPD interaction.
Definition dpd.cpp:175
Utils::Vector3d dpd_noise(DPDThermostat const &dpd, int pid1, int pid2)
Return a random uniform 3D vector with the Philox thermostat.
Definition dpd.cpp:58
Routines to use DPD as thermostat or pair force .
Matrix implementation and trait types for boost qvm interoperability.
System & get_system()
void flatten(Range const &v, OutputIterator out)
Flatten a range of ranges.
Definition flatten.hpp:63
DEVICE_QUALIFIER constexpr T sqr(T x)
Calculates the SQuaRe of x.
Definition sqr.hpp:26
Various procedures concerning interactions between particles.
Random number generation using Philox.
static SteepestDescentParameters params
Currently active steepest descent instance.
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:393
auto const & v() const
Definition Particle.hpp:431
auto const & type() const
Definition Particle.hpp:416
auto const & pos() const
Definition Particle.hpp:429
auto const & id() const
Definition Particle.hpp:412
double gamma
Dampening constant.
Matrix representation with static size.
Definition matrix.hpp:65