ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
bonded_tab.hpp
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
22#pragma once
23
24/** \file
25 * Routines to calculate the energy and/or force for particle bonds, angles
26 * and dihedrals via interpolation of lookup tables.
27 */
28
29#include "config/config.hpp"
30
32#include "angle_common.hpp"
34
35#include <utils/Vector.hpp>
36#include <utils/constants.hpp>
37#include <utils/math/sqr.hpp>
38
39#include <boost/optional.hpp>
40#include <boost/serialization/shared_ptr.hpp>
41
42#include <cassert>
43#include <cmath>
44#include <memory>
45#include <tuple>
46#include <vector>
47
48/** Base class for n-body tabulated potential (n=2,3,4). */
50 std::shared_ptr<TabulatedPotential> pot;
51
52 /** Set the parameters of a bonded tabulated potential.
53 * ia_params and force/energy tables are communicated to each node.
54 *
55 * @param min @copybrief TabulatedPotential::minval
56 * @param max @copybrief TabulatedPotential::maxval
57 * @param energy @copybrief TabulatedPotential::energy_tab
58 * @param force @copybrief TabulatedPotential::force_tab
59 */
60 TabulatedBond(double min, double max, std::vector<double> const &energy,
61 std::vector<double> const &force) {
62 pot = std::make_shared<TabulatedPotential>(min, max, force, energy);
63 }
64
65private:
66 friend boost::serialization::access;
67 template <typename Archive>
68 void serialize(Archive &ar, long int /* version */) {
69 ar & pot;
70 }
71};
72
73/** Parameters for 2-body tabulated potential. */
75 double cutoff() const { return assert(pot), pot->cutoff(); }
76
77 static constexpr int num = 1;
78
79 TabulatedDistanceBond(double min, double max,
80 std::vector<double> const &energy,
81 std::vector<double> const &force)
82 : TabulatedBond(min, max, energy, force) {
83 this->pot->minval = min;
84 this->pot->maxval = max;
85 }
86
87 boost::optional<Utils::Vector3d> force(Utils::Vector3d const &dx) const;
88 boost::optional<double> energy(Utils::Vector3d const &dx) const;
89};
90
91/** Parameters for 3-body tabulated potential. */
93 double cutoff() const { return 0.; }
94
95 static constexpr int num = 2;
96
97 TabulatedAngleBond(double min, double max, std::vector<double> const &energy,
98 std::vector<double> const &force)
99 : TabulatedBond(min, max, energy, force) {
100 this->pot->minval = 0.;
101 this->pot->maxval = Utils::pi() + ROUND_ERROR_PREC;
102 }
103
104 std::tuple<Utils::Vector3d, Utils::Vector3d, Utils::Vector3d>
105 forces(Utils::Vector3d const &vec1, Utils::Vector3d const &vec2) const;
106 double energy(Utils::Vector3d const &vec1, Utils::Vector3d const &vec2) const;
107};
108
109/** Parameters for 4-body tabulated potential. */
111 double cutoff() const { return 0.; }
112
113 static constexpr int num = 3;
114
115 TabulatedDihedralBond(double min, double max,
116 std::vector<double> const &energy,
117 std::vector<double> const &force)
118 : TabulatedBond(min, max, energy, force) {
119 this->pot->minval = 0.;
120 this->pot->maxval = 2. * Utils::pi() + ROUND_ERROR_PREC;
121 }
122
123 boost::optional<std::tuple<Utils::Vector3d, Utils::Vector3d, Utils::Vector3d,
125 forces(Utils::Vector3d const &v12, Utils::Vector3d const &v23,
126 Utils::Vector3d const &v34) const;
127 boost::optional<double> energy(Utils::Vector3d const &v12,
128 Utils::Vector3d const &v23,
129 Utils::Vector3d const &v34) const;
130};
131
132/** Compute a tabulated bond length force.
133 *
134 * The force acts in the direction of the connecting vector between the
135 * particles. For distances smaller than the tabulated range it uses a linear
136 * extrapolation based on the first two tabulated force values.
137 *
138 * @param[in] dx Distance between the particles.
139 */
140inline boost::optional<Utils::Vector3d>
142 auto const dist = dx.norm();
143
144 if (dist < pot->cutoff()) {
145 auto const fac = pot->force(dist) / dist;
146 return fac * dx;
147 }
148 return {};
149}
150
151/** Compute a tabulated bond length energy.
152 *
153 * For distances smaller than the tabulated range it uses a quadratic
154 * extrapolation based on the first two tabulated force values and the first
155 * tabulated energy value.
156 *
157 * @param[in] dx Distance between the particles.
158 */
159inline boost::optional<double>
161 auto const dist = dx.norm();
162
163 if (dist < pot->cutoff()) {
164 return pot->energy(dist);
165 }
166 return {};
167}
168
169/** Compute the three-body angle interaction force.
170 * @param[in] vec1 Vector from central particle to left particle.
171 * @param[in] vec2 Vector from central particle to right particle.
172 * @return Forces on the second, first and third particles, in that order.
173 */
174inline std::tuple<Utils::Vector3d, Utils::Vector3d, Utils::Vector3d>
176 Utils::Vector3d const &vec2) const {
177
178 auto forceFactor = [this](double const cos_phi) {
179 auto const sin_phi = sqrt(1 - Utils::sqr(cos_phi));
180#ifdef TABANGLEMINUS
181 auto const phi = acos(-cos_phi);
182#else
183 auto const phi = acos(cos_phi);
184#endif
185 auto const tab_pot = pot;
186 auto const gradient = tab_pot->force(phi);
187 return -gradient / sin_phi;
188 };
189
190 return angle_generic_force(vec1, vec2, forceFactor, true);
191}
192
193/** Compute the three-body angle interaction energy.
194 * It is assumed that the potential is tabulated
195 * for all angles between 0 and Pi.
196 *
197 * @param[in] vec1 Vector from central particle to left particle.
198 * @param[in] vec2 Vector from central particle to right particle.
199 */
201 Utils::Vector3d const &vec2) const {
202 auto const cos_phi = calc_cosine(vec1, vec2, true);
203 /* calculate phi */
204#ifdef TABANGLEMINUS
205 auto const phi = acos(-cos_phi);
206#else
207 auto const phi = acos(cos_phi);
208#endif
209 return pot->energy(phi);
210}
211
212/** Compute the four-body dihedral interaction force.
213 * The forces have a singularity at @f$ \phi = 0 @f$ and @f$ \phi = \pi @f$
214 * (see @cite swope92a page 592).
215 *
216 * @param[in] v12 Vector from @p p1 to @p p2
217 * @param[in] v23 Vector from @p p2 to @p p3
218 * @param[in] v34 Vector from @p p3 to @p p4
219 * @return the forces on @p p2, @p p1, @p p3
220 */
221inline boost::optional<std::tuple<Utils::Vector3d, Utils::Vector3d,
224 Utils::Vector3d const &v23,
225 Utils::Vector3d const &v34) const {
226 /* vectors for dihedral angle calculation */
227 Utils::Vector3d v12Xv23, v23Xv34;
228 double l_v12Xv23, l_v23Xv34;
229 /* dihedral angle, cosine of the dihedral angle */
230 double phi, cos_phi;
231
232 /* dihedral angle */
233 auto const angle_is_undefined = calc_dihedral_angle(
234 v12, v23, v34, v12Xv23, l_v12Xv23, v23Xv34, l_v23Xv34, cos_phi, phi);
235 /* dihedral angle not defined - force zero */
236 if (angle_is_undefined) {
237 return {};
238 }
239
240 auto const f1 = (v23Xv34 - cos_phi * v12Xv23) / l_v12Xv23;
241 auto const f4 = (v12Xv23 - cos_phi * v23Xv34) / l_v23Xv34;
242
243 auto const v23Xf1 = vector_product(v23, f1);
244 auto const v23Xf4 = vector_product(v23, f4);
245 auto const v34Xf4 = vector_product(v34, f4);
246 auto const v12Xf1 = vector_product(v12, f1);
247
248 /* table lookup */
249 auto const fac = pot->force(phi);
250
251 /* store dihedral forces */
252 auto const force1 = fac * v23Xf1;
253 auto const force2 = fac * (v34Xf4 - v12Xf1 - v23Xf1);
254 auto const force3 = fac * (v12Xf1 - v23Xf4 - v34Xf4);
255
256 return std::make_tuple(force2, force1, force3, -(force2 + force1 + force3));
257}
258
259/** Compute the four-body dihedral interaction energy.
260 * The energy doesn't have any singularity if the angle phi is well-defined.
261 *
262 * @param[in] v12 Vector from @p p1 to @p p2
263 * @param[in] v23 Vector from @p p2 to @p p3
264 * @param[in] v34 Vector from @p p3 to @p p4
265 */
266inline boost::optional<double>
268 Utils::Vector3d const &v23,
269 Utils::Vector3d const &v34) const {
270 /* vectors for dihedral calculations. */
271 Utils::Vector3d v12Xv23, v23Xv34;
272 double l_v12Xv23, l_v23Xv34;
273 /* dihedral angle, cosine of the dihedral angle */
274 double phi, cos_phi;
275 auto const angle_is_undefined = calc_dihedral_angle(
276 v12, v23, v34, v12Xv23, l_v12Xv23, v23Xv34, l_v23Xv34, cos_phi, phi);
277 /* dihedral angle not defined - energy zero */
278 if (angle_is_undefined) {
279 return {};
280 }
281
282 return pot->energy(phi);
283}
Vector implementation and trait types for boost qvm interoperability.
Common code for functions calculating angle forces.
std::tuple< Utils::Vector3d, Utils::Vector3d, Utils::Vector3d > angle_generic_force(Utils::Vector3d const &vec1, Utils::Vector3d const &vec2, ForceFactor forceFactor, bool sanitize_cosine)
Compute a three-body angle interaction force.
double calc_cosine(Utils::Vector3d const &vec1, Utils::Vector3d const &vec2, bool sanitize_cosine=false)
Compute the cosine of the angle between three particles.
__global__ float * force
T norm() const
Definition Vector.hpp:131
This file contains the defaults for ESPResSo.
#define ROUND_ERROR_PREC
Precision for capture of round off errors.
Definition config.hpp:66
Routines to calculate the dihedral energy or/and force for a particle quadruple.
bool calc_dihedral_angle(Utils::Vector3d const &a, Utils::Vector3d const &b, Utils::Vector3d const &c, Utils::Vector3d &aXb, double &l_aXb, Utils::Vector3d &bXc, double &l_bXc, double &cosphi, double &phi)
Calculates the dihedral angle between particle quadruple p1, p2, p3 and p4.
Definition dihedral.hpp:97
__device__ void vector_product(float const *a, float const *b, float *out)
DEVICE_QUALIFIER constexpr T pi()
Ratio of diameter and circumference of a circle.
Definition constants.hpp:36
VectorXd< 3 > Vector3d
Definition Vector.hpp:157
DEVICE_QUALIFIER constexpr T sqr(T x)
Calculates the SQuaRe of x.
Definition sqr.hpp:26
Parameters for 3-body tabulated potential.
TabulatedAngleBond(double min, double max, std::vector< double > const &energy, std::vector< double > const &force)
double energy(Utils::Vector3d const &vec1, Utils::Vector3d const &vec2) const
Compute the three-body angle interaction energy.
static constexpr int num
std::tuple< Utils::Vector3d, Utils::Vector3d, Utils::Vector3d > forces(Utils::Vector3d const &vec1, Utils::Vector3d const &vec2) const
Compute the three-body angle interaction force.
double cutoff() const
Base class for n-body tabulated potential (n=2,3,4).
std::shared_ptr< TabulatedPotential > pot
TabulatedBond(double min, double max, std::vector< double > const &energy, std::vector< double > const &force)
Set the parameters of a bonded tabulated potential.
Parameters for 4-body tabulated potential.
boost::optional< double > energy(Utils::Vector3d const &v12, Utils::Vector3d const &v23, Utils::Vector3d const &v34) const
Compute the four-body dihedral interaction energy.
TabulatedDihedralBond(double min, double max, std::vector< double > const &energy, std::vector< double > const &force)
static constexpr int num
boost::optional< std::tuple< Utils::Vector3d, Utils::Vector3d, Utils::Vector3d, Utils::Vector3d > > forces(Utils::Vector3d const &v12, Utils::Vector3d const &v23, Utils::Vector3d const &v34) const
Compute the four-body dihedral interaction force.
double cutoff() const
Parameters for 2-body tabulated potential.
boost::optional< Utils::Vector3d > force(Utils::Vector3d const &dx) const
Compute a tabulated bond length force.
double cutoff() const
static constexpr int num
boost::optional< double > energy(Utils::Vector3d const &dx) const
Compute a tabulated bond length energy.
TabulatedDistanceBond(double min, double max, std::vector< double > const &energy, std::vector< double > const &force)