Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
OccludedHbondSolEnergy.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 part of the Rosetta software suite and is made available under license.
5 // The Rosetta software is developed by the contributing members of the Rosetta Commons consortium.
6 // (C) 199x-2009 Rosetta Commons participating institutions and developers.
7 // For more information, see http://www.rosettacommons.org/.
8 
9 /// @file core/scoring/geometric_solvation/OccludedHbondSolEnergy.cc
10 /// @brief Solvation model based on penalizing potential for Hbonding to solvent
11 /// @author John Karanicolas
12 
13 
14 
15 
16 // NOTES FOR IMPROVED PERFORMANCE / POTENTIAL IMPROVEMENTS....
17 
18 // The GeometricSolvation implementation was context-dependent,
19 // because backbone groups participating in secondary structure
20 // were considered exempt. Here, though, we'll compute their solvation
21 // energy as for any other group (partly since it's not obvious how
22 // else they *should* be treated). This in turn allows this energy
23 // term to be context-independent. The real question is....
24 // what should be the solvation energy for CO in secondary structure??
25 
26 // Probably the best alternative would be to *NOT* compute solvation energies
27 // here for backbone groups in secondary structure, and instead assign
28 // them a fixed solvation penalty. Not clear what this penalty should be though...
29 
30 // It might make sense to precompute and cache scores and derivatives
31 // in eg. a "geometric solvation potential" object,
32 // so that they don't need to be computed over and over again
33 
34 
35 // Unit Headers
41 // AUTO-REMOVED #include <core/scoring/Energies.hh>
43 // AUTO-REMOVED #include <core/scoring/EnergyGraph.hh>
47 #include <core/pose/Pose.hh>
48 #include <basic/Tracer.hh>
49 // AUTO-REMOVED #include <basic/prof.hh>
50 
51 // Package headers
52 
53 // Project headers
54 #include <numeric/trig.functions.hh>
55 #include <numeric/deriv/distance_deriv.hh>
56 #include <numeric/deriv/angle_deriv.hh>
57 
58 // Utility headers
59 #include <ObjexxFCL/format.hh>
60 
61 #include <utility/vector1.hh>
62 
63 
64 static basic::Tracer tr( "core.scoring.geometric_solvation.OccludedHbondSolEnergy" );
65 
66 namespace core {
67 namespace scoring {
68 namespace geometric_solvation {
69 
70 using namespace ObjexxFCL::fmt;
71 
72 /// @details This must return a fresh instance of the OccludedHbondSolEnergy class,
73 /// never an instance already in use
76  methods::EnergyMethodOptions const & options
77 ) const {
78  return new geometric_solvation::OccludedHbondSolEnergy( options );
79 }
80 
83  ScoreTypes sts;
84  sts.push_back( occ_sol_fitted );
85  return sts;
86 }
87 
88 
89 
91 
92 // jumpouts will apply if this is the best possible energy.
93 // this value corresponds to the discontinuity we'll deem acceptable.
94 // deriv_check starts to give bad results with a value of 0.05 (dist=6.6), but is mostly acceptable with 0.01 (dist=7.5)
95 core::Real const MIN_OCC_ENERGY = { 0.01 };
96 
97 
99  methods::EnergyMethodOptions const & options,
100  bool const verbose )
101 :
103  occ_hbond_sol_database_( ScoringManager::get_instance()->get_DatabaseOccSolEne( options.etable_type(), MIN_OCC_ENERGY ) ),
104  verbose_( verbose )
105 {
106  if ( verbose_ ) tr <<"OccludedHbondSolEnergy constructor" << std::endl;
107 }
108 
110  parent( src ),
111  occ_hbond_sol_database_( src.occ_hbond_sol_database_ ),
112  verbose_( src.verbose_ )
113 {
114  if ( verbose_ ) tr <<"OccludedHbondSolEnergy constructor" << std::endl;
115 }
116 
119 {
120  return new OccludedHbondSolEnergy( *this );
121 }
122 
123 void
125 {
127 }
128 
129 void
131 {
133 }
134 
135 
136 void
138  conformation::Residue const & rsd1,
139  conformation::Residue const & rsd2,
140  pose::Pose const & ,
141  ScoreFunction const &,
142  EnergyMap & emap
143 ) const
144 {
145 
146  if ( verbose_ ) tr << "jk evaluating residue pair energy" << std::endl;
147 
148  // Note: no count-pair stuff, these will just be computed normally
149  // jk is there double-counting with other stuff, eg. backbone-dependent Dunbrack when we include self-terms like this?
150 
151  assert ( rsd1.seqpos() != rsd2.seqpos() ); // this should be computed via eval_intrares_energy
152 
153  Real occ_solE =
154  res_res_occ_sol_one_way( rsd1, rsd2 ) +
155  res_res_occ_sol_one_way( rsd2, rsd1 ) ;
156 
157  // store the energies
158  emap[ occ_sol_fitted ] += occ_solE;
159 
160 }
161 
162 void
164  conformation::Residue const & rsd,
165  pose::Pose const & ,
166  ScoreFunction const & ,
167  EnergyMap & emap ) const {
168 
169  if ( verbose_ ) tr << "jk evaluating intrares energy" << std::endl;
170 
171  // behaves as not-same-residue, except that we only do the calculation once
172  Real occ_solE = res_res_occ_sol_one_way( rsd, rsd );
173  emap[ occ_sol_fitted ] += occ_solE;
174 }
175 
176 /// @details return true if the two residues are moving with respect to each other.
177 bool
179  conformation::Residue const &,
180  conformation::Residue const &,
181  bool res_moving_wrt_eachother
182 ) const
183 {
184  return res_moving_wrt_eachother;
185 }
186 
187 void
189  conformation::Residue const & rsd1,
190  conformation::Residue const & rsd2,
193  ResPairMinimizationData const &,
194  pose::Pose const &, // provides context
195  EnergyMap const & weights,
196  utility::vector1< DerivVectorPair > & r1_atom_derivs,
197  utility::vector1< DerivVectorPair > & r2_atom_derivs
198 ) const
199 {
200  eval_residue_pair_derivatives_one_way( rsd1, rsd2, weights, r1_atom_derivs, r2_atom_derivs );
201  eval_residue_pair_derivatives_one_way( rsd2, rsd1, weights, r2_atom_derivs, r1_atom_derivs );
202 }
203 
204 void
206  conformation::Residue const & rsd1, // polar residue
207  conformation::Residue const & rsd2, // occluding residue
208  EnergyMap const & weights,
209  utility::vector1< DerivVectorPair > & r1_atom_derivs,
210  utility::vector1< DerivVectorPair > & r2_atom_derivs
211 ) const
212 {
213 
214  Real energy(0); // dummy variable
215  Real const atom_pair_cutoff( occ_hbond_sol_database_.atomic_interaction_cutoff() );
216  Real const atom_pair_cutoff2( atom_pair_cutoff*atom_pair_cutoff );
217  Real dcut = ( atom_pair_cutoff + rsd2.nbr_radius() );
218  Real d2cut = dcut * dcut;
219  core::Vector r2_nb_xyz( rsd2.nbr_atom_xyz());
220  for ( chemical::AtomIndices::const_iterator
221  hnum = rsd1.Hpos_polar().begin(),
222  hnume = rsd1.Hpos_polar().end();
223  hnum != hnume; ++hnum ) {
224  Size const don_h_atom( *hnum );
225  Size const don_base_atom( rsd1.atom_base( don_h_atom ) );
226  if ( rsd1.xyz( don_h_atom ).distance_squared( r2_nb_xyz ) > d2cut ) continue;
227  for ( Size jj = 1; jj <= rsd2.nheavyatoms(); ++jj ) {
228  if ( rsd1.xyz( don_h_atom ).distance_squared( rsd2.xyz(jj) ) > atom_pair_cutoff2 ) continue;
229  get_atom_atom_occ_solvation( don_h_atom, don_base_atom, rsd1, jj, rsd2, energy, true, weights[ occ_sol_fitted ],
230  r1_atom_derivs[ don_base_atom ].f1(), r1_atom_derivs[ don_base_atom ].f2(),
231  r1_atom_derivs[ don_h_atom ].f1(), r1_atom_derivs[ don_h_atom ].f2(),
232  r2_atom_derivs[ jj ].f1(), r2_atom_derivs[ jj ].f2() );
233  }
234  }
235 
236  for ( chemical::AtomIndices::const_iterator
237  anum = rsd1.accpt_pos().begin(),
238  anume = rsd1.accpt_pos().end();
239  anum != anume; ++anum ) {
240  Size const acc_atom( *anum );
241  Size const base_atom ( rsd1.atom_base( acc_atom ) );
242  if ( rsd1.xyz( acc_atom ).distance_squared( r2_nb_xyz ) > d2cut ) continue;
243  for ( Size jj = 1; jj <= rsd2.nheavyatoms(); ++jj ) {
244  if ( rsd1.xyz( acc_atom ).distance_squared( rsd2.xyz(jj) ) > atom_pair_cutoff2 ) continue;
245  get_atom_atom_occ_solvation( acc_atom, base_atom, rsd1, jj, rsd2, energy, true, weights[ occ_sol_fitted ],
246  r1_atom_derivs[ base_atom ].f1(), r1_atom_derivs[ base_atom ].f2(),
247  r1_atom_derivs[ acc_atom ].f1(), r1_atom_derivs[ acc_atom ].f2(),
248  r2_atom_derivs[ jj ].f1(), r2_atom_derivs[ jj ].f2() );
249  }
250  }
251 
252 }
253 
254 
255 void
257  conformation::Residue const & rsd,
259  pose::Pose const &,
260  EnergyMap const & weights,
262 ) const
263 {
264  eval_residue_pair_derivatives_one_way( rsd, rsd, weights, atom_derivs, atom_derivs );
265 }
266 
267 
268 
269 Real
271  conformation::Residue const & polar_rsd,
272  conformation::Residue const & occ_rsd
273 ) const
274 {
275 
276  // Rhiju importantly notes: for GeometricSolvation he originally had the code in
277  // the following functions written out inside these loop -- and packing was faster.
278  // Perhaps something to do with inlining or compiler optimization.
279  // I've left it this way for now, because it helps prevent copying too
280  // much of the code shared between residue pair scoring and for the derivatives.
281  // However, if speed becomes important, here's a place to start.
282 
283  // jk note: moved the loop over occluding atoms into the next fxn, this could be the speed diff...
284 
285  Real geo_solE(0.), energy(0.);
286 
288  Real d2cut = dcut * dcut;
289  core::Vector occ_nb_xyz( occ_rsd.nbr_atom_xyz());
290 
291  // cycle through donors in polar_rsd
292  for ( chemical::AtomIndices::const_iterator hnum = polar_rsd.Hpos_polar().begin(), hnume = polar_rsd.Hpos_polar().end(); hnum != hnume; ++hnum ) {
293  Size const don_h_atom( *hnum );
294  Size const don_base_atom( polar_rsd.atom_base( don_h_atom ) );
295  if ( polar_rsd.xyz( don_h_atom ).distance_squared( occ_nb_xyz ) > d2cut ) continue;
296  for ( Size occ_atom = 1; occ_atom <= occ_rsd.natoms(); occ_atom++ ) {
297  get_atom_atom_occ_solvation( don_h_atom, don_base_atom, polar_rsd, occ_atom, occ_rsd, energy );
298  geo_solE += energy;
299  }
300  }
301 
302  // cycle through acceptors in polar_rsd
303  for ( chemical::AtomIndices::const_iterator anum = polar_rsd.accpt_pos().begin(), anume = polar_rsd.accpt_pos().end(); anum != anume; ++anum ) {
304  Size const acc_atom( *anum );
305  Size const base_atom ( polar_rsd.atom_base( acc_atom ) );
306  if ( polar_rsd.xyz( acc_atom ).distance_squared( occ_nb_xyz ) > d2cut ) continue;
307  for ( Size occ_atom = 1; occ_atom <= occ_rsd.natoms(); occ_atom++ ) {
308  get_atom_atom_occ_solvation( acc_atom, base_atom, polar_rsd, occ_atom, occ_rsd, energy );
309  geo_solE += energy;
310  }
311  }
312 
313  return geo_solE;
314 }
315 
316 
317 void
319  Size const polar_atom,
320  Size const base_atom,
321  conformation::Residue const & polar_rsd,
322  Size const occ_atom,
323  conformation::Residue const & occ_rsd,
324  Real & energy,
325  bool const update_deriv, // = false
326  Real const occ_sol_fitted_weight, // = 0.0
327  //bool const update_deriv_base, // = false
328  //bool const update_deriv_occ, // = false
329  Vector & f1_base, // = dummy vector
330  Vector & f2_base, // = dummy vector
331  Vector & f1_polar, // = dummy vector
332  Vector & f2_polar, // = dummy vector
333  Vector & f1_occ, // = dummy vector
334  Vector & f2_occ // = dummy vector
335 ) const
336 {
337 
338  // In case of early return, initialize. Note that energy does NOT accumulate, but f1/f2 do.
339  // Also note that f1 and f2 are returned unweighted.
340  energy = 0.;
341 
342  // note: after testing, hydrogens need not occlude
343  if ( occ_rsd.atom_is_hydrogen(occ_atom) ) return;
344  // if ( occ_atom > occ_rsd.nheavyatoms() ) return;
345 
346  // note: the lines above don't exclude Proline NV...
347  // catch proline NV here (and other virtual atoms, etc.)
348  if ( occ_rsd.atom_type(occ_atom).lj_radius() < 0.1 ) return;
349 
350  // can be occluded by atoms directly bonded to this group, but not by self
351  if ( polar_rsd.seqpos() == occ_rsd.seqpos() ) {
352  if ( polar_atom == occ_atom ) return;
353  if ( base_atom == occ_atom ) return;
354  }
355 
356  bool polar_atom_donates = false;
357  if ( polar_rsd.atom_is_hydrogen(polar_atom) ) polar_atom_donates = true;
358 
359  if ( polar_atom_donates ) {
360  // polar donor cannot be occluded by an acceptor (analogous to exact_occ_skip_Hbonders in exact model, but not quite the same)
361  //for ( chemical::AtomIndices::const_iterator anum = occ_rsd.accpt_pos().begin(), anume = occ_rsd.accpt_pos().end(); anum != anume; ++anum ) {
362  // if ( occ_atom == *anum ) {
363  // return;
364  // }
365  //}
366  if ( occ_rsd.heavyatom_is_an_acceptor( occ_atom )) return;
367  } else {
368  // polar acceptor cannot be occluded by an donor base (analogous to exact_occ_skip_Hbonders in exact model, but not quite the same)
369  //for ( chemical::AtomIndices::const_iterator hnum = occ_rsd.Hpos_polar().begin(), hnume = occ_rsd.Hpos_polar().end(); hnum != hnume; ++hnum ) {
370  // Size const don_h_atom( *hnum );
371  // if ( occ_atom == occ_rsd.atom_base( don_h_atom ) ) {
372  // return;
373  // }
374  //}
375  if ( occ_rsd.heavyatom_has_polar_hydrogens( occ_atom )) return;
376  }
377 
378  //bool update_deriv = false;
379  //if ( update_deriv_polar || update_deriv_base || update_deriv_occ) update_deriv = true;
380  // only one at a time
381  //assert( ! ( update_deriv_polar && update_deriv_base ) );
382  //assert( ! ( update_deriv_polar && update_deriv_occ ) );
383  //assert( ! ( update_deriv_base && update_deriv_occ ) );
384 
385  assert( ( polar_atom_donates && atom_is_donor_h( polar_rsd, polar_atom ) ) ||
386  ( ( ! polar_atom_donates ) && atom_is_acceptor( polar_rsd, polar_atom ) ) );
387 
388  // If acceptor, do lookup on polar atom. If donor (ie. polar atom is a hydrogen), use the base atom instead
389  Size polar_atom_type_lookup_index = polar_rsd.atom_type_index( polar_atom );
390  if ( polar_atom_donates ) polar_atom_type_lookup_index = polar_rsd.atom_type_index( base_atom );
391 
392  Vector const & polar_atom_xyz( polar_rsd.atom( polar_atom ).xyz() );
393  Vector const & base_atom_xyz( polar_rsd.atom( base_atom ).xyz() );
394 
395  Size const occ_atom_type_index = occ_rsd.atom_type_index( occ_atom );
396  Vector const & occ_atom_xyz( occ_rsd.atom( occ_atom ).xyz() );
397 
398  // jumpout with no calculations if easy tests are violated, ie. no contribution to solvation energy
399  Real const dist_sq = ( occ_atom_xyz - polar_atom_xyz).length_squared();
400  if ( dist_sq > occ_hbond_sol_database_( polar_atom_donates, polar_atom_type_lookup_index, occ_atom_type_index, OccFitParam_max_sq_dist ) ) return;
401  Real const curr_cos_angle = get_cos_angle( base_atom_xyz, polar_atom_xyz, occ_atom_xyz );
402  if ( curr_cos_angle < occ_hbond_sol_database_( polar_atom_donates, polar_atom_type_lookup_index, occ_atom_type_index, OccFitParam_min_cos_angle ) ) return;
403 
404  // geometric filters are met, compute energy (and derivatives, if desired)
405  // get the appropriate parameters
406  Real const amp = occ_hbond_sol_database_( polar_atom_donates, polar_atom_type_lookup_index, occ_atom_type_index, OccFitParam_amp );
407  Real const dist_mu = occ_hbond_sol_database_( polar_atom_donates, polar_atom_type_lookup_index, occ_atom_type_index, OccFitParam_dist_mu );
408  Real const twice_dist_sigma_sq = occ_hbond_sol_database_( polar_atom_donates, polar_atom_type_lookup_index, occ_atom_type_index, OccFitParam_twice_dist_sigma_sq );
409  Real const cos_angle_mu = occ_hbond_sol_database_( polar_atom_donates, polar_atom_type_lookup_index, occ_atom_type_index, OccFitParam_cos_angle_mu );
410  Real const twice_cos_angle_sigma_sq = occ_hbond_sol_database_( polar_atom_donates, polar_atom_type_lookup_index, occ_atom_type_index, OccFitParam_twice_cos_angle_sigma_sq );
411 
412  // Note: differences are in different order. Doesn't matter for scores, does for derivatives (and these make derivatives work).
413  // Briefly, we're in the regime where dist energy contribution gets small as we get big values,
414  // while cos_angle contribution gets small as we get smaller values
415  Real const dist_diff = sqrt(dist_sq) - dist_mu;
416  Real const cos_angle_diff = cos_angle_mu - curr_cos_angle;
417 
418  Real dist_exp, cos_angle_exp;
419  if ( update_deriv ) {
420  dist_exp = exp( - ( dist_diff * dist_diff / twice_dist_sigma_sq ) );
421  cos_angle_exp = exp( - ( cos_angle_diff * cos_angle_diff / twice_cos_angle_sigma_sq ) );
422  energy = amp * dist_exp * cos_angle_exp;
423  } else {
424  // do the calculation with a single exp
425  energy = amp *
426  exp( - ( ( dist_diff * dist_diff / twice_dist_sigma_sq ) + ( cos_angle_diff * cos_angle_diff / twice_cos_angle_sigma_sq ) ) );
427  }
428 
429  if ( verbose_ && ( energy > 0. ) ) {
430  tr <<"jk res "<< polar_rsd.name1() << I(3,polar_rsd.seqpos()) <<
431  " atom " << polar_rsd.atom_name( polar_atom ) << " is occluded by occ_res " <<
432  occ_rsd.name1() << I(3, occ_rsd.seqpos()) <<
433  " atom " << occ_rsd.atom_name( occ_atom ) <<
434  " with energy " << F(8,3,energy) << std::endl;
435  }
436 
437  if ( ! update_deriv ) return;
438 
439  // compute angle f1/f2
440  // note: energy is what was computed above, since it does NOT accumulate
441  Real const curr_angle = numeric::arccos(curr_cos_angle); // note: radians
442  Real const cos_angle_dfunc = -2. * cos_angle_diff * energy / twice_cos_angle_sigma_sq;
443  Real const angle_dfunc = -std::sin(curr_angle) * cos_angle_dfunc * occ_sol_fitted_weight;
444  Real theta(0.);
445  Vector angle_f1_p1(0.), angle_f2_p1(0.);
446  Vector angle_f1_p2(0.), angle_f2_p2(0.);
447  Vector angle_f1_p3(0.), angle_f2_p3(0.);
448 
449  numeric::deriv::angle_p1_p2_p3_deriv( base_atom_xyz, polar_atom_xyz, occ_atom_xyz, theta,
450  angle_f1_p1, angle_f2_p1, angle_f1_p2, angle_f2_p2, angle_f1_p3, angle_f2_p3 );
451  //numeric::deriv::angle_p2_deriv( base_atom_xyz, polar_atom_xyz, occ_atom_xyz, theta, angle_f1, angle_f2 );
452  f1_polar += angle_dfunc * angle_f1_p2;
453  f2_polar += angle_dfunc * angle_f2_p2;
454  //numeric::deriv::angle_p1_deriv( base_atom_xyz, polar_atom_xyz, occ_atom_xyz, theta, angle_f1, angle_f2 );
455  f1_base += angle_dfunc * angle_f1_p1;
456  f2_base += angle_dfunc * angle_f2_p1;
457  //numeric::deriv::angle_p1_deriv( occ_atom_xyz, polar_atom_xyz, base_atom_xyz, theta, angle_f1, angle_f2 );
458  f1_occ += angle_dfunc * angle_f1_p3;
459  f2_occ += angle_dfunc * angle_f2_p3;
460 
461  // compute distance f1/f2
462  // note: energy is what was computed above, since it does NOT accumulate
463  Real const dist_dfunc = -2. * dist_diff * energy * occ_sol_fitted_weight / twice_dist_sigma_sq;
464  Real dist(0.);
465  Vector dist_f1(0.), dist_f2(0.);
466 
467  numeric::deriv::distance_f1_f2_deriv( polar_atom_xyz, occ_atom_xyz, dist, dist_f1, dist_f2 );
468  f1_polar += dist_dfunc * dist_f1;
469  f2_polar += dist_dfunc * dist_f2;
470 
471  f1_occ -= dist_dfunc * dist_f1;
472  f2_occ -= dist_dfunc * dist_f2;
473 
474  //} else {
475  // numeric::deriv::distance_f1_f2_deriv( occ_atom_xyz, polar_atom_xyz, dist, dist_f1, dist_f2 );
476  //}
477  //f1 += dist_dfunc * dist_f1;
478  //f2 += dist_dfunc * dist_f2;
479 
480  return;
481 
482 }
483 
484 /*void
485 OccludedHbondSolEnergy::deprecated_eval_atom_derivative(
486  id::AtomID const & atom_id,
487  pose::Pose const & pose,
488  kinematics::DomainMap const & domain_map,
489  ScoreFunction const &,
490  EnergyMap const & weights,
491  Vector & F1,
492  Vector & F2
493  ) const
494 {
495 
496  Size const curr_resnum( atom_id.rsd() );
497  Size const curr_atomno( atom_id.atomno() );
498  conformation::Residue const & curr_rsd( pose.residue( curr_resnum ) );
499  int const curr_res_map( domain_map( curr_resnum ) );
500  bool const curr_res_fixed( curr_res_map != 0 );
501 
502  // Loop over all atoms of neighboring residues, INCLUDING SELF
503  utility::vector1 <core::Size> neighborlist;
504  neighborlist.push_back( curr_resnum );
505  EnergyGraph const & energy_graph( pose.energies().energy_graph() );
506  for ( graph::Graph::EdgeListConstIter
507  iru = energy_graph.get_node( curr_resnum )->const_edge_list_begin(),
508  irue = energy_graph.get_node( curr_resnum )->const_edge_list_end();
509  iru != irue; ++iru ) {
510  Size const other_resnum( (*iru)->get_other_ind( curr_resnum ) );
511  if ( curr_res_fixed && curr_res_map == domain_map( other_resnum ) ) continue; // fixed wrt one another
512  neighborlist.push_back( other_resnum );
513  }
514 
515  Vector f1(0.), f2(0.);
516  core::Real energy(0.); // dummy variable
517 
518  // If this atom is a polar atom, consider its occlusion by all other (neighboring) residues
519  if ( atom_is_donor_h( curr_rsd, curr_atomno ) || atom_is_acceptor( curr_rsd, curr_atomno ) ) {
520  Size const curr_base_atom ( curr_rsd.atom_base( curr_atomno ) );
521  for ( Size other_res_inx = 1; other_res_inx <= neighborlist.size(); ++other_res_inx ) {
522  Size const other_resnum( neighborlist[other_res_inx] );
523  conformation::Residue const & other_rsd( pose.residue( other_resnum ) );
524  for ( Size occ_atom = 1; occ_atom <= other_rsd.natoms(); occ_atom++ ) {
525  get_atom_atom_occ_solvation( curr_atomno, curr_base_atom, curr_rsd, occ_atom, other_rsd, energy, true, false, false, f1, f2 );
526  }
527  }
528  }
529 
530  // If this atom is a base atom, consider occlusion of its polar atom by all other (neighboring) residues
531  if ( atom_is_valid_base( curr_rsd, curr_atomno ) ) {
532  // because a base atom can have multiple polar atoms, we need to loop over them here
533  for ( chemical::AtomIndices::const_iterator hnum = curr_rsd.Hpos_polar().begin(), hnume = curr_rsd.Hpos_polar().end(); hnum != hnume; ++hnum ) {
534  Size const don_h_atom( *hnum );
535  Size const base_atom ( curr_rsd.atom_base( don_h_atom ) );
536  if ( base_atom != curr_atomno ) continue;
537  for ( Size other_res_inx = 1; other_res_inx <= neighborlist.size(); ++other_res_inx ) {
538  Size const other_resnum( neighborlist[other_res_inx] );
539  conformation::Residue const & other_rsd( pose.residue( other_resnum ) );
540  for ( Size occ_atom = 1; occ_atom <= other_rsd.natoms(); occ_atom++ ) {
541  get_atom_atom_occ_solvation( don_h_atom, curr_atomno, curr_rsd, occ_atom, other_rsd, energy, false, true, false, f1, f2 );
542  }
543  }
544  }
545  for ( chemical::AtomIndices::const_iterator anum = curr_rsd.accpt_pos().begin(), anume = curr_rsd.accpt_pos().end(); anum != anume; ++anum ) {
546  Size const acc_atom( *anum );
547  Size const base_atom ( curr_rsd.atom_base( acc_atom ) );
548  if ( base_atom != curr_atomno ) continue;
549  for ( Size other_res_inx = 1; other_res_inx <= neighborlist.size(); ++other_res_inx ) {
550  Size const other_resnum( neighborlist[other_res_inx] );
551  conformation::Residue const & other_rsd( pose.residue( other_resnum ) );
552  for ( Size occ_atom = 1; occ_atom <= other_rsd.natoms(); occ_atom++ ) {
553  get_atom_atom_occ_solvation( acc_atom, curr_atomno, curr_rsd, occ_atom, other_rsd, energy, false, true, false, f1, f2 );
554  }
555  }
556  }
557  }
558 
559  // Now consider occlusion of polar groups on neighboring residues by this atom
560  for ( Size other_res_inx = 1; other_res_inx <= neighborlist.size(); ++other_res_inx ) {
561  Size const other_resnum( neighborlist[other_res_inx] );
562  conformation::Residue const & other_rsd( pose.residue( other_resnum ) );
563  for ( chemical::AtomIndices::const_iterator hnum = other_rsd.Hpos_polar().begin(), hnume = other_rsd.Hpos_polar().end(); hnum != hnume; ++hnum ) {
564  Size const don_h_atom( *hnum );
565  Size const don_base_atom( other_rsd.atom_base( don_h_atom ) );
566  get_atom_atom_occ_solvation( don_h_atom, don_base_atom, other_rsd, curr_atomno, curr_rsd, energy, false, false, true, f1, f2 );
567  }
568  for ( chemical::AtomIndices::const_iterator anum = other_rsd.accpt_pos().begin(), anume = other_rsd.accpt_pos().end(); anum != anume; ++anum ) {
569  Size const acc_atom( *anum );
570  Size const base_atom ( other_rsd.atom_base( acc_atom ) );
571  get_atom_atom_occ_solvation( acc_atom, base_atom, other_rsd, curr_atomno, curr_rsd, energy, false, false, true, f1, f2 );
572  }
573  }
574 
575  // F1/F2 accumulate
576  F1 += weights[ occ_sol_fitted ] * f1;
577  F2 += weights[ occ_sol_fitted ] * f2;
578 
579 }*/
580 
581 
582 Distance
584 {
585  // tr << "atomic_interaction_cutoff is: " << occ_hbond_sol_database_.atomic_interaction_cutoff() << std::endl;
586  // jk max interaction distance is computed using the hydrogen for donors - is this okay? or should we add one to get a heavyatom distance?
587  // probably is doesn't matter, since at worst we'll just end up using an acceptor-based distance, which is fine...
589 }
590 
591 Real
593  Vector const & base_atom_xyz,
594  Vector const & polar_atom_xyz,
595  Vector const & occluding_atom_xyz ) const
596 {
597  return dot( (polar_atom_xyz - base_atom_xyz).normalize(), (occluding_atom_xyz - polar_atom_xyz).normalize() );
598 }
599 
600 
601 
602 // Helper function that should live inside conformation::Residue (Rhiju's comment)
604  for ( chemical::AtomIndices::const_iterator hnum = rsd.Hpos_polar().begin(), hnume = rsd.Hpos_polar().end(); hnum != hnume; ++hnum ) {
605  Size const don_h_atom( *hnum );
606  if ( don_h_atom == atom ) return true;
607  }
608  return false;
609 }
610 
611 // Helper function that should live inside conformation::Residue (Rhiju's comment)
613  for ( chemical::AtomIndices::const_iterator anum = rsd.accpt_pos().begin(), anume = rsd.accpt_pos().end(); anum != anume; ++anum ) {
614  Size const acc_atom( *anum );
615  if ( acc_atom == atom ) return true;
616  }
617  return false;
618 }
619 
620 // Helper function that should live inside conformation::Residue (Rhiju's comment)
622  for ( chemical::AtomIndices::const_iterator hnum = rsd.Hpos_polar().begin(), hnume = rsd.Hpos_polar().end(); hnum != hnume; ++hnum ) {
623  Size const don_h_atom( *hnum );
624  Size const base_atom ( rsd.atom_base( don_h_atom ) );
625  if ( base_atom == atom ) return true;
626  }
627  for ( chemical::AtomIndices::const_iterator anum = rsd.accpt_pos().begin(), anume = rsd.accpt_pos().end(); anum != anume; ++anum ) {
628  Size const acc_atom( *anum );
629  Size const base_atom ( rsd.atom_base( acc_atom ) );
630  if ( base_atom == atom ) return true;
631  }
632  return false;
633 }
636 {
637  return 1; // Initial versioning
638 }
639 
640 
641 
642 } // geometric_solvation
643 } // scoring
644 } // core
645