Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
LK_BallEnergy.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 // This file is made available under the Rosetta Commons license.
5 // See http://www.rosettacommons.org/license
6 // (C) 199x-2007 University of Washington
7 // (C) 199x-2007 University of California Santa Cruz
8 // (C) 199x-2007 University of California San Francisco
9 // (C) 199x-2007 Johns Hopkins University
10 // (C) 199x-2007 University of North Carolina, Chapel Hill
11 // (C) 199x-2007 Vanderbilt University
12 
13 /// @file core/scoring/methods/LK_BallEnergy.hh
14 /// @brief LK Solvation using hemisphere culling class declaration
15 /// @author David Baker
16 /// @author Andrew Leaver-Fay
19 
20 
21 // Unit headers
25 
26 // Package headers
38 
39 // Project headers
40 #include <core/pose/Pose.hh>
41 //#include <core/pack/rotamer_set/RotamerSet.hh>
42 //#include <core/pack/rotamer_set/WaterPackingInfo.hh>
48 #include <ObjexxFCL/format.hh>
49 #include <ObjexxFCL/FArray2D.hh>
52 // #include <core/io/pdb/pose_io.hh> // HACK
53 // #include <fstream> // HACK
54 
56 
57 //#include <core/options/util.hh> // HACK
58 
59 #include <basic/prof.hh>
60 #include <basic/datacache/BasicDataCache.hh>
61 #include <basic/Tracer.hh>
62 
63 #include <numeric/constants.hh>
64 #include <numeric/xyz.functions.hh>
65 
66 #include <utility/vector1.functions.hh> // HACK
67 
68 #ifdef WIN32
70 #endif
71 
72 /// LAZY using
73 //using core::pack::rotamer_set::RotamerSet;
74 
75 namespace core {
76 namespace scoring {
77 namespace methods {
78 
79 
80 /// @details This must return a fresh instance of the LK_hack class,
81 /// never an instance already in use
84  methods::EnergyMethodOptions const & options
85 ) const {
86  return new LK_BallEnergy( options );
87 }
88 
91  ScoreTypes sts;
92  sts.push_back( lk_ball_iso );
93  sts.push_back( lk_ball );
94  return sts;
95 }
96 
97 
98 
99 static basic::Tracer TR("core.scoring.methods.LK_BallEnergy");
100 
102 
103 
104 /// inline retrieval functions here:
105 inline
106 LKB_RotamerSetInfo const &
108  return static_cast< LKB_RotamerSetInfo const & >
110 }
111 
112 inline
113 LKB_ResidueInfo const &
114 retrieve_residue_info( pose::Pose const & pose, Size const seqpos ) {
115  assert( seqpos && seqpos <= ( static_cast< LKB_PoseInfo const & >
117  return ( static_cast< LKB_PoseInfo const & >
118  ( pose.data().get( pose::datacache::CacheableDataType::LK_BALL_POSE_INFO ) )[ seqpos ] );
119 }
120 
121 inline
124  assert( seqpos && seqpos <= ( static_cast< LKB_PoseInfo const & >
126  return ( static_cast< LKB_PoseInfo & >
127  ( pose.data().get( pose::datacache::CacheableDataType::LK_BALL_POSE_INFO ) )[ seqpos ] );
128 }
129 
130 
131 /// HACKING //////////////////////////
132 // void
133 // LK_BallEnergy::setup_hack()
134 // {
135 // using namespace options;
136 // using namespace OptionKeys::dna::specificity::lk_ball_hack;
137 // if ( option[ lk_ball_positions ].user() ) {
138 // positions_ = option[ lk_ball_positions ]();
139 // }
140 // include_all_dna_ = false; // wait on this until we can do some dna relaxes and estimate reference energies
141 // }
142 
143 // bool
144 // LK_BallEnergy::include_residue( conformation::Residue const & rsd ) const {
145 // return ( ( include_all_dna_ && rsd.is_DNA() ) ||
146 // ( utility::has_element( positions_, rsd.seqpos() ) ) );
147 // }
148 
149 // void
150 // LK_BallEnergy::add_my_score_types()
151 // {
152 // add_score_type( lk_ball_iso );
153 // add_score_type( lk_ball );
154 // add_score_type( lk_polar );
155 // add_score_type( lk_polar_nw );
156 // add_score_type( lk_nonpolar );
157 // add_score_type( lk_charged );
158 
159 // add_score_type( lk_ball_xd );
160 // add_score_type( lk_polar_xd );
161 // add_score_type( lk_polar_nw_xd );
162 // add_score_type( lk_nonpolar_xd );
163 
164 
165 // add_score_type( lk_ball_dd );
166 // add_score_type( lk_polar_dd );
167 // add_score_type( lk_polar_nw_dd );
168 // add_score_type( lk_nonpolar_dd );
169 // }
170 
173  etable_ ( *ScoringManager::get_instance()->etable( options.etable_type() ) ),
174  solv1_ ( ScoringManager::get_instance()->etable( options.etable_type() )->solv1()),
175  solv2_ ( ScoringManager::get_instance()->etable( options.etable_type() )->solv2()),
176  dsolv1_ ( ScoringManager::get_instance()->etable( options.etable_type() )->dsolv1()),
177  safe_max_dis2_ ( ScoringManager::get_instance()->etable( options.etable_type() )->get_safe_max_dis2() ),
178  etable_bins_per_A2_( ScoringManager::get_instance()->etable( options.etable_type() )->get_bins_per_A2() ),
179  use_intra_dna_cp_crossover_4_( true )
180 {
181  setup_d2_bounds();
182 }
183 
184 // LK_BallEnergy::LK_BallEnergy( etable::Etable const & etable_in):
185 // etable_(etable_in),
186 // solv1_(etable_in.solv1()),
187 // solv2_(etable_in.solv2()),
188 // dsolv1_( etable_in.dsolv1() ),
189 // safe_max_dis2_( etable_in.get_safe_max_dis2() ),
190 // etable_bins_per_A2_( etable_in.get_bins_per_A2())
191 // // d2_low_ ( 2.0 * 2.0 ),
192 // // d2_high_( 3.1 * 3.1 )
193 // {
194 // //setup_hack();
195 // add_my_score_types();
196 
197 // setup_d2_bounds();
198 // // add_score_type( lk_ball_iso );
199 // // add_score_type( lk_ball_iso_nw );
200 // }
201 
202 
203 Distance
205 {
206  return etable_.max_dis();
207 }
208 
209 
210 /// clone
213 {
214  return new LK_BallEnergy( *this );
215 }
216 
217 
220  etable_(src.etable_),
221  solv1_( src.solv1_ ),
222  solv2_( src.solv2_ ),
223  dsolv1_( src.dsolv1_ ),
224  safe_max_dis2_( src.safe_max_dis2_ ),
225  etable_bins_per_A2_( src.etable_bins_per_A2_ ),
226  use_intra_dna_cp_crossover_4_( src.use_intra_dna_cp_crossover_4_ )
227 {
228  setup_d2_bounds();
229 }
230 
231 
232 ///
233 void
235  pose::Pose & pose
236  )
237 {
238  //std::cout << "LK_BallEnergy.cc: " << __LINE__ << std::endl;
239 // using namespace core::pack::rotamer_set; // WaterPackingInfo
240  LKB_PoseInfoOP info( new LKB_PoseInfo() );
241  for ( Size i=1; i<= pose.total_residue(); ++i ) info->append( new LKB_ResidueInfo( pose, pose.residue(i) ) );
243  //std::cout << "LK_BallEnergy.cc: " << __LINE__ << std::endl;
244 }
245 
246 
247 
248 ///
249 void
251 {
252  //std::cout << "LK_BallEnergy.cc: " << __LINE__ << std::endl;
254  compute_and_store_pose_waters( pose ); // could check task and do only some
255  //std::cout << "LK_BallEnergy.cc: " << __LINE__ << std::endl;
256 }
257 
258 void
260  pose::Pose & pose,
261  Size resid
262 ) const
263 {
264  /// update waters for residue that has changed during packing, eg in rotamer trials
265  /// need to double-check the current logic on this...
266  retrieve_nonconst_residue_info( pose, resid ).build_waters( pose.residue( resid ) );
267 }
268 
269 ///
270 void
272  pose::Pose & pose,
273  ScoreFunction const & //scfxn
274 ) const
275 {
276  //std::cout << "LK_BallEnergy.cc: " << __LINE__ << std::endl;
279  //std::cout << "LK_BallEnergy.cc: " << __LINE__ << std::endl;
280 }
281 
282 void
284  pose::Pose const & pose,
285  conformation::RotamerSetBase & rotamer_set
286 ) const
287 {
288 // using namespace pack::rotamer_set;
289  //TR.Trace << "prepare_rotamers_for_packing: " << rotamer_set.num_rotamers() << std::endl;
290 
291  /// create a rotamer set info object
293 
294  for ( Size n=1; n<= rotamer_set.num_rotamers(); ++n ) {
295  info->append( new LKB_ResidueInfo( pose, *( rotamer_set.rotamer( n ) ) ) );
296  }
297 
299 
300 }
301 
302 
303 /////////////////////////////////////////////////////////////////////////////
304 // scoring
305 /////////////////////////////////////////////////////////////////////////////
306 
307 void
309 {
310  Real const h2o_radius( 1.4 );
311  chemical::AtomTypeSet const & atom_set( *etable_.atom_set() );
312  d2_low_.resize( atom_set.n_atomtypes() );
313  for ( Size i=1; i<= atom_set.n_atomtypes(); ++i ) {
314  chemical::AtomType const & atype( atom_set[ i ] );
315  Real const d2_high( numeric::square( h2o_radius + atype.lj_radius() ) ); // was 3.0 * 3.0
316  d2_low_[ i ] = std::max( 0.0, d2_high - ramp_width_A2_ ); // was 2.1 * 2.1
317  TR.Trace << "d2_low_high: " << atype.name() << ' ' <<
318  std::sqrt( d2_low_[i] ) << ' ' << std::sqrt( d2_high ) << std::endl;
319  }
320 
321  /// which atomtypes are "charged"? Narg, Nlys, OOC (for splitting into a separate score)
322 
323  atom_type_is_charged_.resize( atom_set.n_atomtypes() );
324  for ( Size i=1; i<= atom_set.n_atomtypes(); ++i ) {
325  std::string const & name( atom_set[ i ].name() );
326  assert( Size( atom_set.atom_type_index( name ) ) == i ); // sanity
327  if ( name == "Narg" || name == "Nlys" || name == "OOC" ) atom_type_is_charged_[ i ] = true;
328  else atom_type_is_charged_[ i ] = false;
329  TR.Trace << "atom_type_is_charged_: " << name << ' ' << atom_type_is_charged_[i] << std::endl;
330  }
331 
332  lk_ball_prefactor_.clear();
333  lk_ball_prefactor_.resize( atom_set.n_atomtypes(), 1.0 );
334 
335 // if ( options::option[ options::OptionKeys::dna::specificity::lk_ball_prefactor ].user() ) {
336 // utility::vector1< std::string > const lkbp_string
337 // ( options::option[ options::OptionKeys::dna::specificity::lk_ball_prefactor ] );
338 // if ( lkbp_string.size()%2 != 0 ) utility_exit_with_message("lk_ball_prefactor should have even length");
339 // for ( Size ii=0; ii< lkbp_string.size()/2; ++ii ) {
340 // std::string const atom_type_name( lkbp_string[ 2*ii+1 ] );
341 // Real const prefactor( float_of( lkbp_string[ 2*ii+2 ] ) );
342 // lk_ball_prefactor_[ atom_set.atom_type_index( atom_type_name ) ] = prefactor;
343 // TR.Trace << "lk_ball_prefactor: " << atom_type_name << ' ' << prefactor << std::endl;
344 // }
345 // }
346 }
347 
348 
349 /// @details Stolen from LK_SigmoidalFunc in lk_hack
350 /// d2_delta = d2 - d2_low
351 ///
352 Real
353 LK_BallEnergy::eval_lk_fraction( Real const d2_delta ) const
354 {
355  assert( d2_delta >= -0.001 && d2_delta <= ramp_width_A2_ + 0.001 );
356  static Real const inv_range( 1.0 / ramp_width_A2_ );
357  Real const xprime( inv_range * d2_delta );
358  return ( 1 - xprime*xprime ) * ( 1 - xprime*xprime );
359 }
360 
361 Real
363 {
364  assert( d2_delta >= -0.001 && d2_delta <= ramp_width_A2_ + 0.001 );
365  static Real const inv_range( 1.0 / ramp_width_A2_ );
366  Real const xprime( inv_range * d2_delta );
367  return -8.0 * inv_range * ( 1 - xprime * xprime ) * xprime;
368 
369  //Real const xprime_squared( numeric::square( inv_range * ( d2 - d2_low_ ) ) );
370  //return -8.0 * ( 1 - xprime_squared ) * xprime_squared;
371 
372 }
373 
374 /// @note closest_water may be set to 0 upon return if none of the waters are within ramp_width_A2_
375 Real
377  Vector const & atom2_xyz,
378  Size const atom2_type,
379  Vectors const & atom1_waters,
380  Size & closest_water,
381  Real & closest_water_d2_delta
382  ) const
383 {
384  //Real max_frac( 0.0 ), frac, d2;
385  Real const d2_low( d2_low_[ atom2_type ] );
386 
387  // find the closest water:
388  closest_water = 0;
389  closest_water_d2_delta = 100.0;
390  Real d2_delta;
391  for ( Vectors::const_iterator water= atom1_waters.begin(), water_end= atom1_waters.end();
392  water != water_end; ++water ) {
393  d2_delta = atom2_xyz.distance_squared( *water ) - d2_low;
394  if ( d2_delta > ramp_width_A2_ ) continue; // frac is 0.0
395  else if ( d2_delta < closest_water_d2_delta ) {
396  closest_water_d2_delta = d2_delta;
397  closest_water = water - atom1_waters.begin() + 1; // hack...
398  if ( d2_delta < 0.0 ) break; // no point -- frac is already 1.0 at this point
399  }
400  }
401 
402  /// now compute the fraction
403  Real frac( 0.0 );
404  if ( closest_water ) {
405  frac = ( closest_water_d2_delta < 0.0 ? Real( 1.0 ) : eval_lk_fraction( closest_water_d2_delta ) );
406  }
407  return frac;
408 }
409 
410 //// helper
411 Real
413  Vector const & atom2_xyz,
414  Size const atom2_type,
415  Vector const & atom1_water
416  ) const
417 {
418  //Real max_frac( 0.0 ), frac, d2;
419  Real const d2_low( d2_low_[ atom2_type ] );
420 
421  // find the closest water:
422  Real const d2_delta = atom2_xyz.distance_squared( atom1_water ) - d2_low;
423  if ( d2_delta > ramp_width_A2_ ) return 0.0;
424  else if ( d2_delta < 0.0 ) return 1.0;
425  else return eval_lk_fraction( d2_delta );
426 }
427 
428 
429 Real
431  Vector const & atom2_xyz,
432  Size const atom2_type,
433  Vectors const & atom1_waters
434  ) const
435 {
436  Size closest_water(0);
437  Real closest_water_d2_delta(0.0);
438  return get_lk_fractional_contribution( atom2_xyz, atom2_type, atom1_waters, closest_water, closest_water_d2_delta );
439 }
440 
441 
442 
443 /// This guy is used during scoring
444 void
446  conformation::Residue const & rsd1,
447  conformation::Residue const & rsd2,
448  pose::Pose const & pose,
449  ScoreFunction const &,
450  EnergyMap & emap
451 ) const
452 {
453  LKB_ResidueInfo const & info1( retrieve_residue_info( pose, rsd1.seqpos() ) );
454  LKB_ResidueInfo const & info2( retrieve_residue_info( pose, rsd2.seqpos() ) );
455  residue_pair_energy( rsd1, info1, rsd2, info2, emap );
456  //residue_pair_energy( rsd1, info1.waters(), rsd2, info2.waters(), emap );
457 }
458 
459 
460 /// helper function for outsiders
461 Real
463  Size const atom1,
464  conformation::Residue const & rsd1,
465  conformation::Residue const & rsd2
466  )
467 {
468  using namespace etable::count_pair;
469  CountPairFunctionOP cpfxn =
470  CountPairFactory::create_count_pair_function( rsd1, rsd2, CP_CROSSOVER_4 );
471 
472  // setup residue information
473  Vector const & atom1_xyz( rsd1.xyz( atom1 ) );
474  Size const atom1_type_index( rsd1.atom( atom1 ).type() );
475 
476  Real total_desolvation( 0.0 );
477  for ( Size atom2=1; atom2<= rsd2.nheavyatoms(); ++atom2 ) {
478  Vector const & atom2_xyz( rsd2.xyz( atom2 ) );
479 
480  Real cp_weight = 1.0;
481  Size pathdist;
482  if ( cpfxn->count( atom1, atom2, cp_weight, pathdist ) ) {
483  Real const d2( atom1_xyz.distance_squared( atom2_xyz ) );
484 
485  if ( ( d2 >= safe_max_dis2_) || ( d2 == Real(0.0) ) ) continue;
486 
487  // setup for solvation Etable lookups
488  Size const atom2_type_index( rsd2.atom( atom2 ).type() );
489  Real const d2_bin = d2 * etable_bins_per_A2_;
490  int disbin = static_cast< int >( d2_bin ) + 1;
491  Real frac = d2_bin - ( disbin - 1 );
492  int const l1 = solv1_.index( disbin, atom2_type_index, atom1_type_index );
493 
494  Real const lk_desolvation_of_atom1_by_atom2
495  ( cp_weight * ( ( 1. - frac ) * solv1_[ l1 ] + frac * solv1_[ l1+1 ] ) );
496 
497  total_desolvation += lk_desolvation_of_atom1_by_atom2;
498  }
499  }
500  return total_desolvation;
501 }
502 
503 /// get the lk-ball desolvation of atom1 by atom2, and the unoriented lk desolvation of atom1 by atom2
504 
505 void
507  Size const atom1,
508  conformation::Residue const & rsd1,
509  Vectors const & atom1_waters,
510  Size const atom2,
511  conformation::Residue const & rsd2,
512  Real & lk_desolvation_of_atom1_by_atom2,
513  Real & lk_ball_desolvation_of_atom1_by_atom2 // includes lk-fraction
514  ) const
515 {
516  using namespace etable::count_pair;
517 
518  // initialize values
519  lk_desolvation_of_atom1_by_atom2 = 0.0;
520  lk_ball_desolvation_of_atom1_by_atom2 = 0.0;
521 
522  CountPairFunctionOP cpfxn =
523  CountPairFactory::create_count_pair_function( rsd1, rsd2, CP_CROSSOVER_4 );
524 
525  Real cp_weight = 1.0; Size pathdist;
526  if ( !cpfxn->count( atom1, atom2, cp_weight, pathdist ) ) return; /// NO COUNTPAIR
527 
528  Vector const & atom1_xyz( rsd1.xyz( atom1 ) );
529  Vector const & atom2_xyz( rsd2.xyz( atom2 ) );
530 
531  Real const d2( atom1_xyz.distance_squared( atom2_xyz ) );
532 
533  if ( ( d2 >= safe_max_dis2_) || ( d2 == Real(0.0) ) ) return; // TOO FARAWAY (OR SAME ATOM?)
534 
535  // setup for solvation Etable lookups
536  Size const atom1_type_index( rsd1.atom( atom1 ).type() );
537  Size const atom2_type_index( rsd2.atom( atom2 ).type() );
538 
539  Real const d2_bin = d2 * etable_bins_per_A2_;
540  int disbin = static_cast< int >( d2_bin ) + 1;
541  Real frac = d2_bin - ( disbin - 1 );
542  int const l1 = solv1_.index( disbin, atom2_type_index, atom1_type_index );
543 
544  lk_desolvation_of_atom1_by_atom2 = ( cp_weight * ( ( 1. - frac ) * solv1_[ l1 ] + frac * solv1_[ l1+1 ] ) );
545 
546  Real dummy_real;
547  Size dummy_size;
548  lk_ball_desolvation_of_atom1_by_atom2 = lk_desolvation_of_atom1_by_atom2 *
549  get_lk_fractional_contribution( atom2_xyz, atom2_type_index, atom1_waters, dummy_size, dummy_real );
550 }
551 
552 
553 
554 Real
556  Size const atom1,
557  conformation::Residue const & rsd1,
558  conformation::Residue const & rsd2
559  )
560 {
561  //using namespace etable::count_pair;
562 
563  // setup residue information
564  Vector const & atom1_xyz( rsd1.xyz( atom1 ) );
565  Size const atom1_type_index( rsd1.atom( atom1 ).type() );
566 
567  Real total_desolvation( 0.0 );
568  for ( Size atom2=1; atom2<= rsd2.nheavyatoms(); ++atom2 ) {
569  Vector const & atom2_xyz( rsd2.xyz( atom2 ) );
570 
571  Real const d2( atom1_xyz.distance_squared( atom2_xyz ) );
572 
573  if ( ( d2 >= safe_max_dis2_) || ( d2 < 1e-3 ) ) continue; // exclude self...
574 
575  // setup for solvation Etable lookups
576  Size const atom2_type_index( rsd2.atom( atom2 ).type() );
577  Real const d2_bin = d2 * etable_bins_per_A2_;
578  int disbin = static_cast< int >( d2_bin ) + 1;
579  Real frac = d2_bin - ( disbin - 1 );
580  int const l1 = solv1_.index( disbin, atom2_type_index, atom1_type_index );
581 
582  Real const lk_desolvation_of_atom1_by_atom2
583  ( ( ( 1. - frac ) * solv1_[ l1 ] + frac * solv1_[ l1+1 ] ) );
584 
585  total_desolvation += lk_desolvation_of_atom1_by_atom2;
586 
587  }
588  return total_desolvation;
589 }
590 
591 void
593  Real const d2,
594  Size const atom1,
595  conformation::Residue const & rsd1,
596  Size const atom2,
597  conformation::Residue const & rsd2,
598  Real & atom1_lk_desolvation_by_atom2_deriv,
599  Real & atom2_lk_desolvation_by_atom1_deriv
600  )
601 {
602  if ( ( d2 >= safe_max_dis2_) || ( d2 == Real(0.0) ) ) {
603  atom1_lk_desolvation_by_atom2_deriv = 0.0;
604  atom2_lk_desolvation_by_atom1_deriv = 0.0;
605  return;
606  }
607 
608  Real const d2_bin( d2 * etable_bins_per_A2_ );
609  Size const disbin( static_cast< int >( d2_bin ) + 1 );
610  Real const frac( d2_bin - ( disbin - 1 ) );
611 
612  /// this index into solv1 or dsolv1 should represent desolvation of atom1 by atom2
613  int const linear_index12( dsolv1_.index( disbin, rsd2.atom( atom2 ).type(), rsd1.atom( atom1 ).type() ) );
614  /// this index into solv1 or dsolv1 should represent desolvation of atom2 by atom1
615  int const linear_index21( dsolv1_.index( disbin, rsd1.atom( atom1 ).type(), rsd2.atom( atom2 ).type() ) );
616 
617  atom1_lk_desolvation_by_atom2_deriv = dsolv1_[ linear_index12 ] * ( 1-frac ) + dsolv1_[ linear_index12 + 1 ] * frac;
618  atom2_lk_desolvation_by_atom1_deriv = dsolv1_[ linear_index21 ] * ( 1-frac ) + dsolv1_[ linear_index21 + 1 ] * frac;
619 
620 }
621 
622 /// HACKY HELPER FXN TAKEN DIRECTLY FROM BaseEtableEnergy.tmpl.hh
623 /// IF YOU CHANGE THE BEHAVIOR THERE YOU SHOULD CHANGE HERE AS WELL
624 ///
627  conformation::Residue const & res1,
628  conformation::Residue const & res2,
629  bool const use_intra_dna_cp_crossover_4
630  //pose::Pose const &
631  //ScoreFunction const & sfxn
632 )
633 {
634  using namespace scoring::etable::count_pair;
635  // maybe should ask "are these two residues polymers and do they share a polymeric bond"
636  //assert( !sfxn.has_zero_weight( mm_twist ) );
637  if ( res1.polymeric_sequence_distance(res2) == 1 ) {
638  if ( ( !( res1.is_protein() && res2.is_protein() ) ) &&
639  ( !( use_intra_dna_cp_crossover_4 && res1.is_DNA() && res2.is_DNA() ) ) &&
640  ( !( res1.is_RNA() && res2.is_RNA() ) ) ) {
641  return CP_CROSSOVER_3;
642  } else {
643  return CP_CROSSOVER_4; // peptide bond w/ or w/o rama, but definately w/o mm_twist
644  }
645  } else if ( res1.seqpos() == res2.seqpos() ) {
646  // logic for controlling intra-residue count pair behavior goes here; for now, default to crossover 3
647  return CP_CROSSOVER_3;
648  }else {
649  return CP_CROSSOVER_3; // e.g. disulfides where seqsep != 1
650  }
651 }
652 
653 void
655  Size const,
656  Size const,
657  Vectors const & atom1_waters,
658  conformation::Residue const &,
659  Size const atom2_type_index,
660  Vector const & atom2_xyz,
661  Real const lk_desolvation_of_atom1_by_atom2,
662  EnergyMap & emap
663 ) const
664 {
665  /// for first checkin to trunk, take old approach of only counting things for atoms with waters attached
666  /// more logic here in the blab branch, hence existence as separate fxn
667  if ( !atom1_waters.empty() ) {
668  emap[ lk_ball_iso ] += lk_desolvation_of_atom1_by_atom2;
669  Size dummy_size;
670  Real dummy_real;
671  emap[ lk_ball ] += lk_desolvation_of_atom1_by_atom2 *
672  get_lk_fractional_contribution( atom2_xyz, atom2_type_index, atom1_waters, dummy_size, dummy_real );
673  }
674 }
675 
676 
677 
678 void
680  conformation::Residue const & rsd1,
681  LKB_ResidueInfo const & rsd1_info,
682  conformation::Residue const & rsd2,
683  LKB_ResidueInfo const & rsd2_info,
684  EnergyMap & emap
685 ) const
686 {
687  //PROF_START( basic::LK_BALL_RESIDUE_PAIR_ENERGY );
688 
689  using namespace etable::count_pair;
690  //bool const verbose( false );
691  utility::vector1< Vectors > const & rsd1_waters( rsd1_info.waters() );
692  utility::vector1< Vectors > const & rsd2_waters( rsd2_info.waters() );
693 
694  // the old way:
695  //
696  //CountPairFunctionOP cpfxn =
697  // CountPairFactory::create_count_pair_function( rsd1, rsd2, CP_CROSSOVER_4 );
698 
699  CPCrossoverBehavior crossover = determine_crossover_behavior( rsd1, rsd2, use_intra_dna_cp_crossover_4_ ); //, pose ); //, sfxn );
700  CountPairFunctionOP cpfxn = CountPairFactory::create_count_pair_function( rsd1, rsd2, crossover );
701 
702  // setup residue information
703  for ( Size atom1=1; atom1<= rsd1.nheavyatoms(); ++atom1 ) {
704  Vectors const & atom1_waters( rsd1_waters[ atom1 ] );
705  Vector const & atom1_xyz( rsd1.xyz( atom1 ) );
706  Size const atom1_type_index( rsd1.atom( atom1 ).type() );
707  //chemical::AtomType const & atom1_type( rsd1.atom_type( atom1 ) );
708 
709  for ( Size atom2=1; atom2<= rsd2.nheavyatoms(); ++atom2 ) {
710  Vectors const & atom2_waters( rsd2_waters[ atom2 ] );
711  Vector const & atom2_xyz( rsd2.xyz( atom2 ) );
712  //chemical::AtomType const & atom2_type( rsd2.atom_type( atom2 ) );
713 
714  if ( atom1_waters.empty() && atom2_waters.empty() ) continue;
715 
716  Real cp_weight = 1.0; Size pathdist;
717  if ( cpfxn->count( atom1, atom2, cp_weight, pathdist ) ) {
718  Real const d2( atom1_xyz.distance_squared( atom2_xyz ) );
719 
720  if ( ( d2 >= safe_max_dis2_) || ( d2 == Real(0.0) ) ) continue;
721 
722  // setup for solvation Etable lookups
723  Size const atom2_type_index( rsd2.atom( atom2 ).type() );
724  Real const d2_bin = d2 * etable_bins_per_A2_;
725  int disbin = static_cast< int >( d2_bin ) + 1;
726  Real frac = d2_bin - ( disbin - 1 );
727  int const l1 = solv1_.index( disbin, atom2_type_index, atom1_type_index );
728 
729  Real lk_desolvation_of_atom1_by_atom2
730  ( cp_weight * ( ( 1. - frac ) * solv1_[ l1 ] + frac * solv1_[ l1+1 ] ) );
731 
732  Real lk_desolvation_of_atom2_by_atom1
733  ( cp_weight * ( ( 1. - frac ) * solv2_[ l1 ] + frac * solv2_[ l1+1 ] ) );
734 
735  accumulate_single_atom_contributions( atom1, atom1_type_index, atom1_waters,
736  rsd1, atom2_type_index, atom2_xyz,
737  lk_desolvation_of_atom1_by_atom2, emap );
738 
739  accumulate_single_atom_contributions( atom2, atom2_type_index, atom2_waters,
740  rsd2, atom1_type_index, atom1_xyz,
741  lk_desolvation_of_atom2_by_atom1, emap );
742 
743  } // count pair
744  } // atom2
745  } // atom1
746 
747 
748  //PROF_STOP( basic::LK_BALL_RESIDUE_PAIR_ENERGY );
749 }
750 
751 /////////////////////////////////////////////////////////////////////////////
752 // derivatives
753 /////////////////////////////////////////////////////////////////////////////
754 
755 
756 void
758  pose::Pose & pose,
759  ScoreFunction const &
760 ) const
761 {
762  //std::cout << "LK_BallEnergy.cc: " << __LINE__ << std::endl;
765  //std::cout << "LK_BallEnergy.cc: " << __LINE__ << std::endl;
766 }
767 
768 
769 /**
770 
771  Note that we calculate the lk_ball_iso derivative as well as the lk_ball derivative...
772 
773  Derivatives are only included for heavyatoms.
774 
775  For a non-polar heavyatom, the derivs are for all polar atoms that it desolvates
776 
777  For a polar heavyatom, derivs are for all polar atoms that it desolvates as well as all atoms it's being
778  desolvated by.
779 
780  Given an atom desolvating a polar atom:
781  * the lk_ball_iso deriv is the standard lk deriv, but make sure we use the correct array! (see LK_hack code)
782 
783  * the lk_ball score = wt * lk_polar, so the derivs have two components. One looks like wt * lk_polar deriv
784  contribution. The other looks like the lk_polar term * the derivative of the wt. The derivative of the wt
785  is found by getting the closest water, taking the derivative of the wt term wrt distance and using f1/f2
786  contributions for the desolvating atom xyz and the water xyz.
787 
788  **/
789 
790 /// @details Compute the f1 and f2 vectors for the derivative of the lk_fraction term for atom2 desolvating atom1
791 ///
792 /// @note f1 and f2 are zeroed and filled within this function, rather than being accumulated into
793 /// @note We pretend that atom1 is the "moving" atom
794 /// Should eliminate code duplication with next routine... currently this is for outside use.
795 
796 Real
798  Vector const & atom2_xyz,
799  Size const atom2_type,
800  Vectors const & atom1_waters,
801  bool const evaluate_deriv,
802  Vector & f1,
803  Vector & f2
804  ) const
805 {
806  ///
807  Size closest_water(0);
808  Real closest_water_d2_delta( 100.0);
809  Real const lk_fraction( get_lk_fractional_contribution( atom2_xyz, atom2_type, atom1_waters,
810  closest_water, closest_water_d2_delta ) );
811 
812  if ( evaluate_deriv ) {
813  f1.clear(); f2.clear();
814 
815  // water1-atom2 interaction
816  // note that there's no derivative unless we're in the ramping zone:
817  if ( closest_water_d2_delta < ramp_width_A2_ && closest_water_d2_delta > 0.0 ) {
818  Vector const & atom1_water_xyz( atom1_waters[ closest_water ] );
819  // what is the derivative of the lk_fraction term wrt r?
820  Real const dE_dr_over_r( eval_d_lk_fraction_dr_over_r( closest_water_d2_delta ) );
821  f1 = dE_dr_over_r * ( atom1_water_xyz.cross( atom2_xyz ) );
822  f2 = dE_dr_over_r * ( atom1_water_xyz - atom2_xyz );
823  }
824  }
825  return lk_fraction;
826 }
827 
828 
829 
830 
831 /// @note atom2 is desolvating atom1. atom1_waters is non-empty
832 /// @note Pretend that atom1 is the atom whose derivs are being calculated. weight_factor may include -1 term
833 /// to switch the order...
834 ///
835 void
837  Size const atom1,
838  conformation::Residue const & rsd1,
839  Vectors const & atom1_waters,
840  Size const atom2,
841  conformation::Residue const & rsd2,
842  EnergyMap const & weights,
843  Real const weight_factor,
844  Real const d2,
845  Vector & F1,
846  Vector & F2
847  ) const
848 {
849  //std::cout << "LK_BallEnergy.cc: " << __LINE__ << std::endl;
850  if ( atom1_waters.empty() ) return;
851  //assert( !atom1_waters.empty() );
852  //std::cout << "LK_BallEnergy.cc: " << __LINE__ << std::endl;
853 
854 
855  Real const d2_bin( d2 * etable_bins_per_A2_ );
856  Size const disbin( static_cast< int >( d2_bin ) + 1 );
857  Real const frac( d2_bin - ( disbin - 1 ) );
858 
859  /// this index into solv1 or dsolv1 should represent desolvation of atom1 by atom2
860  Size const atom1_type_index( rsd1.atom( atom1 ).type() );
861  int const linear_index( dsolv1_.index( disbin, rsd2.atom( atom2 ).type(), atom1_type_index ) );
862 
863  Real const lk_deriv( dsolv1_[ linear_index ] * ( 1-frac ) + dsolv1_[ linear_index+1 ] * frac );
864  Real const lk_score( solv1_[ linear_index ] * ( 1-frac ) + solv1_[ linear_index+1 ] * frac );
865 
866  //assert( lk_score >= 0.0 ); // since atom1 is polar -- not anymore!
867 
868  // first for the direct lk interaction between atom1 and atom2:
869  Vector const & atom1_xyz( rsd1.xyz( atom1 ) );
870  Vector const & atom2_xyz( rsd2.xyz( atom2 ) );
871  Vector f1( atom1_xyz.cross( atom2_xyz ) ), f2( atom1_xyz - atom2_xyz );
872 
873  Real const inv_dis( 1.0 / std::sqrt( d2 ) );
874 
875  Real const lk_ball_iso_weight( weights[ lk_ball_iso ] ), lk_ball_weight( weights[ lk_ball ] );
876 
877  { // the derivs for the parts that don't involve waters:
878  Real const dE_dr_over_r( weight_factor * lk_ball_iso_weight * lk_deriv * inv_dis );
879  F1 += dE_dr_over_r * f1;
880  F2 += dE_dr_over_r * f2;
881  }
882 
883 
884  // now the lk_ball deriv
885  //
886  // lk_ball = fraction * lk
887  // so d lk_ball = fraction * ( d lk ) + ( d fraction ) * lk
888  //
889  Size closest_water(0);
890  Real closest_water_d2_delta( 100.0);
891  Real const lk_fraction( get_lk_fractional_contribution( atom2_xyz, rsd2.atom( atom2 ).type(), atom1_waters,
892  closest_water, closest_water_d2_delta ) );
893 
894  // 1st term -- atom1-atom2 interaction
895  {
896  Real const dE_dr_over_r( weight_factor * lk_ball_weight * lk_fraction * lk_deriv * inv_dis );
897  F1 += dE_dr_over_r * f1;
898  F2 += dE_dr_over_r * f2;
899  }
900 
901  // 2nd term -- water1-atom2 interaction
902  // note that there's no derivative unless we're in the ramping zone:
903  if ( closest_water_d2_delta < ramp_width_A2_ && closest_water_d2_delta > 0.0 ) {
904  Vector const & atom1_water_xyz( atom1_waters[ closest_water ] );
905  // update f1 and f2 to reflect water-atom2 as the interaction
906  f1 = atom1_water_xyz.cross( atom2_xyz );
907  f2 = atom1_water_xyz - atom2_xyz;
908  // what is the derivative of the lk_fraction term wrt r?
909  Real const dE_dr_over_r
910  ( weight_factor * lk_ball_weight * lk_score * eval_d_lk_fraction_dr_over_r( closest_water_d2_delta ) );
911  F1 += dE_dr_over_r * f1;
912  F2 += dE_dr_over_r * f2;
913  }
914  //std::cout << "LK_BallEnergy.cc: " << __LINE__ << std::endl;
915 }
916 
917 /// @note Assumes that atom1 is the "moving" atom, ie the atom for which eval_atom_derivative was called
918 /// @note Calculates the water positions for atom2 if d2 < safe_max_dis2
919 void
921  Size const atom1,
922  conformation::Residue const & rsd1,
923  LKB_ResidueInfo const & rsd1_info,
924  Size const atom2,
925  conformation::Residue const & rsd2,
926  LKB_ResidueInfo const & rsd2_info,
927  pose::Pose const &,
928  EnergyMap const & weights,
929  Real const cp_weight,
930  Vector & F1,
931  Vector & F2
932 ) const
933 {
934  //std::cout << "LK_BallEnergy.cc: " << __LINE__ << std::endl;
935  Real const d2( rsd1.xyz( atom1 ).distance_squared( rsd2.xyz( atom2 ) ) );
936 
937  if ( ( d2 >= safe_max_dis2_ ) || ( d2 == Real(0.0) ) ) return; // no contribution
938 // std::cout << "LK_BallEnergy.cc: " << __LINE__ << ' ' <<
939 // atom1 << ' ' << rsd1_info.waters().size() << ' ' <<
940 // atom2 << ' ' << rsd2_info.waters().size() << ' ' <<
941 // std::endl;
942 
943  Vectors const & atom1_waters( rsd1_info.waters()[ atom1 ] );
944  Vectors const & atom2_waters( rsd2_info.waters()[ atom2 ] );
945 
946  sum_contributions_for_atom_pair_one_way( atom1, rsd1, atom1_waters, atom2, rsd2, weights, cp_weight, d2, F1, F2 );
947 
948  sum_contributions_for_atom_pair_one_way( atom2, rsd2, atom2_waters, atom1, rsd1, weights, -1.0 * cp_weight, d2,
949  F1, F2 );
950  //std::cout << "LK_BallEnergy.cc: " << __LINE__ << std::endl;
951 }
952 
953 
954 
955 // void
956 // LK_BallEnergy::eval_atom_derivative(
957 // id::AtomID const & id,
958 // pose::Pose const & pose,
959 // kinematics::DomainMap const &, // domain_map,
960 // ScoreFunction const & /*sfxn*/, // needed for non-nblist minimization
961 // EnergyMap const & weights,
962 // Vector & F1,
963 // Vector & F2
964 // ) const
965 // {
966 // //PROF_START( basic::LK_BALL_EVAL_ATOM_DERIVATIVE );
967 
968 // Size const idresid = id.rsd();
969 // Size const atom1( id.atomno() );
970 // conformation::Residue const & rsd1( pose.residue( idresid ) );
971 // if ( atom1 > rsd1.nheavyatoms() ) {
972 // //PROF_STOP( basic::LK_BALL_EVAL_ATOM_DERIVATIVE );
973 // return; // NO HYDROGEN INTERACTIONS
974 // }
975 
976 // LKB_ResidueInfo const & rsd1_info( retrieve_residue_info( pose, idresid ) );
977 
978 // assert( pose.energies().use_nblist() );
979 
980 // scoring::AtomNeighbors const & nbrs
981 // ( pose.energies().nblist( basic::ETABLE_NBLIST ).atom_neighbors( id ) );
982 
983 // Vector f1,f2;
984 // for ( scoring::AtomNeighbors::const_iterator it2=nbrs.begin(),
985 // it2e=nbrs.end(); it2 != it2e; ++it2 ) {
986 // scoring::AtomNeighbor const & nbr( *it2 );
987 // Real const cp_weight( nbr.weight() );
988 // if ( Size( nbr.atomno() ) > pose.residue( nbr.rsd() ).nheavyatoms() ) continue; // NO HYDROGEN INTERACTIONS
989 // LKB_ResidueInfo const & rsd2_info( retrieve_residue_info( pose, nbr.rsd() ) );
990 // sum_contributions_for_atom_pair( atom1, rsd1, rsd1_info, nbr.atomno(), pose.residue( nbr.rsd() ), rsd2_info, pose,
991 // weights, cp_weight, F1, F2 );
992 // }
993 // //PROF_STOP( basic::LK_BALL_EVAL_ATOM_DERIVATIVE );
994 // }
995 
996 
997 
998 void
1000  utility::vector1< bool > & /* context_graphs_required */ ) const
1001 {}
1002 
1003 
1004 
1005 void
1007  conformation::RotamerSetBase const & set1,
1008  conformation::RotamerSetBase const & set2,
1009  pose::Pose const &, // pose,
1010  ScoreFunction const &, // sfxn,
1011  EnergyMap const & weights,
1012  ObjexxFCL::FArray2D< core::PackerEnergy > & energy_table
1013 ) const
1014 {
1015  using namespace conformation;
1016  using namespace numeric;
1017 
1018  //TR.Trace << "rotamer_pair" << std::endl;
1019 
1020  //PROF_START( basic::LK_BALL_ROTAMER_PAIR_ENERGIES );
1021 
1022  LKB_RotamerSetInfo const & info1( retrieve_rotamer_set_info( set1 ) );
1023  LKB_RotamerSetInfo const & info2( retrieve_rotamer_set_info( set2 ) );
1024 
1025 
1026  for ( Size ii = 1; ii <= set1.get_n_residue_types(); ++ii ) {
1027  Size const ii_offset = set1.get_residue_type_begin( ii );
1028  for ( Size jj = 1; jj <= set2.get_n_residue_types(); ++jj ) {
1029  Size const jj_offset = set2.get_residue_type_begin( jj );
1030  if ( !info1[ ii_offset ].has_waters() && !info2[ jj_offset ].has_waters() ) continue;
1031 
1032  for ( Size kk = 1, kke = set1.get_n_rotamers_for_residue_type( ii ); kk <= kke; ++kk ) {
1033  Size const kk_rot_id = ii_offset + kk - 1;
1034  for ( Size ll = 1, lle = set2.get_n_rotamers_for_residue_type( jj ); ll <= lle; ++ll ) {
1035  Size const ll_rot_id = jj_offset + ll - 1;
1036  EnergyMap emap;
1037  residue_pair_energy( *set1.rotamer( kk_rot_id ), info1[ kk_rot_id ],
1038  *set2.rotamer( ll_rot_id ), info2[ ll_rot_id ], emap );
1039 
1040  energy_table( ll_rot_id, kk_rot_id ) += static_cast< core::PackerEnergy >( weights.dot( emap ) );
1041  }
1042  }
1043  }
1044  }
1045  //PROF_STOP( basic::LK_BALL_ROTAMER_PAIR_ENERGIES );
1046 }
1047 
1048 void
1050  conformation::RotamerSetBase const & set,
1051  conformation::Residue const & rsd,
1052  pose::Pose const & pose,
1053  ScoreFunction const &, // sfxn,
1054  EnergyMap const & weights,
1056 ) const
1057 {
1058 
1059  //PROF_START( basic::LK_BALL_ROTAMER_BACKGROUND_ENERGIES );
1060  //TR.Trace << "rotamer_background!" << std::endl;
1061 
1062  using conformation::Residue;
1063  LKB_ResidueInfo const & rsd_info( retrieve_residue_info( pose, rsd.seqpos() ) );
1064  LKB_RotamerSetInfo const & set_info( retrieve_rotamer_set_info( set ) );
1065 
1066  for ( Size ii = 1; ii <= set.get_n_residue_types(); ++ii ) {
1067  Size const ii_offset = set.get_residue_type_begin( ii );
1068 
1069  if ( !set_info[ ii_offset ].has_waters() && !rsd_info.has_waters() ) continue;
1070 
1071  for ( Size kk = 1, kke = set.get_n_rotamers_for_residue_type( ii ); kk <= kke; ++kk ) {
1072  Size const kk_rot_id = ii_offset + kk - 1;
1073 
1074  EnergyMap emap;
1075  residue_pair_energy( *set.rotamer( kk_rot_id ), set_info[ kk_rot_id ], rsd, rsd_info, emap );
1076 
1077  /**{ // check that this agrees with the old way!
1078  // explicitly build the residue_info's now
1079  LKB_ResidueInfo const info1_redo( *set.rotamer( kk_rot_id ) );
1080  LKB_ResidueInfo const info2_redo( rsd );
1081  Real lk_ball_energy_redo( 0.0 ), lk_ball_iso_energy_redo( 0.0 );
1082  residue_pair_energy( *set.rotamer( kk_rot_id ), info1_redo.waters(),
1083  rsd, info2_redo.waters(),
1084  lk_ball_energy_redo, lk_ball_iso_energy_redo );
1085  assert( std::abs( lk_ball_energy - lk_ball_energy_redo ) +
1086  std::abs( lk_ball_iso_energy - lk_ball_iso_energy_redo ) < 1e-3 );
1087 
1088  }**/
1089 
1090  energy_vector[ kk_rot_id ] += static_cast< core::PackerEnergy >( weights.dot( emap ) );
1091  } // kk - rotamers for residue types
1092  } // ii - residue types for rotamer set
1093 
1094  //PROF_STOP( basic::LK_BALL_ROTAMER_BACKGROUND_ENERGIES );
1095 }
1096 
1097 
1098 void
1100  conformation::Residue const & rsd1,
1101  conformation::Residue const & rsd2,
1102  ResSingleMinimizationData const &,
1103  ResSingleMinimizationData const &,
1104  ResPairMinimizationData const & min_data,
1105  pose::Pose const & pose, // provides context
1106  EnergyMap const & weights,
1107  utility::vector1< DerivVectorPair > & r1_at_derivs,
1109 ) const
1110 {
1111  //std::cout << "LK_BallEnergy.cc: " << __LINE__ << std::endl;
1112  assert( r1_at_derivs.size() >= rsd1.natoms() );
1113  assert( r2_at_derivs.size() >= rsd2.natoms() );
1114 
1115  // retrieve some info
1116  LKB_ResidueInfo const & rsd1_info( retrieve_residue_info( pose, rsd1.seqpos() ) );
1117  LKB_ResidueInfo const & rsd2_info( retrieve_residue_info( pose, rsd2.seqpos() ) );
1118 
1119  assert( dynamic_cast< ResiduePairNeighborList const * > (min_data.get_data( etab_pair_nblist )() ));
1120  ResiduePairNeighborList const & nblist
1121  ( static_cast< ResiduePairNeighborList const & > (min_data.get_data_ref( etab_pair_nblist )) );
1122 
1123  utility::vector1< SmallAtNb > const & neighbs( nblist.atom_neighbors() );
1124  for ( Size ii = 1, iiend = neighbs.size(); ii <= iiend; ++ii ) {
1125  Size const atom1( neighbs[ ii ].atomno1() ), atom2( neighbs[ ii ].atomno2() );
1126  if ( rsd1.atom_is_hydrogen( atom1 ) || rsd2.atom_is_hydrogen( atom2 ) ) continue; // NO HYDROGEN INTXNS
1127  Real const cp_weight( neighbs[ ii ].weight() );
1128 
1129  Vector f1(0,0,0),f2(0,0,0);
1130  sum_contributions_for_atom_pair( atom1, rsd1, rsd1_info, atom2, rsd2, rsd2_info, pose, weights,
1131  cp_weight, f1, f2 );
1132 
1133  r1_at_derivs[ neighbs[ ii ].atomno1() ].f1() += f1;
1134  r1_at_derivs[ neighbs[ ii ].atomno1() ].f2() += f2;
1135  r2_at_derivs[ neighbs[ ii ].atomno2() ].f1() += -1*f1;
1136  r2_at_derivs[ neighbs[ ii ].atomno2() ].f2() += -1*f2;
1137  }
1138  //std::cout << "LK_BallEnergy.cc: " << __LINE__ << std::endl;
1139 }
1140 
1141 Size
1143  chemical::ResidueType const & rsd_type,
1144  Size const hatm
1145 )
1146 {
1147  using namespace chemical;
1148  assert( rsd_type.aa() == aa_arg );
1149  typedef std::map< ResidueTypeCOP, utility::vector1< Size > > H_Map;
1150  static H_Map hmap;
1151  ResidueTypeCOP rsd_type_ptr( &rsd_type );
1152  H_Map::const_iterator iter = hmap.find( rsd_type_ptr );
1153  if ( iter == hmap.end() ) {
1154  // first time seeing this arginine residue type
1155  utility::vector1< Size > parallel_h( rsd_type.natoms(), 0 );
1156  parallel_h[ rsd_type.atom_index( "HE" ) ] = rsd_type.atom_index( "1HH2" );
1157  parallel_h[ rsd_type.atom_index( "1HH2" ) ] = rsd_type.atom_index( "HE" );
1158  parallel_h[ rsd_type.atom_index( "2HH1" ) ] = rsd_type.atom_index( "2HH2" );
1159  parallel_h[ rsd_type.atom_index( "2HH2" ) ] = rsd_type.atom_index( "2HH1" );
1160  hmap.insert( std::make_pair( rsd_type_ptr, parallel_h ) );
1161  iter = hmap.find( rsd_type_ptr );
1162  }
1163  return iter->second[ hatm ];
1164 }
1165 
1166 
1167 /// hack to improve geometries of hbonds:
1168 /// apply an additional weighting factor which is used in LK_BallEnergy
1169 /// Do this for sidechain SP2 or Ring acceptors
1170 /// Do this for all sidechain donors
1171 ///
1172 /// NOTE: also excluding multiple parallel Arg hbonds
1173 ///
1174 /// @note For the deriv calculation, we assume that the deriv passed in has already been evaluated by hb_energy_deriv
1175 /// and thus represents the deriv of the unweighted energy considering the donor as the moving atom.
1176 void
1178  Size const hatm,
1179  conformation::Residue const & don_rsd,
1180  Size const aatm,
1181  conformation::Residue const & acc_rsd,
1182  Vector const & hatm_xyz,
1183  Vector const & datm_xyz,
1184  Real & unweighted_energy,
1185  bool const evaluate_derivative,
1186  hbonds::HBondDerivs & hbderivs,
1187  Real & don_fraction,
1188  Real & acc_fraction
1189  )
1190 {
1191  //std::cout << "LK_BallEnergy.cc: " << __LINE__ << std::endl;
1192  // params
1193  bool const no_lk_ball_for_SP2( false ); //option[ OKDS::no_lk_ball_for_SP2 ] );
1194  bool const exclude_arg_double_parallel_hbonds( true );
1195 
1196 // not considering these next two for the time being:
1197 // bool const use_soft_lk_fraction_for_hbond_acceptors( false );
1198 // bool const use_soft_lk_fraction_for_hbond_acceptors_from_water( false );
1199 
1200 
1201  Size const datm( don_rsd.atom_base( hatm ) );
1202 
1203  // static for efficiency
1204  static Real const optimal_acceptor_water_distance( 2.85 ); /// these should agree with LK_BallInfo.cc, right ??
1205  static Real const optimal_donor_water_distance ( 2.85 ); /// the values there are 2.65 !!
1206  static Real const optimal_acceptor_angle_SP2( numeric::conversions::radians( 120.0 ) );
1207  static Real const n1_coeff_SP2( -1.0 * optimal_acceptor_water_distance * std::cos( optimal_acceptor_angle_SP2 ) );
1208  static Real const n2_coeff_SP2( optimal_acceptor_water_distance * std::sin( optimal_acceptor_angle_SP2 ) );
1209  static methods::EnergyMethodOptions energy_method_options;
1210  static methods::LK_BallEnergy lk_ball_energy( energy_method_options );
1211 
1212  Vector f1_don( 0.0 ), f2_don( 0.0 ), f1_acc( 0.0 ), f2_acc( 0.0 );
1213  don_fraction = acc_fraction = 1.0;
1214 
1215  if ( !don_rsd.atom_is_backbone( datm ) ) {
1216  /// get ideal water location
1218  waters.push_back( datm_xyz + optimal_donor_water_distance * ( hatm_xyz - datm_xyz ).normalized_any() );
1219  if ( don_rsd.aa() == chemical::aa_arg && exclude_arg_double_parallel_hbonds ) {
1220  Size const other_hatm( get_parallel_h_for_arg( don_rsd.type(), hatm ) );
1221  if ( other_hatm ) {
1222  Vector const & other_datm_xyz( don_rsd.xyz( don_rsd.atom_base( other_hatm ) ) ),
1223  & other_hatm_xyz( don_rsd.xyz( other_hatm ) ), & aatm_xyz( acc_rsd.xyz( aatm ) );
1224  Vector const other_water( other_datm_xyz + optimal_donor_water_distance *
1225  ( other_hatm_xyz - other_datm_xyz ).normalized_any() );
1226  if ( aatm_xyz.distance_squared( other_water ) < aatm_xyz.distance_squared( waters.front() ) ) {
1227  // closer to the other hydrogen's water!
1228 // std::cout << "excluding arg hbond: " << acc_rsd.name1() << ' ' << acc_rsd.seqpos() << ' ' <<
1229 // acc_rsd.atom_name( aatm ) << " is closer to ARG " << don_rsd.seqpos() << ' ' <<
1230 // don_rsd.atom_name( other_hatm ) << " than to " << don_rsd.atom_name( hatm ) << std::endl;
1231  don_fraction = acc_fraction = 0.0;
1232  waters.clear(); // prevent re-evaluation of don_fraction
1233  if ( evaluate_derivative ) {
1234  f1_don.zero();
1235  f2_don.zero();
1236  }
1237  }
1238  }
1239  }
1240  if ( !waters.empty() ) {
1241  // otherwise donor is an arginine with wrong water closer
1242  don_fraction = lk_ball_energy.eval_lk_ball_fraction_deriv( acc_rsd.xyz( aatm ),acc_rsd.atom( aatm ).type(),
1243  waters, evaluate_derivative, f1_don, f2_don );
1244  } else {
1245  assert( don_rsd.aa() == chemical::aa_arg );
1246  }
1247  }
1248 
1249 
1250  if ( !acc_rsd.atom_is_backbone( aatm ) ) {
1251  using namespace chemical;
1252  Hybridization const & hybrid( acc_rsd.atom_type( aatm ).hybridization() );
1253  if ( hybrid == SP2_HYBRID && no_lk_ball_for_SP2 && acc_rsd.is_protein() ) {
1254  //TR.Trace << "Not computing acc_fraction " << acc_rsd.atom_name( aatm ) << std::endl;
1255  } else if ( hybrid == SP2_HYBRID || hybrid == RING_HYBRID ) {
1256  /// only cases for which we do this:
1257  Vector const & aatm_xyz( acc_rsd.xyz( aatm ) );
1258  Vector const & abase_xyz( acc_rsd.xyz( acc_rsd.atom_base( aatm ) ) );
1259  Vector const & abase2_xyz( acc_rsd.xyz( acc_rsd.abase2( aatm ) ) );
1261 
1262  if ( hybrid == SP2_HYBRID ) {
1263  Vector const n1( ( aatm_xyz - abase_xyz ).normalized_any() );
1264  Vector n2( ( abase2_xyz - abase_xyz ) );
1265  n2 = ( n2 - n1.dot( n2 ) * n1 ).normalized_any();
1266  assert( std::abs( n1.dot( n2 ) ) < 1e-3 );
1267  waters.push_back( aatm_xyz + n1_coeff_SP2 * n1 + n2_coeff_SP2 * n2 );
1268  waters.push_back( aatm_xyz + n1_coeff_SP2 * n1 - n2_coeff_SP2 * n2 );
1269  //dump_waters_pdb( acc_rsd, waters, "acc_sp2" );
1270  //dumped[2] = true;
1271  } else if ( hybrid == RING_HYBRID ) {
1272  Vector const n1( ( aatm_xyz - 0.5 * abase_xyz - 0.5 * abase2_xyz ).normalized_any() );
1273  waters.push_back( aatm_xyz + optimal_acceptor_water_distance * n1 );
1274  //dump_waters_pdb( acc_rsd, waters, "acc_ring" );
1275  //dumped[3] = true;
1276  } else {
1277  utility_exit_with_message("dont do this hybridization state!");
1278  }
1279 
1280  /// note that this function thinks that the acceptor is the "moving" atom, hence -1.0 in deriv calcs below
1281  acc_fraction = lk_ball_energy.eval_lk_ball_fraction_deriv( datm_xyz, don_rsd.atom( datm ).type(), waters,
1282  evaluate_derivative, f1_acc, f2_acc );
1283  }
1284  }
1285 
1286  if ( acc_fraction < 0.99 || don_fraction < 0.99 ) {
1287  // debugging
1288  using namespace ObjexxFCL::fmt;
1289 // std::cout << "apply_lk_ball_fraction_weight_for_hbonds: " <<
1290 // F(9,3,don_fraction) << I(4,don_rsd.seqpos()) << ' ' << don_rsd.name1() << ' '<< don_rsd.atom_name( hatm ) <<
1291 // F(9,3,acc_fraction) << I(4,acc_rsd.seqpos()) << ' ' << acc_rsd.name1() << ' '<< acc_rsd.atom_name( aatm ) <<
1292 // std::endl;
1293  }
1294 
1295 
1296  { // we used to have an option to soften the dependence, but that was taken out in porting to trunk to get derivs
1297  // correctly first
1298 
1299  /// do this BEFORE we multiply unweighted_energy by don_fraction and acc_fraction
1300  if ( evaluate_derivative ) {
1301  /// note that don_derivs should probably be attached to h_deriv instead, need to think more about this...
1302  /// also note that f12_don think the donor is the moving atom, while f12_acc think the acceptor is moving
1303  /// this is the chain rule, baby:
1304  hbderivs.don_deriv.f1() = ( hbderivs.don_deriv.f1() * don_fraction * acc_fraction +
1305  unweighted_energy * f1_don * acc_fraction +
1306  unweighted_energy * don_fraction * -1 * f1_acc );
1307 
1308  hbderivs.don_deriv.f2() = ( hbderivs.don_deriv.f2() * don_fraction * acc_fraction +
1309  unweighted_energy * f2_don * acc_fraction +
1310  unweighted_energy * don_fraction * -1 * f2_acc );
1311 
1312  hbderivs.acc_deriv.f1() = ( hbderivs.acc_deriv.f1() * don_fraction * acc_fraction +
1313  unweighted_energy * -1 * f1_don * acc_fraction +
1314  unweighted_energy * don_fraction * f1_acc );
1315 
1316  hbderivs.acc_deriv.f2() = ( hbderivs.acc_deriv.f2() * don_fraction * acc_fraction +
1317  unweighted_energy * -1 * f2_don * acc_fraction +
1318  unweighted_energy * don_fraction * f2_acc );
1319 
1320  hbderivs.h_deriv.f1() = ( hbderivs.h_deriv.f1() * don_fraction * acc_fraction );
1321  hbderivs.h_deriv.f2() = ( hbderivs.h_deriv.f2() * don_fraction * acc_fraction );
1322 
1323  hbderivs.abase_deriv.f1() = ( hbderivs.abase_deriv.f1() * don_fraction * acc_fraction );
1324  hbderivs.abase_deriv.f2() = ( hbderivs.abase_deriv.f2() * don_fraction * acc_fraction );
1325 
1326  hbderivs.abase2_deriv.f1() = ( hbderivs.abase2_deriv.f1() * don_fraction * acc_fraction );
1327  hbderivs.abase2_deriv.f2() = ( hbderivs.abase2_deriv.f2() * don_fraction * acc_fraction );
1328 
1329  // the old way: (this was just wrt the donor; we had already negated f1_acc,f2_acc)
1330  //
1331  // deriv.first = ( deriv.first * don_fraction * acc_fraction +
1332  // unweighted_energy * f1_don * acc_fraction +
1333  // unweighted_energy * don_fraction * f1_acc );
1334 
1335  // deriv.second = ( deriv.second * don_fraction * acc_fraction +
1336  // unweighted_energy * f2_don * acc_fraction +
1337  // unweighted_energy * don_fraction * f2_acc );
1338 
1339  }
1340 
1341  /// now apply the new weighting factor
1342  unweighted_energy = unweighted_energy * don_fraction * acc_fraction;
1343 
1344  } // use a softer damping scheme
1345  //std::cout << "LK_BallEnergy.cc: " << __LINE__ << std::endl;
1346 }
1347 
1348 
1349 
1350 
1351 
1352 core::Size
1354 {
1355  return 1; // Initial versioning
1356 }
1357 
1358 
1359 }
1360 }
1361 }
1362 // if ( verbose ) { // HACKING
1363 // Real closest_water_dis2(0.0);
1364 // Size closest_water(0);
1365 // Real const frac( get_lk_fractional_contribution( atom2_xyz, atom2_type_index, atom1_waters, closest_water,
1366 // closest_water_dis2));
1367 // //std::cout << "LK_BALL nwaters= " << atom1_waters.size() << " distance= " << F(9,3,std::sqrt(d2) ) <<
1368 // " lk_ball_iso= " << F(9,3,lk_desolvation_of_atom1_by_atom2)<<
1369 // " lk_fraction= " << F(9,3,frac) <<
1370 // " closest_water_dis= " << F(9,3,std::sqrt( d2_low_[ atom2_type_index ] + closest_water_dis2 ) ) <<
1371 // " desolvated_atom: " << rsd1.name() << ' ' << rsd1.seqpos() << ' ' << rsd1.atom_name( atom1 ) <<
1372 // " desolvating_atom: " << rsd2.name() << ' ' << rsd2.seqpos() << ' ' << rsd2.atom_name( atom2 ) <<
1373 // std::endl;
1374 // }
1375 
1376 
1377 
1378 // if ( verbose ) { // HACKING
1379 // Real closest_water_dis2(0.0);
1380 // Size closest_water(0);
1381 // Real const frac( get_lk_fractional_contribution( atom1_xyz, atom1_type_index, atom2_waters, closest_water,
1382 // closest_water_dis2));
1383 // //std::cout << "LK_BALL nwaters= " << atom2_waters.size() << " distance= " << F(9,3,std::sqrt(d2) ) <<
1384 // " lk_ball_iso= " << F(9,3,lk_desolvation_of_atom2_by_atom1)<<
1385 // " lk_fraction= " << F(9,3,frac) <<
1386 // " closest_water_dis= " << F(9,3,std::sqrt( d2_low_[ atom1_type_index ] + closest_water_dis2 ) ) <<
1387 // " desolvated_atom: " << rsd2.name() << ' ' << rsd2.seqpos() << ' ' << rsd2.atom_name( atom2 ) <<
1388 // " desolvating_atom: " << rsd1.name() << ' ' << rsd1.seqpos() << ' ' << rsd1.atom_name( atom1 ) <<
1389 // std::endl;
1390 // }
1391 
1392 
1393 
1394 
1395 // if ( ( atom1_is_polar && lk_desolvation_of_atom1_by_atom2 < -1e-3 ) || // debugging
1396 // ( !atom1_is_polar && lk_desolvation_of_atom1_by_atom2 > 1e-3 ) ) {
1397 // //std::cout << "lk_funny_sign: " << lk_desolvation_of_atom1_by_atom2 << ' ' <<
1398 // rsd1.atom_name( atom1 ) << ' ' << rsd1.name() << std::endl;
1399 // }
1400 
1401 // if ( ( atom2_is_polar && lk_desolvation_of_atom2_by_atom1 < -1e-3 ) || // debugging
1402 // ( !atom2_is_polar && lk_desolvation_of_atom2_by_atom1 > 1e-3 ) ) {
1403 // //std::cout << "lk_funny_sign: " << lk_desolvation_of_atom2_by_atom1 << ' ' <<
1404 // rsd2.atom_name( atom2 ) << ' ' << rsd2.name() << std::endl;
1405 // }