Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
GenBornPotential.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/GenBornPotential.cc
11 /// @brief
12 /// @author JIM HAVRANEK (originally)
13 
14 // Project headers
16 
18 //#include <core/scoring/etable/count_pair/CountPairIntraResC3.hh>
19 //#include <core/scoring/etable/count_pair/CountPair1BC3.hh>
20 //#include <core/scoring/etable/count_pair/CountPairAll.hh>
23 
25 
29 #include <core/pose/Pose.hh>
30 // AUTO-REMOVED #include <core/kinematics/DomainMap.hh>
31 //#include <core/pack/task/PackerTask.hh>
35 #include <basic/datacache/BasicDataCache.hh>
36 #include <basic/prof.hh>
37 
38 // Utility headers
39 #include <utility/exit.hh>
40 
43 #include <core/id/AtomID.hh>
44 #include <utility/vector1.hh>
45 #include <ObjexxFCL/FArray1D.hh>
46 
47 
48 
49 
50 
51 //////////////////////////////////////////////////////////////////////////////////
52 //////////////////////////////////////////////////////////////////////////////////
53 //////////////////////////////////////////////////////////////////////////////////
54 /**
55 
56  This is a reimplementation of Jim Havranek's original rosetta++ Gen Born code.
57  source files: rosetta++/gb_elec*
58 
59 **/
60 //////////////////////////////////////////////////////////////////////////////////
61 //////////////////////////////////////////////////////////////////////////////////
62 //////////////////////////////////////////////////////////////////////////////////
63 
64 
65 namespace core {
66 namespace scoring {
67 
69 
70 ///
71 void
73 {
74  Size const natoms( rsd.natoms() );
75  born_radius_.resize( natoms );
76  atomic_radius_.resize( natoms );
77  scale_factor_.resize( natoms );
78 
79  // important: initialize with 0.0 prior to burial calculations
80  std::fill( born_radius_.begin(), born_radius_.end(), 0.0 );
81 
82  // atom index for looking up an extra data type stored in the AtomTypes
83  Size const GB_RADIUS_INDEX( rsd.atom_type_set().extra_parameter_index( "GB_RADIUS" ) );
84  Size const GB_SCALE_FACTOR_INDEX( rsd.atom_type_set().extra_parameter_index( "GB_SCALE_FACTOR" ) );
85 
86  for ( Size i=1; i<= natoms; ++i ) {
87  atomic_radius_[i] = rsd.atom_type(i).extra_parameter( GB_RADIUS_INDEX );
88  scale_factor_ [i] = rsd.atom_type(i).extra_parameter( GB_SCALE_FACTOR_INDEX );
89  }
90 }
91 
92 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
94  CacheableData()
95 {
96  Size const src_size( src.size() );
97 
98  residue_info_.resize( src_size );
99  placeholder_residue_.resize( src_size );
100  placeholder_info_.resize( src_size );
101 
102  for ( Size i=1; i<= src_size; ++i ) {
103  residue_info_[i] = src.residue_info_[i]->clone();
104  if ( src.placeholder_residue_[i] ) {
105  placeholder_residue_[i] = src.placeholder_residue_[i]->clone();
106  placeholder_info_[i] = src.placeholder_info_[i]->clone();
107  } else {
108  placeholder_residue_[i] = 0;
109  placeholder_info_[i] = 0;
110  }
111  }
113 }
114 
115 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
116 ///
117 void
119 {
120  Size const nres( pose.total_residue() );
121 
122  residue_info_.resize( nres, 0 );
123  placeholder_residue_.resize( nres, 0 );
124  placeholder_info_.resize( nres, 0 );
125 
126  for ( Size i=1; i<= nres; ++i ) {
127  if ( !residue_info_[i] ) residue_info_[i] = new GenBornResidueInfo( pose.residue(i) );
128  else residue_info_[i]->initialize( pose.residue(i) );
129  }
130 
131  being_packed_.clear();
132 }
133 
134 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
135 void
137 {
138  placeholder_residue_[ i ] = rsd;
139  placeholder_info_[ i ] = info;
140 }
141 
142 
143 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
144 void
146 {
147  being_packed_.resize( size(), false );
148  for ( Size i=1; i<= size(); ++i ) {
149  being_packed_[i] = repacking_residues[ i ];
150  }
151 }
152 
153 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
154 /// dont forget to 0 the born_radii
155 void
157 {
158  Size const nrot( rotamer_set.num_rotamers() );
159  residue_info_.resize( nrot );
160  for ( Size i=1; i<= nrot; ++i ) {
161  residue_info_[i] = new GenBornResidueInfo( *rotamer_set.rotamer(i) );
162  }
163 }
164 
165 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
166 
167 void
169  Residue const & rsd1,
170  GenBornResidueInfo & gb1,
171  Residue const & rsd2,
172  GenBornResidueInfo const & gb2
173 ) const
174 {
175  bool const same_res( rsd1.seqpos() == rsd2.seqpos() );
176 
177 //jjh local
178  utility::vector1< Real > atm_radii1( rsd1.natoms() );
179  utility::vector1< Real > atm_radii2( rsd2.natoms() );
180 
181 //jjh Fill the radii array - later will allow for overrides
182  for ( int atm1 = 1, atm1e = rsd1.natoms(); atm1 <= atm1e; ++atm1 ) {
183  atm_radii1[ atm1 ] = gb1.atomic_radius( atm1 );
184  }
185  for ( int atm2 = 1, atm2e = rsd2.natoms(); atm2 <= atm2e; ++atm2 ) {
186  atm_radii2[ atm2] = gb2.scale_factor( atm2 ) * ( gb2.atomic_radius( atm2 ) - ParamS );
187  }
188 
189 
190  for ( int atm1 = 1, atm1e = rsd1.natoms(); atm1 <= atm1e; ++atm1 ) {
191  Real const rad1 = atm_radii1[ atm1 ];
192  Real const rwork1 = rad1 - ParamS;
193  Real const inv_r1 = 1.0/rwork1;
194  Vector const & xyz1( rsd1.xyz( atm1 ) );
195 
196  for ( int atm2 = 1, atm2e = rsd2.natoms(); atm2 <= atm2e; ++atm2 ) {
197  Real const rwork2 = atm_radii2[ atm2 ];
198  Real const dis2( xyz1.distance_squared( rsd2.xyz( atm2 ) ) );
199  Real const dis = std::sqrt(dis2);
200  Real const inv_dis = 1.0/(dis+1.0e-6);
201  Real const rwork2_sq = rwork2*rwork2;
202 
203  if ( same_res && (atm1 == atm2) ) continue;
204 
205  if ( dis > (3.5 * rwork2) ) {
206  Real const inv_dis2 = inv_dis * inv_dis;
207  Real const tmpsd = rwork2_sq * inv_dis2;
208  Real const dumbo = Param_TA+tmpsd*(Param_TB+tmpsd*(Param_TC+tmpsd*(Param_TD+tmpsd*Param_TDD)));
209  gb1.born_radius( atm1 ) -= rwork2_sq*rwork2*inv_dis2*inv_dis2*dumbo;
210 
211  } else if ( dis > (rwork1 + rwork2)) {
212  gb1.born_radius( atm1 ) -= (0.5*(rwork2/(dis2 - rwork2_sq) +
213  0.5*inv_dis*std::log((dis-rwork2)/(dis+rwork2))));
214 
215  } else if ( dis > std::abs( rwork1 - rwork2 ) ) {
216  Real const theta = 0.5*inv_r1*inv_dis*(dis2+rwork1*rwork1 - rwork2_sq);
217  Real const U12 = 1.0/(dis+rwork2);
218  gb1.born_radius( atm1 ) -= 0.25*(inv_r1 * (2.0-theta) - U12 + inv_dis*std::log(rwork1*U12));
219 
220  } else if ( rwork1 < rwork2 ) {
221  gb1.born_radius( atm1 ) -= 0.5*(rwork2/(dis2-rwork2_sq) + 2.0*inv_r1 +
222  0.5*inv_dis*std::log( (rwork2-dis)/(rwork2+dis)));
223 
224  }
225  }
226  }
227 
228 
229 }
230 
231 
232 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
233 // helper function
234 
235 void
237 {
238  for ( Size atm=1; atm<= gb_info.size(); ++atm ) {
239  Real const radius = gb_info.atomic_radius( atm );
240  Real const factor = radius - ParamS;
241  Real const br_save = gb_info.born_radius( atm );
242  Real const integral = (-1.0)*factor*br_save;
243  Real const inv_brad = (1.0/factor) - std::tanh( ( ParamD - ParamB*integral +
244  ParamG*integral*integral)*integral)/radius;
245  gb_info.born_radius( atm ) = 1.0 / inv_brad;
246  }
247 }
248 
249 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
250 
251 
252 void
254  pose::Pose & pose
255 ) const
256 {
257  // ////using core::pose::datacache::CacheableDataType::GEN_BORN_POSE_INFO;
258 
259  PROF_START( basic::GB_GET_ALL_BORN_RADII );
260 
261  Size const nres( pose.total_residue() );
262 
263  // initialize gb info:
264  // * zeros born radii for start of calculations
265  // * fills the atomic radii (from the Pose/AtomTypeSet)
266  // * fills the scale factors (from the Pose/AtomTypeSet)
267  //
268 
269  GenBornPoseInfoOP gb_info;
270 
272  gb_info = static_cast< GenBornPoseInfo* >( pose.data().get_ptr( core::pose::datacache::CacheableDataType::GEN_BORN_POSE_INFO )() );
273  } else {
274  gb_info = new GenBornPoseInfo();
275  }
276 
277  //jjh zero out arrays
278  //born_radius = 0.0;
279  gb_info->initialize( pose );
280 
281 
282 //jjh get the residue-residue burial
283  for ( Size res1 = 1; res1 <= nres; ++res1 ) {
284  Residue const & rsd1( pose.residue( res1 ) );
285  GenBornResidueInfo & gb1( gb_info->residue_info( res1 ) );
286  assert( std::abs( gb1.born_radius(1) ) < 1e-3 ); // ensure that this has been zeroed out
287  for ( Size res2 = 1; res2 <= nres; ++res2 ) {
288  res_res_burial( rsd1, gb1, pose.residue( res2 ), gb_info->residue_info( res2 ) );
289  }
290  }
291 
292 //jjh convert to Born radius
293 
294  for ( Size res1 = 1; res1 <= nres; ++res1 ) {
295  finalize_born_radii( gb_info->residue_info( res1 ) );
296  }
297 
299 
300  PROF_STOP( basic::GB_GET_ALL_BORN_RADII );
301 
302 }
303 
304 
305 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
306 /// \brief
307 /// Note: when called at the beginning of rotamer_trials, task.being_packed(i) will be false for all i
308 /// this ensures that we use all the information we have to compute the current set of radii
309 
310 void
312  pose::Pose & pose,
313  utility::vector1< bool > const & repacking_residues
314 ) const
315 {
316  // ////using core::pose::datacache::CacheableDataType::GEN_BORN_POSE_INFO;
317 
318  PROF_START( basic::GB_SETUP_FOR_PACKING );
319 
320  GenBornPoseInfoOP gb_info;
321 
323  gb_info = static_cast< GenBornPoseInfo* >( pose.data().get_ptr( core::pose::datacache::CacheableDataType::GEN_BORN_POSE_INFO )() );
324  } else {
325  gb_info = new GenBornPoseInfo();
326  }
327 
328  //jjh zero out arrays
329  //born_radius = 0.0;
330  gb_info->initialize( pose );
331 
332  /// store info about which positions are moving
333  gb_info->set_repack_list( repacking_residues );
334 
335  build_placeholders( pose, *gb_info );
336 
337  get_template_born_radii( pose, *gb_info );
338 
340 
341  PROF_STOP( basic::GB_SETUP_FOR_PACKING );
342 
343 }
344 
345 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
346 /// private
347 void
349  pose::Pose const & pose,
350  GenBornPoseInfo & gb_info
351 ) const
352 {
353  Size const nres( pose.total_residue() );
354 
355  chemical::ResidueTypeSet const & residue_set( pose.residue(1).residue_type_set() );
356  //chemical::ResidueType const & protein_placeholder_residue_type( residue_set.name_map("GB_AA_PLACEHOLDER") );
357 
358  for ( Size i=1; i<= nres; ++i ) {
359  if ( gb_info.being_packed(i) ) {
360  Residue const & existing_rsd( pose.residue(i) );
361  // build a placeholder at this position
362  if ( existing_rsd.is_protein() ) {
363  chemical::ResidueTypeCOP protein_placeholder_residue_type( &( residue_set.name_map("GB_AA_PLACEHOLDER") ) );
364  // use appropriate termini variants if necessary:
365  if ( existing_rsd.is_lower_terminus() ) {
366  protein_placeholder_residue_type =
367  &(residue_set.get_residue_type_with_variant_added( *protein_placeholder_residue_type,
369  }
370  if ( existing_rsd.is_upper_terminus() ) {
371  protein_placeholder_residue_type =
372  &(residue_set.get_residue_type_with_variant_added( *protein_placeholder_residue_type,
374  }
375 
377  ( conformation::ResidueFactory::create_residue( *protein_placeholder_residue_type, existing_rsd,
378  pose.conformation() ) );
379  GenBornResidueInfoOP rsd_info( new GenBornResidueInfo( *rsd ) );
380 
381  Size const dummy_index( rsd->atom_index("DUMM") );
382  rsd_info->atomic_radius( dummy_index ) = dummy_radius;
383  rsd_info->scale_factor ( dummy_index ) = dummy_scale;
384 
385  // debug placement of dummy atom
386  assert( std::abs( rsd->xyz("CA").distance( rsd->xyz( dummy_index )) - dummy_distance ) < 1e-2 );
387  gb_info.set_placeholder( i, rsd, rsd_info );
388 
389  } else {
390  std::cout << "WARNING: no mechanism for building genborn placeholders at non-protein positions\n" <<
391  "Using existing residue coords" << std::endl;
392  gb_info.set_placeholder( i, existing_rsd.clone(), new GenBornResidueInfo( existing_rsd ) );
393  }
394  }
395  }
396 
397 
398 }
399 
400 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
401 /// private
402 void
404  pose::Pose const & pose,
405  //pack::task::PackerTask const & task,
406  GenBornPoseInfo & gb_info
407 ) const
408 {
409  Size const nres( pose.total_residue() );
410 
411  assert( gb_info.size() == nres );
412 
413  for ( Size i=1; i<= nres; ++i ) {
414  if ( gb_info.being_packed( i ) ) continue;
415  Residue const & rsd1( pose.residue( i ) );
416  GenBornResidueInfo & gb1( gb_info.residue_info( i ) );
417  assert( rsd1.natoms()<1 || std::abs( gb1.born_radius(1) ) < 1e-3 ); // ensure radii have been initialized to 0
418  for ( Size j=1; j<= nres; ++j ) {
419 
420  if ( gb_info.being_packed( j ) ) {
421  // use placeholder
422  res_res_burial( rsd1, gb1, gb_info.placeholder_residue( j ), gb_info.placeholder_info( j ) );
423  } else {
424  res_res_burial( rsd1, gb1, pose.residue(j), gb_info.residue_info( j ) );
425  }
426  }
427  }
428 
429  for ( Size i=1; i<= nres; ++i ) {
430  if ( gb_info.being_packed( i ) ) continue;
431  finalize_born_radii( gb_info.residue_info(i) );
432  }
433 }
434 
435 
436 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
437 /// called eg after a rotamer substitution is accepted during rotamer trials
438 void
440  pose::Pose & pose,
441  Size const seqpos
442 ) const
443 {
444  // ////using core::pose::datacache::CacheableDataType::GEN_BORN_POSE_INFO;
445 
446  GenBornPoseInfo & gb_info( static_cast< GenBornPoseInfo & >( pose.data().get( core::pose::datacache::CacheableDataType::GEN_BORN_POSE_INFO ) ) );
447  GenBornResidueInfo & gb( gb_info.residue_info( seqpos ) );
448 
449  Residue const & rsd( pose.residue( seqpos ) );
450 
451  gb.initialize( rsd );
452 
453  get_single_rotamer_born_radii( rsd, pose, gb_info, gb );
454 }
455 
456 
457 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
458 /// uses placeholder info at positions i with gb_info.being_packed(i) == true
459 ///
460 
461 void
463  Residue const & rsd1,
464  pose::Pose const & pose,
465  GenBornPoseInfo const & gb_info,
466  GenBornResidueInfo & gb1
467 ) const
468 {
469 
470  assert( rsd1.natoms()<1 || std::abs( gb1.born_radius(1) ) < 1e-3 ); // ensure radii have been initialized to 0
471 
472  for ( Size res2=1; res2<= pose.total_residue(); ++res2 ) {
473  if ( gb_info.being_packed( res2 ) ) {
474  // use placeholder
475  res_res_burial( rsd1, gb1, gb_info.placeholder_residue( res2 ), gb_info.placeholder_info( res2));
476  } else {
477  res_res_burial( rsd1, gb1, pose.residue( res2 ), gb_info.residue_info( res2 ) );
478  }
479  }
480 
481  finalize_born_radii( gb1 );
482 }
483 
484 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
485 void
487  pose::Pose const & pose,
488  conformation::RotamerSetBase & rotamer_set
489 ) const
490 {
492  // ////using core::pose::datacache::CacheableDataType::GEN_BORN_POSE_INFO;
493 
494  // this holds placeholders, info for non-packed residues
495  GenBornPoseInfo const & gb_info_pose
496  ( static_cast< GenBornPoseInfo const & >(pose.data().get( core::pose::datacache::CacheableDataType::GEN_BORN_POSE_INFO )));
497 
498  // this will get cached in the rotamer set
499  // this call should initialize the residue_info objects with the appropriate Residue info
500  GenBornRotamerSetInfoOP gb_info_rotamers( new GenBornRotamerSetInfo( rotamer_set ) );
501 
502  for ( Size n=1; n<= rotamer_set.num_rotamers(); ++n ) {
503  get_single_rotamer_born_radii( *rotamer_set.rotamer(n), pose, gb_info_pose, gb_info_rotamers->residue_info( n ) );
504  }
505 
506  rotamer_set.data().set( GEN_BORN_ROTAMER_SET_INFO, gb_info_rotamers );
507 }
508 
509 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
510 Real
512  Residue const & rsd1,
513  GenBornResidueInfo const & gb1,
514  Residue const & rsd2,
515  GenBornResidueInfo const & gb2
516 ) const
517 {
518  using namespace etable::count_pair;
519 
520  int natoms1 = rsd1.natoms();
521  int natoms2 = rsd2.natoms();
522 
523  Real const inv_Ep = 1.0/Ep;
524  Real const tau = (1.0/Ep - 1.0/Ew);
525  bool const same_res = ( rsd1.seqpos() == rsd2.seqpos() );
526 
528  if ( same_res ) {
529  cpfxn = CountPairFactory::create_intrares_count_pair_function( rsd1, CP_CROSSOVER_3 );
530  //} else if ( rsd1.is_bonded( rsd2 ) ) {
531  // cpfxn = new etable::count_pair::CountPair1BC3( rsd1, rsd1.connect_atom( rsd2 ), rsd2, rsd2.connect_atom( rsd1 ) );
532  //} else {
533  // cpfxn = new etable::count_pair::CountPairAll();
534  //}
535  } else if ( rsd1.is_bonded( rsd2 ) || rsd1.is_pseudo_bonded( rsd2 ) ) {
536  cpfxn = CountPairFactory::create_count_pair_function( rsd1, rsd2, CP_CROSSOVER_3 );
537  }
538 
539  Real elecE = 0.0;
540  for ( int atm1 = 1; atm1 <= natoms1; ++atm1 ) {
541  Real const q1 = rsd1.atomic_charge( atm1 );
542 
543  if( std::fabs( q1 ) < 0.00001 ) continue;
544 
545  Real const brad1( gb1.born_radius( atm1 ) );
546  Real const r1 = gb1.atomic_radius( atm1 );
547  Vector const & xyz1( rsd1.xyz( atm1 ) );
548 
549  for ( int atm2 = 1; atm2 <= natoms2; ++atm2 ) {
550  Real const q2 = rsd2.atomic_charge( atm2 );
551  if( std::fabs( q2 ) < 0.0001 ) continue;
552 
553  Real const brad2( gb2.born_radius( atm2 ) );
554 
555  Real const dis2( xyz1.distance_squared( rsd2.xyz( atm2 ) ) );
556  Real const exparg = (-dis2)/(4.0 * brad1 * brad2 );
557  Real const denom = std::sqrt( dis2 + brad1 * brad2 * std::exp( exparg ) );
558  Real this_intx;
559  if ( same_res ) {
560  // tau = (1.0/Ep - 1.0/Ew) Ep = 4.0 Ew=80.0
561  this_intx = (-166.0)*tau*q1*q2/denom;
562  } else {
563  this_intx = (-332.0)*tau*q1*q2/denom;
564  }
565  elecE += this_intx;
566  // total_gb += this_intx;
567 
568  this_intx = 0.0;
569  Real weight; // unused
570  Size path_dist( 0 );
571  if ( !cpfxn || cpfxn->count( atm1, atm2, weight, path_dist ) ) {
572  // 3 or more bonds away
573  Real const dis = std::sqrt( dis2 );
574  Real const r2 = gb2.atomic_radius( atm2 );
575  this_intx = 166.0 * gb_shell_intxn( inv_Ep * q1, r1, q2, r2, dis);
576  if (!same_res) this_intx *= 2.0;
577  }
578 
579  elecE += this_intx;
580  // total_coul += this_intx;
581  }
582  }
583 
584  return elecE;
585 }
586 
587 
588 
589 ////////////////////////////////////////////////////////////////////////////////
590 /// @brief Calculates the interaction energy of two shells of charge.
591 /// Doesn't blow up as shells pass through each other
592 ///
593 /// @authors jjh 5/17/2004
594 ///
595 /////////////////////////////////////////////////////////////////////////////////
596 Real
598  Real const qai,
599  Real const rai,
600  Real const qbi,
601  Real const rbi,
602  Real const dist
603 ) const
604 {
605 
606  if (dist >= (rai+rbi))
607  return (qai * qbi /dist);
608 
609 // Make sure rb is larger than ra
610 
611  Real qa;
612  Real ra;
613  Real qb;
614  Real rb;
615 
616  if (rai > rbi) {
617  qa = qbi;
618  ra = rbi;
619  qb = qai;
620  rb = rai;
621  } else {
622  qa = qai;
623  ra = rai;
624  qb = qbi;
625  rb = rbi;
626  }
627 
628  if (((ra+rb) > dist) && (dist > (rb - ra))) {
629  Real fout;
630  if (ra == rb) {
631  fout = 0.5 * (1.0+0.5*dist/ra);
632  } else {
633  fout = 0.5*(1.0 + 0.5*(ra*ra - rb*rb)/(ra*dist) + 0.5*dist/ra);
634  }
635  Real fin = 1.0 - fout;
636  return qa*qb*(fin/rb + fout*2.0/(dist+ra+rb));
637  } else {
638  return qa*qb/rb;
639  }
640 }
641 
642 ///////////////////////////////////////////////////////////////////////////////
643 Real
645  Real const qai,
646  Real const rai,
647  Real const qbi,
648  Real const rbi,
649  Real const dist
650 ) const
651 {
652 
653  if (dist >= (rai+rbi))
654  return (-1.0 * qai * qbi / ( dist * dist ) );
655 
656 
657 // Make sure rb is larger than ra
658 
659  Real qa;
660  Real ra;
661  Real qb;
662  Real rb;
663 
664  if (rai > rbi) {
665  qa = qbi;
666  ra = rbi;
667  qb = qai;
668  rb = rai;
669  } else {
670  qa = qai;
671  ra = rai;
672  qb = qbi;
673  rb = rbi;
674  }
675 
676  if (((ra+rb) > dist) && (dist > (rb - ra))) {
677  Real dfout;
678  Real fout;
679  if (ra == rb) {
680  fout = 0.5 * (1.0+0.5*dist/ra);
681  dfout = 0.25/ra;
682  } else {
683  fout = 0.5*(1.0 + 0.5*(ra*ra - rb*rb)/(ra*dist) + 0.5*dist/ra);
684  dfout = 0.25*(rb*rb - ra*ra)/(ra*dist*dist) + 0.25/ra;
685  }
686  Real dfin = -1.0*dfout;
687  return qa*qb*(dfin/rb -
688  2.0*fout/( (dist+ra+rb)*(dist+ra+rb) ) +
689  2.0*dfout/( dist + ra + rb ) );
690  } else {
691  ///jjh already fully buried
692  return 0.0;
693  }
694 }
695 
696 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
697 void
699  id::AtomID const & id,
700  Real const weight,
701  pose::Pose const & pose,
702  kinematics::DomainMap const & domain_map,
703  bool const exclude_DNA_DNA,
704  Vector & F1,
705  Vector & F2
706 ) const
707 {
708  using namespace etable::count_pair;
709  // ////using core::pose::datacache::CacheableDataType::GEN_BORN_POSE_INFO;
710 
711  Size const i( id.rsd() ), ii( id.atomno() );
712 
713  GenBornPoseInfo const & gb_info( static_cast< GenBornPoseInfo const & >( pose.data().get( core::pose::datacache::CacheableDataType::GEN_BORN_POSE_INFO)));
714 
715  Residue const & rsd1( pose.residue( i ) );
716  GenBornResidueInfo const & gb1( gb_info.residue_info( i ) );
717 
718 
719  // pose stuff
720  Size const nres( pose.total_residue() );
721  int const i_map( domain_map( i ) );
722  bool const i_fixed( i_map != 0 );
723 
724  Vector const & xyzi( rsd1.xyz( ii ) );
725 
726  // gb stuff
727  //Real const Ep = 4.0; // dielectric for protein
728  //Real const Ew = 80.0; // dielectric for water
729  Real const tau = (1.0/Ep - 1.0/Ew);
730  Real const q1 = rsd1.atomic_charge( ii );
731  Real const b1 = gb1.born_radius( ii );
732 
733  for ( Size j=1; j<= nres; ++j ) {
734  Residue const & rsd2( pose.residue( j ) );
735  if ( i_fixed && domain_map( j ) == i_map ) continue; // DANGER
736  if ( exclude_DNA_DNA && rsd1.is_DNA() && rsd2.is_DNA() ) continue;
737 
738  GenBornResidueInfo const & gb2( gb_info.residue_info( j ) );
739 
740  CountPairFunctionOP cpfxn( 0 );
741  if ( i == j ) {
742  cpfxn = CountPairFactory::create_intrares_count_pair_function( rsd1, CP_CROSSOVER_3 );
743  } else if ( rsd1.is_bonded( rsd2 ) || rsd1.is_pseudo_bonded( rsd2 ) ) {
744  cpfxn = CountPairFactory::create_count_pair_function( rsd1, rsd2, CP_CROSSOVER_3 );
745  }
746 
747 
748  for ( Size jj=1, jj_end=rsd2.natoms(); jj<= jj_end; ++jj ) {
749  Real cp_weight;
750  Size path_dist( 0 );
751  if ( cpfxn && !cpfxn->count( ii, jj, cp_weight, path_dist ) ) continue; // less than 3 bonds away
752 
753  //bool const same_atom( j == i && jj == ii );
754  assert( j != i || jj != ii );
755 
756  Vector const & xyzj( rsd2.xyz(jj) );
757  Vector const f2( xyzi - xyzj );
758 
759  Real const dis2( f2.length_squared() );
760  Real const dis = std::sqrt( dis2 );
761 
762  ///jjh First the dielectric screening term
763  Real const q2 = rsd2.atomic_charge( jj );
764  Real const b2 = gb2.born_radius( jj );
765 
766  Real const exparg = (-dis2)/(4.0*b1*b2);
767  Real const expon = std::exp( exparg );
768  Real const denom = 1.0 / ( std::sqrt( dis2 + b1*b2*expon ) );
769  Real const deriv_denom = denom * denom * denom;
770 
771  Real dE_dR
772  ( +166.0*tau*q1*q2*dis * ( 2.0 - 0.5*expon ) * deriv_denom );
773 
774  Real const r1( gb1.atomic_radius(ii) );
775  Real const r2( gb2.atomic_radius(jj) );
776 
777  Real const dE_dR_coul( gb_shell_intxn_deriv( q1, r1, q2, r2, dis ) );
778 
779  dE_dR += 332.0*dE_dR_coul/Ep;
780 
781  //if ( same_atom ) dE_dR *= 0.5;
782 
783  if ( dis > 0.0 ) {
784  Real const factor( weight * dE_dR / dis );
785  Vector const f1( xyzi.cross( xyzj ) );
786  F1 += factor * f1;
787  F2 += factor * f2;
788  }
789  }
790  }
791 }
792 
793 
794 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
795 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
796 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
797 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
798 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
799 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
800 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
801 
802 } // namespace scoring
803 } // namespace core