Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
HackElecEnergy.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/methods/HackElecEnergy.cc
11 /// @brief Electrostatic energy with a distance-dependant dielectric
12 /// @author Phil Bradley
13 /// @author Andrew Leaver-Fay
14 /// modified by James Gleixner and Liz Kellogg
15 
16 
17 // Unit headers
20 
21 // Package headers
25 #include <core/scoring/Energies.hh>
35 
36 // Project headers
38 #include <core/pose/Pose.hh>
39 
47 
52 
57 
59 
60 // Utility headers
61 #include <utility/vector1.hh>
62 
63 // Numeric headers
64 #include <numeric/xyzVector.hh>
65 #include <numeric/interpolation/spline/SplineGenerator.hh>
66 #include <numeric/interpolation/spline/SimpleInterpolator.hh>
67 
68 // Basic headers
69 #include <basic/Tracer.hh>
70 
71 // option key includes
72 #include <basic/options/option.hh>
73 #include <basic/options/keys/run.OptionKeys.gen.hh>
74 #include <basic/options/keys/score.OptionKeys.gen.hh>
75 
76 static basic::Tracer TR("core.scoring.hackelec.HackElecEnergy");
77 
78 /////////////////////////////////////////////////////////////////////////////////////////
79 ///
80 /// Hacky (hence the name) implementation of distance dependant dielectric electrostatics,
81 /// with near and far distance cutoffs.
82 ///
83 
84 //
85 // alternatives: WARSHEL (from ligand.cc)
86 // E = 322.0637*q1*q2/r/e(r)
87 // if ( r < 3 ) e(r) = 16.55
88 // else e(r) = 1 + 60*(1-exp(-0.1*r))
89 // Warshel, A. Russell, S. T., Q. Rev. Biophys., 1984, 17, 283-422
90 //
91 //
92 // sigmoidal dielectric: (hingerty 1985)
93 //
94 // e(r) = D - (D-D0)/2 [ (rS)**2 + 2rS + 2]exp(-rS)
95 // with eg:
96 // D = 78, D0 = 1, S = 0.3565 (rouzina&bloomfield)
97 // D = 80, D0 = 4, S = 0.4 (rohs)
98 
99 namespace core {
100 namespace scoring {
101 namespace hackelec {
102 
103 
104 /// @details This must return a fresh instance of the HackElecEnergy class,
105 /// never an instance already in use
108  methods::EnergyMethodOptions const & options
109 ) const {
110  return new HackElecEnergy( options );
111 }
112 
115  ScoreTypes sts;
116  sts.push_back( hack_elec );
117  sts.push_back( hack_elec_bb_bb );
118  sts.push_back( hack_elec_bb_sc );
119  sts.push_back( hack_elec_sc_sc );
120  return sts;
121 }
122 
123 
124 ////////////////////////////////////////////////////////////////////////////
127  max_dis_( options.hackelec_max_dis() ),
128  min_dis_( options.hackelec_min_dis() ),
129  smooth_hack_elec_( options.smooth_hack_elec() ),
130  die_( options.hackelec_die() ),
131  no_dis_dep_die_( options.hackelec_no_dis_dep_die() ),
132  exclude_protein_protein_( options.exclude_protein_protein_hack_elec() ),
133  exclude_monomer_( options.exclude_monomer_hack_elec() ),
134  exclude_DNA_DNA_( options.exclude_DNA_DNA() )
135 {
136  initialize();
137 }
138 
139 
140 ////////////////////////////////////////////////////////////////////////////
142  parent( src ),
143  max_dis_( src.max_dis_ ),
144  min_dis_( src.min_dis_ ),
145  smooth_hack_elec_( src.smooth_hack_elec_ ),
146  die_( src.die_ ),
147  no_dis_dep_die_( src.no_dis_dep_die_ ),
148  exclude_protein_protein_( src.exclude_protein_protein_ ),
149  exclude_monomer_( src.exclude_monomer_ ),
150  exclude_DNA_DNA_( src.exclude_DNA_DNA_ )
151 {
152  initialize();
153 }
154 
155 
156 void
158  // Must have already initialized max_dis_, min_dis_, die_, and no_dis_dep_die_
159 
160  //max_dis_ = 5.5;
162  //min_dis_ = 1.5;
164 
165  // default dielectric is 10r
166  //die_ = 10.0;
167  //no_dis_dep_die_ = false;
168 
169  C0_ = 322.0637 ;
170  C1_ = C0_ / die_ ;
171  if( no_dis_dep_die_ ) {
172  C2_ = C1_ / max_dis_ ;
173  min_dis_score_ = C1_ / min_dis_ - C2_ ;
174  dEfac_ = -1.0 * C0_ / die_ ;
175  } else {
176  C2_ = C1_ / max_dis2_ ;
178  dEfac_ = -2.0 * C0_ / die_ ;
179  }
180 
181  if ( smooth_hack_elec_ ) {
182 
183 
184  low_poly_start_ = min_dis_ - 0.25;
185  low_poly_end_ = min_dis_ + 0.25;
188  low_poly_width_ = low_poly_end_ - low_poly_start_;
190 
191  // scope low polynomial
192  {
193  using namespace numeric::interpolation::spline;
194  Real low_poly_end_score(0.0), low_poly_end_deriv(0.0);
195  if ( no_dis_dep_die_ ) {
196  low_poly_end_score = C1_ / low_poly_end_ - C2_;
197  low_poly_end_deriv = -1 * C1_ / low_poly_end2_ ;
198 
199  } else {
200  low_poly_end_score = C1_ / low_poly_end2_ - C2_;
201  low_poly_end_deriv = -2 * C1_ / ( low_poly_end2_ * low_poly_end_ );
202  }
203  SplineGenerator gen_low_poly(
204  low_poly_start_, min_dis_score_, 0,
205  low_poly_end_, low_poly_end_score, low_poly_end_deriv );
206  InterpolatorOP interp_low( gen_low_poly.get_interpolator() );
207  SimpleInterpolatorOP sinterp_low = dynamic_cast< SimpleInterpolator * > (interp_low() );
208  if ( ! sinterp_low ) {
209  utility_exit_with_message( "Hack Elec created non-simple-interpolator in initialize()" );
210  }
211  low_poly_.ylo = sinterp_low->y()[ 1 ];
212  low_poly_.yhi = sinterp_low->y()[ 2 ];
213  low_poly_.y2lo = sinterp_low->ddy()[ 1 ];
214  low_poly_.y2hi = sinterp_low->ddy()[ 2 ];
215  }
216 
217  hi_poly_start_ = max_dis_ - 1.0;
221  hi_poly_width_ = hi_poly_end_ - hi_poly_start_;
223 
224  // scope hi polynomial
225  {
226  using namespace numeric::interpolation::spline;
227  Real hi_poly_start_score(0.0), hi_poly_start_deriv(0.0);
228  if ( no_dis_dep_die_ ) {
229  hi_poly_start_score = C1_ / hi_poly_start_ - C2_;
230  hi_poly_start_deriv = -1 * C1_ / hi_poly_start2_ ;
231 
232  } else {
233  hi_poly_start_score = C1_ / hi_poly_start2_ - C2_;
234  hi_poly_start_deriv = -2 * C1_ / ( hi_poly_start2_ * hi_poly_start_ );
235  }
236 
237  SplineGenerator gen_hi_poly(
238  hi_poly_start_, hi_poly_start_score, hi_poly_start_deriv,
239  hi_poly_end_, 0, 0 );
240  InterpolatorOP interp_hi( gen_hi_poly.get_interpolator() );
241  SimpleInterpolatorOP sinterp_hi = dynamic_cast< SimpleInterpolator * > (interp_hi() );
242  if ( ! sinterp_hi ) {
243  utility_exit_with_message( "Hack Elec created non-simple-interpolator in initialize()" );
244  }
245  hi_poly_.ylo = sinterp_hi->y()[ 1 ];
246  hi_poly_.yhi = sinterp_hi->y()[ 2 ];
247  hi_poly_.y2lo = sinterp_hi->ddy()[ 1 ];
248  hi_poly_.y2hi = sinterp_hi->ddy()[ 2 ];
249  }
250  } else {
252  low_poly_end_ = min_dis_ / 2; low_poly_end2_ = std::pow( low_poly_end_, 2 );
256  }
257 
258 
259  //low_fade_start_ = min_dis_;
260  //low_fade_start2_ = low_fade_start_ * low_fade_start_;
261  //low_fade_end_ = min_dis_ + 0.75;
262  //low_fade_end2_ = low_fade_end_ * low_fade_end_;
263  //low_fade_d0_ = min_dis_ + 0.25;
264  //low_fade_K_ = 16;
265  //high_fade_start_ = max_dis_ - 1.0;
266  //high_fade_start2_ = high_fade_start_ * high_fade_start_;
267  //high_fade_end_ = max_dis_;
268  //high_fade_end2_ = high_fade_end_ * high_fade_end_;
269  //high_fade_K_ = -12;
270  //high_fade_d0_ = max_dis_ - 0.25;
271 
272 }
273 
274 
275 /// clone
278 {
279  return new HackElecEnergy( *this );
280 }
281 
282 void
284  pose::Pose & pose,
285  ScoreFunction const & sfxn,
286  kinematics::MinimizerMapBase const & min_map
287 ) const
288 {
289  using namespace basic::options;
290  using namespace basic::options::OptionKeys;
291 
292  set_nres_mono(pose);
293 
294  if ( pose.energies().use_nblist() ) {
295  // stash our nblist inside the pose's energies object
296  Energies & energies( pose.energies() );
297 
298  // setup the atom-atom nblist
299  NeighborListOP nblist;
300  Real const tolerated_motion = pose.energies().use_nblist_auto_update() ? option[ run::nblist_autoupdate_narrow ] : 1.5;
301  Real const XX = max_dis_ + 2 * tolerated_motion;
302  nblist = new NeighborList( min_map.domain_map(), XX*XX, XX*XX, XX*XX);
303  if ( pose.energies().use_nblist_auto_update() ) {
304  nblist->set_auto_update( tolerated_motion );
305  }
306  // this partially becomes the EtableEnergy classes's responsibility
307  nblist->setup( pose, sfxn, *this);
308  energies.set_nblist( EnergiesCacheableDataType::HACKELEC_NBLIST, nblist );
309  }
310 }
311 
312 
313 ///
314 void
316 {
317  set_nres_mono(pose);
318  wbb_bb_ = sfxn.weights()[ hack_elec ] + sfxn.weights()[ hack_elec_bb_bb ];
319  wbb_sc_ = sfxn.weights()[ hack_elec ] + sfxn.weights()[ hack_elec_bb_sc ];
320  wsc_sc_ = sfxn.weights()[ hack_elec ] + sfxn.weights()[ hack_elec_sc_sc ];
322 }
323 
324 ///
325 void
327 {
328  set_nres_mono(pose);
330  if ( pose.energies().use_nblist() ) {
332  nblist.prepare_for_scoring( pose, scfxn, *this );
333  }
334 }
335 
336 
337 // The HackElectEnergy method stores a vector of rotamer trie objects in the Energies
338 // object for use in rapid rotamer/background energy calculations. Overrides default
339 // do-nothing behavior.
340 void
342  pose::Pose & pose,
343  utility::vector1< bool > const &,
345 ) const
346 {
347  using namespace trie;
348 
349  set_nres_mono(pose);
350 
351  TrieCollectionOP tries = new TrieCollection;
352  tries->total_residue( pose.total_residue() );
353  for ( Size ii = 1; ii <= pose.total_residue(); ++ii ) {
354  // Do not compute energy for virtual residues.
355  if ( pose.residue(ii).aa() == core::chemical::aa_vrt) continue;
356 
357  RotamerTrieBaseOP one_rotamer_trie = create_rotamer_trie( pose.residue( ii ), pose );
358  tries->trie( ii, one_rotamer_trie );
359  }
361 
362 }
363 
364 // @brief Creates a rotamer trie for the input set of rotamers and stores the trie
365 // in the rotamer set.
366 void
368  pose::Pose const & pose,
370 ) const
371 {
372 
373  trie::RotamerTrieBaseOP rottrie = create_rotamer_trie( set, pose );
374  set.store_trie( methods::hackelec_method, rottrie );
375 }
376 
377 
378 // @brief Updates the cached rotamer trie for a residue if it has changed during the course of
379 // a repacking
380 void
382  pose::Pose & pose,
383  Size resid
384 ) const
385 {
386  using namespace trie;
387  trie::RotamerTrieBaseOP one_rotamer_trie = create_rotamer_trie( pose.residue( resid ), pose );
388 
389  // grab non-const & of the cached tries and replace resid's trie with a new one.
390  TrieCollection & trie_collection
391  ( static_cast< TrieCollection & > (pose.energies().data().get( EnergiesCacheableDataType::HACKELEC_TRIE_COLLECTION )));
392  trie_collection.trie( resid, one_rotamer_trie );
393 
394 }
395 
396 /////////////////////////////////////////////////////////////////////////////
397 // scoring
398 /////////////////////////////////////////////////////////////////////////////
399 
400 ///
401 void
403  conformation::Residue const & rsd1,
404  conformation::Residue const & rsd2,
405  pose::Pose const & pose,
406  ScoreFunction const &,
407  EnergyMap & emap
408 ) const
409 {
410  if ( pose.energies().use_nblist() ) return;
411 
412  using namespace etable::count_pair;
413 
414  Real score(0.0);
415 
416  Real const attached_h_max_dis2 = hydrogen_interaction_cutoff2();
417 
418  if ( ! defines_score_for_residue_pair(rsd1, rsd2, true) ) return;
419 
420  if ( rsd1.is_bonded( rsd2 ) || rsd1.is_pseudo_bonded( rsd2 ) ) {
421  // assuming only a single bond right now -- generalizing to arbitrary topologies
422  // also assuming crossover of 4, should be closest (?) to classic rosetta
423  CountPairFunctionOP cpfxn =
424  CountPairFactory::create_count_pair_function( rsd1, rsd2, CP_CROSSOVER_4 );
425  /*
426  for ( Size i=1, i_end = rsd1.natoms(); i<= i_end; ++i ) {
427  Vector const & i_xyz( rsd1.xyz(i) );
428  Real const i_charge( rsd1.atomic_charge(i) );
429  if ( i_charge == 0.0 ) continue;
430  for ( Size j=1, j_end = rsd2.natoms(); j<= j_end; ++j ) {
431  Real const j_charge( rsd2.atomic_charge(j) );
432  if ( j_charge == 0.0 ) continue;
433  Real weight(1.0);
434  if ( cpfxn->count( i, j, weight ) ) {
435  Real energy = weight *
436  eval_atom_atom_hack_elecE( i_xyz, i_charge, rsd2.xyz(j), j_charge);
437  score += energy;
438 
439  if (rsd1.atom_is_backbone(i) && rsd2.atom_is_backbone(j)){
440  emap[hack_elec_bb_bb]+=energy;
441  }else if (!rsd1.atom_is_backbone(i) && ! rsd2.atom_is_backbone(j)){
442  emap[hack_elec_sc_sc]+=energy;
443  } else {
444  emap[hack_elec_bb_sc]+=energy;
445  }
446  }
447  }
448  }*/
449  Real d2;
450  for ( Size ii = 1; ii <= rsd1.nheavyatoms(); ++ii ) {
451  for ( Size jj = 1; jj <= rsd2.nheavyatoms(); ++jj ) {
452 
453  Real weight = 1.0;
454  Size path_dist( 0 );
455  if ( cpfxn->count( ii, jj, weight, path_dist )) {
456  score += score_atom_pair( rsd1, rsd2, ii, jj, emap, weight, d2 );
457  } else {
458  d2 = rsd1.xyz(ii).distance_squared( rsd2.xyz(jj) );
459  }
460 
461  if ( d2 > attached_h_max_dis2 ) continue;
462 
463  Size ii_hatbegin( rsd1.attached_H_begin()[ ii ] ), ii_hatend( rsd1.attached_H_end()[ ii ] );
464  Size jj_hatbegin( rsd2.attached_H_begin()[ jj ] ), jj_hatend( rsd2.attached_H_end()[ jj ] );
465  for ( Size kk = ii_hatbegin; kk <= ii_hatend; ++kk ) {
466  weight = 1.0;
467  path_dist = 0;
468  if ( cpfxn->count( kk, jj, weight, path_dist )) score += score_atom_pair( rsd1, rsd2, kk, jj, emap, weight, d2 );
469  }
470  for ( Size kk = jj_hatbegin; kk <= jj_hatend; ++kk ) {
471  weight = 1.0;
472  path_dist = 0;
473  if ( cpfxn->count( ii, kk, weight, path_dist )) score += score_atom_pair( rsd1, rsd2, ii, kk, emap, weight, d2 );
474  }
475  for ( Size kk = ii_hatbegin; kk <= ii_hatend; ++kk ) {
476  for ( Size ll = jj_hatbegin; ll <= jj_hatend; ++ll ) {
477  weight = 1.0;
478  path_dist = 0;
479  if ( cpfxn->count( kk, ll, weight, path_dist )) score += score_atom_pair( rsd1, rsd2, kk, ll, emap, weight, d2 );
480  }
481  }
482  }
483  }
484 
485 
486  } else {
487  // no countpair!
488  /*
489  for ( Size i=1, i_end = rsd1.natoms(); i<= i_end; ++i ) {
490  Vector const & i_xyz( rsd1.xyz(i) );
491  Real const i_charge( rsd1.atomic_charge(i) );
492  if ( i_charge == 0.0 ) continue;
493  for ( Size j=1, j_end = rsd2.natoms(); j<= j_end; ++j ) {
494  Real const j_charge( rsd2.atomic_charge(j) );
495  if ( j_charge == 0.0 ) continue;
496 
497  float energy = eval_atom_atom_hack_elecE( i_xyz, i_charge, rsd2.xyz(j), j_charge);
498  score += energy;
499  if (rsd1.atom_is_backbone(i) && rsd2.atom_is_backbone(j)){
500  emap[hack_elec_bb_bb]+=energy;
501  }else if (!rsd1.atom_is_backbone(i) && ! rsd2.atom_is_backbone(j)){
502  emap[hack_elec_sc_sc]+=energy;
503  } else {
504  emap[hack_elec_bb_sc]+=energy;
505  }
506 
507  // score += eval_atom_atom_hack_elecE( i_xyz, i_charge, rsd2.xyz(j), j_charge );
508  }
509  }*/
510  Real d2;
511  for ( Size ii = 1; ii <= rsd1.nheavyatoms(); ++ii ) {
512  for ( Size jj = 1; jj <= rsd2.nheavyatoms(); ++jj ) {
513 
514  Real weight = 1.0;
515  score += score_atom_pair( rsd1, rsd2, ii, jj, emap, weight, d2 );
516 
517  if ( d2 > attached_h_max_dis2 ) continue;
518 
519  Size ii_hatbegin( rsd1.attached_H_begin()[ ii ] ), ii_hatend( rsd1.attached_H_end()[ ii ] );
520  Size jj_hatbegin( rsd2.attached_H_begin()[ jj ] ), jj_hatend( rsd2.attached_H_end()[ jj ] );
521  for ( Size kk = ii_hatbegin; kk <= ii_hatend; ++kk ) {
522  score += score_atom_pair( rsd1, rsd2, kk, jj, emap, weight, d2 );
523  }
524  for ( Size kk = jj_hatbegin; kk <= jj_hatend; ++kk ) {
525  score += score_atom_pair( rsd1, rsd2, ii, kk, emap, weight, d2 );
526  }
527  for ( Size kk = ii_hatbegin; kk <= ii_hatend; ++kk ) {
528  for ( Size ll = jj_hatbegin; ll <= jj_hatend; ++ll ) {
529  score += score_atom_pair( rsd1, rsd2, kk, ll, emap, weight, d2 );
530  }
531  }
532  }
533  }
534 
535 
536  }
537  emap[ hack_elec ] += score;
538  //std::cout << rsd1.seqpos() << ' ' << rsd2.seqpos() << ' ' << score << std::endl;
539 }
540 
541 bool
543 {
544  return pose.energies().use_nblist_auto_update();
545 }
546 
547 
548 
549 bool
551  conformation::Residue const & rsd1,
552  conformation::Residue const & rsd2,
553  bool res_moving_wrt_eachother
554 ) const
555 {
556  if ( rsd1.seqpos() == rsd2.seqpos() ) {
557  return false;
558  } else if ( exclude_protein_protein_ && rsd1.is_protein() && rsd2.is_protein() ) {
559  return false;
560  } else if ( exclude_monomer_ && monomer_test( rsd1.seqpos(), rsd2.seqpos()) ) {
561  return false;
562  } else if ( exclude_DNA_DNA_ && rsd1.is_DNA() && rsd2.is_DNA() ) {
563  return false;
564  }
565 
566  return res_moving_wrt_eachother;
567 }
568 
569 
570 bool
572 {
573  return true;
574 }
575 
576 
577 void
579  conformation::Residue const & rsd1,
580  conformation::Residue const & rsd2,
581  ResPairMinimizationData const & min_data,
582  pose::Pose const &,
583  ScoreFunction const &,
584  EnergyMap & emap
585 ) const
586 {
587  assert( rsd1.seqpos() < rsd2.seqpos() );
588  assert( dynamic_cast< ResiduePairNeighborList const * > (min_data.get_data( hackelec_pair_nblist )() ));
589  ResiduePairNeighborList const & nblist( static_cast< ResiduePairNeighborList const & > ( min_data.get_data_ref( hackelec_pair_nblist ) ) );
590  Real dsq, score( 0.0 );
591  utility::vector1< SmallAtNb > const & neighbs( nblist.atom_neighbors() );
592  for ( Size ii = 1, iiend = neighbs.size(); ii <= iiend; ++ii ) {
593  score += score_atom_pair( rsd1, rsd2, neighbs[ ii ].atomno1(), neighbs[ ii ].atomno2(), emap, neighbs[ ii ].weight(), dsq );
594  }
595  emap[ hack_elec ] += score;
596 }
597 
598 void
600  conformation::Residue const & rsd1,
601  conformation::Residue const & rsd2,
602  pose::Pose const &,
603  ScoreFunction const &,
607  ResPairMinimizationData & pair_data
608 ) const
609 {
610  using namespace basic::options;
611  using namespace basic::options::OptionKeys;
613  assert( rsd1.seqpos() < rsd2.seqpos() );
614 
615  // update the existing nblist if it's already present in the min_data object
616  ResiduePairNeighborListOP nblist( static_cast< ResiduePairNeighborList * > (pair_data.get_data( hackelec_pair_nblist )() ));
617  if ( ! nblist ) nblist = new ResiduePairNeighborList;
618 
619  /// STOLEN CODE!
620  Real const tolerated_narrow_nblist_motion = 0.75; //option[ run::nblist_autoupdate_narrow ];
621  Real const XX2 = std::pow( max_dis_ + 2*tolerated_narrow_nblist_motion, 2 );
622 
623  nblist->initialize_from_residues( XX2, XX2, XX2, rsd1, rsd2, count_pair );
624 
625  pair_data.set_data( hackelec_pair_nblist, nblist );
626 }
627 
628 
629 void
631  conformation::Residue const & rsd1,
632  conformation::Residue const & rsd2,
635  ResPairMinimizationData const & min_data,
636  pose::Pose const &, // provides context
637  EnergyMap const & weights,
638  utility::vector1< DerivVectorPair > & r1_atom_derivs,
639  utility::vector1< DerivVectorPair > & r2_atom_derivs
640 ) const
641 {
642  assert( rsd1.seqpos() < rsd2.seqpos() );
643  assert( dynamic_cast< ResiduePairNeighborList const * > (min_data.get_data( hackelec_pair_nblist )() ));
644  ResiduePairNeighborList const & nblist( static_cast< ResiduePairNeighborList const & > ( min_data.get_data_ref( hackelec_pair_nblist ) ) );
645 
646  utility::vector1< SmallAtNb > const & neighbs( nblist.atom_neighbors() );
647 
648  weight_triple wtrip;
649  setup_weight_triple( weights, wtrip );
650  for ( Size ii = 1, iiend = neighbs.size(); ii <= iiend; ++ii ) {
651  Vector const & atom1xyz( rsd1.xyz( neighbs[ ii ].atomno1() ) );
652  Vector const & atom2xyz( rsd2.xyz( neighbs[ ii ].atomno2() ) );
653 
654  Real const at1_charge( rsd1.atomic_charge( neighbs[ ii ].atomno1() ) );
655  Real const at2_charge( rsd2.atomic_charge( neighbs[ ii ].atomno2() ) );
656 
657  Vector f2 = ( atom1xyz - atom2xyz );
658  Real const dis2( f2.length_squared() );
659  Real const dE_dr_over_r = neighbs[ ii ].weight() * eval_dhack_elecE_dr_over_r( dis2, at1_charge, at2_charge );
660  if ( dE_dr_over_r != 0.0 ) {
661  Real sfxn_weight = hackelec_weight(
662  rsd1.atom_is_backbone( neighbs[ ii ].atomno1() ),
663  rsd2.atom_is_backbone( neighbs[ ii ].atomno2() ),
664  wtrip );
665  Vector f1 = atom1xyz.cross( atom2xyz );
666  f1 *= dE_dr_over_r * sfxn_weight;
667  f2 *= dE_dr_over_r * sfxn_weight;
668  r1_atom_derivs[ neighbs[ ii ].atomno1() ].f1() += f1;
669  r1_atom_derivs[ neighbs[ ii ].atomno1() ].f2() += f2;
670  r2_atom_derivs[ neighbs[ ii ].atomno2() ].f1() -= f1;
671  r2_atom_derivs[ neighbs[ ii ].atomno2() ].f2() -= f2;
672  }
673  }
674 
675 }
676 
677 
678 void
680  conformation::Residue const & rsd1,
681  conformation::Residue const & rsd2,
682  pose::Pose const & ,
683  ScoreFunction const & ,
684  EnergyMap & emap
685 ) const
686 {
687  using namespace etable::count_pair;
688  using namespace chemical;
689 
690  Real score(0.0);
691 
692  if ( ! defines_score_for_residue_pair(rsd1, rsd2, true) ) return;
693 
694  if ( rsd1.is_bonded( rsd2 ) || rsd1.is_pseudo_bonded( rsd2 ) ) {
695  // assuming only a single bond right now -- generalizing to arbitrary topologies
696  // also assuming crossover of 4, should be closest (?) to classic rosetta
697  CountPairFunctionOP cpfxn =
698  CountPairFactory::create_count_pair_function( rsd1, rsd2, CP_CROSSOVER_4 );
699 
700  AtomIndices const & rsd1_bb_atoms( rsd1.type().all_bb_atoms() );
701  AtomIndices const & rsd2_bb_atoms( rsd2.type().all_bb_atoms() );
702 
703  for ( Size ii=1, ii_end = rsd1_bb_atoms.size(); ii<= ii_end; ++ii ) {
704  Size const i = rsd1_bb_atoms[ ii ];
705  Vector const & i_xyz( rsd1.xyz(i) );
706  Real const i_charge( rsd1.atomic_charge(i) );
707  if ( i_charge == 0.0 ) continue;
708  for ( Size jj=1, jj_end = rsd2_bb_atoms.size(); jj<= jj_end; ++jj ) {
709  Size const j = rsd2_bb_atoms[ jj ];
710  Real const j_charge( rsd2.atomic_charge(j) );
711  if ( j_charge == 0.0 ) continue;
712  Real weight(1.0);
713  Size path_dist( 0 );
714  if ( cpfxn->count( i, j, weight, path_dist ) ) {
715  score += weight *
716  eval_atom_atom_hack_elecE( i_xyz, i_charge, rsd2.xyz(j), j_charge);
717  }
718  }
719  }
720 
721  } else {
722  // no countpair!
723  AtomIndices const & rsd1_bb_atoms( rsd1.type().all_bb_atoms() );
724  AtomIndices const & rsd2_bb_atoms( rsd2.type().all_bb_atoms() );
725  for ( Size ii=1, ii_end = rsd1_bb_atoms.size(); ii<= ii_end; ++ii ) {
726  Size const i = rsd1_bb_atoms[ ii ];
727  Vector const & i_xyz( rsd1.xyz(i) );
728  Real const i_charge( rsd1.atomic_charge(i) );
729  if ( i_charge == 0.0 ) continue;
730  for ( Size jj=1, jj_end = rsd2_bb_atoms.size(); jj<= jj_end; ++jj ) {
731  Size const j = rsd2_bb_atoms[ jj ];
732  Real const j_charge( rsd2.atomic_charge(j) );
733  if ( j_charge == 0.0 ) continue;
734  score += eval_atom_atom_hack_elecE( i_xyz, i_charge, rsd2.xyz(j), j_charge );
735  }
736  }
737  }
738  emap[ hack_elec_bb_bb ] += score;
739  emap[ hack_elec ] += score;
740  //std::cout << rsd1.seqpos() << ' ' << rsd2.seqpos() << ' ' << score << std::endl;
741 }
742 
743 void
745  conformation::Residue const & rsd1,
746  conformation::Residue const & rsd2,
747  pose::Pose const & ,
748  ScoreFunction const & ,
749  EnergyMap & emap
750 ) const
751 {
752  using namespace etable::count_pair;
753  using namespace chemical;
754 
755  Real score(0.0);
756 
757  if ( ! defines_score_for_residue_pair(rsd1, rsd2, true) ) return;
758 
759  if ( rsd1.is_bonded( rsd2 ) || rsd1.is_pseudo_bonded( rsd2 ) ) {
760  // assuming only a single bond right now -- generalizing to arbitrary topologies
761  // also assuming crossover of 4, should be closest (?) to classic rosetta
762  CountPairFunctionOP cpfxn =
763  CountPairFactory::create_count_pair_function( rsd1, rsd2, CP_CROSSOVER_4 );
764 
765  AtomIndices const & rsd1_bb_atoms( rsd1.type().all_bb_atoms() );
766  AtomIndices const & rsd2_sc_atoms( rsd2.type().all_sc_atoms() );
767 
768  for ( Size ii=1, ii_end = rsd1_bb_atoms.size(); ii<= ii_end; ++ii ) {
769  Size const i = rsd1_bb_atoms[ ii ];
770  Vector const & i_xyz( rsd1.xyz(i) );
771  Real const i_charge( rsd1.atomic_charge(i) );
772  if ( i_charge == 0.0 ) continue;
773  for ( Size jj=1, jj_end = rsd2_sc_atoms.size(); jj<= jj_end; ++jj ) {
774  Size const j = rsd2_sc_atoms[ jj ];
775  Real const j_charge( rsd2.atomic_charge(j) );
776  if ( j_charge == 0.0 ) continue;
777  Real weight(1.0);
778  Size path_dist( 0 );
779  if ( cpfxn->count( i, j, weight, path_dist ) ) {
780  score += weight *
781  eval_atom_atom_hack_elecE( i_xyz, i_charge, rsd2.xyz(j), j_charge);
782  }
783  }
784  }
785 
786  } else {
787  // no countpair!
788  AtomIndices const & rsd1_bb_atoms( rsd1.type().all_bb_atoms() );
789  AtomIndices const & rsd2_sc_atoms( rsd2.type().all_sc_atoms() );
790  for ( Size ii=1, ii_end = rsd1_bb_atoms.size(); ii<= ii_end; ++ii ) {
791  Size const i = rsd1_bb_atoms[ ii ];
792  Vector const & i_xyz( rsd1.xyz(i) );
793  Real const i_charge( rsd1.atomic_charge(i) );
794  if ( i_charge == 0.0 ) continue;
795  for ( Size jj=1, jj_end = rsd2_sc_atoms.size(); jj<= jj_end; ++jj ) {
796  Size const j = rsd2_sc_atoms[ jj ];
797  Real const j_charge( rsd2.atomic_charge(j) );
798  if ( j_charge == 0.0 ) continue;
799  score += eval_atom_atom_hack_elecE( i_xyz, i_charge, rsd2.xyz(j), j_charge );
800  }
801  }
802  }
803  emap[ hack_elec_bb_sc ] += score;
804  emap[ hack_elec ] += score;
805  //std::cout << rsd1.seqpos() << ' ' << rsd2.seqpos() << ' ' << score << std::endl;
806 
807 }
808 
809 
810 void
812  conformation::Residue const & rsd1,
813  conformation::Residue const & rsd2,
814  pose::Pose const & ,
815  ScoreFunction const & ,
816  EnergyMap & emap
817 ) const
818 {
819  using namespace etable::count_pair;
820  using namespace chemical;
821 
822  Real score(0.0);
823 
824  if ( ! defines_score_for_residue_pair(rsd1, rsd2, true) ) return;
825 
826  if ( rsd1.is_bonded( rsd2 ) || rsd1.is_pseudo_bonded( rsd2 ) ) {
827  // assuming only a single bond right now -- generalizing to arbitrary topologies
828  // also assuming crossover of 4, should be closest (?) to classic rosetta
829  CountPairFunctionOP cpfxn =
830  CountPairFactory::create_count_pair_function( rsd1, rsd2, CP_CROSSOVER_4 );
831 
832  AtomIndices const & rsd1_sc_atoms( rsd1.type().all_sc_atoms() );
833  AtomIndices const & rsd2_sc_atoms( rsd2.type().all_sc_atoms() );
834 
835  for ( Size ii=1, ii_end = rsd1_sc_atoms.size(); ii<= ii_end; ++ii ) {
836  Size const i = rsd1_sc_atoms[ ii ];
837  Vector const & i_xyz( rsd1.xyz(i) );
838  Real const i_charge( rsd1.atomic_charge(i) );
839  if ( i_charge == 0.0 ) continue;
840  for ( Size jj=1, jj_end = rsd2_sc_atoms.size(); jj<= jj_end; ++jj ) {
841  Size const j = rsd2_sc_atoms[ jj ];
842  Real const j_charge( rsd2.atomic_charge(j) );
843  if ( j_charge == 0.0 ) continue;
844  Real weight(1.0);
845  Size path_dist( 0 );
846  if ( cpfxn->count( i, j, weight, path_dist ) ) {
847  score += weight *
848  eval_atom_atom_hack_elecE( i_xyz, i_charge, rsd2.xyz(j), j_charge);
849  }
850  }
851  }
852 
853  } else {
854  // no countpair!
855  AtomIndices const & rsd1_sc_atoms( rsd1.type().all_sc_atoms() );
856  AtomIndices const & rsd2_sc_atoms( rsd2.type().all_sc_atoms() );
857  for ( Size ii=1, ii_end = rsd1_sc_atoms.size(); ii<= ii_end; ++ii ) {
858  Size const i = rsd1_sc_atoms[ ii ];
859  Vector const & i_xyz( rsd1.xyz(i) );
860  Real const i_charge( rsd1.atomic_charge(i) );
861  if ( i_charge == 0.0 ) continue;
862  for ( Size jj=1, jj_end = rsd2_sc_atoms.size(); jj<= jj_end; ++jj ) {
863  Size const j = rsd2_sc_atoms[ jj ];
864  Real const j_charge( rsd2.atomic_charge(j) );
865  if ( j_charge == 0.0 ) continue;
866  score += eval_atom_atom_hack_elecE( i_xyz, i_charge, rsd2.xyz(j), j_charge );
867  }
868  }
869  }
870  emap[ hack_elec_sc_sc ] += score;
871  emap[ hack_elec ] += score;
872  //std::cout << rsd1.seqpos() << ' ' << rsd2.seqpos() << ' ' << score << std::endl;
873 
874 }
875 
876 void
878  pose::Pose & pose,
879  ScoreFunction const &,
880  EnergyMap & totals
881 ) const
882 {
883  if ( ! pose.energies().use_nblist() || ! pose.energies().use_nblist_auto_update() ) return;
884 
885  EnergyMap tbenergy_map;
886  // add in contributions from the nblist atom-pairs
887  NeighborList const & nblist
889 
890  nblist.check_domain_map( pose.energies().domain_map() );
892  resvect.reserve( pose.total_residue() );
893  for ( Size ii = 1; ii <= pose.total_residue(); ++ii ) {
894  resvect.push_back( & pose.residue( ii ) );
895  }
896 
897  for ( Size i=1, i_end = pose.total_residue(); i<= i_end; ++i ) {
898  conformation::Residue const & ires( *resvect[i] );
899  for ( Size ii=1, ii_end=ires.natoms(); ii<= ii_end; ++ii ) {
900  AtomNeighbors const & nbrs( nblist.upper_atom_neighbors(i,ii) );
901  Real const ii_charge = ires.atomic_charge( ii );
902  for ( AtomNeighbors::const_iterator nbr_iter=nbrs.begin(),
903  nbr_end=nbrs.end(); nbr_iter!= nbr_end; ++nbr_iter ) {
904  AtomNeighbor const & nbr( *nbr_iter );
905  Size const j( nbr.rsd() );
906  Size const jj( nbr.atomno() );
907  // could reorder the nbr lists so that we dont need this check:
908  //if ( ( j < i ) || ( j == i && jj <= ii ) ) continue;
909  conformation::Residue const & jres( *resvect[j] );
910 
911  Real d2 = ires.xyz( ii ).distance_squared( jres.xyz( jj ) );
912  nbr.temp1() = nbr.weight() * ii_charge * jres.atomic_charge( jj ) * ( C1_ / ( d2 + 1e-300 ) - C2_ );
913  nbr.temp2() = d2 < max_dis2_ ? 1.0 : 0.0;
914  nbr.temp3() = d2 > min_dis2_ ? 1.0 : 0.0;
915  nbr.temp4() = nbr.weight() * ii_charge * jres.atomic_charge(jj) * min_dis_score_;
916  }
917  }
918  }
919 
920  Real bb_sc_scores[ 3 ] = {0.0, 0.0, 0.0};
921  Real total_score( 0.0 );
922  for ( Size i=1, i_end = pose.total_residue(); i<= i_end; ++i ) {
923  conformation::Residue const & ires( *resvect[i] );
924  for ( Size ii=1, ii_end=ires.natoms(); ii<= ii_end; ++ii ) {
925  AtomNeighbors const & nbrs( nblist.upper_atom_neighbors(i,ii) );
926  int ii_isbb = ires.atom_is_backbone( ii );
927  for ( AtomNeighbors::const_iterator nbr_iter=nbrs.begin(),
928  nbr_end=nbrs.end(); nbr_iter!= nbr_end; ++nbr_iter ) {
929  AtomNeighbor const & nbr( *nbr_iter );
930 
931  Size const j( nbr.rsd() );
932  Size const jj( nbr.atomno() );
933  // could reorder the nbr lists so that we dont need this check:
934  //if ( ( j < i ) || ( j == i && jj <= ii ) ) continue;
935 
936  conformation::Residue const & jres( *resvect[j] );
937  int jj_isbb = jres.atom_is_backbone( jj );
938 
939  Real score = nbr.temp1() * nbr.temp2() * nbr.temp3() + nbr.temp4() * ( 1.0 - nbr.temp3());
940  assert( ii_isbb + jj_isbb >= 0 && ii_isbb + jj_isbb < 3 );
941 
942  assert( std::abs( nbr.weight() *
943  eval_atom_atom_hack_elecE( ires.xyz(ii), ires.atomic_charge(ii), jres.xyz(jj), jres.atomic_charge(jj) )
944  - score ) < 1e-15 );
945  //{
946  // std::cerr << "score discrepancy: " << ires.xyz(ii).distance( jres.xyz(jj) ) << " " << nbr.weight() * eval_atom_atom_hack_elecE( ires.xyz(ii), ires.atomic_charge(ii), jres.xyz(jj), jres.atomic_charge(jj) ) << " " << nbr.temp1() << " " << nbr.temp2() << " " << nbr.temp3() << " " << 1-nbr.temp3() << " " << nbr.temp4() << std::endl;
947  //}
948 
949  bb_sc_scores[ ii_isbb + jj_isbb ] += score;
950  total_score += score;
951  }
952  }
953  }
954  totals[ hack_elec ] += total_score;
955  totals[ hack_elec_bb_bb ] += bb_sc_scores[ 2 ];
956  totals[ hack_elec_bb_sc ] += bb_sc_scores[ 1 ];
957  totals[ hack_elec_sc_sc ] += bb_sc_scores[ 0 ];
958 }
959 
960 void
962  conformation::RotamerSetBase const & set1,
963  conformation::RotamerSetBase const & set2,
964  pose::Pose const & pose,
965  ScoreFunction const & sfxn,
966  EnergyMap const & /*weights*/,
967  ObjexxFCL::FArray2D< core::PackerEnergy > & energy_table
968 ) const
969 {
970  assert( set1.resid() != set2.resid() );
971 
972  // Since a rotamer set may include multiple residue types,
973  // we'll make our decision based on what's currently in the Pose.
974  if ( ! defines_score_for_residue_pair(pose.residue(set1.resid()), pose.residue(set2.resid()), true) ) return;
975 
976  using namespace methods;
977  using namespace trie;
978  ObjexxFCL::FArray2D< core::PackerEnergy > temp_table1( energy_table );
979  ObjexxFCL::FArray2D< core::PackerEnergy > temp_table2( energy_table );
980 
981  temp_table1 = 0; temp_table2 = 0;
982 
983  // save weight information so that its available during tvt execution
984  wbb_bb_ = sfxn.weights()[ hack_elec ] + sfxn.weights()[ hack_elec_bb_bb ];
985  wbb_sc_ = sfxn.weights()[ hack_elec ] + sfxn.weights()[ hack_elec_bb_sc ];
986  wsc_sc_ = sfxn.weights()[ hack_elec ] + sfxn.weights()[ hack_elec_sc_sc ];
987 
988  /// this will later retrieve a stored rotamer trie from inside the set;
989  //EtableRotamerTrieBaseOP trie1 = create_rotamer_trie( set1, pose );
990  //EtableRotamerTrieBaseOP trie2 = create_rotamer_trie( set2, pose );
991 
992  RotamerTrieBaseCOP trie1( static_cast< trie::RotamerTrieBase const * > ( set1.get_trie( hackelec_method )() ));
993  RotamerTrieBaseCOP trie2( static_cast< trie::RotamerTrieBase const * > ( set2.get_trie( hackelec_method )() ));
994 
995  // figure out which trie countPairFunction needs to be used for this set
996  TrieCountPairBaseOP cp = get_count_pair_function_trie( set1, set2, pose, sfxn );
997 
998  /// now execute the trie vs trie algorithm.
999  /// this steps through three rounds of type resolution before finally arriving at the
1000  /// actual trie_vs_trie method. The type resolution calls allow the trie-vs-trie algorithm
1001  /// to be templated with full type knowledge (and therefore be optimized by the compiler for
1002  /// each variation on the count pair data used and the count pair funtions invoked.
1003  trie1->trie_vs_trie( *trie2, *cp, *this, temp_table1, temp_table2 );
1004 
1005  /// add in the energies calculated by the tvt alg.
1006  energy_table += temp_table1;
1007  //std::cout << "FINISHED evaluate_rotamer_pair_energies" << std::endl;
1008 
1009  /*
1010  // There should be a way to turn this on without recompiling...
1011  // debug
1012  ObjexxFCL::FArray2D< core::PackerEnergy > temp_table3( energy_table );
1013  temp_table3 = 0;
1014  EnergyMap emap;
1015  for ( Size ii = 1, ii_end = set1.num_rotamers(); ii <= ii_end; ++ii ) {
1016  for ( Size jj = 1, jj_end = set2.num_rotamers(); jj <= jj_end; ++jj ) {
1017  emap.zero();
1018  residue_pair_energy( *set1.rotamer( ii ), *set2.rotamer( jj ), pose, sfxn, emap );
1019  temp_table3( jj, ii ) += weights.dot( emap );
1020  if ( std::abs( temp_table1( jj, ii ) - temp_table3( jj, ii )) > 0.001 ) {
1021  std::cout << "HackElecE: Residues " << set1.resid() << " & " << set2.resid() << " rotamers: " << ii << " & " << jj;
1022  std::cout << " tvt/reg discrepancy: tvt= " << temp_table1( jj, ii ) << " reg= " << temp_table3( jj, ii );
1023  std::cout << " delta: " << temp_table1( jj, ii ) - temp_table3( jj, ii ) << std::endl;
1024  }
1025  }
1026  }
1027  std::cout << "Finished RPE calcs for residues " << set1.resid() << " & " << set2.resid() << std::endl;
1028  */
1029 
1030 
1031 }
1032 
1033 void
1035  conformation::RotamerSetBase const & set,
1036  conformation::Residue const & residue,
1037  pose::Pose const & pose,
1038  ScoreFunction const & sfxn,
1039  EnergyMap const & /*weights*/,
1041 ) const
1042 {
1043  //iwd Temporary hack: for ligands, call base class implementation
1044  //if ( !residue.is_polymer() ) {
1045  // ShortRangeTwoBodyEnergy::evaluate_rotamer_background_energies(set, residue, pose, sfxn, weights, energy_vector);
1046  // return;
1047  //}
1048 
1049  // Since a rotamer set may include multiple residue types,
1050  // we'll make our decision based on what's currently in the Pose.
1051  if ( ! defines_score_for_residue_pair( pose.residue(set.resid()), residue, true) ) return;
1052 
1053  using namespace methods;
1054  using namespace trie;
1055 
1056  // allocate space for the trie-vs-trie algorithm
1057  utility::vector1< core::PackerEnergy > temp_vector1( set.num_rotamers(), 0.0 );
1058  utility::vector1< core::PackerEnergy > temp_vector2( set.num_rotamers(), 0.0 );
1059 
1060  // save weight information so that its available during tvt execution
1061  wbb_bb_ = sfxn.weights()[ hack_elec ] + sfxn.weights()[ hack_elec_bb_bb ];
1062  wbb_sc_ = sfxn.weights()[ hack_elec ] + sfxn.weights()[ hack_elec_bb_sc ];
1063  wsc_sc_ = sfxn.weights()[ hack_elec ] + sfxn.weights()[ hack_elec_sc_sc ];
1064 
1065  RotamerTrieBaseCOP trie1( static_cast< trie::RotamerTrieBase const * > ( set.get_trie( hackelec_method )() ));
1066  RotamerTrieBaseCOP trie2 = ( static_cast< TrieCollection const & >
1067  ( pose.energies().data().get( EnergiesCacheableDataType::HACKELEC_TRIE_COLLECTION )) ).trie( residue.seqpos() );
1068 
1069  // figure out which trie countPairFunction needs to be used for this set
1070  TrieCountPairBaseOP cp = get_count_pair_function_trie( pose.residue( set.resid() ), residue, trie1, trie2, pose, sfxn );
1071 
1072  /// now execute the trie vs trie algorithm.
1073  /// this steps through three rounds of type resolution before finally arriving at the
1074  /// actual trie_vs_trie method. The type resolution calls allow the trie-vs-trie algorithm
1075  /// to be templated with full type knowledge (and therefore be optimized by the compiler for
1076  /// each variation on the count pair data used and the count pair funtions invoked.
1077  trie1->trie_vs_path( *trie2, *cp, *this, temp_vector1, temp_vector2 );
1078 
1079  /// add in the energies calculated by the tvt alg.
1080  for ( Size ii = 1; ii <= set.num_rotamers(); ++ii ) {
1081  energy_vector[ ii ] += temp_vector1[ ii ];
1082  }
1083  //std::cout << "FINISHED evaluate_rotamer_background_energies" << std::endl;
1084 
1085  /*
1086  //debug
1087  utility::vector1< Energy > temp_vector3( energy_vector.size(), 0.0f );
1088  EnergyMap emap;
1089  for ( Size ii = 1, ii_end = set.num_rotamers(); ii <= ii_end; ++ii ) {
1090  emap.zero();
1091  residue_pair_energy( *set.rotamer( ii ), residue, pose, sfxn, emap );
1092  temp_vector3[ ii ] += weights.dot( emap );
1093  if ( std::abs( temp_vector1[ ii ] - temp_vector3[ ii ]) > 0.001 ) {
1094  std::cout << "HackElecE: Residues " << set.resid() << " & " << residue.seqpos() << " rotamers: " << ii << " & bg";
1095  std::cout << " tvt/reg discrepancy: tvt= " << temp_vector1[ ii ] << " reg= " << temp_vector3[ ii ];
1096  std::cout << " delta: " << temp_vector1[ ii ] - temp_vector3[ ii ] << std::endl;
1097  }
1098  }
1099  //std::cout << "Finished Rotamer BG calcs for residues " << set.resid() << " & " << residue.seqpos() << std::endl;
1100  */
1101 
1102 }
1103 
1104 
1105 /// @brief HackElecEnergy distance cutoff
1106  ///
1107  /// Reports the maximum heavy atom/heavy atom distance at which two residues have a non-zero hack_elec interaction energy.
1108 Distance
1110 {
1111  return hydrogen_interaction_cutoff();
1112 }
1113 
1116  conformation::Residue const &,
1117  pose::Pose const &,
1118  ScoreFunction const &
1119 ) const
1120 {
1121  utility_exit_with_message( "HackElecEnergy does not define intra-residue pair energies; do not call get_intrares_countpair()" );
1122  return 0;
1123 }
1124 
1127  Size const res1,
1128  Size const res2,
1129  pose::Pose const & pose,
1130  ScoreFunction const &
1131 ) const
1132 {
1133  using namespace etable::count_pair;
1134  if ( res1 == res2 ) {
1135  return new CountPairNone;
1136  }
1137 
1138  conformation::Residue const & rsd1( pose.residue( res1 ) );
1139  conformation::Residue const & rsd2( pose.residue( res2 ) );
1140  return get_count_pair_function( rsd1, rsd2 );
1141 }
1142 
1143 
1146  conformation::Residue const & rsd1,
1147  conformation::Residue const & rsd2
1148 ) const
1149 {
1150  using namespace etable::count_pair;
1151 
1152  if ( ! defines_score_for_residue_pair(rsd1, rsd2, true) ) return new CountPairNone;
1153 
1154  if ( rsd1.is_RNA() && rsd2.is_RNA() ) {
1155  /// IMPLEMENT THIS!
1156  } else if ( rsd1.is_bonded( rsd2 ) || rsd1.is_pseudo_bonded( rsd2 ) ) {
1157  return CountPairFactory::create_count_pair_function( rsd1, rsd2, CP_CROSSOVER_4 );
1158  }
1159  return new CountPairAll;
1160 
1161 }
1162 
1163 
1164 /// @brief HackElecEnergy
1165 void
1167 {
1168 }
1169 
1170 
1171 void
1173  EnergyMap const & weights,
1174  weight_triple & wttrip
1175 ) const
1176 {
1177  wttrip.wbb_bb_ = weights[ hack_elec ] + weights[ hack_elec_bb_bb ];
1178  wttrip.wbb_sc_ = weights[ hack_elec ] + weights[ hack_elec_bb_sc ];
1179  wttrip.wsc_sc_ = weights[ hack_elec ] + weights[ hack_elec_sc_sc ];
1180 }
1181 
1182 /// @brief create a rotamer trie for a particular set, deciding upon the kind of count pair data that
1183 /// needs to be contained by the trie.
1184 ///
1187  conformation::RotamerSetBase const & rotset,
1188  pose::Pose const & // will be need to create tries for disulfides
1189 ) const
1190 {
1191  using namespace trie;
1192  using namespace etable::etrie;
1193 
1194  CPDataCorrespondence cpdata_map( create_cpdata_correspondence_for_rotamerset( rotset ) );
1195  if ( cpdata_map.has_pseudobonds() ||
1196  cpdata_map.max_connpoints_for_residue() > 1 ||
1197  cpdata_map.n_entries() > 3 ) {
1198  ElecAtom at; CountPairDataGeneric cpdat;
1199  return create_trie( rotset, at, cpdat, cpdata_map, atomic_interaction_cutoff() );
1200  } else if ( cpdata_map.n_entries() == 1 || cpdata_map.n_entries() == 0 /* HACK! */ ) {
1201  ElecAtom at; CountPairData_1_1 cpdat;
1202  return create_trie( rotset, at, cpdat, cpdata_map, hydrogen_interaction_cutoff() );
1203  } else if ( cpdata_map.n_entries() == 2 ) {
1204  ElecAtom at; CountPairData_1_2 cpdat;
1205  return create_trie( rotset, at, cpdat, cpdata_map, hydrogen_interaction_cutoff() );
1206  } else if ( cpdata_map.n_entries() == 3 ) {
1207  ElecAtom at; CountPairData_1_3 cpdat;
1208  return create_trie( rotset, at, cpdat, cpdata_map, hydrogen_interaction_cutoff() );
1209  } else {
1210  std::cerr << "Unsupported number of residue connections in trie construction." << std::endl;
1211  utility_exit();
1212  return 0;
1213  }
1214 }
1215 
1216 ///@details Create a one-residue rotamer trie
1219  conformation::Residue const & res,
1220  pose::Pose const & // will be need to create tries for disulfides
1221 ) const
1222 {
1223  using namespace trie;
1224  using namespace etable::etrie;
1225 
1226  CPDataCorrespondence cpdata_map( create_cpdata_correspondence_for_rotamer( res ) );
1227  if ( cpdata_map.has_pseudobonds() ||
1228  cpdata_map.max_connpoints_for_residue() > 1 ||
1229  cpdata_map.n_entries() > 3 ) {
1230  ElecAtom at; CountPairDataGeneric cpdat;
1231  return create_trie( res, at, cpdat, cpdata_map, atomic_interaction_cutoff() );
1232  } else if ( cpdata_map.n_entries() == 1 || cpdata_map.n_entries() == 0 /* HACK! */ ) {
1233  ElecAtom at; CountPairData_1_1 cpdat;
1234  return create_trie( res, at, cpdat, cpdata_map, hydrogen_interaction_cutoff() );
1235  } else if ( cpdata_map.n_entries() == 2 ) {
1236  ElecAtom at; CountPairData_1_2 cpdat;
1237  return create_trie( res, at, cpdat, cpdata_map, hydrogen_interaction_cutoff() );
1238  } else if ( cpdata_map.n_entries() == 3 ) {
1239  ElecAtom at; CountPairData_1_3 cpdat;
1240  return create_trie( res, at, cpdat, cpdata_map, hydrogen_interaction_cutoff() );
1241  } else {
1242  std::cerr << "Unsupported number of residue connections in trie construction." << std::endl;
1243  utility_exit();
1244  return 0;
1245  }
1246 }
1247 
1248 /// @brief figure out the trie count pair function to use
1249 /// Need to refactor this so that the decision "what kind of count pair behavior should I use" can be decoupled
1250 /// from class instantiation, and therefore shared between the creation of the trie count pair classes and the regular
1251 /// count pair classes
1254  conformation::RotamerSetBase const & set1,
1255  conformation::RotamerSetBase const & set2,
1256  pose::Pose const & pose,
1257  ScoreFunction const & sfxn
1258 ) const
1259 {
1260  conformation::Residue const & res1( pose.residue( set1.resid() ) );
1261  conformation::Residue const & res2( pose.residue( set2.resid() ) );
1262 
1263  trie::RotamerTrieBaseCOP trie1( static_cast< trie::RotamerTrieBase const * > ( set1.get_trie( methods::hackelec_method )() ));
1264  trie::RotamerTrieBaseCOP trie2( static_cast< trie::RotamerTrieBase const * > ( set2.get_trie( methods::hackelec_method )() ));
1265 
1266  return get_count_pair_function_trie( res1, res2, trie1, trie2, pose, sfxn );
1267 }
1268 
1269 
1272  conformation::Residue const & res1,
1273  conformation::Residue const & res2,
1276  pose::Pose const &,
1277  ScoreFunction const &
1278 ) const
1279 {
1280  using namespace etable::count_pair;
1281  using namespace trie;
1282  using namespace etable::etrie;
1283 
1284  TrieCountPairBaseOP tcpfxn;
1285  if ( ! defines_score_for_residue_pair(res1, res2, true) ) return new TrieCountPairNone();
1286 
1287  /// code needs to be added here to deal with multiple bonds (and psuedubonds!) between residues,
1288  /// but ultimately, this code is incompatible with designing both disulfides and non-disulfies
1289  /// at the same residue...
1290  CPResidueConnectionType connection = CountPairFactory::determine_residue_connection( res1, res2 );
1291  Size conn1 = trie1->get_count_pair_data_for_residue( res2.seqpos() );
1292  Size conn2 = trie2->get_count_pair_data_for_residue( res1.seqpos() );
1293 
1294  if ( connection == CP_ONE_BOND ) {
1295  tcpfxn = new TrieCountPair1BC4( conn1, conn2 );
1296  } else if ( connection == CP_NO_BONDS) {
1297  tcpfxn = new TrieCountPairAll;
1298  } else {
1299  tcpfxn = new TrieCountPairGeneric( res1, res2, conn1, conn2 );
1300  }
1301  return tcpfxn;
1302 
1303 }
1304 
1305 
1306 inline
1307 Real
1309  conformation::Residue const & rsd1,
1310  conformation::Residue const & rsd2,
1311  Size const at1,
1312  Size const at2,
1313  EnergyMap & emap,
1314  Real const cpweight,
1315  Real & d2
1316 ) const
1317 {
1318  Real energy = cpweight * eval_atom_atom_hack_elecE(
1319  rsd1.xyz(at1), rsd1.atomic_charge(at1),
1320  rsd2.xyz(at2), rsd2.atomic_charge(at2), d2);
1321 
1322  if (rsd1.atom_is_backbone(at1) && rsd2.atom_is_backbone(at2)){
1323  emap[ hack_elec_bb_bb ] += energy;
1324  }else if (!rsd1.atom_is_backbone(at1) && ! rsd2.atom_is_backbone(at2)){
1325  emap[ hack_elec_sc_sc ] += energy;
1326  } else {
1327  emap[ hack_elec_bb_sc ] += energy;
1328  }
1329  /* TR << "Residue " << rsd1.seqpos() << " atom " << rsd1.atom_name(at1) << " to Residue " << rsd2.seqpos() << " atom " << rsd2.atom_name(at2)
1330  << " q1 " << rsd1.atomic_charge(at1) << " q2 " << rsd2.atomic_charge(at2)
1331  << " dist " << rsd1.xyz(at1).distance( rsd2.xyz(at2) ) << " energy " << energy << " cpwt " << cpweight << " d2 " << d2 << std::endl;
1332  */
1333  return energy;
1334 }
1335 
1336 
1337 core::Size
1339 {
1340  return 1; // Initial versioning
1341 }
1342 
1343 
1344 void
1346  core::pose::Pose const & pose
1347 ) const {
1348  for(Size i = 1; i <= pose.n_residue(); ++i) {
1349  if(pose.residue(i).is_upper_terminus()) {
1350  nres_monomer_ = i;
1351  //std::cerr << "nres_monomer_ " << i << std::endl;
1352  return;
1353  }
1354  }
1355 }
1356 
1357 
1358 bool
1360  Size irsd,
1361  Size jrsd
1362 ) const {
1363  return (irsd <= nres_monomer_ && jrsd <= nres_monomer_ ) ||
1364  (irsd > nres_monomer_ && jrsd > nres_monomer_ );
1365 
1366 }
1367 
1368 
1369 } // namespace hackelec
1370 } // namespace scoring
1371 } // namespace core