Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
FACTSPotential.cc
Go to the documentation of this file.
1 // -*- mode:c++;tab-width:2;indent-tabs-mode:t;show-trailing-whitespace:f;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/facts/FACTSPotential.cc
11 // @brief: The definitions of 3 classes of the FACTS algorithm resides here (see devel/khorvash/FACTSPotential.hh
12 // @author: Massih Khoravash
13 // @author: Hahnbeom Park
14 
15 // Unit headers
17 
18 // Project headers
23 #include <core/pose/Pose.hh>
24 //#include <core/pack/task/PackerTask.hh>
28 
29 #include <core/scoring/Energies.hh>
32 
33 #include <core/id/AtomID.hh>
34 #include <core/id/AtomID_Map.hh>
37 
38 //#include <core/chemical/MMAtomTypeSet.hh>
39 //#include <core/chemical/ChemicalManager.hh>
40 
41 #include <basic/prof.hh>
42 #include <basic/datacache/BasicDataCache.hh>
43 #include <basic/options/option.hh>
44 #include <basic/options/keys/in.OptionKeys.gen.hh>
45 #include <basic/options/keys/score.OptionKeys.gen.hh>
46 #include <basic/Tracer.hh>
47 
48 // Utility headers
49 #include <utility/exit.hh>
50 #include <math.h>
51 #include <stdio.h>
52 //#include <sys/time.h>
53 
54 static basic::Tracer TR("core.scoring.FACTSPotential");
55 
56 using namespace std;
57 
58 # define Math_PI 3.14159265358979323846
59 
60 namespace core {
61 namespace scoring {
62 
63 /**************************************************************************************************/
64 /* */
65 /* @brief: The FACTSResidueInfo class provides all the functions, constants and parameters */
66 /* for different atoms, which are required to calculate the solvation free energy of */
67 /* of a molecule embedded in water using FACTS method */
68 /* */
69 /**************************************************************************************************/
70 
71 //This function initializes all the values for FACTS original parameters, atomic volume, Ai, Bi, esolvE, sasa...
72 void FACTSResidueInfo::initialize( conformation::Residue const & rsd )
73 {
74  initialize_number_of_atoms( rsd );
75 
76  // This variable is used in res_res_burial and evaluate_polar(nonpolar)_energy
77  flag_for_calculation_ = utility::vector1< bool >( natoms(), false );
78 
79  // Initialize Arrays
80  Vector i( 0.0 );
81  nmtr_ = utility::vector1< Vector >( natoms(), i ); // dnmtr of Ai (equation 4 on page 704 of FACTS paper)
82  dnmtr_ = utility::vector1< Real >( natoms(), 1.0 ); // dnmtr of Bi (equation 4 on page 704 of FACTS paper)
83  Ai_ = utility::vector1< Real >( natoms(), 0.0 );// Ai (equation 3 on page 704 of FACTS paper)
84  Bi_ = utility::vector1< Real >( natoms(), 0.0 );// Bi (equation 4 on page 704 of FACTS paper)
85  Ci_ = utility::vector1< Real >( natoms(), 0.0 );// Ci (equation 6 on page 704 of FACTS paper)
86  Di_ = utility::vector1< Real >( natoms(), 0.0 );// Di (equation 10 on page 704 of FACTS paper)
87  Ei_ = utility::vector1< Real >( natoms(), 0.0 );// Ei - not being used
88  esolvE_ = utility::vector1< Real >( natoms(), 0.0 ); // DeltaGi (equation 7 on page 704 of FACTS paper)
89  sasa_ = utility::vector1< Real >( natoms(), 0.0 ); // atomic SASA (equation 11 on page 706 of FACTS paper)
90  alpha_ = utility::vector1< Real >( natoms(), 0.0 ); // Gamma used in equation 12 on page 706 of FACTS paper)
91  BR_ = utility::vector1< Real >( natoms(), 0.0 ); // BornRadius
92 
93 
94  selfneigh_ = utility::vector1< SelfNeighInfo >( natoms() ); // Array for containing Self-neighbors
95  for( Size i_atm = 1; i_atm <= natoms(); ++i_atm ){
96  selfneigh_[i_atm].nneigh = 0;
97  selfneigh_[i_atm].resID.resize( MAXNEIGH );
98  selfneigh_[i_atm].atmID.resize( MAXNEIGH );
99  }
100 
101  // auxiliary arrays for calculating derivatives
102  dG_dCi_ = utility::vector1< Real >( natoms() );
103  dSA_dDi_ = utility::vector1< Real >( natoms() );
104  dE_dBR_ = utility::vector1< Real >( natoms() );
105  dE_drij2_ = utility::vector1< Vector >( natoms(), i );
106  polarF2d_ = utility::vector1< Vector >( natoms(), i );
107  polarF2BR_ = utility::vector1< Vector >( natoms(), i );
108  nonpolarF2_ = utility::vector1< Vector >( natoms(), i );
109 
110  // Initialize native parameters & partial charges
111  initialize_parameters( rsd );
112  initialize_charge( rsd );
113 
114 } // END void FACTSResidueInfo::initialize( conformation::Residue const & rsd){
115 
116 //This function initializes the natoms variable to the number of atoms of the residue rsd
117 void FACTSResidueInfo::initialize_number_of_atoms(conformation::Residue const & rsd){
118  natoms_ = rsd.natoms();
119 } // END void FACTSResidueInfo::initialize_number_of_atoms(conformation::Residue const & rsd)
120 
121 // This function initializes native parameters that are used for empirical function calculations
122 void FACTSResidueInfo::initialize_parameters(conformation::Residue const & rsd){
123 
124  using namespace basic::options;
125  using namespace basic::options::OptionKeys;
126 
127  //grab data from "database/chemical/atom_type_sets/fa_standard/extras/facts_params.txt
128  Size const FACTS_RADIUS_INDEX( rsd.atom_type_set().extra_parameter_index( "FACTS_RADIUS" ) );
129  Size const FACTS_CUT_INDEX ( rsd.atom_type_set().extra_parameter_index( "FACTS_CUT" ) );
130  Size const FACTS_B1_INDEX ( rsd.atom_type_set().extra_parameter_index( "FACTS_B1" ) );
131  Size const FACTS_B2_INDEX ( rsd.atom_type_set().extra_parameter_index( "FACTS_B2" ) );
132  Size const FACTS_D1_INDEX ( rsd.atom_type_set().extra_parameter_index( "FACTS_D1" ) );
133  Size const FACTS_D2_INDEX ( rsd.atom_type_set().extra_parameter_index( "FACTS_D2" ) );
134  Size const FACTS_A0_INDEX ( rsd.atom_type_set().extra_parameter_index( "FACTS_A0" ) );
135  Size const FACTS_A1_INDEX ( rsd.atom_type_set().extra_parameter_index( "FACTS_A1" ) );
136  Size const FACTS_A2_INDEX ( rsd.atom_type_set().extra_parameter_index( "FACTS_A2" ) );
137  Size const FACTS_A3_INDEX ( rsd.atom_type_set().extra_parameter_index( "FACTS_A3" ) );
138  Size const FACTS_C0_INDEX ( rsd.atom_type_set().extra_parameter_index( "FACTS_C0" ) );
139  Size const FACTS_C1_INDEX ( rsd.atom_type_set().extra_parameter_index( "FACTS_C1" ) );
140  Size const FACTS_C2_INDEX ( rsd.atom_type_set().extra_parameter_index( "FACTS_C2" ) );
141  Size const FACTS_C3_INDEX ( rsd.atom_type_set().extra_parameter_index( "FACTS_C3" ) );
142 
143  Size FACTS_ALPHA_INDEX;
144  if ( option[ score::facts_asp_patch ]() ){
145  FACTS_ALPHA_INDEX = rsd.atom_type_set().extra_parameter_index( "FACTS_ALPHA2" );
146  } else {
147  FACTS_ALPHA_INDEX = rsd.atom_type_set().extra_parameter_index( "FACTS_ALPHA" );
148  }
149 
150  // Initialize array sizes & put in parameters
151  COradius_.resize( natoms() );
152  volume_.resize( natoms() );
153  a0_.resize( natoms() );
154  a1_.resize( natoms() );
155  a2_.resize( natoms() );
156  a3_.resize( natoms() );
157  b1_.resize( natoms() );
158  b2_.resize( natoms() );
159  c0_.resize( natoms() );
160  c1_.resize( natoms() );
161  c2_.resize( natoms() );
162  c3_.resize( natoms() );
163  d1_.resize( natoms() );
164  d2_.resize( natoms() );
165  not_using_.resize( natoms() );
166 
167  for(Size i = 1; i <= natoms(); ++i){
168  Real vdw_radius = rsd.atom_type(i).extra_parameter( FACTS_RADIUS_INDEX );
169  if ( vdw_radius <= 1.0e-6 ){
170  not_using_[i] = true;
171  } else {
172  not_using_[i] = false;
173  }
174 
175  volume_[i] = (4.0/3.0) * Math_PI * vdw_radius * vdw_radius * vdw_radius;
176  //if ( option[ score::facts_apprx ]() ){
177  // modify_volume( rsd, i );
178  //}
179 
180  alpha_[i] = rsd.atom_type(i).extra_parameter( FACTS_ALPHA_INDEX );
181 
182  COradius_[i] = rsd.atom_type(i).extra_parameter( FACTS_CUT_INDEX );
183  b1_[i] = rsd.atom_type(i).extra_parameter( FACTS_B1_INDEX );
184  b2_[i] = rsd.atom_type(i).extra_parameter( FACTS_B2_INDEX );
185  d1_[i] = rsd.atom_type(i).extra_parameter( FACTS_D1_INDEX );
186  d2_[i] = rsd.atom_type(i).extra_parameter( FACTS_D2_INDEX );
187  a0_[i] = rsd.atom_type(i).extra_parameter( FACTS_A0_INDEX );
188  a1_[i] = rsd.atom_type(i).extra_parameter( FACTS_A1_INDEX );
189  a2_[i] = rsd.atom_type(i).extra_parameter( FACTS_A2_INDEX );
190  a3_[i] = rsd.atom_type(i).extra_parameter( FACTS_A3_INDEX );
191  c0_[i] = rsd.atom_type(i).extra_parameter( FACTS_C0_INDEX );
192  c1_[i] = rsd.atom_type(i).extra_parameter( FACTS_C1_INDEX );
193  c2_[i] = rsd.atom_type(i).extra_parameter( FACTS_C2_INDEX );
194  c3_[i] = rsd.atom_type(i).extra_parameter( FACTS_C3_INDEX );
195  }
196 } // END void FACTSResidueInfo::initialize_parameters(conformation::Residue const & rsd)
197 
198 //This function initializes the atomic partial charges
199 void FACTSResidueInfo::initialize_charge(conformation::Residue const & rsd){
200  q_ = utility::vector1< Real >( natoms() );
201  for(Size atm = 1;atm <= natoms(); atm++){
202  q_[atm] = rsd.atomic_charge( atm );
203  }
204 } // END void FACTSResidueInfo::initialize_charge(conformation::Residue const & rsd)
205 
206 void FACTSResidueInfo::modify_volume( conformation::Residue const & rsd, Size i ){
207  string atmname = rsd.atom_type(i).atom_type_name();
208  string resname = rsd.name();
209 
210  Real volume_per_Hapo = (4.0/3.0) * Math_PI * 1.0 * 1.0 * 1.0;
211 
212  if (atmname.compare("Hapo") == 0){
213  volume_[i] = 0.0;
214 
215  } else if (atmname.compare("CH3") == 0){
216  volume_[i] += 3.0*volume_per_Hapo;
217  } else if (atmname.compare("CH2") == 0){
218  volume_[i] += 2.0*volume_per_Hapo;
219  } else if (atmname.compare("CH1") == 0){
220  volume_[i] += volume_per_Hapo;
221  } else if (atmname.compare("aroC") == 0){
222  volume_[i] += volume_per_Hapo;
223  } else if (resname.compare("GLY") == 0 && atmname.compare("CAbb") == 0){
224  volume_[i] += 2.0*volume_per_Hapo;
225  } else if (resname.compare("GLY") != 0 && atmname.compare("CAbb") == 0){
226  volume_[i] += volume_per_Hapo;
227  } else if (resname.compare("CYS") == 0 && atmname.compare("S") == 0){
228  volume_[i] += volume_per_Hapo;
229  }
230 }
231 
232 /**************************************************************************************************/
233 /* */
234 /* @breif: The class FACTSPoseInfo */
235 /* */
236 /**************************************************************************************************/
237 
238 // Constructor
239 FACTSPoseInfo::FACTSPoseInfo( FACTSPoseInfo const & src ):CacheableData()
240 {
241  Size const src_size( src.size() );
242 
243  residue_info_.resize( src_size );
244  placeholder_residue_.resize( src_size );
245  placeholder_info_.resize( src_size );
246 
247  for ( Size i=1; i<= src_size; ++i ) {
248  residue_info_[i] = src.residue_info_[i]->clone();
249  if ( src.placeholder_residue_[i] ) {
250  placeholder_residue_[i] = src.placeholder_residue_[i]->clone();
251  placeholder_info_[i] = src.placeholder_info_[i]->clone();
252  } else {
253  placeholder_residue_[i] = 0;
254  placeholder_info_[i] = 0;
255  }
256  }
258 }
259 
261  Size const nres( pose.total_residue() );
262 
263  residue_info_.resize( nres, 0 );
264  placeholder_residue_.resize( nres, 0 );
265  placeholder_info_.resize( nres, 0 );
266 
267  for ( Size i=1; i<= nres; ++i ) {
268  if ( !residue_info_[i] ){
269  residue_info_[i] = new FACTSResidueInfo( pose.residue(i) );
270  }else {
271  residue_info_[i]->initialize( pose.residue(i) );
272  }
273  }
274  being_packed_.clear();
275 }
276 
278 {
279  placeholder_residue_[ i ] = rsd;
280  placeholder_info_[ i ] = info;
281 }
282 
284 {
285  being_packed_.resize( size(), false );
286  for ( Size i=1; i<= size(); ++i ) {
287  being_packed_[i] = repacking_residues[ i ];
288  }
289 }
290 
291 /**************************************************************************************************/
292 /* */
293 /* @brief: The class FACTSRotamerSetInfo */
294 /* */
295 /**************************************************************************************************/
296 
297 /// dont forget to 0 the born_radii
298 void FACTSRotamerSetInfo::initialize( RotamerSet const & rotamer_set )
299 {
300  Size const nrot( rotamer_set.num_rotamers() );
301  residue_info_.resize( nrot );
302  for ( Size i=1; i<= nrot; ++i ) {
303  residue_info_[i] = new FACTSResidueInfo( *rotamer_set.rotamer(i) );
304  }
305 }
306 
307 /**************************************************************************************************/
308 /* */
309 /* @breif: The FACTSPotential class provides all the functions, constants, and parameters */
310 /* common to all atoms required to calculate the free energy of solvation of a */
311 /* (macro)molecule embedded in a continuum solvent using FACTS method */
312 /* */
313 /**************************************************************************************************/
315  MultiplicitiveFactor_(332.07156)
316 {
317  using namespace basic::options;
318  using namespace basic::options::OptionKeys;
319 
320  Kappa_ = option[ score::facts_kappa ]();
321  GBpair_cut_ = option[ score::facts_GBpair_cut ]();
322  Tau_ = (1.0/option[ score::hackelec_die ]() ) - (1.0/78.5);
323  do_apprx = option[ score::facts_apprx ]();
324 
325  if( do_apprx ){
326  TR << "FACTS Approximation turned on." << endl;
327  }
328 
329  if( option[ score::facts_asp_patch ] ){
330  TR << "FACTS ASP patch applied." << endl;
331  }
332 
333  assert( option[score::hackelec_die]() == 1.0 );
334  assert( option[score::hackelec_r_option]() );
335 }
336 
337 // Dummy thing... I don't know why this is required
339  pose::Pose const & pose,
340  FACTSPoseInfo & facts_info
341  ) const
342 {
343  Size const nres( pose.total_residue() );
344 
345  chemical::ResidueTypeSet const & residue_set( pose.residue(1).residue_type_set() );
346 
347  for ( Size i=1; i<= nres; ++i ) {
348  if ( facts_info.being_packed(i) ) {
349  Residue const & existing_rsd( pose.residue(i) );
350  // build a placeholder at this position
351  if ( existing_rsd.is_protein() ) {
352  chemical::ResidueTypeCAP protein_placeholder_residue_type( &( residue_set.name_map("GB_AA_PLACEHOLDER") ) );
353  // use appropriate termini variants if necessary:
354  if ( existing_rsd.is_lower_terminus() ) {
355  protein_placeholder_residue_type =
356  &(residue_set.get_residue_type_with_variant_added( *protein_placeholder_residue_type,
358  }
359  if ( existing_rsd.is_upper_terminus() ) {
360  protein_placeholder_residue_type =
361  &(residue_set.get_residue_type_with_variant_added( *protein_placeholder_residue_type,
363  }
364 
366  ( conformation::ResidueFactory::create_residue( *protein_placeholder_residue_type, existing_rsd,
367  pose.conformation() ) );
368  FACTSResidueInfoOP rsd_info( new FACTSResidueInfo( *rsd ) );
369 
370  Size const dummy_index( rsd->atom_index("DUMM") );
371  //rsd_info->set_atomic_radius( dummy_index, dummy_radius_);
372  assert( std::fabs( rsd->xyz("CA").distance( rsd->xyz( dummy_index )) - 2.44 ) < 1e-2 );
373  facts_info.set_placeholder( i, rsd, rsd_info );
374  }
375  }
376  }
377 }
378 
379  //This function "pre-calculates" all the atomic contents (Born radius, sasa,...) and energy values
381  Size res1;
382  Size res2;
383 
384  //timeval t1, t2, t3, t4;
385 
386  //gettimeofday(&t1, NULL );
387 
388  PROF_START( basic::FACTS_GET_ALL_BORN_RADII );
389  Size const nres( pose.total_residue() );
390  FACTSPoseInfoOP facts_info;
391 
392  if ( pose.data().has( core::pose::datacache::CacheableDataType::FACTS_POSE_INFO ) ) {
393  facts_info = static_cast< FACTSPoseInfo* >
394  ( pose.data().get_ptr( core::pose::datacache::CacheableDataType::FACTS_POSE_INFO )() );
395  } else {
396  facts_info = new FACTSPoseInfo();
397  }
398 
399  facts_info->initialize( pose );
400 
401  Energies const & energies( pose.energies() );
402  EnergyGraph const & energy_graph( energies.energy_graph() );
403 
404  // 1. First get Born radius, Solvation energy, SASA for all atoms
405  for ( res1 = 1; res1 <= nres; ++res1 ) {
406  Residue const & rsd1( pose.residue( res1 ) );
407  Size natoms1 = rsd1.natoms();
408  FACTSResidueInfo & facts1( facts_info->residue_info( res1 ) );
409 
410  if( facts1.natoms() == 0) continue;
411 
412  res_res_burial_for_scoring( rsd1, facts1, rsd1, facts1 );
413 
415  iru = energy_graph.get_node( res1 )->const_edge_list_begin(),
416  irue = energy_graph.get_node( res1 )->const_edge_list_end();
417  iru != irue; ++iru ) {
418  Size const res2( (*iru)->get_other_ind( res1 ) );
419 
420  // Iter over upper only
421  if (res2 < res1) continue;
422 
423  conformation::Residue const & rsd2( pose.residue( res2 ) );
424  res_res_burial_for_scoring( rsd1, facts1, pose.residue( res2 ), facts_info->residue_info( res2 ) );
425  }
426  }
427 
428  //gettimeofday(&t2, NULL );
429  //Real elapsedTime1 = (t2.tv_sec - t1.tv_sec) * 1000.0;
430  //elapsedTime1 += (t2.tv_usec - t1.tv_usec) / 1000.0;
431 
432  //core::chemical::AtomTypeSetCAP atom_types =
433  // core::chemical::ChemicalManager::get_instance()->atom_type_set("fa_standard");
434 
435  // 2. Refresh Born radii / SASA
436  for ( res1 = 1; res1 <= nres; ++res1 ){
437  FACTSResidueInfo & facts1( facts_info->residue_info( res1 ) );
438  get_self_terms( facts1 );
439 
440  // Log for Born radii and SASA
441  /*
442  for( Size atm1 = 1; atm1 <= pose.residue(res1).natoms(); ++atm1 ){
443  string atmname = pose.residue(res1).atom_type(atm1).atom_type_name();
444  cout << "Res/Atm/Type/" << setw(4) << res1 << setw(4) << atm1 << " " << setw(4) << atmname;
445  cout << " " << setw(10) << facts1.BR(atm1);
446  cout << " " << setw(10) << facts1.sasa(atm1);
447  cout << "|" << setw(10) << facts1.b1(atm1) << "|" << setw(10) << facts1.b2(atm1);
448  cout << "|" << setw(10) << facts1.d1(atm1) << "|" << setw(10) << facts1.d2(atm1);
449  cout << "|" << setw(10) << facts1.Ai(atm1) << "|" << setw(10) << facts1.Bi(atm1);
450  cout << "|" << setw(10) << facts1.Ci(atm1) << "|" << setw(10) << facts1.Di(atm1) << endl;
451  }
452  */
453  }
454 
455  //gettimeofday(&t3, NULL );
456  //Real elapsedTime2 = (t3.tv_sec - t2.tv_sec) * 1000.0;
457  //elapsedTime2 += (t3.tv_usec - t2.tv_usec) / 1000.0;
458 
459  // 3. Then Pre-calculate all GB-pair-related parts and store them in FACTSINFO
460  for ( res1 = 1; res1 <= nres; ++ res1 ){
461  FACTSResidueInfo & facts1( facts_info->residue_info( res1 ) );
462  Residue const & rsd1( pose.residue( res1 ) );
463  facts1.GBpair_ = utility::vector1< Real >( nres, 0.0 );
464 
465  calculate_GBpair_exact( rsd1, rsd1, facts1, facts1 );
466 
468  iru = energy_graph.get_node( res1 )->const_edge_list_begin(),
469  irue = energy_graph.get_node( res1 )->const_edge_list_end();
470  iru != irue; ++iru ) {
471 
472  Size const res2( (*iru)->get_other_ind( res1 ) );
473  // Iter over upper only
474  if (res2 < res1) continue;
475 
476  FACTSResidueInfo & facts2( facts_info->residue_info( res2 ) );
477  Residue const & rsd2( pose.residue( res2 ) );
478  if ( do_apprx ){
479  calculate_GBpair_apprx( rsd1, rsd2, facts1, facts2 );
480  } else {
481  calculate_GBpair_exact( rsd1, rsd2, facts1, facts2 );
482  }
483  }
484  }
485 
486  // 3. Finally store everything into pose
487  pose.data().set( core::pose::datacache::CacheableDataType::FACTS_POSE_INFO, facts_info );
488  PROF_STOP( basic::FACTS_GET_ALL_BORN_RADII );
489 
490  //gettimeofday(&t4, NULL );
491  //Real elapsedTime3 = (t4.tv_sec - t3.tv_sec) * 1000.0;
492  //elapsedTime3 += (t4.tv_usec - t3.tv_usec) / 1000.0;
493  //cout << "Setup for scoring 1/2/3: " << elapsedTime1 << " " << elapsedTime2 << " " << elapsedTime3 << " ms." << endl;
494 }// END setup_for_scoring
495 
496 // This function evaluates Ai (volume of each atom) and components of Bi (symmetry of each atom),
497 // which are converted to Born Radius & SASA in the next step
499  conformation::Residue const & rsd1,
500  FACTSResidueInfo & facts1,
501  conformation::Residue const & rsd2,
502  FACTSResidueInfo const & facts2
503  ) const
504 {
505  bool const same_res( rsd1.seqpos() == rsd2.seqpos() );
506  Size natoms1 = rsd1.natoms();
507  Size natoms2 = rsd2.natoms();
508  Vector xyz2, xyz1, dyxz;
509 
510  // START: This part calculates the volume and symmetry of the solute around atom atm
511  // and maintains it in Ai_ and nmtr_ & dnmtr_
512  for ( Size atm1 = 1; atm1 <= natoms1; ++atm1 ) {
513  xyz1 = rsd1.xyz(atm1);
514 
515  if ( facts1.not_using(atm1) ) continue;
516 
517  for ( Size atm2 = 1; atm2 <= natoms2; ++atm2 ) {
518  if (same_res && (atm1 == atm2 )) continue;
519 
520  xyz2 = (rsd2.xyz( atm2 ));
521  Vector const dxyz( xyz1 - xyz2 );
522 
523  if ( facts2.not_using(atm2) || facts2.volume(atm2) < 1e-3) continue;
524 
525  Real dis2 = xyz1.distance_squared( xyz2 );
526  Real dis = std::sqrt(dis2);
527 
528  Real CutOff_sqr = facts1.COradius(atm1)*facts1.COradius(atm1);
529 
530  //this is a redundant check as there is a stricter check on the next if statment ...
531  if( dis2 >= CutOff_sqr ) continue;
532  facts1.flag_for_calculation_[atm1] = true;
533 
534  // Equation 5 on page 704 of FACTS paper
535  Real theta_sqrt = 1.0 - (dis2 / CutOff_sqr);
536  Real thetaij = theta_sqrt*theta_sqrt;
537 
538  // The term within the sigma of equation 3 on page 704 of FACTS'
539  Real Vi = facts2.volume(atm2) * thetaij;
540 
541  // 1. Ai in equation 3 of page 704 of FACTS paper
542  facts1.Ai_[atm1] += Vi;
543 
544  // 2. Bi: the xyz coordinate of the nmtr of equation 4 on page 704 of FACTS paper
545  facts1.nmtr_[atm1] += (Vi/dis2)*dxyz;
546  facts1.dnmtr_[atm1] += Vi/dis;
547  }
548  }
549 }//end res_res_burial
550 
551 // This function has same logic with res_res_burial, but modified for efficient scoring
552 // and for derivative evaluation
554  conformation::Residue const & rsd1,
555  FACTSResidueInfo & facts1,
556  conformation::Residue const & rsd2,
557  FACTSResidueInfo & facts2
558  ) const
559 {
560  bool const same_res( rsd1.seqpos() == rsd2.seqpos() );
561  Size natoms1 = rsd1.natoms();
562  Size natoms2 = rsd2.natoms();
563  Real thetaij, theta_sqrt;
564  Real MAX_SELFDCUT2 = min(100.0, GBPair_cut()*GBPair_cut());
565 
566  // START: This part calculates the volume and symmetry of the solute around atom atm
567  // and maintains it in Ai_ and nmtr_ & dnmtr_
568  for ( Size atm1 = 1; atm1 <= natoms1; ++atm1 ) {
569  Vector const &xyz1 = rsd1.xyz(atm1);
570  if ( facts1.not_using(atm1) ) continue;
571 
572  Real CutOff_sqr1 = min(facts1.COradius(atm1)*facts1.COradius(atm1),
573  MAX_SELFDCUT2);
574  SelfNeighInfo &neigh1 = facts1.selfneigh_[atm1];
575  Real const &V1 = facts1.volume(atm1);
576 
577  // Iterate only for upper diagonal :)
578  for ( Size atm2 = 1; atm2 <= natoms2; ++atm2 ) {
579  if (same_res && (atm1 >= atm2)) continue;
580  if ( facts2.not_using(atm2) ) continue;
581 
582  Vector const &xyz2 = rsd2.xyz( atm2 );
583  Vector const dxyz( xyz1 - xyz2 );
584  Real const dis2 = dxyz[0]*dxyz[0] + dxyz[1]*dxyz[1] + dxyz[2]*dxyz[2];
585 
586  if ( dis2 > MAX_SELFDCUT2 ) continue;
587 
588  Real dis = std::sqrt(dis2);
589  Real CutOff_sqr2 = min(facts2.COradius(atm2)*facts2.COradius(atm2),
590  MAX_SELFDCUT2);
591 
592  // Consideration for the first atom
593  if( dis2 <= CutOff_sqr1 && facts2.volume(atm2) > 1e-3 ){
594  if (neigh1.nneigh >= facts1.MAXNEIGH) continue;
595  facts1.flag_for_calculation_[atm1] = true;
596  neigh1.nneigh++;
597  neigh1.resID[ neigh1.nneigh ] = rsd2.seqpos();
598  neigh1.atmID[ neigh1.nneigh ] = atm2;
599 
600  // Equation 5 on page 704 of FACTS paper
601  theta_sqrt = 1.0 - (dis2 / CutOff_sqr1);
602  thetaij = theta_sqrt*theta_sqrt;
603  // The term within the sigma of equation 3 on page 704 of FACTS'
604  Real Vi = facts2.volume(atm2) * thetaij;
605 
606  // 1. Ai in equation 3 of page 704 of FACTS paper
607  facts1.Ai_[atm1] += Vi;
608 
609  // 2. Bi: the xyz coordinate of the nmtr of equation 4 on page 704 of FACTS paper
610  facts1.nmtr_[atm1] += (Vi/dis2)*dxyz;
611  facts1.dnmtr_[atm1] += Vi/dis;
612  }
613 
614  // Consideration for the second atom
615  if( dis2 <= CutOff_sqr2 && facts1.volume(atm1) > 1e-3 ){
616 
617  SelfNeighInfo &neigh2 = facts2.selfneigh_[atm2];
618 
619  if (neigh2.nneigh >= facts2.MAXNEIGH) continue;
620 
621  facts2.flag_for_calculation_[atm2] = true;
622  neigh2.nneigh++;
623  neigh2.resID[ neigh2.nneigh ] = rsd1.seqpos();
624  neigh2.atmID[ neigh2.nneigh ] = atm1;
625 
626  // Equation 5 on page 704 of FACTS paper
627  theta_sqrt = 1.0 - (dis2 / CutOff_sqr2);
628  thetaij = theta_sqrt*theta_sqrt;
629 
630  // The term within the sigma of equation 3 on page 704 of FACTS'
631  Real const Vi = V1*thetaij;
632 
633  // 1. Ai in equation 3 of page 704 of FACTS paper
634  facts2.Ai_[atm2] += Vi;
635 
636  // 2. Bi: the xyz coordinate of the nmtr of equation 4 on page 704 of FACTS paper
637  facts2.nmtr_[atm2] -= (Vi/dis2)*dxyz;
638  facts2.dnmtr_[atm2] += Vi/dis; // the dnmtr of equation 4 on page 704 of FACTS paper
639  }
640  }
641  }
642 }//end res_res_burial_for_scoring
643 
644 // Converts Ai & Bi (actually its nmtr & dnmtr) into Born Radius & SASA
646  FACTSResidueInfo & facts1
647  ) const
648 {
649  for( Size atm1 = 1 ;atm1<=facts1.natoms(); atm1++ ){
650 
651  if (facts1.flag_for_calculation(atm1) ){
652  // Bi needs to be calculated after all vectors are collected in res_res_burial
653  // Bi in equation 4 of page 704 of FACTS paper
654  facts1.Bi_[atm1] = (facts1.nmtr(atm1)).norm() / facts1.dnmtr(atm1);
655 
656  // 1. Born Radius & Self Polar energy!
657  facts1.Ci_[atm1] = facts1.Ai(atm1) + (facts1.b1( atm1 ) * facts1.Bi(atm1)) +
658  (facts1.b2(atm1) * facts1.Ai(atm1) * facts1.Bi(atm1) );
659 
660  Real expterm = exp( -facts1.a2(atm1) * (facts1.Ci(atm1) - facts1.a3(atm1)) );
661  Real tmp = facts1.a1(atm1)/(1.0 + expterm);
662 
663  // Equation 7 of page 704 of FACTS paper
664  facts1.esolvE_[atm1] = facts1.a0(atm1) + tmp;
665  facts1.BR_[atm1] = -0.5*Tau()*MultiplicitiveFactor()/facts1.esolvE_[atm1];
666 
667  // Save partial derivative for nonpolar term here
668  facts1.dG_dCi_[atm1] = facts1.a2(atm1)*expterm*tmp/( 1.0 + expterm );
669 
670  // 2. SASA!
671  // Equation 10 of page 706 of FACTS paper
672  facts1.Di_[atm1] = facts1.Ai(atm1) + (facts1.d1( atm1 ) * facts1.Bi(atm1)) +
673  (facts1.d2(atm1) * facts1.Ai(atm1) * facts1.Bi(atm1) );
674 
675  // Equation 11 of page 706 of FACTS paper
676  expterm = exp( -facts1.c2(atm1) * (facts1.Di(atm1) - facts1.c3(atm1)) );
677  tmp = facts1.c1(atm1)/(1.0 + expterm);
678 
679  facts1.sasa_[atm1] = facts1.c0(atm1) + tmp;
680 
681  // Save partial derivative for nonpolar term here
682  facts1.dSA_dDi_[atm1] = facts1.c2(atm1)*expterm*tmp/( 1.0 + expterm );
683 
684  //Ei is not being used actually; Gamma is used uniformly for alpha - the Atomic Solvation Parameter
685  /*facts1.Ei_[atm1] = facts1.Ai(atm1) + (facts1.native_f1(id1) * facts1.Bi(atm1)) +
686  (facts1.native_f2(id1) * facts1.Ai(atm1) * facts1.Bi(atm1) );
687  facts1.alpha_[atm1] = facts1.native_e0(id1) +
688  (facts1.native_e1(id1) / (1 + exp( -facts1.native_e2(id1)*(Ei - facts1.native_e3(id1)) ) ) ); */
689  }
690  }
691 }
692 
693 // Calculate polar interaction between rsd1 & rsd2 using Born Radius information
695  conformation::Residue const & rsd1,
696  conformation::Residue const & rsd2,
697  FACTSResidueInfo & facts1,
698  FACTSResidueInfo & facts2 ) const
699 {
700  bool const same_res = ( rsd1.seqpos() == rsd2.seqpos() );
701  Real cut_off_square = GBpair_cut_ * GBpair_cut_;
702  Real GBpair = 0.0;
703 
704  for ( Size atm1 = 1; atm1 <= rsd1.natoms(); ++atm1 ) {
705  Vector const &xyz1 = rsd1.xyz(atm1);
706  Real const &q1 = facts1.q(atm1);
707 
708  if( facts1.not_using(atm1) || std::fabs( q1 ) < 1.0e-6 ) continue;
709 
710  Real dE_dBR = 0.0;
711 
712  for ( Size atm2 = 1; atm2 <= rsd2.natoms(); ++atm2 ) {
713  Real const &q2 = facts2.q( atm2 );
714 
715  if( facts2.not_using(atm2) || std::fabs( q2 ) < 1.0e-6 ) continue;
716 
717  Vector const &xyz2 = rsd2.xyz( atm2 );
718  Real dis2 = xyz1.distance_squared( xyz2 );
719 
720  if ( dis2 >= cut_off_square ) continue;
721 
722  Real dis = std::sqrt(dis2);
723  Vector dxyz = xyz1 - xyz2;
724 
725  Real const &BRi = facts1.BR(atm1);
726  Real const &BRj = facts2.BR(atm2);
727 
728  Real BRij = BRi*BRj;
729  Real tmp1 = dis2/Kappa();
730  Real tmp2 = exp(-tmp1/BRij);
731  Real tmp3 = sqrt(dis2 + BRij*tmp2);
732 
733  // To avoid dividing by zero
734  if (tmp3 == 0) continue;
735 
736  Real fpair = MultiplicitiveFactor()*Tau()*(q1*q2/tmp3);
737 
738  // Shift function (required for truncation at cut_off)
739  Real sf1 = 1.0 - dis2/cut_off_square;
740  Real sf2 = sf1*sf1;
741 
742  // Derivative stuffs
743  Real g1 = 0.5*fpair/(tmp3*tmp3);
744  Real g2 = 2.0 - 2.0*tmp2/Kappa();
745  Real dE_drij = g1*g2;
746  Real dsf2_drij = 4.0*sf1/cut_off_square;
747  Real dEsf_drij = dE_drij*sf2 + fpair*dsf2_drij;
748 
749  // Store here and reuse at res_pair scoring & derivative call
750  if ( same_res ){
751  GBpair -= 0.5*fpair*sf2;
752 
753  facts1.dE_drij2_[atm1] += dEsf_drij*dxyz;
754  facts1.dE_dBR_[atm1] -= 0.5*sf2*g1*tmp2*(BRj + tmp1/BRi);
755  facts2.dE_dBR_[atm2] -= 0.5*sf2*g1*tmp2*(BRi + tmp1/BRj);
756 
757  } else {
758  GBpair -= fpair*sf2;
759 
760  facts1.dE_drij2_[atm1] += dEsf_drij*dxyz;
761  facts2.dE_drij2_[atm2] -= dEsf_drij*dxyz;
762  facts1.dE_dBR_[atm1] -= sf2*g1*tmp2*(BRj + tmp1/BRi);
763  facts2.dE_dBR_[atm2] -= sf2*g1*tmp2*(BRi + tmp1/BRj);
764  }
765  }//atm2
766  }//atm1
767 
768  facts1.GBpair_[rsd2.seqpos()] = GBpair;
769 } //END FACTSPotential::calculate_GBpair
770 
771 // Calculate polar interaction between rsd1 & rsd2 using Born Radius information
772 // Note that this function is applied when rsd1=rsd2; use exact instead to reduce error
774  conformation::Residue const & rsd1,
775  conformation::Residue const & rsd2,
776  FACTSResidueInfo & facts1,
777  FACTSResidueInfo & facts2 ) const
778 {
779  Real cut_off_square = GBpair_cut_ * GBpair_cut_;
780  Real GBpair = 0.0;
781  Real Kappa_sqrt = sqrt(Kappa());
782  Real a12 = 0.865924478668;
783  Real b12 = 0.4399086973;
784 
785  for ( Size atm1 = 1; atm1 <= rsd1.natoms(); ++atm1 ) {
786  Vector const &xyz1 = rsd1.xyz(atm1);
787  Real const &q1 = facts1.q(atm1);
788 
789  if( facts1.not_using(atm1) || std::fabs( q1 ) < 1.0e-6 ) continue;
790  Real dE_dBR = 0.0;
791 
792  for ( Size atm2 = 1; atm2 <= rsd2.natoms(); ++atm2 ) {
793  Real const &q2 = facts2.q( atm2 );
794 
795  if( facts2.not_using(atm2) || std::fabs( q2 ) < 1.0e-6 ) continue;
796 
797  Vector const &xyz2 = rsd2.xyz( atm2 );
798  Real dis2 = xyz1.distance_squared( xyz2 );
799 
800  if ( dis2 >= cut_off_square ) continue;
801 
802  Real const &BRi = facts1.BR(atm1);
803  Real const &BRj = facts2.BR(atm2);
804 
805  Real BRij = BRi*BRj;
806  Real m = sqrt(BRi*BRj);
807  Real dis = std::sqrt(dis2);
808  Vector dxyz = xyz1 - xyz2;
809 
810  Real fpair_exact = -MultiplicitiveFactor()*Tau()*q1*q2/
811  sqrt(dis2+BRij*exp(-dis2/(Kappa()*BRij)))*(1.0-dis2/cut_off_square)*(1.0-dis2/cut_off_square);
812 
813  if ( dis < m ){ // Inside approximator
814  Real arg = 1.0/((a12+b12)*m);
815  Real sfm = (1.0 - BRij/cut_off_square);
816  Real fm = arg*sfm*sfm;
817  Real gm = -arg*(sfm*sfm*a12*arg + sfm*4.0*m/cut_off_square);
818 
819  Real c = (gm - 2.0*fm/m + 2.0/BRij)/BRij;
820  Real d = (-gm + 3.0*fm/m - 3.0/BRij)/m;
821 
822  Real fpair = -MultiplicitiveFactor()*Tau()*q1*q2*(c*dis2*dis + d*dis2 + 1.0/m);
823  Real gpair = -MultiplicitiveFactor()*Tau()*q1*q2*(c*dis + d);
824 
825  // Store here and reuse at res_pair scoring & derivative call
826  GBpair += fpair;
827  facts1.dE_drij2_[atm1] += gpair*dxyz;
828  facts2.dE_drij2_[atm2] -= gpair*dxyz;
829 
830  // Forget about dE_dBR for now... too messy
831  //facts1.dE_dBR_[atm1] += ;
832  //facts2.dE_dBR_[atm2] += ;
833 
834  } else { // Outside approximater
835  Real sf1 = 1.0 - dis2/cut_off_square;
836  Real dsf2_drij = 4.0*sf1/cut_off_square;
837  Real farg = a12*dis + b12*m;
838  Real fpair = -MultiplicitiveFactor()*Tau()*(q1*q2/farg);
839  Real farg2 = fpair*sf1*sf1/farg;
840 
841  // Shift function (required for truncation at cut_off)
842  Real dEsf_drij = -farg2/dis - fpair*dsf2_drij;
843 
844  // Store here and reuse at res_pair scoring & derivative call
845  GBpair += fpair*sf1*sf1;
846 
847  facts1.dE_drij2_[atm1] += dEsf_drij*dxyz;
848  facts2.dE_drij2_[atm2] -= dEsf_drij*dxyz;
849  facts1.dE_dBR_[atm1] += 0.5*farg2*b12*BRj / m;
850  facts2.dE_dBR_[atm2] += 0.5*farg2*b12*BRi / m;
851 
852  }
853  }//atm2
854 
855  }//atm1
856 
857  facts1.GBpair_[rsd2.seqpos()] = GBpair;
858 } //END FACTSPotential::calculate_GBpair
859 
860 // Calculate derivatives for both polar & nonpolar interactions
861 // "res_res_burial, get_self_terms, calculate_GBpair" should precede this function,
862 // otherwise derivative will be inconsistent to current structure
864 {
865  FACTSPoseInfoOP facts_info;
866  Vector virtualcrd;
867  Vector cross_v;
868 
869  //timeval t1, t2;
870  //gettimeofday(&t1, NULL );
871 
872  if ( pose.data().has( core::pose::datacache::CacheableDataType::FACTS_POSE_INFO ) ) {
873  facts_info = static_cast< FACTSPoseInfo* >
874  ( pose.data().get_ptr( core::pose::datacache::CacheableDataType::FACTS_POSE_INFO )() );
875  } else {
876  facts_info = new FACTSPoseInfo();
877  }
878 
879  for ( Size res1 = 1; res1 <= facts_info->size(); ++res1){
880  FACTSResidueInfo & facts1( facts_info->residue_info( res1 ) );
881 
882  for ( Size atm1 = 1; atm1 <= facts1.natoms(); ++atm1){
883  Vector const &crd1 = pose.residue(res1).xyz(atm1);
884 
885  // Warning: Below should be problematic for SASA... must be checked
886  if ( (fabs(facts1.esolvE(atm1)) <= 1e-6) || (facts1.not_using(atm1)) ) continue;
887 
888  // 1. Derivative for distance dependent term
889  facts1.polarF2d_[atm1] += facts1.dE_drij2_[atm1];
890 
891  // 2. Derivative for Born Radius & SASA dependent term
892  Real dB_dBdnmtr = -facts1.Bi(atm1)/facts1.dnmtr(atm1);
893  Real dB_dBnmtr = 1.0/(facts1.nmtr(atm1).norm() * facts1.dnmtr(atm1));
894  Real dBR_dG = facts1.BR(atm1)/facts1.esolvE(atm1);
895 
896  Real CutOff_sqr = facts1.COradius(atm1)*facts1.COradius(atm1);
897 
898  SelfNeighInfo const &neigh = facts1.selfneigh(atm1);
899  Size const &n_neigh = neigh.nneigh;
900 
901  // Self-Neighbor needs to be defined (this is defined at res_res_burial, prior to this function call)
902  for (Size i_j = 1; i_j <= n_neigh; ++i_j){
903  Size const &res2 = neigh.resID[i_j];
904  Size const &atm2 = neigh.atmID[i_j];
905 
906  Vector const &crd2 = pose.residue(res2).xyz(atm2);
907 
908  FACTSResidueInfo & facts2( facts_info->residue_info( res2 ) );
909 
910  Vector const dxyz( crd1 - crd2 );
911  Real const dis2 ( dxyz.length_squared() );
912  Real const dis ( std::sqrt(dis2) );
913  Real const i_dis2 ( 1.0/dis2 );
914 
915  Real theta_sqrt = 1.0 - (dis2 / CutOff_sqr);
916  Real dtheta_tmp1 = facts2.volume(atm2) * theta_sqrt*theta_sqrt;
917  Real dtheta_tmp2 = 4.0*facts2.volume(atm2) *theta_sqrt/CutOff_sqr;
918  Real tmp1 = dtheta_tmp1*i_dis2; // = theta*Vj*xij/r ;
919  Real tmp2 = (tmp1 + dtheta_tmp2)/dis;
920 
921  // Derivative for Ai
922  Real dAi_drij = -dtheta_tmp2;
923 
924  // Derivative for Bi
925  Real arg12 = -2.0*dtheta_tmp1*i_dis2 - dtheta_tmp2;
926  Vector argv1 = i_dis2*arg12*dxyz;
927  Real dBn_drij = argv1[0]*facts1.nmtr(atm1)[0] + argv1[1]*facts1.nmtr(atm1)[1] + argv1[2]*facts1.nmtr(atm1)[2];
928  Vector dBn_drij2 = facts1.nmtr(atm1)*dtheta_tmp1*i_dis2;
929  Vector dBi_drij = (dB_dBnmtr*dBn_drij - dB_dBdnmtr*tmp2)*dxyz + dB_dBnmtr*dBn_drij2;
930 
931  // 2-1. Derivatives for Polar Interaction
932  Vector dCi_drij_for_F2 = dAi_drij*dxyz + facts1.b1(atm1)*dBi_drij +
933  facts1.b2(atm1)*(facts1.Ai(atm1)*dBi_drij + facts1.Bi(atm1)*dAi_drij*dxyz);
934 
935  Vector dE_drij_for_F2 = facts1.dE_dBR(atm1)*dBR_dG*facts1.dG_dCi(atm1)*dCi_drij_for_F2;
936 
937  facts1.polarF2BR_[atm1] += dE_drij_for_F2;
938  facts2.polarF2BR_[atm2] -= dE_drij_for_F2;
939 
940  // 2-2. Derivatives for NonPolar Interaction
941  Vector dDi_drij_for_F2 = dAi_drij*dxyz + facts1.d1(atm1)*dBi_drij +
942  facts1.d2(atm1)*(facts1.Ai(atm1)*dBi_drij + facts1.Bi(atm1)*dAi_drij*dxyz);
943 
944  Vector dSA_drij_for_F2 = facts1.alpha(atm1)*facts1.dSA_dDi(atm1)*dDi_drij_for_F2;
945 
946  facts1.nonpolarF2_[atm1] += dSA_drij_for_F2;
947  facts2.nonpolarF2_[atm2] -= dSA_drij_for_F2;
948  }
949  }
950  }
951 
952  pose.data().set( core::pose::datacache::CacheableDataType::FACTS_POSE_INFO, facts_info );
953  PROF_STOP( basic::FACTS_GET_ALL_BORN_RADII );
954 
955  //gettimeofday(&t2, NULL );
956  //Real elapsedTime = (t2.tv_sec - t1.tv_sec) * 1000.0;
957  //elapsedTime += (t2.tv_usec - t1.tv_usec) / 1000.0;
958  //cout << "Setup for derivative 1/2: " << elapsedTime << " ms." << endl;
959 
960 }
961 
962 // Called at scoring step - for polar energy
963 // Just reuse scores calculated at setup_for_scoring
965  FACTSResidueInfo const & facts1,
966  Residue const & rsd2
967  ) const {
968 
969  return facts1.GBpair( rsd2.seqpos() );
970 }
971 
972 // Called at scoring step - for nonpolar energy
973 // Just reuse scores calculated at setup_for_scoring
975  FACTSResidueInfo const & facts1,
976  Residue const & rsd2
977  ) const {
978  Real E_SA = 0.0;
979  if ( rsd1.seqpos() == rsd2.seqpos() ){
980  for ( Size atm1 = 1; atm1 <= rsd1.natoms(); ++ atm1 ){
981  E_SA += facts1.alpha(atm1)*facts1.sasa(atm1);
982  }
983  }
984  return E_SA;
985 }
986 
987 // Given rotamer pair, calculate BR & SA change induced by each other
988 // This is not being used currently
990  Residue const & rsd1_ref,
991  Residue const & rsd1,
992  FACTSResidueInfo const & facts1,
993  Residue const & rsd2_ref,
994  Residue const & rsd2,
995  FACTSResidueInfo const & facts2,
996  utility::vector1< Real > & dBRi1,
997  utility::vector1< Real > & dBRi2,
998  utility::vector1< Real > & dSAi1,
1000  ) const {
1001 
1002  bool const same_res = ( rsd1.seqpos() == rsd2.seqpos() );
1003  Real fct = 1.0;
1004  if ( same_res ) {
1005  fct = 0.5;
1006  }
1007 
1008  Real theta_sqrt, thetaij, thetaij_ref;
1009 
1010  utility::vector1< Real > Ai1 = facts1.Ai();
1011  utility::vector1< Vector > nmtr1 = facts1.nmtr();
1012  utility::vector1< Real > dnmtr1 = facts1.dnmtr();
1013  utility::vector1< Real > Ai2 = facts2.Ai();
1014  utility::vector1< Vector > nmtr2 = facts2.nmtr();
1015  utility::vector1< Real > dnmtr2 = facts2.dnmtr();
1016 
1017  for ( Size atm1 = 1; atm1 <= rsd1.natoms(); ++atm1 ) {
1018  Vector xyz1 = rsd1.xyz(atm1);
1019  Real CutOff_sqr1 = facts1.COradius(atm1)*facts1.COradius(atm1);
1020 
1021  for ( Size atm2 = 1; atm2 <= rsd2.natoms(); ++atm2 ) {
1022  if ( same_res && atm1 == atm2 ) continue;
1023 
1024  Real CutOff_sqr2 = facts2.COradius(atm2)*facts2.COradius(atm2);
1025  Vector xyz2 = rsd2.xyz( atm2 );
1026  Vector dxyz = xyz1 - xyz2;
1027 
1028  Real dis2 = dxyz[0]*dxyz[0] + dxyz[1]*dxyz[1] + dxyz[2]*dxyz[2];
1029  Real dis = sqrt(dis2);
1030 
1031  // rotamer1
1032  Vector dxyz_ref1 = xyz1 - rsd2_ref.xyz(atm2);
1033  Real dis2_ref1 = dxyz_ref1[0]*dxyz_ref1[0] + dxyz_ref1[1]*dxyz_ref1[1]
1034  + dxyz_ref1[2]*dxyz_ref1[2];
1035 
1036  if ( abs(facts1.esolvE(atm1)) > 1e-6 && abs(dis2 - dis2_ref1) > 1e-3
1037  && ( dis2 < CutOff_sqr1 || dis2_ref1 < CutOff_sqr1 )) {
1038  Real dis_ref = sqrt(dis2_ref1);
1039 
1040  if ( dis2 < CutOff_sqr1 ){
1041  theta_sqrt = 1.0 - (dis2 / CutOff_sqr1);
1042  thetaij = theta_sqrt*theta_sqrt;
1043  } else {
1044  thetaij = 0.0;
1045  }
1046 
1047  if ( dis2_ref1 < CutOff_sqr1 ){
1048  theta_sqrt = 1.0 - (dis2_ref1 / CutOff_sqr1);
1049  thetaij_ref = theta_sqrt*theta_sqrt;
1050  } else {
1051  thetaij_ref = 0.0;
1052  }
1053 
1054  Ai1[atm1] += fct*facts2.volume(atm2)*(thetaij - thetaij_ref);
1055 
1056  nmtr1[atm1] += fct*facts2.volume(atm2)*(thetaij*dxyz/dis2
1057  - thetaij_ref*dxyz_ref1/dis2_ref1);
1058  dnmtr1[atm1] += fct*facts2.volume(atm2)*(thetaij/dis - thetaij_ref/dis_ref);
1059 
1060  }
1061 
1062  // rotamer2
1063  Vector dxyz_ref2 = xyz2 - rsd1_ref.xyz(atm1);
1064  Real dis2_ref2 = dxyz_ref2[0]*dxyz_ref2[0] + dxyz_ref2[1]*dxyz_ref2[1]
1065  + dxyz_ref2[2]*dxyz_ref2[2];
1066 
1067  if ( abs(facts2.esolvE(atm2)) > 1e-6 && abs(dis2_ref2 - dis2) > 1e-3
1068  && (dis2 < CutOff_sqr2 || dis2_ref2 < CutOff_sqr2) ) {
1069  Real dis_ref = sqrt(dis2_ref2);
1070 
1071  if ( dis2 < CutOff_sqr2 ){
1072  theta_sqrt = 1.0 - (dis2 / CutOff_sqr2);
1073  thetaij = theta_sqrt*theta_sqrt;
1074  } else {
1075  thetaij = 0.0;
1076  }
1077 
1078  if ( dis2_ref2 < CutOff_sqr2 ){
1079  theta_sqrt = 1.0 - (dis2_ref2 / CutOff_sqr2);
1080  thetaij_ref = theta_sqrt*theta_sqrt;
1081  } else {
1082  thetaij_ref = 0.0;
1083  }
1084 
1085  Ai2[atm2] += fct*facts1.volume(atm1)*(thetaij - thetaij_ref);
1086  nmtr2[atm2] += fct*facts1.volume(atm1)*(thetaij*(-dxyz)/dis2
1087  - thetaij_ref*dxyz_ref2/dis2_ref2);
1088  dnmtr2[atm2] += fct*facts1.volume(atm1)*(thetaij/dis - thetaij_ref/dis_ref);
1089  }
1090 
1091  }
1092  }
1093 
1094  // Re-evalute Ci and Di
1095  for ( Size atm1 = 1; atm1 <= rsd1.natoms(); ++atm1 ) {
1096  Real const &Ai = Ai1[atm1];
1097  Real const &Bi = nmtr1[atm1].norm()/dnmtr1[atm1];
1098 
1099  if ( abs(facts1.esolvE(atm1)) > 1e-6 ){
1100  Real Ci = Ai + facts1.b1(atm1)*Bi + facts1.b2(atm1)*Ai*Bi;
1101  Real Gi = facts1.a0(atm1) + facts1.a1(atm1)/
1102  (1.0 + exp( -facts1.a2(atm1) * (Ci - facts1.a3(atm1)) ) );
1103  dBRi1[atm1] = -0.5*Tau()*MultiplicitiveFactor()/Gi;
1104  }
1105  Real dDi = Ai + facts1.d1(atm1)*Bi + facts1.d2(atm1)*Ai*Bi - facts1.Di(atm1);
1106  dSAi1[atm1] = facts1.alpha(atm1)*facts1.dSA_dDi(atm1)*dDi;
1107 
1108  }
1109 
1110  for ( Size atm2 = 1; atm2 <= rsd2.natoms(); ++atm2 ) {
1111  Real const &Ai = Ai2[atm2];
1112  Real const &Bi = nmtr2[atm2].norm()/dnmtr2[atm2];
1113 
1114  if ( abs(facts2.esolvE(atm2)) > 1e-6 ){
1115  Real Ci = Ai + facts2.b1(atm2)*Bi + facts2.b2(atm2)*Ai*Bi;
1116  Real Gi = facts2.a0(atm2) + facts2.a1(atm2)/
1117  (1.0 + exp( -facts2.a2(atm2) * (Ci - facts2.a3(atm2)) ) );
1118  dBRi2[atm2] = -0.5*Tau()*MultiplicitiveFactor()/Gi;
1119  }
1120 
1121  Real dDi = Ai + facts2.d1(atm2)*Bi + facts2.d2(atm2)*Ai*Bi - facts2.Di(atm2);
1122  dSAi2[atm2] = facts2.alpha(atm2)*facts2.dSA_dDi(atm2)*dDi;
1123 
1124  }
1125 }
1126 
1127 // Given precalculated born radius, called at packing - for polar energy
1129  FACTSResidueInfo const & facts1,
1130  Residue const & rsd2,
1131  FACTSResidueInfo const & facts2,
1132  utility::vector1< Real > const & dBRi1,
1133  utility::vector1< Real > const & dBRi2,
1134  bool do_correction
1135  ) const {
1136 
1137  Real score = 0.0;
1138  Real cut_off_square = GBpair_cut_ * GBpair_cut_;
1139  bool const same_res = ( rsd1.seqpos() == rsd2.seqpos() );
1140  Real BRi, BRj;
1141 
1142  for ( Size atm1 = 1; atm1 <= rsd1.natoms(); ++atm1 ) {
1143  Vector xyz1 = rsd1.xyz(atm1);
1144  Real q1 = facts1.q(atm1);
1145 
1146  if( facts1.not_using(atm1) || std::fabs( q1 ) < 1.0e-6 ) continue;
1147 
1148  for ( Size atm2 = 1; atm2 <= rsd2.natoms(); ++atm2 ) {
1149  Real q2 = facts2.q( atm2 );
1150 
1151  if( facts2.not_using(atm2) || std::fabs( q2 ) < 1.0e-6 ) continue;
1152 
1153  Vector xyz2 = rsd2.xyz( atm2 );
1154  Real dis2 = xyz1.distance_squared( xyz2 );
1155 
1156  if ( dis2 >= cut_off_square ) continue;
1157 
1158  Real dis = std::sqrt(dis2);
1159 
1160  if (do_correction){
1161  BRi = dBRi1[atm1];
1162  BRj = dBRi2[atm2];
1163  } else {
1164  BRi = facts1.BR(atm1);
1165  BRj = facts2.BR(atm2);
1166  }
1167 
1168  Real BRij = BRi*BRj;
1169 
1170  Real tmp1 = dis2/Kappa();
1171  Real tmp2 = exp(-tmp1/BRij);
1172  Real tmp3 = sqrt(dis2 + BRij*tmp2);
1173 
1174  Real fpair = MultiplicitiveFactor()*Tau()*(q1*q2/tmp3);
1175 
1176  // Shift function (required for truncation at cut_off)
1177  Real sf1 = 1.0 - dis2/cut_off_square;
1178  Real sf2 = sf1*sf1;
1179 
1180  if ( same_res ){
1181  score -= 0.5*sf2*fpair;
1182  } else {
1183  score -= sf2*fpair;
1184  }
1185  }
1186  }
1187  return score;
1188 }
1189 
1191  id::AtomID const & id,
1192  Real const weight,
1193  pose::Pose const & pose,
1194  kinematics::DomainMap const & domain_map,
1195  bool const exclude_DNA_DNA,
1196  Vector & F1,
1197  Vector & F2
1198  ) const
1199 {
1200  FACTSPoseInfo const & facts_info( static_cast< FACTSPoseInfo const & >
1201  ( pose.data().get( core::pose::datacache::CacheableDataType::FACTS_POSE_INFO )));
1202  Size const atm1( id.atomno() );
1203  Size const res1( id.rsd() );
1204 
1205  // Pose stuff - this is not supported currently
1206  //int const i_map( domain_map( res2 ) );
1207  //bool const i_fixed( i_map != 0 );
1208 
1209  FACTSResidueInfo const & facts1( facts_info.residue_info( res1 ) );
1210 
1211  Vector tmpv = weight * (facts1.polarF2d(atm1) + facts1.polarF2BR(atm1));
1212  F2 += tmpv;
1213 
1214  Vector const &crd1 = pose.residue(res1).xyz(atm1);
1215  Vector virtualcrd = -tmpv + crd1;
1216  F1 += crd1.cross( virtualcrd );
1217 }
1218 
1219 // Called during minimization; Just call derivatives calculated at setup_for_derivative
1221  id::AtomID const & id,
1222  Real const weight,
1223  pose::Pose const & pose,
1224  kinematics::DomainMap const & domain_map,
1225  bool const exclude_DNA_DNA,
1226  Vector & F1,
1227  Vector & F2
1228  ) const
1229 {
1230  FACTSPoseInfo const & facts_info( static_cast< FACTSPoseInfo const & >
1231  ( pose.data().get( core::pose::datacache::CacheableDataType::FACTS_POSE_INFO )));
1232  Size const atm1( id.atomno() );
1233  Size const res1( id.rsd() );
1234 
1235  // Pose stuff - this is not supported currently
1236  //int const i_map( domain_map( res2 ) );
1237  //bool const i_fixed( i_map != 0 );
1238 
1239  FACTSResidueInfo const & facts1( facts_info.residue_info( res1 ) );
1240 
1241  Vector tmpv = weight * facts1.nonpolarF2(atm1);
1242  F2 += tmpv;
1243 
1244  Vector const &crd1 = pose.residue(res1).xyz(atm1);
1245  Vector virtualcrd = -tmpv + crd1;
1246  F1 += crd1.cross( virtualcrd );
1247 }
1248 
1249 /// Note: when called at the beginning of rotamer_trials, task.being_packed(i) will be false for all i
1250 /// this ensures that we use all the information we have to compute the current set of radii
1252  pose::Pose & pose,
1253  utility::vector1< bool > const & repacking_residues ) const
1254 {
1255  PROF_START( basic::FACTS_SETUP_FOR_PACKING );
1256 
1257  FACTSPoseInfoOP facts_info;
1258 
1259  //if ( pose.data().has( core::pose::datacache::CacheableDataType::FACTS_POSE_INFO ) ) {
1260  // facts_info = static_cast< FACTSPoseInfo* >
1261  // ( pose.data().get_ptr( core::pose::datacache::CacheableDataType::FACTS_POSE_INFO )() );
1262  //} else {
1263  //}
1264 
1265  //if ( !pose.data().has( core::pose::datacache::CacheableDataType::FACTS_POSE_INFO ) ) {
1266 
1267  //}
1268  //facts_info = static_cast< FACTSPoseInfo* >
1269  // ( pose.data().get_ptr( core::pose::datacache::CacheableDataType::FACTS_POSE_INFO )() );
1270 
1271  facts_info = new FACTSPoseInfo();
1272 
1273  setup_for_scoring( pose );
1274  setup_for_derivatives( pose );
1275 
1276  facts_info = static_cast< FACTSPoseInfo* >
1277  ( pose.data().get_ptr( core::pose::datacache::CacheableDataType::FACTS_POSE_INFO )() );
1278 
1279  /// store info about which positions are moving
1280  facts_info->set_repack_list( repacking_residues );
1281 
1282  build_placeholders( pose, *facts_info );
1283 
1284  get_template_born_radii( pose, *facts_info );
1285 
1286  pose.data().set( core::pose::datacache::CacheableDataType::FACTS_POSE_INFO, facts_info );
1287  PROF_STOP( basic::FACTS_SETUP_FOR_PACKING );
1288 }
1289 
1291  Size const nres( pose.total_residue() );
1292  assert( facts_info.size() == nres );
1293 
1294  for ( Size i=1; i<= nres; ++i ) {
1295  if ( facts_info.being_packed( i ) ) continue;
1296 
1297  Residue const & rsd1( pose.residue( i ) );
1298  FACTSResidueInfo & facts1( facts_info.residue_info( i ) );
1299  assert( rsd1.natoms()<1 || std::fabs(facts1.Ai(1)) < 1e-3 );
1300 
1301  for ( Size j=1; j<= nres; ++j ) {
1302  // we are not using placeholder in FACTS - this can be changed if we want to do "Design"
1303  //if ( facts_info.being_packed(j) ) {
1304  // res_res_burial( rsd1, facts1, facts_info.placeholder_residue(j), facts_info.placeholder_info(j) );
1305  //} else {
1306  res_res_burial( rsd1, facts1, pose.residue(j), facts_info.residue_info(j) );
1307  //}
1308  }
1309  get_self_terms( facts1 );
1310  }
1311 }
1312 
1313 /// called eg after a rotamer substitution is accepted during rotamer trials
1315 {
1316  FACTSPoseInfo & facts_info( static_cast< FACTSPoseInfo & >
1317  ( pose.data().get( core::pose::datacache::CacheableDataType::FACTS_POSE_INFO ) ) );
1318  FACTSResidueInfo & facts( facts_info.residue_info( seqpos ) );
1319 
1320  Residue const & rsd( pose.residue( seqpos ) );
1321  facts.initialize( rsd );
1322 
1323  get_single_rotamer_born_radii( rsd, pose, facts_info, facts );
1324 }
1325 
1327 
1328  FACTSPoseInfo const & facts_info_pose( static_cast< FACTSPoseInfo const & >
1329  (pose.data().get( core::pose::datacache::CacheableDataType::FACTS_POSE_INFO )));
1330 
1331  // this will get cached in the rotamer set
1332  // this call should initialize the residue_info objects with the appropriate Residue info
1333  FACTSRotamerSetInfoOP facts_info_rotamers( new FACTSRotamerSetInfo( rotamer_set ) );
1334 
1335  for ( Size n=1; n<= rotamer_set.num_rotamers(); ++n ) {
1336  get_single_rotamer_born_radii( *rotamer_set.rotamer(n),
1337  pose, facts_info_pose,
1338  facts_info_rotamers->residue_info( n ) );
1339  }
1340 
1341  rotamer_set.data().set( core::conformation::RotamerSetCacheableDataType::FACTS_ROTAMER_SET_INFO, facts_info_rotamers );
1342 }
1343 
1345  pose::Pose const & pose,
1346  FACTSPoseInfo const & facts_info,
1347  FACTSResidueInfo & facts1) const
1348 {
1349  Size natoms1, natoms2;
1350 
1351  assert( rsd1.natoms()<1 || std::fabs(facts1.Ai(1)) < 1e-3 );
1352  for (Size res2=1; res2<= pose.total_residue(); ++res2 ) {
1353  // we are not using placeholder in FACTS - this can be changed if we want to do "Design"
1354  //if ( facts_info.being_packed( res2 ) ) {
1355  // res_res_burial( rsd1, facts1, facts_info.placeholder_residue( res2 ), facts_info.placeholder_info( res2));
1356 
1357  //} else {
1358  res_res_burial( rsd1, facts1, pose.residue( res2 ), facts_info.residue_info( res2 ) );
1359  //}
1360 
1361  get_self_terms( facts1 );
1362 
1363  }//end for loop 1
1364 }
1365 
1367  Residue const & rsd,
1368  FACTSResidueInfo const & facts_info
1369  ) const
1370 {
1371  Real score_correction = 0.0;
1372 
1373  for( Size iatm = 1; iatm <= rsd.natoms(); ++iatm ){
1374  Vector const &dxyz = rsd.xyz(iatm) - ref_rsd.xyz(iatm);
1375  Vector const &drv = facts_info.polarF2BR(iatm); //+ facts_info.polarF2d(iatm);
1376 
1377  Real dabs = dxyz[0]*dxyz[0] + dxyz[1]*dxyz[1] + dxyz[2]*dxyz[2];
1378 
1379  if( dabs > 1.0e-3 && dabs < 0.25 ){
1380  score_correction += drv[0]*dxyz[0] + drv[1]*dxyz[1] + drv[2]*dxyz[2];
1381  }
1382  }
1383  return score_correction;
1384 }
1385 
1386 } // namespace scoring
1387 } // namespace core