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