Rosetta
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
dihedral_deriv.hh
Go to the documentation of this file.
1 // -*- mode:c++;tab-width:2;indent-tabs-mode:t;show-trailing-whitespace:t;rm-trailing-spaces:t -*-
2 // vi: set ts=2 noet:
3 //
4 // (c) Copyright Rosetta Commons Member Institutions.
5 // (c) This file is part of the Rosetta software suite and is made available under license.
6 // (c) The Rosetta software is developed by the contributing members of the Rosetta Commons.
7 // (c) For more information, see http://www.rosettacommons.org. Questions about this can be
8 // (c) addressed to University of Washington UW TechTransfer, email: license@u.washington.edu.
9 
10 /// @file numeric/deriv/dihedral_deriv.hh
11 /// @brief inline function for computing f1/f2 derivatives for a function of a dihedral
12 /// @author Phil Bradley did all the hard work deriving the math represented here.
13 /// @author Andrew Leaver-Fay copy-and-pasted Phil's code into this file from
14 /// the DihedralConstraint.cc file for general use.
15 
16 #ifndef INCLUDED_numeric_deriv_dihedral_deriv_hh
17 #define INCLUDED_numeric_deriv_dihedral_deriv_hh
18 
19 #include <numeric/xyz.functions.hh>
20 #include <numeric/xyzVector.hh>
22 #include <numeric/conversions.hh>
23 #include <utility/assert.hh>
24 
25 #include <float.h>
26 
27 namespace numeric {
28 namespace deriv {
29 
30 /////////////////////////////////////////////////////////////////////////////
31 // contributions for a term that looks like
32 //
33 // d(M-F)
34 // ( ------ x v ) dot w
35 // d phi
36 //
37 // F1 collects terms f1 that look like: (-u_phi) dot f1
38 // F2 collects terms f2 that look like: (-u_phi x R_phi) dot f2
39 //
40 //
41 // where u_phi is the torsion axis of rotation
42 // and R_phi is a terminal atom of this axis
43 template < class P >
44 inline
45 void
47  xyzVector< P > const & M,
48  xyzVector< P > const & v,
49  xyzVector< P > const & w,
50  xyzVector< P > & F1,
51  xyzVector< P > & F2
52 )
53 {
54  typedef xyzVector< P > Vector;
55 
56  Vector const f2 = cross(v,w);
57  F2 += f2;
58  F1 += cross(f2,M);
59 }
60 
61 /// @brief Whether computing the f1/f2 derivatives for a function of a dihedral
62 /// for the end points (p1 or p4) or the middle points (p2 or p3), the second
63 /// half of the computation is the same. This "second" function expects
64 /// the F1 and F2 arrays to have been partially computed, as well as the cosine
65 /// of the angle theta. It scales the F1 and F2 vectors by
66 /// dtheta_dthetaU * dthetaU_dx
67 template < class P >
68 inline
69 void
71  xyzVector< P > const & p1,
72  xyzVector< P > const & p2,
73  xyzVector< P > const & p3,
74  xyzVector< P > const & p4,
75  P x,
76  P & theta,
77  xyzVector< P > & F1,
78  xyzVector< P > & F2
79 )
80 {
81  typedef P Real;
82 
83  // to avoid problems with dtheta/dx around 0 and 180 degrees
84  // truncate x a bit in the calculation of the derivative
85  Real const small_angle( numeric::conversions::radians( Real(0.1) ) );
86  Real const big_angle( numeric::conversions::radians( Real(179.9) ) );
87  Real const max_x( std::cos( small_angle ));
88  Real const min_x( std::cos( big_angle ));
89  // dtheta_dx has a value of ~ 572.96 for min_x and max_x
90  // this goes to infinity as x goes to -1 or 1
91 
92  // unsigned version of theta
93  ASSERT_ONLY(Real const thetaU( numeric::arccos( x ));)
94 
95  theta = dihedral_radians( p1, p2, p3, p4 );
96 
97  assert( std::abs( std::abs( theta ) - thetaU ) < 1e-2 );
98 
99  x = std::min( std::max( min_x, x ), max_x );
100  Real const dthetaU_dx = -1 / sqrt( 1- x*x );
101  Real const dtheta_dthetaU( theta < 0 ? -1 : 1 );
102 
103  F1 *= dtheta_dthetaU * dthetaU_dx;
104  F2 *= dtheta_dthetaU * dthetaU_dx;
105 
106 }
107 
108 /// @brief The first half of the computation of the f1/f2 derivatives for
109 /// an end point of a dihedral. The values in the output-parameter
110 /// vectors F1 and F2 are overwritten. The cosine of the dihedral theta
111 /// is returned in the output parameter x.
112 template < class P >
113 inline
114 void
116  xyzVector< P > const & p1,
117  xyzVector< P > const & p2,
118  xyzVector< P > const & p3,
119  xyzVector< P > const & p4,
120  P & x,
121  bool & colinearity_flag,
122  xyzVector< P > & F1,
123  xyzVector< P > & F2
124 )
125 {
126  typedef P Real;
127  typedef xyzVector< P > Vector;
128 
129  F1 = 0.0;
130  F2 = 0.0;
131  colinearity_flag = false;
132 
133  Vector v1( p1-p2 );
134  Vector v2( p2-p3 );
135  Vector v3( p3-p4 );
136 
137  Vector v12( cross( v1, v2 ));
138  Vector v23( cross( v2, v3 ));
139 
140  Real const n12( v12.length() );
141  Real const n23( v23.length() );
142 
143  if ( n12 < Real(1e-9) || n23 < Real(1e-9) ) {
144  colinearity_flag = true;
145  return;
146  }
147 
148  x = dot( v12, v23 ) / ( n12 * n23 );
149 
150  // first term:
151  {
152  Real const f( Real(1.0) / ( n12 * n23 ) );
153  helper( p1, f * v2, v23 , F1, F2);
154  }
155 
156  // second term
157  {
158  Real const f( Real(-1.0) * x / ( n12 * n12 ) );
159  helper( p1, f * v2, v12, F1, F2 );
160  }
161 
162 
163  // debugging
164  // translation of p1 in the place spanned by v1 and v2
165  // does not affect the torsion angle
166  // ==> rotation of p1 about an axis perpendicular to this plane
167  // also does not change the torsion angle, ie deriv should be 0
168  assert( std::abs( dot( F2, v1 ) ) < Real(1e-3) );
169  assert( std::abs( dot( F2, v2 ) ) < Real(1e-3) );
170  assert( std::abs( dot( F1, cross( v1, v2 ) ) ) < Real(1e-3) );
171 }
172 
173 /// @brief compute f1/f2 atom derivative vectors for one of the two end points defining
174 /// a dihedral angle for some function F. Templated on the precision of the coordinates
175 /// being represented. Returns the dihedral angle, theta, defined by p1->p2->p3->p4,
176 /// which should be used to evaluate the derivative of the function F. dF_dtheta should
177 /// then be multiplied into both derivative vectors that are returned. The values of the
178 /// output variables f1 and f2 are overwritten. Theta is computed in radians.
179 /// @brief compute f1/f2 atom derivative vectors for one of the two middle points defining
180 /// a dihedral angle for some function F. Templated on the precision of the coordinates
181 /// being represented. Returns the dihedral angle, theta, defined by p1->p2->p3->p4,
182 /// which should be used to evaluate the derivative of the function F. dF_dtheta should
183 /// then be multiplied into both derivative vectors that are returned. The values of the
184 /// output variables f1 and f2 are overwritten. Theta is computed in radians.
185 template < class P >
186 inline
187 void
189  xyzVector< P > const & p1,
190  xyzVector< P > const & p2,
191  xyzVector< P > const & p3,
192  xyzVector< P > const & p4,
193  P & theta,
194  xyzVector< P > & f1,
195  xyzVector< P > & f2
196 )
197 {
198  typedef P Real;
199 
200  Real x( 0.0 ); bool colinearity;
201  dihedral_p1_cosine_deriv_first( p1, p2, p3, p4, x, colinearity, f1, f2 );
202  if ( colinearity ) return;
203  dihedral_deriv_second( p1, p2, p3, p4, x, theta, f1, f2 );
204 
205 }
206 
207 /// @brief The first half of the computation of the f1/f2 derivatives for
208 /// a central point of a dihedral. The values in the output-parameter
209 /// vectors F1 and F2 are overwritten. The cosine of the dihedral theta
210 /// is returned in the output parameter x.
211 template < class P >
212 inline
213 void
215  xyzVector< P > const & p1,
216  xyzVector< P > const & p2,
217  xyzVector< P > const & p3,
218  xyzVector< P > const & p4,
219  P & x,
220  bool & colinearity_flag,
221  xyzVector< P > & F1,
222  xyzVector< P > & F2
223 )
224 {
225  typedef P Real;
226  typedef xyzVector< P > Vector;
227 
228  //std::cout << "p2_cosine_deriv!" << std::endl;
229 
230  F1 = Real(0.0);
231  F2 = Real(0.0);
232  colinearity_flag = false;
233 
234  Vector v1( p1-p2 );
235  Vector v2( p2-p3 );
236  Vector v3( p3-p4 );
237 
238  Vector v12( cross( v1, v2 ));
239  Vector v23( cross( v2, v3 ));
240 
241  Real const n12( v12.length() );
242  Real const n23( v23.length() );
243 
244  if ( n12 < Real(1e-9) || n23 < Real(1e-9) ) {
245  colinearity_flag = true;
246  return;
247  }
248 
249  x = dot( v12, v23) / ( n12 * n23 );
250 
251  // here we are taking derivatives of an expression that looks like
252  //
253  // dot( v12, v23 )
254  // x = cos theta = -----------------
255  // n12 * n23
256  //
257  // where theta is our dihedral angle
258 
259 
260  { // derivatives of the numerator
261  // v1 and v2 both depend on position of p2
262 
263  { // first term
264  Real const f( Real(-1.0)/ ( n12 * n23 ) );
265  helper( p2, f * v2, v23 , F1, F2);
266  }
267 
268  { // second term
269  Real const f( Real(-1.0)/ ( n12 * n23 ) );
270  helper( p2, f * v1, v23 , F1, F2);
271  }
272 
273  { // third term
274  Real const f( Real(1.0)/ ( n12 * n23 ) );
275  helper( p2, f * v3, v12 , F1, F2);
276  }
277  }
278 
279  { // derivatives of the denominator
280  // v1 and v2 both depend on position of p2
281 
282  { // first term
283  Real const f( x / ( n12 * n12 ) );
284  helper( p2, f * v2, v12, F1, F2 );
285  }
286 
287  { // second term
288  Real const f( x / ( n12 * n12 ) );
289  helper( p2, f * v1, v12, F1, F2 );
290  }
291 
292  { // third term
293  Real const f( Real(-1.0) * x / ( n23 * n23 ) );
294  helper( p2, f * v3, v23, F1, F2 );
295  }
296  }
297 
298  // debugging
299  // translation of p2 along v2 does not change the torsion angle
300  assert( std::abs( dot( F2, v2 ) ) < Real(1e-3) );
301 
302 }
303 
304 
305 /// @brief compute f1/f2 atom derivative vectors for one of the two middle points defining
306 /// a dihedral angle for some function F. Templated on the precision of the coordinates
307 /// being represented. Returns the dihedral angle, theta, defined by p1->p2->p3->p4,
308 /// which should be used to evaluate the derivative of the function F. dF_dtheta should
309 /// then be multiplied into both derivative vectors that are returned. The values of the
310 /// output variables f1 and f2 are overwritten. Theta is computed in radians.
311 template < class P >
312 inline
313 void
315  xyzVector< P > const & p1,
316  xyzVector< P > const & p2,
317  xyzVector< P > const & p3,
318  xyzVector< P > const & p4,
319  P & theta,
320  xyzVector< P > & f1,
321  xyzVector< P > & f2
322 )
323 {
324  typedef P Real;
325 
326  Real x( 0.0 ); bool colinearity;
327  dihedral_p2_cosine_deriv_first( p1, p2, p3, p4, x, colinearity, f1, f2 );
328  if ( colinearity ) return;
329  dihedral_deriv_second( p1, p2, p3, p4, x, theta, f1, f2 );
330 
331 }
332 
333 
334 }
335 }
336 
337 #endif
338 
339 
static T min(T x, T y)
Definition: Svm.cc:16
void dihedral_radians(xyzVector< T > const &p1, xyzVector< T > const &p2, xyzVector< T > const &p3, xyzVector< T > const &p4, T &angle)
Dihedral (torsion) angle in radians: angle value passed.
cmplx w(cmplx z, double relerr)
Definition: functions.cc:470
def x
#define ASSERT_ONLY(x)
Macro wrapper for paramters that used only indebug_assert(...) statments. Intended to supress 'unused...
Definition: assert.hh:28
Conversions between degrees and radians.
void dihedral_p1_cosine_deriv_first(xyzVector< P > const &p1, xyzVector< P > const &p2, xyzVector< P > const &p3, xyzVector< P > const &p4, P &x, bool &colinearity_flag, xyzVector< P > &F1, xyzVector< P > &F2)
The first half of the computation of the f1/f2 derivatives for an end point of a dihedral. The values in the output-parameter vectors F1 and F2 are overwritten. The cosine of the dihedral theta is returned in the output parameter x.
Value length() const
Length.
Definition: xyzVector.hh:1638
xyzVector: Fast (x,y,z)-coordinate numeric vector
xyzVector< Real > Vector
T abs(T const &x)
std::abs( x ) == | x |
Definition: Fmath.hh:295
void dihedral_p2_cosine_deriv_first(xyzVector< P > const &p1, xyzVector< P > const &p2, xyzVector< P > const &p3, xyzVector< P > const &p4, P &x, bool &colinearity_flag, xyzVector< P > &F1, xyzVector< P > &F2)
The first half of the computation of the f1/f2 derivatives for a central point of a dihedral...
void helper(xyzVector< P > const &M, xyzVector< P > const &w, xyzVector< P > &F1, xyzVector< P > &F2)
Definition: angle_deriv.hh:49
double Real
Definition: types.hh:39
xyzTriple< T > cross(xyzTriple< T > const &a, xyzTriple< T > const &b)
Cross product.
T radians(T const &degrees)
Radians of degrees.
Definition: conversions.hh:32
xyzVector and xyzMatrix functions
Fast (x,y,z)-coordinate numeric vector.
T arccos(T const x)
like std::acos but with range checking
static T max(T x, T y)
Definition: Svm.cc:19
Trigonometric functions.
void dihedral_p2_cosine_deriv(xyzVector< P > const &p1, xyzVector< P > const &p2, xyzVector< P > const &p3, xyzVector< P > const &p4, P &theta, xyzVector< P > &f1, xyzVector< P > &f2)
compute f1/f2 atom derivative vectors for one of the two middle points defining a dihedral angle for ...
void dihedral_p1_cosine_deriv(xyzVector< P > const &p1, xyzVector< P > const &p2, xyzVector< P > const &p3, xyzVector< P > const &p4, P &theta, xyzVector< P > &f1, xyzVector< P > &f2)
compute f1/f2 atom derivative vectors for one of the two end points defining a dihedral angle for som...
void dihedral_deriv_second(xyzVector< P > const &p1, xyzVector< P > const &p2, xyzVector< P > const &p3, xyzVector< P > const &p4, P x, P &theta, xyzVector< P > &F1, xyzVector< P > &F2)
Whether computing the f1/f2 derivatives for a function of a dihedral for the end points (p1 or p4) or...
T dot(Quaternion< T > const &q1, Quaternion< T > const &q2)
Dot product.