Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
MMTorsionEnergy.cc
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 core/scoring/ScoreFunction.hh
11 /// @brief molecular mechanics torsion energy
12 /// @author P. Douglas Renfrew (renfrew@unc.edu)
13 
14 // Unit headers
18 
19 // Project headers
23 #include <core/pose/Pose.hh>
25 //#include <core/scoring/ScoringManager.hh>
26 #include <basic/Tracer.hh>
27 
28 // Numeric headers
29 #include <numeric/xyz.functions.hh>
30 #include <numeric/deriv/dihedral_deriv.hh>
31 
32 // C++ headers
33 #include <iostream>
34 
35 #include <core/id/AtomID.hh>
36 #include <utility/vector1.hh>
37 
38 
39 namespace core {
40 namespace scoring {
41 namespace methods {
42 
43 
44 /// @details This must return a fresh instance of the MMTorsionEnergy class,
45 /// never an instance already in use
49 ) const {
50  return new MMTorsionEnergy;
51 }
52 
55  ScoreTypes sts;
56  sts.push_back( mm_twist );
57  return sts;
58 }
59 
60 
61 static basic::Tracer TR("core.scoring.methods.MMTorsionEnergy");
62 
63 
64 typedef std::pair< mm::mm_torsion_atom_quad, core::Real > mm_torsion_atom_quad_angle_pair;
66 
69 {}
70 
71 /// clone
74 {
75  return new MMTorsionEnergy;
76 }
77 
78 ///
79 void
81 {
83 }
84 
85 ///
86 void
88 {
90 }
91 
92 ///
93 void
95 {
97 }
98 
99 ///
100 bool
102 {
103  return true;
104 }
105 
106 void
108  conformation::Residue const & rsd1,
109  conformation::Residue const & rsd2,
110  pose::Pose const & ,
111  ScoreFunction const & ,
112  EnergyMap & emap
113 ) const
114 {
115  Real energy = 0;
116 /*
117  // if not sequential
118  if( rsd2.seqpos() != rsd1.seqpos() + 1 ) {
119  // add energy to emap
120  emap[ mm_twist ] += energy;
121  } else {
122  // get residue types
123  chemical::ResidueType const & rsd1_type = rsd1.type();
124  chemical::ResidueType const & rsd2_type = rsd2.type();
125 
126  // get residue 1 upper connect (r1uc) and residue 2 lower connect (r2lc)
127  Size r1uc = rsd1_type.upper_connect_atom();
128  Size r2lc = rsd2_type.lower_connect_atom();
129 
130  // generate list of new dihedrals about the bond formed between the r1uc and the r2lc
131  // as well as anything with a path distance of 1 from either the r1uc (r1ca) and r2lc (r2ca)
132  utility::vector1< mm_torsion_atom_quad_angle_pair > mm_torsion_atom_quad_angle_pairs_;
133 
134  // get all the atoms that are one away from the r1uc
135  utility::vector1< Size > r1ucd1;
136  for ( Size i = 1; i <= rsd1_type.natoms(); ++i ) {
137  if ( ( rsd1_type.path_distance( r1uc, i ) == 1 ) ) {
138  r1ucd1.push_back( i );
139  }
140  }
141 
142  // get all the atoms that are one away from the r2lc
143  utility::vector1< Size > r2lcd1;
144  for ( Size j = 1; j <= rsd2_type.natoms(); ++j ) {
145  if ( rsd2_type.path_distance( r2lc, j ) == 1 ) {
146  r2lcd1.push_back( j );
147  }
148  }
149 
150  // torsions about the bonds imediatly preceding r1uc and r2lc bond
151  for ( utility::vector1< Size >::iterator r1ca = r1ucd1.begin(); r1ca != r1ucd1.end(); ++r1ca ) {
152  for ( Size r1ta = 1; r1ta <= rsd1_type.natoms(); ++r1ta ) {
153  if ( ( rsd1_type.path_distance( *r1ca, r1ta ) == 1 ) && r1ta != r1uc) {
154  // get mm atom type index
155  Size mmat1 = rsd1_type.mm_atom_type_index( r1ta );
156  Size mmat2 = rsd1_type.mm_atom_type_index(*r1ca );
157  Size mmat3 = rsd1_type.mm_atom_type_index( r1uc );
158  Size mmat4 = rsd2_type.mm_atom_type_index( r2lc );
159 
160  // get angle
161  Real angle = numeric::dihedral_radians
162  ( rsd1.atom( r1ta ).xyz(),
163  rsd1.atom(*r1ca ).xyz(),
164  rsd1.atom( r1uc ).xyz(),
165  rsd2.atom( r2lc ).xyz() );
166 
167  // make pair
168  mm_torsion_atom_quad_angle_pair temp( mm::mm_torsion_atom_quad( mmat1, mmat2, mmat3, mmat4 ), angle );
169 
170  // add to list
171  mm_torsion_atom_quad_angle_pairs_.push_back( temp );
172  }
173  }
174  }
175 
176  // torsions about the r1uc and r2lc bond
177  for ( utility::vector1< Size >::iterator terminal_atom1 = r1ucd1.begin();
178  terminal_atom1 != r1ucd1.end(); ++terminal_atom1 ) {
179  for ( utility::vector1< Size >::iterator terminal_atom2 = r2lcd1.begin();
180  terminal_atom2 != r2lcd1.end(); ++terminal_atom2 ) {
181  // get mm atom type index
182  Size mmat1 = rsd1_type.mm_atom_type_index( *terminal_atom1 );
183  Size mmat2 = rsd1_type.mm_atom_type_index( r1uc );
184  Size mmat3 = rsd2_type.mm_atom_type_index( r2lc );
185  Size mmat4 = rsd2_type.mm_atom_type_index( *terminal_atom2 );
186 
187  // get angle
188  Real angle = numeric::dihedral_radians
189  ( rsd1.atom( *terminal_atom1 ).xyz(),
190  rsd1.atom( r1uc ).xyz(),
191  rsd2.atom( r2lc ).xyz(),
192  rsd2.atom( *terminal_atom2 ).xyz() );
193 
194  // make pair
195  mm_torsion_atom_quad_angle_pair temp( mm::mm_torsion_atom_quad( mmat1, mmat2, mmat3, mmat4 ), angle );
196 
197  // add to list
198  mm_torsion_atom_quad_angle_pairs_.push_back( temp );
199  }
200  }
201 
202  // torsions about the bonds imediatly following r1uc and r2lc bond
203  for ( utility::vector1< Size >::iterator r2ca = r2lcd1.begin(); r2ca != r2lcd1.end(); ++r2ca ) {
204  for ( Size r2ta = 1; r2ta <= rsd2_type.natoms(); ++r2ta ) {
205  if ( ( rsd2_type.path_distance( *r2ca, r2ta ) == 1 ) && r2ta != r2lc ) {
206  // get mm atom type index
207  Size mmat1 = rsd1_type.mm_atom_type_index( r1uc );
208  Size mmat2 = rsd2_type.mm_atom_type_index( r2lc );
209  Size mmat3 = rsd2_type.mm_atom_type_index(*r2ca );
210  Size mmat4 = rsd2_type.mm_atom_type_index( r2ta );
211 
212  // get angle
213  Real angle = numeric::dihedral_radians
214  ( rsd1.atom( r1uc ).xyz(),
215  rsd2.atom( r2lc ).xyz(),
216  rsd2.atom(*r2ca ).xyz(),
217  rsd2.atom( r2ta ).xyz() );
218 
219  // make pair
220  mm_torsion_atom_quad_angle_pair temp( mm::mm_torsion_atom_quad( mmat1, mmat2, mmat3, mmat4 ), angle );
221 
222  // add to list
223  mm_torsion_atom_quad_angle_pairs_.push_back( temp );
224  }
225  }
226  }
227 
228  // score each pair
229  for ( Size i = 1; i <= mm_torsion_atom_quad_angle_pairs_.size(); ++i )
230  {
231  // score dihedral
232  energy += potential_.core::scoring::mm::MMTorsionScore::score
233  ( mm_torsion_atom_quad_angle_pairs_[ i ].first, mm_torsion_atom_quad_angle_pairs_[ i ].second );
234  }
235 
236  // add energy to emap
237  emap[ mm_twist ] += energy;
238  }
239 */
240 
241  if ( ! rsd1.is_bonded( rsd2 ) ) return;
242 
243  // get residue types
244  chemical::ResidueType const & rsd1_type = rsd1.type();
245  chemical::ResidueType const & rsd2_type = rsd2.type();
246 
247  TR(basic::t_trace) << "residue_pair_energy: processing residues "
248  << rsd1.seqpos() << "." << rsd1_type.name() << "-"
249  << rsd2.seqpos() << "." << rsd2_type.name() << std::endl;
250 
251  utility::vector1< Size > const & r1_resconn_ids( rsd1.connections_to_residue( rsd2 ) );
252 
253  for ( Size ii = 1; ii <= r1_resconn_ids.size(); ++ii ) {
254 
255  Size const resconn_id1( r1_resconn_ids[ii] );
256  Size const resconn_id2( rsd1.residue_connection_conn_id( resconn_id1 ) );
257 
258  Size const resconn_atomno1( rsd1.residue_connection( resconn_id1 ).atomno() );
259  Size const resconn_atomno2( rsd2.residue_connection( resconn_id2 ).atomno() );
260 
261  TR(basic::t_trace) << "Found residue connection id " << resconn_id1 << "-" << resconn_id2 << ": "
262  << rsd1.atom_name( resconn_atomno1 ) << "-" << rsd2.atom_name( resconn_atomno2 ) << std::endl;
263 
264  Size const resconn_mmat1 = rsd1_type.atom( resconn_atomno1 ).mm_atom_type_index();
265  Size const resconn_mmat2 = rsd2_type.atom( resconn_atomno2 ).mm_atom_type_index();
266 
267  /// Iterate across all atom-quadrouples that define dihedral angles spanning the interface.
268  /// 1. iterate over all pairs of pairs within 1 bond of either residue connection atom.
269  /// 2. iterate over all triples on residue 1 within 2 bonds of resconn_atomno1.
270  /// 3. iterate over all triples on residue 2 within 2 bonds of resconn_atomno2.
271 
272 
273  { // Scope Section 1.
274  Size const mmat2 = resconn_mmat1;
275  Size const mmat3 = resconn_mmat2;
276 
277  utility::vector1< chemical::two_atom_set > const & rsd1_atoms_wi1_bond_of_ii(
278  rsd1_type.atoms_within_one_bond_of_a_residue_connection( resconn_id1 ));
279 
280  utility::vector1< chemical::two_atom_set > const & rsd2_atoms_wi1_bond_of_ii(
281  rsd2_type.atoms_within_one_bond_of_a_residue_connection( resconn_id2 ));
282 
283  for ( Size jj = 1; jj <= rsd1_atoms_wi1_bond_of_ii.size(); ++jj ) {
284  assert( rsd1_atoms_wi1_bond_of_ii[ jj ].key1() == resconn_atomno1 );
285  Size const jj_term_atomno = rsd1_atoms_wi1_bond_of_ii[ jj ].key2();
286  Size const mmat1 = rsd1_type.atom( jj_term_atomno ).mm_atom_type_index();
287 
288  for ( Size kk = 1; kk <= rsd2_atoms_wi1_bond_of_ii.size(); ++kk ) {
289  assert( rsd2_atoms_wi1_bond_of_ii[ kk ].key1() == resconn_atomno2 );
290  Size const kk_term_atomno = rsd2_atoms_wi1_bond_of_ii[ kk ].key2();
291  Size const mmat4 = rsd2_type.atom( kk_term_atomno ).mm_atom_type_index();
292 
293  Real const angle = numeric::dihedral_radians(
294  rsd1.xyz( jj_term_atomno ),
295  rsd1.xyz( resconn_atomno1 ),
296  rsd2.xyz( resconn_atomno2 ),
297  rsd2.xyz( kk_term_atomno ) );
298 
299  TR(basic::t_trace)
300  << "r1 " << jj_term_atomno << " " << rsd1.atom_name( jj_term_atomno ) << "("
301  << rsd1_type.atom( jj_term_atomno ).mm_name() << ") - "
302  << "r1 " << resconn_atomno1 << " " << rsd1.atom_name( resconn_atomno1 ) << "("
303  << rsd1_type.atom( resconn_atomno1 ).mm_name() << ") - "
304  << "r2 " << resconn_atomno2 << " " << rsd2.atom_name( resconn_atomno2 ) << "("
305  << rsd2_type.atom( resconn_atomno2 ).mm_name() << ") - "
306  << "r2 " << kk_term_atomno << " " << rsd2.atom_name( kk_term_atomno ) << "("
307  << rsd2_type.atom( kk_term_atomno ).mm_name() << ")" << std::endl;
308 
309  energy += potential_.core::scoring::mm::MMTorsionScore::score(
310  mm::mm_torsion_atom_quad( mmat1, mmat2, mmat3, mmat4 ), angle );
311 
312  }
313 
314  }
315  } // end Scope section 1.
316 
317  { // Scope section 2.
318  Size const mmat3 = resconn_mmat1;
319  Size const mmat4 = resconn_mmat2;
320 
321  utility::vector1< chemical::three_atom_set > const & rsd1_atoms_wi2_bonds_of_ii(
322  rsd1_type.atoms_within_two_bonds_of_a_residue_connection( resconn_id1 ));
323 
324  for ( Size jj = 1; jj <= rsd1_atoms_wi2_bonds_of_ii.size(); ++jj ) {
325  assert( rsd1_atoms_wi2_bonds_of_ii[ jj ].key1() == resconn_atomno1 );
326 
327  Size const jj_atom2 = rsd1_atoms_wi2_bonds_of_ii[ jj ].key2();
328  Size const mmat2 = rsd1_type.atom( jj_atom2 ).mm_atom_type_index();
329 
330  Size const jj_atom1 = rsd1_atoms_wi2_bonds_of_ii[ jj ].key3();
331  Size const mmat1 = rsd1_type.atom( jj_atom1 ).mm_atom_type_index();
332 
333  Real const angle = numeric::dihedral_radians(
334  rsd1.xyz( jj_atom1 ),
335  rsd1.xyz( jj_atom2 ),
336  rsd1.xyz( resconn_atomno1 ),
337  rsd2.xyz( resconn_atomno2 ) );
338 
339  energy += potential_.core::scoring::mm::MMTorsionScore::score(
340  mm::mm_torsion_atom_quad( mmat1, mmat2, mmat3, mmat4 ), angle );
341 
342 
343 
344  }
345  } // end Scope section 2.
346 
347 
348  { // Scope section 3.
349  Size const mmat1 = resconn_mmat1;
350  Size const mmat2 = resconn_mmat2;
351 
352  utility::vector1< chemical::three_atom_set > const & rsd2_atoms_wi2_bonds_of_ii(
353  rsd2_type.atoms_within_two_bonds_of_a_residue_connection( resconn_id2 ));
354 
355  for ( Size jj = 1; jj <= rsd2_atoms_wi2_bonds_of_ii.size(); ++jj ) {
356  assert( rsd2_atoms_wi2_bonds_of_ii[ jj ].key1() == resconn_atomno2 );
357 
358  Size const jj_atom3 = rsd2_atoms_wi2_bonds_of_ii[ jj ].key2();
359  Size const mmat3 = rsd2_type.atom( jj_atom3 ).mm_atom_type_index();
360 
361  Size const jj_atom4 = rsd2_atoms_wi2_bonds_of_ii[ jj ].key3();
362  Size const mmat4 = rsd2_type.atom( jj_atom4 ).mm_atom_type_index();
363 
364  Real const angle = numeric::dihedral_radians(
365  rsd1.xyz( resconn_atomno1 ),
366  rsd2.xyz( resconn_atomno2 ),
367  rsd2.xyz( jj_atom3 ),
368  rsd2.xyz( jj_atom4 ) );
369 
370  energy += potential_.core::scoring::mm::MMTorsionScore::score(
371  mm::mm_torsion_atom_quad( mmat1, mmat2, mmat3, mmat4 ), angle );
372 
373 
374 
375  }
376  } // end Scope section 3.
377  }
378 
379  emap[ mm_twist ] += energy;
380 
381 }
382 
383 void
385  conformation::Residue const & rsd,
386  pose::Pose const &,
387  ScoreFunction const &,
388  EnergyMap & emap
389 ) const
390 {
391  Real energy = 0;
392 
393  // get residue type
394  chemical::ResidueType const & rsd_type = rsd.type();
395 
396  TR(basic::t_trace) << "Intrares Processing residue " << rsd.seqpos() << " " << rsd_type.name()
397  << std::endl;
398 
399  // for each dihedral angle in the residue type
400  for ( Size dihe = 1; dihe <= rsd_type.ndihe(); ++dihe )
401  {
402  // get ResidueType ints
403  int rt1 = ( rsd_type.dihedral( dihe ) ).key1();
404  int rt2 = ( rsd_type.dihedral( dihe ) ).key2();
405  int rt3 = ( rsd_type.dihedral( dihe ) ).key3();
406  int rt4 = ( rsd_type.dihedral( dihe ) ).key4();
407 
408  // get mm atom type index
409  int mmat1 = rsd_type.atom( rt1 ).mm_atom_type_index();
410  int mmat2 = rsd_type.atom( rt2 ).mm_atom_type_index();
411  int mmat3 = rsd_type.atom( rt3 ).mm_atom_type_index();
412  int mmat4 = rsd_type.atom( rt4 ).mm_atom_type_index();
413 
414  // get angle
415  Real angle = numeric::dihedral_radians
416  ( rsd.atom( rt1 ).xyz(), rsd.atom( rt2 ).xyz(),
417  rsd.atom( rt3 ).xyz(), rsd.atom( rt4 ).xyz() );
418 
419  TR(basic::t_trace) << rt1 << " " << rsd.atom_name( rt1 ) << "(" << rsd_type.atom( rt1 ).mm_name()
420  << ") - " << rt2 << " " << rsd.atom_name( rt2 ) << "(" << rsd_type.atom( rt2 ).mm_name()
421  << ") - " << rt3 << " " << rsd.atom_name( rt3 ) << "(" << rsd_type.atom( rt3 ).mm_name()
422  << ") - " << rt4 << " " << rsd.atom_name( rt4 ) << "(" << rsd_type.atom( rt4 ).mm_name()
423  << ") angle " << angle << std::endl;
424 
425  // score dihedral
426  energy += potential_.core::scoring::mm::MMTorsionScore::score
427  ( mm::mm_torsion_atom_quad( mmat1, mmat2, mmat3, mmat4 ), angle );
428  }
429 
430  // add energy to emap
431  emap[ mm_twist ] += energy;
432 }
433 
434 void
436  id::AtomID const & id,
437  pose::Pose const & pose,
438  kinematics::DomainMap const &,
439  ScoreFunction const &,
440  EnergyMap const & weights,
441  Vector & F1,
442  Vector & F2
443 ) const
444 {
445  //TR << "Evaluating derivatives for rsd# " << id.rsd() << " atom# " << id.atomno() << std::endl;
446 
447  Vector LF1( 0.0 ); // Local F1 -- for debuggin'
448  Vector LF2( 0.0 ); // Local F2 -- for debuggin'
449 
450  //Vector f1(0.0), f2(0.0);
451  /// 1. Evaluate intraresidue torsion angle derivatives.
452  /// for torsions where this atom is scored
453  /// 2. Evaluate interresidue torsion angle derivatives.
454  /// KNOWN BUG: This does not evaluate derivatives for torsion angles
455  /// spanning three or more residues.
456  /// a. Calculate derivatives when exactly three of the atoms come from id.rsd()
457  /// b. Calculate derivatives when exactly two of the atoms come from id.rsd()
458  /// c. Calculate derivatives when exactly one of the atoms comes from id.rsd()
459 
460  core::chemical::ResidueType const & restype( pose.residue_type( id.rsd() ) );
461  core::conformation::Residue const & res( pose.residue( id.rsd() ) );
462  Size const atomno( id.atomno());
463 
464  /// 1.
465  utility::vector1< Size > const & diheds( restype.dihedrals_for_atom( id.atomno() ) );
466 
467  for ( Size ii = 1, ii_end = diheds.size(); ii <= ii_end; ++ii ) {
468  chemical::dihedral_atom_set const & ii_dihed( restype.dihedral( diheds[ ii ] ) );
469  assert( ii_dihed.key1() == atomno || ii_dihed.key2() == atomno || ii_dihed.key3() == atomno || ii_dihed.key4() == atomno );
470 
471  //TR << " 1. Deriv for angle# " << angs[ ii ] << " between " << ii_bangle.key1() << " " << ii_bangle.key2() << " " << ii_bangle.key3() << std::endl;
472 
473  Size const mmat1 = restype.atom( ii_dihed.key1()).mm_atom_type_index();
474  Size const mmat2 = restype.atom( ii_dihed.key2()).mm_atom_type_index();
475  Size const mmat3 = restype.atom( ii_dihed.key3()).mm_atom_type_index();
476  Size const mmat4 = restype.atom( ii_dihed.key4()).mm_atom_type_index();
477 
478  Vector f1(0.0), f2(0.0);
479  Real theta(0.0);
480  if ( ii_dihed.key1() == atomno ) {
481  numeric::deriv::dihedral_p1_cosine_deriv(
482  res.xyz( ii_dihed.key1() ),
483  res.xyz( ii_dihed.key2() ),
484  res.xyz( ii_dihed.key3() ),
485  res.xyz( ii_dihed.key4() ),
486  theta, f1, f2 );
487  } else if ( ii_dihed.key2() == atomno ) {
488  numeric::deriv::dihedral_p2_cosine_deriv(
489  res.xyz( ii_dihed.key1() ),
490  res.xyz( ii_dihed.key2() ),
491  res.xyz( ii_dihed.key3() ),
492  res.xyz( ii_dihed.key4() ),
493  theta, f1, f2 );
494  } else if ( ii_dihed.key3() == atomno ) {
495  numeric::deriv::dihedral_p2_cosine_deriv(
496  res.xyz( ii_dihed.key4() ),
497  res.xyz( ii_dihed.key3() ),
498  res.xyz( ii_dihed.key2() ),
499  res.xyz( ii_dihed.key1() ),
500  theta, f1, f2 );
501  } else {
502  numeric::deriv::dihedral_p1_cosine_deriv(
503  res.xyz( ii_dihed.key4() ),
504  res.xyz( ii_dihed.key3() ),
505  res.xyz( ii_dihed.key2() ),
506  res.xyz( ii_dihed.key1() ),
507  theta, f1, f2 );
508  }
509 
510  Real const dE_dtheta = weights[ mm_twist ] * potential_.core::scoring::mm::MMTorsionScore::dscore(
511  mm::mm_torsion_atom_quad( mmat1, mmat2, mmat3, mmat4 ), theta );
512  //TR << " theta " << numeric::conversions::degrees( theta ) << " dE_dtheta " << dE_dtheta << " f1: " << f1.x() << " " << f1.y() << " " << f1.z() << " f2: " << f2.x() << " " << f2.y() << " " << f2.z() << std::endl;
513 
514 
515  LF1 += dE_dtheta * f1;
516  LF2 += dE_dtheta * f2;
517 
518  }
519 
520  { // Scope 2a. Bond angles involving three atoms on this residue.
521  utility::vector1< std::pair< Size, Size > > const & interres_wi2_for_this_atom(
522  restype.within2bonds_sets_for_atom( atomno ));
523  for ( Size ii = 1; ii <= interres_wi2_for_this_atom.size(); ++ii ) {
524  Size const ii_resconn = interres_wi2_for_this_atom[ ii ].first;
525  Size const ii_whichpair = interres_wi2_for_this_atom[ ii ].second;
526 
527  chemical::three_atom_set const & ii_triple = restype.
528  atoms_within_two_bonds_of_a_residue_connection( ii_resconn )[ ii_whichpair ];
529  assert( ii_triple.key1() == atomno || ii_triple.key2() == atomno || ii_triple.key3() == atomno );
530 
531  /// Find the neighbor residue and atom
532  Size const ii_neighb = res.residue_connection_partner( ii_resconn );
533  Size const neighb_resconn = res.residue_connection_conn_id( ii_resconn );
534  conformation::Residue const & neighb_res( pose.residue( ii_neighb ));
535  chemical::ResidueType const & neighb_restype( pose.residue_type( ii_neighb ) );
536  Size const neighb_atom = neighb_restype.residue_connection( neighb_resconn ).atomno();
537 
538 
539  //TR << " 2a. Deriv for interres angle between (" << ii_neighb << "," << neighb_atom << ") " << ii_pair.key1() << " " << ii_pair.key2() << std::endl;
540 
541  Size const mmat1 = neighb_restype.atom( neighb_atom ).mm_atom_type_index();
542  Size const mmat2 = restype.atom( ii_triple.key1()).mm_atom_type_index();
543  Size const mmat3 = restype.atom( ii_triple.key2()).mm_atom_type_index();
544  Size const mmat4 = restype.atom( ii_triple.key3()).mm_atom_type_index();
545 
546 
547  Vector f1(0.0), f2(0.0);
548  Real theta(0.0);
549  if ( ii_triple.key1() == atomno ) {
550  numeric::deriv::dihedral_p2_cosine_deriv(
551  neighb_res.xyz( neighb_atom ),
552  res.xyz( ii_triple.key1() ),
553  res.xyz( ii_triple.key2() ),
554  res.xyz( ii_triple.key3() ),
555  theta, f1, f2 );
556  } else if ( ii_triple.key2() == atomno ) {
557  numeric::deriv::dihedral_p2_cosine_deriv(
558  res.xyz( ii_triple.key3() ),
559  res.xyz( ii_triple.key2() ),
560  res.xyz( ii_triple.key1() ),
561  neighb_res.xyz( neighb_atom ),
562  theta, f1, f2 );
563  } else {
564  numeric::deriv::dihedral_p1_cosine_deriv(
565  res.xyz( ii_triple.key3() ),
566  res.xyz( ii_triple.key2() ),
567  res.xyz( ii_triple.key1() ),
568  neighb_res.xyz( neighb_atom ),
569  theta, f1, f2 );
570  }
571  Real const dE_dtheta = weights[ mm_twist ] * potential_.core::scoring::mm::MMTorsionScore::dscore(
572  mm::mm_torsion_atom_quad( mmat1, mmat2, mmat3, mmat4 ), theta );
573 
574  //TR << " theta " << numeric::conversions::degrees( theta ) << " dE_dtheta " << dE_dtheta << " f1: " << f1.x() << " " << f1.y() << " " << f1.z() << " f2: " << f2.x() << " " << f2.y() << " " << f2.z() << std::endl;
575 
576  LF1 += dE_dtheta * f1;
577  LF2 += dE_dtheta * f2;
578  }
579  } // end scope 2a
580 
581  /// b. Bond angles involving two atoms on this residue.
582  /// Iterate across residue connections for this atom -- for each residue connection,
583  /// find the residue connection partner, and the list of within-1-bond atom pairs
584  /// for the atom forming the residue connection. Then iterate across this list.
585  { // Scope 2b.
586  utility::vector1< std::pair< Size, Size > > const & interres_wi1_for_this_atom(
587  restype.within1bonds_sets_for_atom( atomno ));
588  for ( Size ii = 1; ii <= interres_wi1_for_this_atom.size(); ++ii ) {
589  Size const ii_resconn = interres_wi1_for_this_atom[ ii ].first;
590  Size const ii_whichpair = interres_wi1_for_this_atom[ ii ].second;
591 
592  chemical::two_atom_set const & ii_pair = restype.
593  atoms_within_one_bond_of_a_residue_connection( ii_resconn )[ ii_whichpair ];
594  assert( ii_pair.key1() == atomno || ii_pair.key2() == atomno );
595 
596 
597  Size const mmat1 = restype.atom( ii_pair.key2()).mm_atom_type_index();
598  Size const mmat2 = restype.atom( ii_pair.key1()).mm_atom_type_index();
599 
600  /// Find the neighbor residue and connection atom
601  Size const ii_neighb = res.residue_connection_partner( ii_resconn );
602  Size const neighb_resconn = res.residue_connection_conn_id( ii_resconn );
603  conformation::Residue const & neighb_res( pose.residue( ii_neighb ));
604  chemical::ResidueType const & neighb_restype( pose.residue_type( ii_neighb ) );
605  Size const neighb_atom1 = neighb_restype.residue_connection( neighb_resconn ).atomno();
606  Size const mmat3 = neighb_restype.atom( neighb_atom1 ).mm_atom_type_index();
607 
608  utility::vector1< chemical::two_atom_set > const & neighb_atoms_wi1_bond_of_ii(
609  neighb_restype.atoms_within_one_bond_of_a_residue_connection( neighb_resconn ));
610 
611  for ( Size jj = 1; jj <= neighb_atoms_wi1_bond_of_ii.size(); ++jj ) {
612  chemical::two_atom_set neighb_pair( neighb_atoms_wi1_bond_of_ii[ jj ] );
613  assert( neighb_pair.key1() == neighb_atom1 );
614 
615  Size const mmat4 = neighb_restype.atom( neighb_pair.key2() ).mm_atom_type_index();
616 
617  Vector f1(0.0), f2(0.0);
618  Real theta(0.0);
619  if ( ii_pair.key1() == atomno ) {
620  numeric::deriv::dihedral_p2_cosine_deriv(
621  res.xyz( ii_pair.key2() ),
622  res.xyz( ii_pair.key1() ),
623  neighb_res.xyz( neighb_atom1 ),
624  neighb_res.xyz( neighb_pair.key2() ),
625  theta, f1, f2 );
626  } else {
627  numeric::deriv::dihedral_p1_cosine_deriv(
628  res.xyz( ii_pair.key2() ),
629  res.xyz( ii_pair.key1() ),
630  neighb_res.xyz( neighb_atom1 ),
631  neighb_res.xyz( neighb_pair.key2() ),
632  theta, f1, f2 );
633  }
634 
635  Real const dE_dtheta = weights[ mm_twist ] * potential_.core::scoring::mm::MMTorsionScore::dscore(
636  mm::mm_torsion_atom_quad( mmat1, mmat2, mmat3, mmat4 ), theta );
637 
638  //TR << " theta " << numeric::conversions::degrees( theta ) << " dE_dtheta " << dE_dtheta << " f1: " << f1.x() << " " << f1.y() << " " << f1.z() << " f2: " << f2.x() << " " << f2.y() << " " << f2.z() << std::endl;
639 
640  LF1 += dE_dtheta * f1;
641  LF2 += dE_dtheta * f2;
642  }
643  }
644  } /// end scope 2b.
645 
646  { // Scope 2c. All the inter-residue connections involving this atom and all within-2-bond triples
647  /// of the bonded residues.
648  utility::vector1< Size > const & connections( restype.residue_connections_for_atom( atomno ) );
649  Size const mmat1 = restype.atom( atomno ).mm_atom_type_index();
650 
651  for ( Size ii = 1; ii <= connections.size(); ++ii ) {
652  Size const ii_resconn = connections[ ii ];
653 
654  /// Find the neighbor residue and connection atom
655  Size const ii_neighb = res.residue_connection_partner( ii_resconn );
656  Size const neighb_resconn = res.residue_connection_conn_id( ii_resconn );
657  conformation::Residue const & neighb_res( pose.residue( ii_neighb ));
658  chemical::ResidueType const & neighb_restype( pose.residue_type( ii_neighb ) );
659  Size const neighb_atom1 = neighb_restype.residue_connection( neighb_resconn ).atomno();
660  Size const mmat2 = neighb_restype.atom( neighb_atom1 ).mm_atom_type_index();
661 
662  utility::vector1< chemical::three_atom_set > const & neighb_atoms_wi2(
663  neighb_restype.atoms_within_two_bonds_of_a_residue_connection( neighb_resconn ));
664 
665  for ( Size jj = 1; jj <= neighb_atoms_wi2.size(); ++jj ) {
666 
667  chemical::three_atom_set const & neighb_triple = neighb_atoms_wi2[ jj ];
668  assert( neighb_triple.key1() == neighb_atom1 );
669 
670  Size const neighb_atom2 = neighb_triple.key2();
671  Size const mmat3 = neighb_restype.atom( neighb_atom2 ).mm_atom_type_index();
672 
673  Size const neighb_atom3 = neighb_triple.key3();
674  Size const mmat4 = neighb_restype.atom( neighb_atom3 ).mm_atom_type_index();
675 
676  //TR << " 2c. Deriv for interres angle between (" << ii_neighb << "," << neighb_atom2 << ") ("<< ii_neighb << "," << neighb_atom1 << ") " << atomno << std::endl;
677 
678 
679  Vector f1(0.0), f2(0.0);
680  Real theta(0.0);
681 
682  numeric::deriv::dihedral_p1_cosine_deriv(
683  res.xyz( atomno ),
684  neighb_res.xyz( neighb_atom1 ),
685  neighb_res.xyz( neighb_atom2 ),
686  neighb_res.xyz( neighb_atom3 ),
687  theta, f1, f2 );
688 
689  Real const dE_dtheta = weights[ mm_twist ] * potential_.core::scoring::mm::MMTorsionScore::dscore(
690  mm::mm_torsion_atom_quad( mmat1, mmat2, mmat3, mmat4 ), theta );
691 
692  //TR << " theta " << numeric::conversions::degrees( theta ) << " dE_dtheta " << dE_dtheta << " f1: " << f1.x() << " " << f1.y() << " " << f1.z() << " f2: " << f2.x() << " " << f2.y() << " " << f2.z() << std::endl;
693 
694  LF1 += dE_dtheta * f1;
695  LF2 += dE_dtheta * f2;
696 
697  }
698  }
699  } // end scope 2c.
700 
701  //TR << "Finished dihedral derivatives for rsd# " << id.rsd() << " atom# " << id.atomno() << " F1: " << LF1.x() << " " << LF1.y() << " " << LF1.z() << " F2: " << LF2.x() << " " << LF2.y() << " " << LF2.z() << std::endl;
702  F1 += LF1;
703  F2 += LF2;
704 
705 
706 }
707 
708 /// @brief MMTorsionEnergy does not have an atomic interation threshold
709 Distance
711 {
712  return 0.0;
713 }
714 
715 /// @brief MMTorsionEnergy is context independent; indicates that no context graphs are required
716 void
718 {}
721 {
722  return 1; // Initial versioning
723 }
724 
725 } // namespace methods
726 } // namespace scoring
727 } // namespace core