Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
GeometricSolEnergy.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/GeometricSolEnergy.fwd.hh
11 /// @brief Hydrogen bond energy method forward declaration
12 /// @author Phil Bradley
13 /// @author Andrew Leaver-Fay
14 /// @author Rhiju Das
15 
16 // Unit Headers
19 
20 // Package headers
21 #include <core/scoring/Energies.hh>
34 
35 // Project headers
36 #include <core/chemical/types.hh>
39 #include <core/id/AtomID.hh>
40 #include <core/id/types.hh>
41 #include <basic/options/option.hh>
42 #include <basic/options/keys/score.OptionKeys.gen.hh>
43 
44 // Utility headers
45 #include <ObjexxFCL/format.hh>
46 
47 #include <core/pose/Pose.hh>
48 
49 #include <basic/Tracer.hh>
50 // AUTO-REMOVED #include <basic/prof.hh>
51 
52 #include <utility/vector1.hh>
53 #include <utility/options/IntegerVectorOption.hh>
54 #include <utility/options/StringVectorOption.hh>
55 #include <ObjexxFCL/FArray3D.hh>
56 
57 //Auto Headers
59 
60 static basic::Tracer tr( "core.scoring.geometric_solvation.GeometricSolEnergy" );
61 
62 
63 //////////////////////////////////////////////////
64 //////////////////////////////////////////////////
65 // Added Apr. 21, 2008, Rhiju.
66 // TO DO --
67 // Probably should put most of
68 // geometric sol machinery, and
69 // associated constants,
70 // in its own class. Also
71 // would allow cached calculation of derivatives.
72 ///////////////////////////////////////////////////
73 
74 namespace core {
75 namespace scoring {
76 namespace geometric_solvation {
77 
78 using namespace ObjexxFCL::fmt;
79 
80 /// @details This must return a fresh instance of the GeometricSolEnergy class,
81 /// never an instance already in use
84  methods::EnergyMethodOptions const & options
85 ) const {
86  return new GeometricSolEnergy( options );
87 }
88 
91  ScoreTypes sts;
92  sts.push_back( geom_sol );
93  sts.push_back( geom_sol_intra_RNA );
94  return sts;
95 }
96 
97 
98 using namespace core::scoring::hbonds;
99 
100 ///@brief copy c-tor
102 ) :
104  options_( new methods::EnergyMethodOptions( opts ) ),
105  hb_database_( HBondDatabase::get_database( opts.hbond_options().params_database_tag() )),
106  dist_cut2_( 27.0 ), // 5.2*5.2
107  geometric_sol_scale_( 0.4 * 1.17 / 0.65 ),
108  correct_geom_sol_acceptor_base_( basic::options::option[ basic::options::OptionKeys::score::geom_sol_correct_acceptor_base ]() ),
109  verbose_( false )
110 {
111  options_->exclude_DNA_DNA( false /*GEOMETRIC SOLVATION NOT COMPATIBLE WITH EXCLUDE_DNA_DNA FLAG YET*/ );
112  options_->hbond_options().use_incorrect_deriv( true ); // override command line.
113  options_->hbond_options().use_sp2_chi_penalty( false ); // override command line.
114 }
115 
116 /// copy ctor
119  options_( new methods::EnergyMethodOptions( * src.options_ )),
120  hb_database_( src.hb_database_ ),
121  dist_cut2_( src.dist_cut2_ ), // 5.2*5.2
122  geometric_sol_scale_( src.geometric_sol_scale_ ),
123  correct_geom_sol_acceptor_base_( src.correct_geom_sol_acceptor_base_ ),
124  verbose_( src.verbose_ )
125 {}
126 
127 /// clone
130 {
131  return new GeometricSolEnergy( *this );
132 }
133 
134 ///
135 void
137 {
139 
140  // We need the H-bond set -- well, at least the backbone/backbone h-bonds
141  // when computing geometric solvation scores.
142  // Since this is probably being computed elsewhere, might make sense
143  // to have a "calculated" flag.
144  // But, anyway, the geometric sol calcs take way longer than this.
146 
147  hbonds::HBondSetOP hbond_set( new hbonds::HBondSet( options_->hbond_options() ) );
148  hbond_set->setup_for_residue_pair_energies( pose );
149  pose.energies().data().set( HBOND_SET, hbond_set );
150 }
151 
152 /////////////////////////////////////////////////////////////////////////////
153 void
155 {
157 
158 // same setup as for HBondEnergy.cc. Note that this is probably repeating some work
159 // that has already occurred in hbonds calculation. Probably could have a "calculated"
160 // flag to save the computation ... but the geometric sol. calculation takes so
161 // much longer that this initial hbond loop isn't too bad.
163 
164  hbonds::HBondSetOP hbond_set( new hbonds::HBondSet( options_->hbond_options() ) );
165  hbonds::fill_hbond_set( pose, true /*calc derivs*/, *hbond_set );
166  hbond_set->resize_bb_donor_acceptor_arrays( pose.total_residue() );
167  pose.energies().data().set( HBOND_SET, hbond_set );
168 }
169 
170 
171 //void
172 //GeometricSolEnergy::setup_for_derivatives( pose::Pose & /*pose*/, ScoreFunction const & ) const
173 //{
174 //}
175 
176 
177 /////////////////////////////////////////////////////////////////////////////
178 // scoring
179 /////////////////////////////////////////////////////////////////////////////
180 
181 /// Everything in here.
182 void
184  conformation::Residue const & rsd1,
185  conformation::Residue const & rsd2,
186  pose::Pose const & pose,
187  ScoreFunction const &,
188  EnergyMap & emap
189 ) const
190 {
191 
192 
193  if ( rsd1.seqpos() == rsd2.seqpos() ) return; //Is this necessary?
194  // if ( exclude_DNA_DNA_ && rsd1.is_DNA() && rsd2.is_DNA() ) return;
195 
196  //////////////////////////////////
197  //Yo, what about count_pair?
198  //////////////////////////////////
199 
200  Real geo_solE =
201  res_res_geometric_sol_one_way( rsd1, rsd2, pose ) +
202  res_res_geometric_sol_one_way( rsd2, rsd1, pose ) ;
203 
204  // store the energies
205  emap[ geom_sol ] += geo_solE;
206 
207 }
208 
209 
210 /////////////////////////////////////////////////////////////////////
211 // This is meant to be a reasonable clone of John Karanicolas'
212 // Rosetta++ code. Some of the crazy options to do backbone only
213 // or side chain only are not ported over, but they could
214 // be implemented using the "atom_is_backbone" information.
215 //
216 // [Note to self (rhiju) : It might also make sense to precompute and cache this data
217 // in, say, a geometric solvation potential object, so that derivatives
218 // don't need to be computed over and over again, and code won't be
219 // copied. ]
220 //
221 Real
223  conformation::Residue const & polar_rsd,
224  conformation::Residue const & occ_rsd,
225  pose::Pose const & pose ) const
226 {
227 
228  Real geo_solE =
229  donorRes_occludingRes_geometric_sol_one_way( polar_rsd, occ_rsd, pose ) +
230  acceptorRes_occludingRes_geometric_sol_one_way( polar_rsd, occ_rsd, pose );
231 
232  return geo_solE;
233 }
234 
235 //////////////////////////////////////////////////////////////////////////////////////
236 Real
238  conformation::Residue const & don_rsd,
239  conformation::Residue const & occ_rsd,
240  pose::Pose const & pose ) const
241 {
242 
243  Real res_solE( 0.0 ), energy( 0.0 );
244 
245  // Here we go -- cycle through polar hydrogens in don_aa, everything heavy in occluding atom.
246  for ( chemical::AtomIndices::const_iterator
247  hnum = don_rsd.Hpos_polar().begin(),
248  hnume = don_rsd.Hpos_polar().end(); hnum != hnume; ++hnum ) {
249  Size const don_h_atm( *hnum );
250  for ( Size occ_atm = 1; occ_atm <= occ_rsd.nheavyatoms(); occ_atm++ ) {
251 
252  //Important NOTE. I originally had the code in the following function
253  // written out inside this loop -- and packing was faster.
254  // Perhaps something to do with inlining or compiler optimization.
255  // I've left it this way for now, because it helps prevent copying too
256  // much of the code shared between residue pair
257  // scoring and for the derivatives.
258  // However, if speed becomes important, here's a place to start.
260  occ_atm, occ_rsd, pose, energy );
261  res_solE += energy;
262  }
263  }
264 
265  return res_solE;
266 }
267 
268 ///////////////////////////////////////////////////////////////////////////////////////
269 Real
271  conformation::Residue const & acc_rsd,
272  conformation::Residue const & occ_rsd,
273  pose::Pose const & pose ) const
274 {
275 
276  Real res_solE( 0.0 ), energy( 0.0 );
277 
278  for ( chemical::AtomIndices::const_iterator
279  anum = acc_rsd.accpt_pos().begin(),
280  anume = acc_rsd.accpt_pos().end(); anum != anume; ++anum ) {
281  Size const acc_atm( *anum );
282  for ( Size occ_atm = 1; occ_atm <= occ_rsd.nheavyatoms(); occ_atm++ ) {
283 
284  //Important NOTE. I originally had the code in the following function
285  // written out inside this loop -- and packing was faster.
286  // Perhaps something to do with inlining or compiler optimization.
287  // I've left it this way for now, because it helps prevent copying too
288  // much of the code shared between residue pair
289  // scoring and for the derivatives.
290  // However, if speed becomes important, here's a place to start.
292  occ_atm, occ_rsd, pose, energy);
293  res_solE += energy;
294  }
295  }
296 
297  return res_solE;
298 }
299 
300 
301 //////////////////////////////////////////////////////////////////////////////
302 // Helper function for creating a mock H or O for the mock water.
303 // Assume it is in the same plane as that defined by the other
304 // atoms involved in the hydrogen bond.
305 // There are probably (better) examples of this function elsewhere in the code.
306 //
307 inline
308 void
310  Vector const & base_v,
311  Vector const & atom_v,
312  Vector const & water_v,
313  Vector & water_base_v,
314  Real const & xH /*cos(theta)*/,
315  Distance const & bond_length
316 ) const
317 {
318  Vector x,y,z, direction;
319 
320  //Define coordinate system.
321  z = cross( (water_v - atom_v), (atom_v - base_v) );
322  z.normalize();
323  y = water_v - atom_v;
324  y.normalize();
325  x = cross( y, z );
326 
327  // Plop the atom down
328  direction = xH * y + Real( std::sqrt( 1 - (xH * xH) ) ) * x;
329  water_base_v = water_v + bond_length * direction;
330 
331 }
332 
333 
334 /////////////////////////////////////////////////////////////////////////////////////////
335 inline
336 Real
338  bool const & is_donor,
339  hbonds::HBEvalTuple const & hbond_eval_type,
340  Vector const & polar_atm_xyz,
341  Vector const & base_atm_xyz,
342  Vector const & occluding_atm_xyz,
343  Size const & polar_nb,
344  Size const & occ_nb,
345  bool const update_deriv /* = false*/,
346  HBondDerivs & deriv /* = DUMMY_DERIV2D*/ ) const
347 {
348 
349  static bool const always_do_full_calculation( true );
350 
351  // jumpout criteria copied from hb_energy_deriv in hbonds.cc
352 
353  // Compute geometry
354  Real AHdis( 0.0 ), xD( 0.0 ), xH( 0.0 ), energy( 0.0 );
355 
356  //Craziness... create an artifical atom to complete "water molecule".
357  Vector water_base_atm;
358  static Distance const water_O_H_distance( 0.958 );
359  Real environment_weight( 1.0 );
360 
361  //Might be cleaner to separate this into two functions, one for donor, one for acceptor?
362  if ( is_donor ) {
363 
364  // water is the acceptor, give it perfect geometry
365  xH = 1./3.; // perfect geometry is cos( 180 - 109.5 degrees), which is 1/3
366 
367  // compute the distance to the accepting water
368  Real const AHdis2 = (polar_atm_xyz - occluding_atm_xyz).length_squared();
369  if ( AHdis2 > MAX_R2 ) return 0.0;
370  if ( AHdis2 < MIN_R2 ) return 0.0;
371  AHdis = std::sqrt(AHdis2);
372 
373  // find the cosine of the base-proton-water angle (xD)
374  xD = get_water_cos( base_atm_xyz, polar_atm_xyz, occluding_atm_xyz );
375  if ( xD < MIN_xD ) return 0.0;
376  if ( xD > MAX_xD ) return 0.0;
377 
378  //rhiju, testing alternative calculation that will give derivative.
379  Vector occluding_base_atm_xyz( 0.0 );
380  if ( update_deriv || always_do_full_calculation ) {
381  set_water_base_atm( base_atm_xyz, polar_atm_xyz, occluding_atm_xyz, occluding_base_atm_xyz,
382  xH, water_O_H_distance );
383  hb_energy_deriv( *hb_database_, options_->hbond_options(),
384  hbond_eval_type, base_atm_xyz, polar_atm_xyz,
385  occluding_atm_xyz,
386  occluding_base_atm_xyz,
387  occluding_base_atm_xyz,
388  energy, hbderiv_ABE_GO_NO_xH, deriv);
389  if (verbose_) tr << "DERIV ENERGY DONOR: " << energy;
390  }
391 
392  if (options_->hbond_options().use_hb_env_dep() ) {
393  environment_weight = hbonds::get_environment_dependent_weight( hbond_eval_type, polar_nb, occ_nb, options_->hbond_options() );
394  }
395 
396  } else {
397 
398  // water is the donor, give it perfect geometry
399  xD = 0.9999;
400 
401  // compute the distance to the accepting water proton
402  // subtract the water's OH distance to get the AHdis,
403  // since the distance computed was from the acceptor to the water oxygen
404  // note: water proton lies on the line between the acceptor and the water oxygen
405  AHdis = ( polar_atm_xyz - occluding_atm_xyz ).length();
406  AHdis -= water_O_H_distance; // water O-H distance
407  Real const AHdis2 = AHdis * AHdis;
408  if ( AHdis2 > MAX_R2 ) return 0.;
409  if ( AHdis2 < MIN_R2 ) return 0.;
410 
411  // find cosine of the base-acceptor-water_proton angle (xH)
412  // note: this is the same as the base-acceptor-water_oxygen angle
413  xH = get_water_cos( base_atm_xyz, polar_atm_xyz, occluding_atm_xyz );
414  if ( xH < MIN_xH ) return 0.;
415  if ( xH > MAX_xH ) return 0.;
416 
417  //rhiju, testing alternative calculation that will give derivative.
418  if ( update_deriv || always_do_full_calculation ) {
419  Vector occluding_base_atm_xyz( 0.0 );
420  set_water_base_atm( base_atm_xyz, polar_atm_xyz, occluding_atm_xyz, occluding_base_atm_xyz,
421  -xD, water_O_H_distance );
422  hb_energy_deriv( *hb_database_, options_->hbond_options(), hbond_eval_type,
423  occluding_atm_xyz, occluding_base_atm_xyz,
424  polar_atm_xyz, base_atm_xyz, base_atm_xyz,
425  energy, hbderiv_ABE_GO_NO_xD, deriv);
426  if (verbose_) tr << "DERIV ENERGY ACCPT: " << energy;
427 
428  if (options_->hbond_options().use_hb_env_dep() ) {
429  environment_weight = hbonds::get_environment_dependent_weight( hbond_eval_type, polar_nb, occ_nb, options_->hbond_options() );
430  }
431 
432  }
433 
434 
435  }
436 
437  // Note that following should be a little faster and could be used if derivative is not necessary
438  // However, use of hb_energy_deriv gives nearly exact match of analytical and numerical.
439  // while every once in a while this does not...
440  if ( !always_do_full_calculation ) {
441  Real dummy_chi( 0.0 );
442  assert( ! options_->hbond_options().use_sp2_chi_penalty() ); // APL avoid the new sp2 chi term.
444  *hb_database_, options_->hbond_options(), hbond_eval_type,
445  AHdis, xD, xH, dummy_chi, energy );
446  }
447 
448  if (verbose_ ) tr << " jk ENERGY: " << energy << std::endl;
449 
450  core::Real sol_penalty = -1.0 * energy;
451 
452  // jk THIS NEEDS TO BE FIT MORE RIGOROUSLY LATER...
453  // Apply a scaling factor (effectively a weight), tying the weight of the
454  // solvation term to the Hbond term (rather than to the LK weight)
455  // Note: chose the bb-sc Hbond weight, because they're all about the same
456  // core::Real const sol_weight = geometric_sol_weight * pack_wts.Whbond_bb_sc() / pack_wts.Wsol();
457  Real reweight = geometric_sol_scale_ * environment_weight;
458 
459  sol_penalty *= reweight;
460 
461  /////////////////////////////////////////////////////////
462  /////////////////////////////////////////////////////////
463  /////////////////////////////////////////////////////////
464  // WHERE DOES THE ENVIRONMENT WEIGHT COME IN?
465  // -- wasn't taken into account in rosetta++ --
466  /////////////////////////////////////////////////////////
467  /////////////////////////////////////////////////////////
468  /////////////////////////////////////////////////////////
469  if ( update_deriv ){
470  if ( is_donor ) {
471  deriv.h_deriv.f1() *= -1.0 * reweight;
472  deriv.h_deriv.f2() *= -1.0 * reweight;
473  deriv.don_deriv.f1() *= -1.0 * reweight;
474  deriv.don_deriv.f2() *= -1.0 * reweight;
475  } else {
476  // had to flip reference frame to get HB energy and derivative.
477  deriv.h_deriv.f1() *= +1.0 * reweight;
478  deriv.h_deriv.f2() *= +1.0 * reweight;
479  deriv.don_deriv.f1() *= +1.0 * reweight;
480  deriv.don_deriv.f2() *= +1.0 * reweight;
481  }
482 
483  }
484 
485  // this is a penalty, don't return a negative number
486  if (sol_penalty < 0.) {
487  if ( update_deriv ) deriv = ZERO_DERIV2D;
488  return 0.;
489  }
490 
491  // if (sol_penalty > 0. ) {
492  // tr << F(7,3,polar_atm_xyz(1)) << " " << F(7,3,base_atm_xyz(1)) << " " << F(7,3,occluding_atm_xyz(1) ) << std::endl;
493  // tr << "[AHdis " << F(7,3,AHdis) << "; xD " << F(7,3,xD) << "; xH " << F(7,3,xH) << ", e " << F(7,3,energy) << "]" ;
494  // }
495 
496  return sol_penalty; // return a positive number (this is a penalty)
497 
498 }
499 
500 
501 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
502 inline
503 void
505  Size const & don_h_atm,
506  conformation::Residue const & don_rsd,
507  Size const & occ_atm,
508  conformation::Residue const & occ_rsd,
509  pose::Pose const & pose,
510  Real & energy,
511  bool const update_deriv /*= false*/,
512  HBondDerivs & deriv /* = DUMMY_DERIVS */
513 ) const
514 {
516 
517  //Why do we need to send in the pose and the residue stuff?
518  // Well, the pose has info on backbone H-bonds.
519  // and, during design, the residue type doesn't actually
520  // have to match what's in the pose! Tricky!
521 
522  // In case of early return, initialize. Note that energy *does not* accumulate
523  energy = 0.0;
524  deriv = ZERO_DERIV2D;
525 
526  //Need to know about backbone/backbone H-bonds for proteins
527  hbonds::HBondSet const & hbond_set
528  ( static_cast< hbonds::HBondSet const & >
529  ( pose.energies().data().get( HBOND_SET )));
530  TenANeighborGraph const & tenA_neighbor_graph
531  ( pose.energies().tenA_neighbor_graph() );
532 
533  assert( atom_is_donor_h( don_rsd, don_h_atm ) );
534 
535  Size const don_base_atm( don_rsd.atom_base( don_h_atm ) );
536 
537  Vector const & don_h_atm_xyz( don_rsd.atom( don_h_atm ).xyz() );
538  Vector const & don_base_atm_xyz( don_rsd.atom( don_base_atm ).xyz() );
539 
540  // the base atom isn't allowed to occlude solvent
541  // Note: In current implementation, intraresidue pairs aren't checked...
542  if ( ( don_rsd.seqpos() == occ_rsd.seqpos() ) && ( occ_atm == don_base_atm ) ) return;
543 
544  ////////////////06/26/2011: Parin Sripakdeevong (sripakpa@stanford.edu)/////////////////////
545  if(occ_rsd.is_virtual(occ_atm)) return;
546  if(don_rsd.is_virtual(don_h_atm)) return;
547  ////////////////////////////////////////////////////////////////////////////////////////////
548 
549  // if a backbone donor participates in a backbone-backbone Hbond,
550  // nothing is allowed to occlude solvent except a backbone acceptor
551  bool const don_h_atm_is_protein_backbone
552  ( don_rsd.is_protein() && don_rsd.atom_is_backbone( don_h_atm ) );
553  bool const occ_atm_is_protein_backbone_acceptor
554  ( occ_rsd.is_protein() && occ_rsd.atom_is_backbone( occ_atm ) && atom_is_acceptor(occ_rsd, occ_atm ) );
555  if ( don_h_atm_is_protein_backbone && hbond_set.don_bbg_in_bb_bb_hbond( don_rsd.seqpos() ) &&
556  !occ_atm_is_protein_backbone_acceptor ) {
557  return;
558  }
559 
560  // if the distance is > 5.2 A, from the base atom, it doesn't occlude solvent
561  Vector const & occ_atm_xyz( occ_rsd.atom( occ_atm ).xyz() );
562  Real const base_dis2 = ( occ_atm_xyz - don_base_atm_xyz).length_squared();
563  if ( base_dis2 > dist_cut2_ ) return;
564 
565  // if distance to base atom is greater than distance to donor, it doesn't occlude solvent
566  Real const hdis2 = ( occ_atm_xyz - don_h_atm_xyz ).length_squared();
567  if ( hdis2 > base_dis2 ) return;
568 
569  // For a backbone CO occluding a backbone NH, use the backbone-backbone (linear) geometry
570  // to compute solvation penalty (only really matters for the CO acceptor's geometry, but
571  // do it here as well for consistency)
572  bool const potential_backbone_backbone_hbond =
573  ( don_h_atm_is_protein_backbone && occ_atm_is_protein_backbone_acceptor );
574  HBEvalTuple hbe = potential_backbone_backbone_hbond ? ( HBEvalTuple( don_base_atm, don_rsd, occ_atm, occ_rsd) ) : HBEvalTuple( hbdon_HXL, hbacc_HXL, seq_sep_other ); // apl note: the false condition maps to hbe_dHXLaHXL
575 
576  Size const don_nbrs = tenA_neighbor_graph.get_node( don_rsd.seqpos() )->num_neighbors_counting_self();
577  Size const occ_nbrs = tenA_neighbor_graph.get_node( occ_rsd.seqpos() )->num_neighbors_counting_self();
578 
579  // jk Compute the Hbond energy as if this was a water
580  // jk Add the water Hbond energy to a running total sum, as well as to the residue sum
581  // mjo not sure what hbe should be if potential_backbone_backbone_hbond is false,
582  // mjo I'm setting it to arbitrary type that previously was hbe_SP3SC just for consistency.
583  // mjo Previously it ignores sequence separation. why?
585  true /*is_donor*/, hbe,
586  don_h_atm_xyz, don_base_atm_xyz, occ_atm_xyz,
587  don_nbrs, occ_nbrs,
588  update_deriv, deriv);
589 
590  if ( verbose_ && ( energy > 0.0 ) ) {
591  tr <<"jk DON res "<< don_rsd.name1() << I(3,don_rsd.seqpos())<<
592  " atom "<< don_rsd.atom_name( don_h_atm )<<" is occluded by occ_res " <<
593  occ_rsd.name1()<< I(3, occ_rsd.seqpos()) <<
594  " atom "<< occ_rsd.atom_name( occ_atm ) <<
595  " (HBEvalType " << I(2,hbe.eval_type()) << ") " <<
596  " with energy "<< F(8,3,energy)<< std::endl;
597  }
598 }
599 
600 
601 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
602 inline
603 Vector
605 
606  Vector base_atm_xyz;
607 
609  // following handles the special case in which acceptor has two base residues -- occurs for
610  // N inside rings.
611  // This matches machinery in hbonds_geom.cc. That doesn't mean that the base atom is set
612  // totally correctly -- water (TIP3.params) and O4* in nucleic acids still have weird base atoms,
613  // but at least the hbonds and geom_sol match up.
614  Vector dummy;
615  chemical::Hybridization acc_hybrid( acc_rsd.atom_type( acc_atm ).hybridization());
617  options_->hbond_options(),
618  acc_hybrid,
619  acc_rsd.atom( acc_atm ).xyz(),
620  acc_rsd.xyz( acc_rsd.atom_base( acc_atm ) ),
621  acc_rsd.xyz( acc_rsd.abase2( acc_atm ) ),
622  base_atm_xyz, dummy );
623  } else {
624  base_atm_xyz = acc_rsd.atom( acc_rsd.atom_base( acc_atm ) ).xyz();
625  }
626  return base_atm_xyz;
627 }
628 
629 
630 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
631 inline
632 void
634  Size const & acc_atm,
635  conformation::Residue const & acc_rsd,
636  Size const & occ_atm,
637  conformation::Residue const & occ_rsd,
638  pose::Pose const & pose,
639  Real & energy,
640  bool const update_deriv /*= false*/,
641  HBondDerivs & deriv /* = DUMMY_DERIV2D */) const
642 {
644 
645  //Why do we need to send in the pose and the residue stuff?
646  // Well, the pose has info on backbone H-bonds.
647  // and, during design, the residue type doesn't actually
648  // have to match what's in the pose! Tricky!
649 
650  // In case of early return, initialize. Note that energy *does not* accumulate
651  energy = 0.0;
652  deriv = ZERO_DERIV2D;
653 
654  //Need to know about backbone/backbone H-bonds for proteins
655  hbonds::HBondSet const & hbond_set
656  ( static_cast< hbonds::HBondSet const & >
657  ( pose.energies().data().get( HBOND_SET )));
658  TenANeighborGraph const & tenA_neighbor_graph
659  ( pose.energies().tenA_neighbor_graph() );
660 
661  assert( atom_is_acceptor( acc_rsd, acc_atm ) );
662 
663  Size const base_atm ( acc_rsd.atom_base( acc_atm ) );
664 
665  Vector const & acc_atm_xyz( acc_rsd.atom( acc_atm ).xyz() );
666 
667  Vector base_atm_xyz = get_acceptor_base_atm_xyz( acc_rsd, acc_atm );
668 
669  bool const acc_atm_is_protein_backbone
670  ( acc_rsd.is_protein() && acc_rsd.atom_is_backbone( acc_atm ) );
671 
672  // Virtual atom (e.g., Andrew Leaver-Fay's NV in proline) don't count.
673  // Maybe this should be a helper function inside residue.
674 
675  ////////////////06/26/2011: Parin Sripakdeevong (sripakpa@stanford.edu)/////////////////////
676  if(occ_rsd.is_virtual(occ_atm)) return;
677  if(acc_rsd.is_virtual(acc_atm)) return;
678  ////////////////////////////////////////////////////////////////////////////////////////////
679 
680  // the base atom isn't allowed to occlude solvent
681  // Note: In current implementation, intraresidue pairs aren't checked...
682  if ( ( acc_rsd.seqpos() == occ_rsd.seqpos() ) && ( occ_atm == base_atm ) ) return;
683 
684  // if a backbone acceptor participates in a backbone-backbone Hbond,
685  // nothing is allowed to occlude solvent except a backbone donor
686  bool const occ_atm_is_protein_backbone_donor
687  ( occ_rsd.is_protein() && occ_rsd.atom_is_backbone( occ_atm ) && atom_is_donor(occ_rsd, occ_atm ) );
688  if ( acc_atm_is_protein_backbone && hbond_set.acc_bbg_in_bb_bb_hbond( acc_rsd.seqpos() ) &&
689  !occ_atm_is_protein_backbone_donor ) return;
690 
691  // an atom directly bound to the acceptor isn't allowed to occlude solvent
692  // Note: In current implementation, intraresidue pairs aren't checked...
693  if ( ( acc_rsd.seqpos() == occ_rsd.seqpos() ) && acc_rsd.path_distance( acc_atm, occ_atm ) < 2 ) return;
694 
695  // if the distance is > 5.2 A, from the acceptor, it doesn't occlude solvent
696  Vector const & occ_atm_xyz( occ_rsd.atom( occ_atm ).xyz() );
697  Real const acc_dis2 = ( occ_atm_xyz - acc_atm_xyz ).length_squared();
698  if ( acc_dis2 > dist_cut2_ ) return;
699 
700  // if distance to base atom is greater than distance to donor, it doesn't occlude solvent
701  Real const base_dis2 = ( occ_atm_xyz - base_atm_xyz ).length_squared();
702  if ( acc_dis2 > base_dis2 ) return;
703 
704  // For a backbone NH occluding a backbone CO, use the backbone-backbone (linear) geometry
705  // to compute solvation penalty
706  bool const potential_backbone_backbone_hbond =
707  ( acc_atm_is_protein_backbone && occ_atm_is_protein_backbone_donor );
708  // Following distinguished between helix/turn/etc. based on seq. separation. Is that what we want? Not in original jk code, so not for now.
709  // HBEvalType hbe = potential_backbone_backbone_hbond ? ( hbond_evaluation_type( occ_atm, occ_rsd, acc_atm, acc_rsd) ) : hbe_SP3SC;
710  // HBEvalType hbe = potential_backbone_backbone_hbond ? hbe_BSC : hbe_SP3SC;
711  HBEvalTuple hbe = potential_backbone_backbone_hbond ? ( HBEvalTuple( occ_atm, occ_rsd, acc_atm, acc_rsd ) ) :
713 
714  Size const acc_nbrs = tenA_neighbor_graph.get_node( acc_rsd.seqpos() )->num_neighbors_counting_self();
715  Size const occ_nbrs = tenA_neighbor_graph.get_node( occ_rsd.seqpos() )->num_neighbors_counting_self();
716 
717  // jk Compute the Hbond energy as if this was a water
718  // jk Add the water Hbond energy to a running total sum, as well as to the residue sum
720  false /*is_donor*/, hbe,
721  acc_atm_xyz, base_atm_xyz, occ_atm_xyz,
722  acc_nbrs, occ_nbrs,
723  update_deriv, deriv);
724 
725  if ( verbose_ && ( energy > 0.0 ) ) {
726  tr<<"jk ACC res "<< acc_rsd.name1() << I(3, acc_rsd.seqpos())<<
727  " atom "<< acc_rsd.atom_name( acc_atm )<<" is occluded by occ_res "<<
728  occ_rsd.name1()<< I(3, occ_rsd.seqpos()) <<
729  " atom "<< occ_rsd.atom_name( occ_atm ) <<
730  " (HBEvalType " << I(2,hbe.eval_type()) << ") " <<
731  " with energy "<< F(8,3,energy)<<std::endl;
732 
733  }
734 
735 }
736 
737 
738 ///////////////////////////////////////////////////////////////////////////////
739 /// Compute the cosine required for calling water Hbond energies
740 inline
741 Real
743  Vector const & polar_atm_xyz,
744  Vector const & occluding_atm_xyz ) const
745 {
746  return dot( (polar_atm_xyz - base_atm_xyz).normalize(), (occluding_atm_xyz - polar_atm_xyz).normalize() );
747 }
748 
749 
750 //////////////////////////////////////////////////////////////////////////////////////
751 // Stupid helper function
752 // These should probably live inside conformation::Residue.
753 //
754 bool
756 {
757  for ( chemical::AtomIndices::const_iterator
758  hnum = rsd.Hpos_polar().begin(),
759  hnume = rsd.Hpos_polar().end(); hnum != hnume; ++hnum ) {
760  Size const don_h_atm( *hnum );
761  Size const don_base_atm( rsd.atom_base( don_h_atm ) );
762  if ( don_base_atm == atm ) return true;
763  }
764  return false;
765 }
766 //////////////////////////////////////////////////////////////////////////////////////
767 // Stupid helper function
768 // These should probably live inside conformation::Residue.
769 //
770 bool
772 {
773  for ( chemical::AtomIndices::const_iterator
774  hnum = rsd.Hpos_polar().begin(),
775  hnume = rsd.Hpos_polar().end(); hnum != hnume; ++hnum ) {
776  Size const don_h_atm( *hnum );
777  if ( don_h_atm == atm ) return true;
778  }
779  return false;
780 }
781 //////////////////////////////////////////////////////////////////////////////
782 // Stupid helper function
783 // These should probably live inside conformation::Residue.
784 bool
786 {
787  for ( chemical::AtomIndices::const_iterator
788  anum = rsd.accpt_pos().begin(),
789  anume = rsd.accpt_pos().end(); anum != anume; ++anum ) {
790  Size const acc_atm( *anum );
791  if ( acc_atm == atm ) return true;
792  }
793  return false;
794 }
795 
796 //////////////////////////////////////////////////////////////////////////////
797 // Stupid helper function
798 // These should probably live inside conformation::Residue.
799 bool
801 {
802  //Could check if its hydrogen, but this is the same delineation used in the
803  // residue-residue pair energy loop.
804  return (atm <= rsd.nheavyatoms() );
805 }
806 
807 //////////////////////////////////////////////////////////////////////////////
808 void
810  id::AtomID const & atom_id,
811  pose::Pose const & pose,
812  EnergyMap const & weights,
813  Vector & F1,
814  Vector & F2
815 ) const
816 {
817 
818  Size const i( atom_id.rsd() );
819 
820  conformation::Residue const & current_rsd( pose.residue( i ) );
821  conformation::Residue const & other_rsd( pose.residue( i ) );
822 
823  //Ok right now intrares energy is define only for the RNA case. Parin Sripakdeevong, June 26, 2011.
824  if(current_rsd.is_RNA()==false) return;
825  if(other_rsd.is_RNA()==false) return; //no effect!
826 
827  static bool const update_deriv( true );
828 
829  Real energy( 0.0 );
830  hbonds::HBondDerivs deriv;
831 
832  Size const current_atm( atom_id.atomno() );
833 
834  if(verbose_) std::cout << "Start eval_atom_derivative, intra_res case, res= " << i << " atomno= " << current_atm << "[" << current_rsd.atom_name(current_atm) << "]" << std::endl;
835 
836  // If this atom is a donor, go over heavy atoms in other residue.
837  if ( atom_is_donor_h( current_rsd, current_atm ) ) {
838  for (Size m = 1; m <= other_rsd.nheavyatoms(); m++ ){
839 
840  if(core::scoring::rna::Is_base_phosphate_atom_pair(current_rsd, other_rsd, current_atm, m)==false) continue;
841 
842  get_atom_atom_geometric_solvation_for_donor( current_atm, current_rsd, m, other_rsd, pose, energy, update_deriv, deriv );
843 
844  F1 += weights[ geom_sol_intra_RNA ] * ( deriv.h_deriv.f1() + deriv.don_deriv.f1() );
845  F2 += weights[ geom_sol_intra_RNA ] * ( deriv.h_deriv.f2() + deriv.don_deriv.f2() );
846  }
847  }
848 
849  // If this atom is an acceptor, go over heavy atoms in other residue.
850  if ( atom_is_acceptor( current_rsd, atom_id.atomno() ) ) {
851  for (Size m = 1; m <= other_rsd.nheavyatoms(); m++ ){
852 
853  if(core::scoring::rna::Is_base_phosphate_atom_pair(current_rsd, other_rsd, current_atm, m)==false) continue;
854 
855  get_atom_atom_geometric_solvation_for_acceptor( current_atm, current_rsd, m, other_rsd, pose, energy, update_deriv, deriv );
856 
857  F1 += weights[ geom_sol_intra_RNA ] * ( deriv.h_deriv.f1() + deriv.don_deriv.f1() );
858  F2 += weights[ geom_sol_intra_RNA ] * ( deriv.h_deriv.f2() + deriv.don_deriv.f2() );
859  }
860  }
861 
862  //Treat atom as occluder if its heavy.
863  if ( atom_is_heavy( current_rsd, atom_id.atomno() ) ) {
864  // Go over donors in other atom.
865  for ( chemical::AtomIndices::const_iterator hnum = other_rsd.Hpos_polar().begin(), hnume = other_rsd.Hpos_polar().end(); hnum != hnume; ++hnum ) {
866  Size const don_h_atm( *hnum );
867 
868  if(core::scoring::rna::Is_base_phosphate_atom_pair(current_rsd, other_rsd, current_atm, don_h_atm)==false) continue;
869 
870  get_atom_atom_geometric_solvation_for_donor( don_h_atm, other_rsd, atom_id.atomno(), current_rsd, pose, energy, update_deriv, deriv );
871 
872  F1 -= weights[ geom_sol_intra_RNA ] * ( deriv.h_deriv.f1() + deriv.don_deriv.f1() );
873  F2 -= weights[ geom_sol_intra_RNA ] * ( deriv.h_deriv.f2() + deriv.don_deriv.f2() );
874  }
875 
876  // Go over acceptors in other atom.
877  for ( chemical::AtomIndices::const_iterator anum = other_rsd.accpt_pos().begin(), anume = other_rsd.accpt_pos().end(); anum != anume; ++anum ) {
878  Size const acc_atm ( *anum );
879 
880  if(core::scoring::rna::Is_base_phosphate_atom_pair(current_rsd, other_rsd, current_atm, acc_atm)==false) continue;
881 
882  get_atom_atom_geometric_solvation_for_acceptor( acc_atm, other_rsd, atom_id.atomno(), current_rsd, pose, energy, update_deriv, deriv );
883 
884  F1 -= weights[ geom_sol_intra_RNA ] * ( deriv.h_deriv.f1() + deriv.don_deriv.f1() );
885  F2 -= weights[ geom_sol_intra_RNA ] * ( deriv.h_deriv.f2() + deriv.don_deriv.f2() );
886  }
887  }
888 
889  if(verbose_){
890  std::cout << "eval_atom_derivative, intra_res :";
891  std::cout << " F1= " << F1[0] << " " << F1[1] << " " << F1[2];
892  std::cout << " F2= " << F2[0] << " " << F2[1] << " " << F2[2] << std::endl;
893  std::cout << "Finish eval_atom_derivative, intra_res case, res= " << i << " atomno= " << current_atm << "[" << current_rsd.atom_name(current_atm) << "]" << std::endl;
894  }
895 }
896 
897 
898 //////////////////////////////////////////////////////////////////////////////
899 // Note that this computes every interaction *twice* -- three times if you
900 // note that the score calculation above does most of the computation already.
901 // Oh well -- we currently assume derivative calculation doesn't happen to often!
902 //
903 void
905  id::AtomID const & atom_id,
906  pose::Pose const & pose,
907  kinematics::DomainMap const &,
908  ScoreFunction const &,
909  EnergyMap const & weights,
910  Vector & F1,
911  Vector & F2
912 ) const
913 {
914 
915  Real energy( 0.0 );
916  hbonds::HBondDerivs deriv;
917 
918  eval_atom_derivative_intra_RNA(atom_id, pose, weights, F1, F2);
919 
920  conformation::Residue const & current_rsd( pose.residue( atom_id.rsd() ) );
921 
922  Size const i( atom_id.rsd() );
923  Size const current_atm( atom_id.atomno() );
924 
925  // Size const nres = pose.total_residue();
926  static bool const update_deriv( true );
927 
928  EnergyGraph const & energy_graph( pose.energies().energy_graph() );
929 
931  iter = energy_graph.get_node( i )->const_edge_list_begin();
932  iter != energy_graph.get_node( i )->const_edge_list_end();
933  ++iter ){
934 
935  Size j( (*iter)->get_other_ind( i ) );
936 
937  if ( i == j ) continue; //Parin S. Already dealt with above for the intra_RNA case! Plus I think a edge doesn't point to itself!
938 
939  conformation::Residue const & other_rsd( pose.residue( j ) );
940 
941  // If this atom is a donor, go over heavy atoms in other residue.
942  if ( atom_is_donor_h( current_rsd, current_atm ) ) {
943  for (Size m = 1; m <= other_rsd.nheavyatoms(); m++ ){
944  get_atom_atom_geometric_solvation_for_donor( current_atm, current_rsd,
945  m, other_rsd,
946  pose, energy, update_deriv, deriv );
947  F1 += weights[ geom_sol ] * ( deriv.h_deriv.f1() + deriv.don_deriv.f1() );
948  F2 += weights[ geom_sol ] * ( deriv.h_deriv.f2() + deriv.don_deriv.f2() );
949 
950  }
951  }
952 
953  // If this atom is an acceptor, go over heavy atoms in other residue.
954  if ( atom_is_acceptor( current_rsd, atom_id.atomno() ) ) {
955  for (Size m = 1; m <= other_rsd.nheavyatoms(); m++ ){
956  get_atom_atom_geometric_solvation_for_acceptor( current_atm, current_rsd,
957  m, other_rsd,
958  pose, energy, update_deriv, deriv );
959  F1 += weights[ geom_sol ] * ( deriv.h_deriv.f1() + deriv.don_deriv.f1() );
960  F2 += weights[ geom_sol ] * ( deriv.h_deriv.f2() + deriv.don_deriv.f2() );
961 
962  }
963  }
964 
965  //Treat atom as occluder if its heavy.
966  if ( atom_is_heavy( current_rsd, atom_id.atomno() ) ) {
967  // Go over donors in other atom.
968  for ( chemical::AtomIndices::const_iterator
969  hnum = other_rsd.Hpos_polar().begin(),
970  hnume = other_rsd.Hpos_polar().end(); hnum != hnume; ++hnum ) {
971  Size const don_h_atm( *hnum );
972  get_atom_atom_geometric_solvation_for_donor( don_h_atm, other_rsd,
973  atom_id.atomno(), current_rsd,
974  pose, energy, update_deriv, deriv );
975  F1 -= weights[ geom_sol ] * ( deriv.h_deriv.f1() + deriv.don_deriv.f1() );
976  F2 -= weights[ geom_sol ] * ( deriv.h_deriv.f2() + deriv.don_deriv.f2() );
977 
978  }
979 
980  // Go over acceptors in other atom.
981  for ( chemical::AtomIndices::const_iterator
982  anum = other_rsd.accpt_pos().begin(),
983  anume = other_rsd.accpt_pos().end(); anum != anume; ++anum ) {
984  Size const acc_atm ( *anum );
986  atom_id.atomno(), current_rsd,
987  pose, energy, update_deriv, deriv );
988  F1 -= weights[ geom_sol ] * ( deriv.h_deriv.f1() + deriv.don_deriv.f1() );
989  F2 -= weights[ geom_sol ] * ( deriv.h_deriv.f2() + deriv.don_deriv.f2() );
990 
991  }
992  }
993 
994  }
995 
996 }
997 
998 ////////////////////////////////////////////////////////////////////
999 // Only return energy for occluded polar atoms.
1000 Real
1002  id::AtomID const & atom_id,
1003  pose::Pose const & pose
1004 ) const
1005 {
1006 
1007 
1008  Real total_energy( 0.0 );
1009 
1010  conformation::Residue const & current_rsd( pose.residue( atom_id.rsd() ) );
1011 
1012  Size const i( atom_id.rsd() );
1013  Size const current_atm( atom_id.atomno() );
1014 
1015  EnergyGraph const & energy_graph( pose.energies().energy_graph() );
1016 
1018  iter = energy_graph.get_node( i )->const_edge_list_begin();
1019  iter != energy_graph.get_node( i )->const_edge_list_end();
1020  ++iter ){
1021 
1022  Size j( (*iter)->get_other_ind( i ) );
1023 
1024  //As above disallow contribution within a residue. Is this OK? Sure there shouldn't be an "intra" term?
1025  // anyway list of neighbors does not include i==j.
1026  if ( i == j ) continue;
1027 
1028  conformation::Residue const & other_rsd( pose.residue( j ) );
1029 
1030  // If this atom is a donor, go over heavy atoms in other residue.
1031  if ( atom_is_donor_h( current_rsd, current_atm ) ) {
1032  for (Size m = 1; m <= other_rsd.nheavyatoms(); m++ ){
1033  Real energy( 0.0 );
1034  get_atom_atom_geometric_solvation_for_donor( current_atm, current_rsd,
1035  m, other_rsd, pose, energy );
1036  total_energy += energy;
1037  }
1038  }
1039 
1040  // If this atom is an acceptor, go over heavy atoms in other residue.
1041  if ( atom_is_acceptor( current_rsd, atom_id.atomno() ) ) {
1042  for (Size m = 1; m <= other_rsd.nheavyatoms(); m++ ){
1043  Real energy( 0.0 );
1044  get_atom_atom_geometric_solvation_for_acceptor( current_atm, current_rsd,
1045  m, other_rsd, pose, energy );
1046  total_energy += energy;
1047  }
1048  }
1049 
1050  }
1051 
1052  return total_energy;
1053 }
1054 
1055 
1056 ///////////////////////////////////////////////////////////
1057 /// Note -- this is used in HBonds to
1058 /// add up backbone/backbone energies,
1059 /// while the residue_pair_energy does the
1060 /// sidechain stuff. For now make this an
1061 /// empty function, although it will come back into
1062 /// the game if we decide to speed up the packer.
1063 ///////////////////////////////////////////////////////////
1064 //void
1065 //GeometricSolEnergy::finalize_total_energy(
1066 // pose::Pose &,
1067 // ScoreFunction const &,
1068 // EnergyMap & totals
1069 //) const
1070 //{
1071 // using core::scoring::EnergiesCacheableDataType::HBOND_SET;
1072 //
1073 // hbonds::GeometricSolSet const & hbond_set
1074 // ( static_cast< hbonds::GeometricSolSet const & >
1075 // ( pose.energies().data().get( HBOND_SET )));
1076 
1077 // Real lr_bbE( 0.0 ), sr_bbE( 0.0 ), bb_scE( 0.0 ), scE( 0.0 );
1078 
1079 // get_hbond_energies( hbond_set, sr_bbE, lr_bbE, bb_scE, scE );
1080 
1081 // // the current logic is that we fill the hbond set with backbone
1082 // // hbonds only at the beginning of scoring. this is done to setup
1083 // // the bb-bb hbond exclusion logic. so the hbondset should only
1084 // // include bb-bb hbonds.
1085 // // but see get_hb_don_chem_type in hbonds_geom.cc -- that only
1086 // // classifies protein backbone donors as backbone, and the energy
1087 // // accumulation by type is influenced by that via HBeval_lookup
1088 // //
1089 // // the important thing is that there's no double counting, which
1090 // // is I think true since both fill_hbond_set and get_rsd-rsd-energy
1091 // // use atom_is_backbone to check...
1092 // //assert( std::abs( bb_scE ) < 1e-3 && std::abs( scE ) < 1e-3 );
1093 // totals[ hbond_sr_bb ] += sr_bbE;
1094 // totals[ hbond_lr_bb ] += lr_bbE;
1095 //}
1096 
1097 // COPIED OVER FROM HBondEnergy.cc ==> comment is not rhiju's!
1098 ///@brief HACK! MAX_R defines the maximum donorH to acceptor distance.
1099 // The atomic_interaction_cutoff method is meant to return the maximum distance
1100 // between two *heavy atoms* for them to have a zero interaction energy.
1101 // I am currently assuming a 1.35 A maximum distance between a hydrogen and the
1102 // heavy atom it is bound to, stealing this number from the CYS.params file since
1103 // the HG in CYS is much further from it's SG than aliphatic hydrogens are from their carbons.
1104 // This is a bad idea. Someone come up with a way to fix this!
1105 //
1106 // At 4.35 A interaction cutoff, the hbond energy function is incredibly short ranged!
1107 Distance
1109 {
1110  return MAX_R + 1.35; // MAGIC NUMBER
1111 }
1112 
1113 ///////////////////////////////////////////////////////////////////////////////////////
1114 bool
1116 {
1117  //bool condition_1= (weights[geom_sol_intra_RNA]>0.0) ? true : false;
1118 
1119  bool condition_1= (weights[geom_sol_intra_RNA]>0.0001) ? true : false; //Change to this on Feb 06, 2012. Ensure that the function returns false if weights[geom_sol_intra_RNA]==0.0
1120 
1121  return condition_1;
1122 }
1123 
1124 ///////////////////////////////////////////////////////////////////////////////////////
1125 void
1127  conformation::Residue const & rsd,
1128  pose::Pose const & pose,
1129  ScoreFunction const & ,
1130  EnergyMap & emap
1131 ) const{
1132 
1133  if(rsd.is_RNA()==false) return;
1134 
1135  Real geo_solE_intra_RNA =
1138 
1139  // store the energies
1140  emap[ geom_sol_intra_RNA ] += geo_solE_intra_RNA;
1141 
1142 }
1143 
1144 ///////////////////////////////////////////////////////////////////////////////////////
1145 Real
1147  conformation::Residue const & rsd,
1148  pose::Pose const & pose ) const
1149 {
1150 
1151 
1152  Real res_solE( 0.0 ), energy( 0.0 );
1153 
1154  conformation::Residue const & don_rsd=rsd;
1155  conformation::Residue const & occ_rsd=rsd;
1156 
1157  // Here we go -- cycle through polar hydrogens in don_aa, everything heavy in occluding atom.
1158  for ( chemical::AtomIndices::const_iterator hnum = don_rsd.Hpos_polar().begin(), hnume = don_rsd.Hpos_polar().end(); hnum != hnume; ++hnum ) {
1159  Size const don_h_atm( *hnum );
1160  for ( Size occ_atm = 1; occ_atm <= occ_rsd.nheavyatoms(); occ_atm++ ) {
1161 
1162  if(core::scoring::rna::Is_base_phosphate_atom_pair(rsd, rsd, occ_atm, don_h_atm)==false) continue;
1163 
1164  get_atom_atom_geometric_solvation_for_donor( don_h_atm, don_rsd, occ_atm, occ_rsd, pose, energy );
1165  res_solE += energy;
1166  }
1167  }
1168 
1169  return res_solE;
1170 }
1171 
1172 ///////////////////////////////////////////////////////////////////////////////////////
1173 Real
1175  conformation::Residue const & rsd,
1176  pose::Pose const & pose ) const
1177 {
1178 
1179  conformation::Residue const & acc_rsd=rsd;
1180  conformation::Residue const & occ_rsd=rsd;
1181 
1182 
1183  Real res_solE( 0.0 ), energy( 0.0 );
1184 
1185  for ( chemical::AtomIndices::const_iterator anum = acc_rsd.accpt_pos().begin(), anume = acc_rsd.accpt_pos().end(); anum != anume; ++anum ) {
1186  Size const acc_atm( *anum );
1187  for ( Size occ_atm = 1; occ_atm <= occ_rsd.nheavyatoms(); occ_atm++ ) {
1188 
1189  if(core::scoring::rna::Is_base_phosphate_atom_pair(rsd, rsd, occ_atm, acc_atm)==false) continue;
1190 
1191  get_atom_atom_geometric_solvation_for_acceptor( acc_atm, acc_rsd, occ_atm, occ_rsd, pose, energy);
1192  res_solE += energy;
1193 
1194  }
1195  }
1196 
1197  return res_solE;
1198 }
1199 
1200 ///////////////////////////////////////////////////////////////////////////////////////
1201 
1202 ///@brief GeometricSolEnergy is context sensitive
1203 void
1205  utility::vector1< bool > & context_graphs_required
1206 ) const
1207 {
1208  context_graphs_required[ ten_A_neighbor_graph ] = true;
1209 }
1210 core::Size
1212 {
1213  return 1; // Initial versioning
1214 }
1215 
1216 
1217 } // hbonds
1218 } // scoring
1219 } // core
1220