ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
dihedral.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 dihedral energy or/and
26 * force for a particle quadruple. Note that usage of dihedrals
27 * increases the interaction range of bonded interactions to 2 times
28 * the maximal bond length!
29 */
30
31#include "config/config.hpp"
32
33#include <utils/Vector.hpp>
34#include <utils/constants.hpp>
35
36#include <boost/optional.hpp>
37
38#include <cmath>
39#include <tuple>
40
41/** Parameters for four-body angular potential (dihedral-angle potentials). */
43 double mult;
44 double bend;
45 double phase;
46
47 double cutoff() const { return 0.; }
48
49 static constexpr int num = 3;
50
51 DihedralBond(int mult, double bend, double phase) {
52 this->mult = mult;
53 this->bend = bend;
54 this->phase = phase;
55 }
56
57 boost::optional<std::tuple<Utils::Vector3d, Utils::Vector3d, Utils::Vector3d,
59 forces(Utils::Vector3d const &v12, Utils::Vector3d const &v23,
60 Utils::Vector3d const &v34) const;
61
62 boost::optional<double> energy(Utils::Vector3d const &v12,
63 Utils::Vector3d const &v23,
64 Utils::Vector3d const &v34) const;
65
66private:
67 friend boost::serialization::access;
68 template <typename Archive>
69 void serialize(Archive &ar, long int /* version */) {
70 ar & mult;
71 ar & bend;
72 ar & phase;
73 }
74};
75
76/**
77 * @brief Calculates the dihedral angle between particle quadruple p1, p2, p3
78 * and p4.
79 *
80 * The dihedral angle is the angle between the planes
81 * specified by the particle triples (p1,p2,p3) and (p2,p3,p4).
82 * Vectors a, b and c are the bond vectors between consecutive particles.
83 * If the a,b or b,c are parallel the dihedral angle is not defined in which
84 * case the function returns true. Calling functions should check for that.
85 *
86 * @param[in] a Vector from @p p1 to @p p2
87 * @param[in] b Vector from @p p2 to @p p3
88 * @param[in] c Vector from @p p3 to @p p4
89 * @param[out] aXb Vector product of a and b
90 * @param[out] l_aXb |aXB|
91 * @param[out] bXc Vector product of b and c
92 * @param[out] l_bXc |bXc|
93 * @param[out] cosphi Cosine of the dihedral angle
94 * @param[out] phi Dihedral angle in the range [0, pi]
95 * @return Whether the angle is undefined.
96 */
98 Utils::Vector3d const &b,
99 Utils::Vector3d const &c, Utils::Vector3d &aXb,
100 double &l_aXb, Utils::Vector3d &bXc,
101 double &l_bXc, double &cosphi, double &phi) {
102
103 /* calculate vector product a X b and b X c */
104 aXb = vector_product(a, b);
105 bXc = vector_product(b, c);
106
107 /* calculate the unit vectors */
108 l_aXb = aXb.norm();
109 l_bXc = bXc.norm();
110
111 /* catch case of undefined dihedral angle */
112 if (l_aXb <= TINY_LENGTH_VALUE || l_bXc <= TINY_LENGTH_VALUE) {
113 phi = -1.0;
114 cosphi = 0.0;
115 return true;
116 }
117
118 aXb /= l_aXb;
119 bXc /= l_bXc;
120
121 cosphi = aXb * bXc;
122
123 if (fabs(fabs(cosphi) - 1) < TINY_SIN_VALUE)
124 cosphi = std::round(cosphi);
125
126 /* Calculate dihedral angle */
127 phi = acos(cosphi);
128 if ((aXb * c) < 0.0)
129 phi = (2.0 * Utils::pi()) - phi;
130 return false;
131}
132
133/** Compute the four-body dihedral interaction force.
134 * The forces have a singularity at @f$ \phi = 0 @f$ and @f$ \phi = \pi @f$
135 * (see @cite swope92a page 592).
136 *
137 * @param[in] v12 Vector from @p p1 to @p p2
138 * @param[in] v23 Vector from @p p2 to @p p3
139 * @param[in] v34 Vector from @p p3 to @p p4
140 * @return the forces on @p p2, @p p1, @p p3
141 */
142inline boost::optional<std::tuple<Utils::Vector3d, Utils::Vector3d,
145 Utils::Vector3d const &v34) const {
146 /* vectors for dihedral angle calculation */
147 Utils::Vector3d v12Xv23, v23Xv34;
148 double l_v12Xv23, l_v23Xv34;
149 /* dihedral angle, cosine of the dihedral angle */
150 double phi, cos_phi, sin_mphi_over_sin_phi;
151
152 /* dihedral angle */
153 auto const angle_is_undefined = calc_dihedral_angle(
154 v12, v23, v34, v12Xv23, l_v12Xv23, v23Xv34, l_v23Xv34, cos_phi, phi);
155 /* dihedral angle not defined - force zero */
156 if (angle_is_undefined) {
157 return {};
158 }
159
160 auto const f1 = (v23Xv34 - cos_phi * v12Xv23) / l_v12Xv23;
161 auto const f4 = (v12Xv23 - cos_phi * v23Xv34) / l_v23Xv34;
162
163 auto const v23Xf1 = vector_product(v23, f1);
164 auto const v23Xf4 = vector_product(v23, f4);
165 auto const v34Xf4 = vector_product(v34, f4);
166 auto const v12Xf1 = vector_product(v12, f1);
167
168 /* calculate force magnitude */
169 auto fac = -bend * mult;
170
171 if (fabs(sin(phi)) < TINY_SIN_VALUE) {
172 /* comes from taking the first term of the MacLaurin expansion of
173 * sin(n * phi - phi0) and sin(phi) and then making the division */
174 sin_mphi_over_sin_phi = mult * cos(mult * phi - phase) / cos_phi;
175 } else {
176 sin_mphi_over_sin_phi = sin(mult * phi - phase) / sin(phi);
177 }
178
179 fac *= sin_mphi_over_sin_phi;
180
181 /* store dihedral forces */
182 auto const force1 = fac * v23Xf1;
183 auto const force2 = fac * (v34Xf4 - v12Xf1 - v23Xf1);
184 auto const force3 = fac * (v12Xf1 - v23Xf4 - v34Xf4);
185
186 return std::make_tuple(force2, force1, force3, -(force1 + force2 + force3));
187}
188
189/** Compute the four-body dihedral interaction energy.
190 * The energy doesn't have any singularity if the angle phi is well-defined.
191 *
192 * @param[in] v12 Vector from @p p1 to @p p2
193 * @param[in] v23 Vector from @p p2 to @p p3
194 * @param[in] v34 Vector from @p p3 to @p p4
195 */
196inline boost::optional<double>
198 Utils::Vector3d const &v34) const {
199 /* vectors for dihedral calculations. */
200 Utils::Vector3d v12Xv23, v23Xv34;
201 double l_v12Xv23, l_v23Xv34;
202 /* dihedral angle, cosine of the dihedral angle */
203 double phi, cos_phi;
204
205 auto const angle_is_undefined = calc_dihedral_angle(
206 v12, v23, v34, v12Xv23, l_v12Xv23, v23Xv34, l_v23Xv34, cos_phi, phi);
207 /* dihedral angle not defined - energy zero */
208 if (angle_is_undefined) {
209 return {};
210 }
211
212 return bend * (1. - cos(mult * phi - phase));
213}
Vector implementation and trait types for boost qvm interoperability.
T norm() const
Definition Vector.hpp:131
This file contains the defaults for ESPResSo.
#define TINY_LENGTH_VALUE
Tiny length cutoff.
Definition config.hpp:79
#define TINY_SIN_VALUE
Tiny angle cutoff for sinus calculations.
Definition config.hpp:71
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
Parameters for four-body angular potential (dihedral-angle potentials).
Definition dihedral.hpp:42
double phase
Definition dihedral.hpp:45
double cutoff() const
Definition dihedral.hpp:47
boost::optional< double > energy(Utils::Vector3d const &v12, Utils::Vector3d const &v23, Utils::Vector3d const &v34) const
Compute the four-body dihedral interaction energy.
Definition dihedral.hpp:197
DihedralBond(int mult, double bend, double phase)
Definition dihedral.hpp:51
double mult
Definition dihedral.hpp:43
double bend
Definition dihedral.hpp:44
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.
Definition dihedral.hpp:144
static constexpr int num
Definition dihedral.hpp:49