IMP logo
IMP Reference Guide  2.20.0
The Integrative Modeling Platform
SitesPairScore.h
Go to the documentation of this file.
1 /**
2  * \file SitesPairScore.h
3  * \brief A Score on the distance between a pair of particles.
4  *
5  * Copyright 2007-2022 IMP Inventors. All rights reserved.
6  */
7 
8 // TODO: verify if energy units are kcal/mol or KT
9 
10 #ifndef IMPNPCTRANSPORT_SITES_PAIR_SCORE_H
11 #define IMPNPCTRANSPORT_SITES_PAIR_SCORE_H
12 
13 #include "npctransport_config.h"
16 #include "internal/RigidBodyInfo.h"
17 #include "internal/sites.h"
18 #include <IMP/PairScore.h>
19 #include <IMP/UnaryFunction.h>
20 #include <IMP/Pointer.h>
21 #include <IMP/core/XYZR.h>
22 #include <IMP/core/Typed.h>
25 #include <IMP/generic.h>
28 #include <IMP/set_map_macros.h>
30 #include <IMP/atom/estimates.h>
31 #include <boost/unordered_set.hpp>
32 
33 #include <boost/array.hpp>
34 
35 IMPNPCTRANSPORT_BEGIN_NAMESPACE
36 
37 
38 /** \brief Apply a function to the distance between two particles with
39  a set of specific binding sites
40 
41  The sites are expressed in the local reference frame of
42  the two rigid bodies. Care must be taken to pass the bodies
43  in the appropriate order. See construction documentation for more details.
44 */
45 class IMPNPCTRANSPORTEXPORT SitesPairScore
47 {
48  private:
50 
51 
52  /************************* class variables ****************/
53  bool is_orientational_score_; // if true, use orientation-dependent score
56  sites0_, sites1_;
57 
58 
59  //! Maximal square of distance between particles with interacting sites
60  //! based on the interaction range and list of sites
61  double ubound_distance2_;
62 
63  // //! Cache:
64  // typedef IMP_KERNEL_LARGE_UNORDERED_MAP<ParticleIndex,internal::RigidBodyInfo>
65  // t_particles_rb_cache;
66  // mutable t_particles_rb_cache particles_rb_cache_;
67  // mutable bool is_cache_active_;
68  // mutable unsigned int cur_cache_id_; // to keep track of caching rounds
69 
70  public:
71 
72  /**
73  For positive sigmas, this is an orientation dependent score between two
74  spherical particles that
75  contain a fixed set of interaction sites, sites0 and sites1 (for
76  first and second particle, resp.).
77 
78  The interaction is composed of a non-specific interaction term
79  between the bead spheres, and the sum of interactions between
80  specific interactions sites of each bead.
81 
82  If \sigma{0} and \sigma{1} are positive, the attractive force
83  between pairs of sites at an optimal orientation (sites facing
84  each other) depends on their distance x. The attraction force
85  magnitude is k*x when x<=0.5*range and k*(range-x) when x is
86  between 0.5*range and range. When site0 is rotated by \sigma <
87  \sigma{0}, this force decays further by a factor
88  (cos{\sigma}-cos{\sigma}0)/(1.0-cos{\sigma0}). The force decays
89  similarly when site1 is rotated by \sigma < \sigma{1}. The
90  maximal potential energy difference due to such pair of
91  interacting sites is:
92  max\DELTA{U}_{site_site} = 0.25 * k * range^2 [kcal/mol]
93 
94  If sigma0_deg or sigma1_deg are non-positive, the attractive
95  force between pairs of sites within the attraction range is a
96  constant k, and the maximal interaction energy is instead:
97  max\DELTA{U}_{site-site} = k * range [kCal/mol]
98 
99  In addition to site-site interaction, there is a constant
100  attractive force k_nonspec_attraction between the sphere surfaces
101  up to a range range_nonspec_attraction, with maximal energy
102  contribution:
103  max\DELTA{U}_{non-specific} = 0.5 * k_nonspec_attraction * range_nonspec_attraction [kcal/mol]
104 
105  Note that for a specific pair of particles, each particle might have
106  a different reference frame (rigid body translation and rotation),
107  which is applied to the sites list upon score evaluation.
108 
109  @param range Maximal range of site specific attraction in any direction
110  of specific sites placed on particles
111  @param k Maximal site specific attraction coefficient (in
112  kcal/mol/A^2 when sigma0_deg and sigma1_deg are positive,
113  or kcal/mol/A otherwise, i.e., for orientation-independent interactions)
114  @param sigma0_deg, sigma1_deg Maximal rotational range of sites 0 and 1, respectively,
115  on the particle surface, specified in degrees. If either is 0,
116  the pair score between site centers is used with a constant k.
117  @param range_nonspec_attraction Range for non-specific attraction term
118  between particles that contain the sites
119  @param k_nonspec_attraction Non-specific attraction coefficient between particles
120  (constant force in kCal/mol/A within specified range)
121  @param k_nonspec_repulsion Repulsion coefficient between particles (constant force
122  applied when particle spheres overlap in kCal/mol/A)
123  @param sites0 List of sites on the first particle, in its local reference frame
124  @param sites1 List of sites on the second particle, in its local reference frame
125  */
126  SitesPairScore(double range, double k,
127  double sigma0_deg, double sigma1_deg,
128  double range_nonspec_attraction, double k_nonspec_attraction,
129  double k_nonspec_repulsion,
130  const algebra::Sphere3Ds &sites0,
131  const algebra::Sphere3Ds &sites1);
132 
133 
134  public:
135 
136  virtual double evaluate_indexes(
138  unsigned int lower_bound,
139  unsigned int upper_bound) const override final;
140 
141  //! evaluated indexes for the range from lower_bound to upper_bound
142  //! in p, if score>max then return max value of double
144  ( Model *m, const ParticleIndexPairs &p,
146  double max, unsigned int lower_bound,
147  unsigned int upper_bound) const override
148  {
149  // activate_cache();
150  double ret = 0.0;
151  for (unsigned int i = lower_bound; i < upper_bound; ++i) {
152  ret += evaluate_if_good_index(m, p[i], da, max - ret);
153  if (ret > max) return std::numeric_limits<double>::max();
154  }
155  // deactivate_cache();
156  return ret;
157  }
158 
159 
160  /** evaluate the score for the pair of model particle indexes in p,
161  updating score derivatives to da
162  */
163  virtual double evaluate_index(Model *m, const ParticleIndexPair &p,
164  DerivativeAccumulator *da) const override;
165 
166 #ifndef SWIG
167  /**
168  EvaluatE all site-site interactions
169  for evaluate_index() for the pair pip in model m. If da is not nullptr,
170  it accumulated appropriate derivatives. If contacts_accumulator is not null,
171  then the number of individual contacts and occupied sites is asscumulated there.
172 
173  @param sphere_table An array storing of sphere coordinates by particle index
174  @param quaternions_tables An array of quaternions by particle index
175  @param sphere_table An array storing of sphere coordinate derivatives by particle index
176  @param torque_tables An array of torques by particle index
177  @param pip the pair of particle indexes in m
178  @param da optional accumulator for force and torque derivatives
179  @param contacts_accumulator A pointer to a tuple of output values
180  [num-contacts, sites0-bound, sites1-bound, is_nonspec].
181  num-contacts is the total number of site-site contacts between pip.
182  sites0-bound and sites1-bound are vectors of contact counts
183  for each site of pip[0] and pip[1], resp, with one entry per site.
184  is_nonspec is true if the molecules have non-zero
185  nonspecific interactions Ignored if Null
186 
187  @return the site-site contributions for the score for the pair
188  pip in model m.
189  */
190  double
191  evaluate_site_contributions_with_internal_tables
192  (algebra::Sphere3D const* spheres_table,
193  double const**quaternions_tables,
194  algebra::Sphere3D *sphere_derivatives_table,
195  double **torques_tables,
196  const ParticleIndexPair &pip,
198  boost::tuple< unsigned int, std::vector<unsigned int>, std::vector<unsigned int>, bool >
199  (*contacts_accumulator) = nullptr
200  ) const;
201 
202  /**
203  EvaluatE all site-site interactions
204  for evaluate_index() for the pair pip in model m. If da is not nullptr,
205  it accumulated appropriate derivatives. If contacts_accumulator is not null,
206  then the number of individual contacts and occupied sites is asscumulated there.
207 
208  @param m the model
209  @param pip the pair of particle indexes in m
210  @param da optional accumulator for force and torque derivatives
211  @param contacts_accumulator A pointer to a tuple of output values
212  [num-contacts, sites0-bound, sites1-bound, is_nonspec].
213  num-contacts is the total number of site-site contacts between pip.
214  sites0-bound and sites1-bound are vectors of contact counts
215  for each site of pip[0] and pip[1], resp. is_nonspec is true if the
216  spheres have non-zero non-specific interactions
217  Ignored if Null
218 
219  @return the site-site contributions for the score for the pair
220  pip in model m.
221  */
222  double
223  evaluate_site_contributions
224  (Model* m,
225  const ParticleIndexPair &pip,
227  boost::tuple< unsigned int, std::vector<unsigned int>, std::vector<unsigned int>, bool >
228  (*contacts_accumulator)
229  ) const;
230 
231 #endif
232 
234  const ParticleIndexes &pis) const override;
235 
236  // Restraints do_create_current_decomposition(Model *m,
237  // const ParticleIndexPair &vt)
238  // const override;
239 
240  //! return the range for site-site attraction
241  double get_sites_range() const { return params_.r; }
242 
243  //! return the k for site-site attraction
244  double get_sites_k() const { return params_.k; }
245 
246  SitesPairScoreParameters get_parameters() const {return params_;}
247 
248  public:
250 
251  private:
252 
253  /** evaluate the score for the pair of model particle indexes in p,
254  updating score derivatives to da, and using internal attribute
255  tables in Model
256  */
257  inline double evaluate_index_with_internal_tables
258  ( Model* m,
259  algebra::Sphere3D const* spheres_table,
260  double const **quaternions_tables,
261  algebra::Sphere3D *sphere_derivatives_table,
262  double **torques_tables,
263  const ParticleIndexPair &p,
264  DerivativeAccumulator *da) const;
265 
266  // gets the rigid body information (e.g., translation, inverse rotation)
267  // associated with particle m.pi, possibly from cache (depending on internal
268  // cache definitions)
269  inline internal::RigidBodyInfo
270  get_rigid_body_info
271  (algebra::Sphere3D const* spheres_table,
272  double const** quaternions_tables,
273  ParticleIndex pi) const;
274 
275  public:
276  // sets the sites associated with each partner to sites0
277  // and sites1, respectively (in local reference frame)
278  void set_sites(const algebra::Sphere3Ds &sites0,
279  const algebra::Sphere3Ds &sites1){
280  sites0_= sites0;
281  sites1_= sites1;
282  }
283 
284  // sets the sites associated with the first partner
285  // (in local reference frame)
286  void set_sites0(const algebra::Sphere3Ds &sites0){
287  sites0_= sites0;
288  }
289 
290  // sets the sites associated with the first partner
291  // (in local reference frame)
292  void set_sites1(const algebra::Sphere3Ds &sites1){
293  sites1_= sites1;
294  }
295 
296  private:
297  /* // maintain a cache for evaluate_index() till call to deactivate_cache() */
298  /* inline void activate_cache() const */
299  /* { */
300  /* // (note: cache is mutable) */
301  /* is_cache_active_ = true; cur_cache_id_++; */
302  /* } */
303 
304  /* inline void deactivate_cache() const */
305  /* { */
306  /* // (note: cache is mutable) */
307  /* is_cache_active_ = false; */
308  /* } */
309 
310 
311 };
312 
313 //!
314 inline double
315 SitesPairScore::evaluate_index
316 (Model *m, const ParticleIndexPair &p,
317  DerivativeAccumulator *da) const{
318  // get internal tables:
319  algebra::Sphere3D const* spheres_table=
320  m->access_spheres_data();
321  double const* quaternions_tables[4];
322  for(unsigned int i = 0; i < 4; i++){
323  quaternions_tables[i]=
324  core::RigidBody::access_quaternion_i_data(m, i);
325  }
326  algebra::Sphere3D* sphere_derivatives_table=
327  m->access_sphere_derivatives_data();
328  double* torques_tables[3];
329  for(unsigned int i = 0; i < 3; i++){
330  torques_tables[i]=
331  core::RigidBody::access_torque_i_data(m, i);
332  }
333  // evaluate:
334  return evaluate_index_with_internal_tables(m,
335  spheres_table,
336  quaternions_tables,
337  sphere_derivatives_table,
338  torques_tables,
339  p,
340  da);
341 }
342 
343 
344 
345 
346 /**
347  the sites of each particle are transformed to a common frame of reference
348  (using the reference frame of each particle), and the site-specific
349  attraction, and the inter-particle non specific attraction and repulsion
350  are evaluated and summed.
351 */
352 inline double
353 SitesPairScore::evaluate_index_with_internal_tables
354 ( Model* m,
355  algebra::Sphere3D const* spheres_table,
356  double const** quaternions_tables,
357  algebra::Sphere3D *sphere_derivatives_table,
358  double **torques_tables,
359  const ParticleIndexPair &pip,
360  DerivativeAccumulator *da) const {
362 
363  // I. evaluate non-specific attraction and repulsion between
364  // parent particles before computing for specific sites :
365  double non_specific_score = P::evaluate_index(m, pip, da);
367  lips_cache= P::get_evaluation_cache();
368 
369  // II. Return if parent particles are out of site-specific interaction range
370  // using cache to avoid some redundant calcs
371  double const& distance2= lips_cache.particles_delta_squared;
372  IMP_LOG(PROGRESS, "distance2 " << distance2
373  << " ; distance upper-bound " << ubound_distance2_ << std::endl);
374  if (distance2 > ubound_distance2_) {
375  IMP_LOG(PROGRESS, "Sites contribution is 0.0 and non-specific score is "
376  << non_specific_score << std::endl);
377  return non_specific_score;
378  }
379 
380  double site_score=evaluate_site_contributions_with_internal_tables
381  (spheres_table,
382  quaternions_tables,
383  sphere_derivatives_table,
384  torques_tables,
385  pip, da);
386  // III. evaluate site-specific contributions :
387  return site_score + non_specific_score;
388 }
389 
390 #ifndef SWIG
391 
392 //!
393 inline double
394 SitesPairScore::evaluate_site_contributions_with_internal_tables
395 ( algebra::Sphere3D const* spheres_table,
396  double const**quaternions_tables,
397  algebra::Sphere3D *sphere_derivatives_table,
398  double **torques_tables,
399  const ParticleIndexPair &pip,
401  boost::tuple<unsigned int,
402  std::vector<unsigned int>,
403  std::vector<unsigned int>,
404  bool>
405  * contacts_accumulator
406  ) const
407 {
409  // interaction statistics variables
410  static unsigned int n_contacts;
411  static std::vector<unsigned int> occupied_sites0; // how many contacts at each site of particle 0
412  static std::vector<unsigned int> occupied_sites1; // how many contacts at each site of particle 1
413  if(contacts_accumulator){
414  n_contacts= 0;
415  occupied_sites0.resize(sites0_.size());
416  occupied_sites1.resize(sites1_.size());
417  std::fill(occupied_sites0.begin(), occupied_sites0.end(),0);
418  std::fill(occupied_sites1.begin(), occupied_sites1.end(),0);
419  }
420 
421  // bring sites_ to the frame of reference of nn_sites_ and nn_
422  ParticleIndex pi0 = pip[0];
423  ParticleIndex pi1 = pip[1];
424  // get rbi0/1 info, update if needed
425  internal::RigidBodyInfo rbi0 = get_rigid_body_info(spheres_table,
426  quaternions_tables,
427  pi0);
428  internal::RigidBodyInfo rbi1 = get_rigid_body_info(spheres_table,
429  quaternions_tables,
430  pi1);
431  IMP_LOG_PROGRESS( "RBI0.pi " << rbi0.pi
432  << " RB0.cache_id " << rbi0.cache_id
433  << "RBI0.tr " << rbi0.tr << std::endl);
434  IMP_LOG_PROGRESS( "RBI1.cache_id " << rbi1.cache_id
435  << "RBI1.pi " << rbi1.pi
436  << "RBI1.tr " << rbi1.tr << std::endl);
437  // sum over specific interactions between all pairs of sites:
438  double sum = 0;
439  if(is_orientational_score_){
440  // Pre-compute a few variables that do not depend on either both sites or on site1
441  algebra::Vector3D const& gRB0= rbi0.tr.get_translation();
442  algebra::Vector3D const& gRB1= rbi1.tr.get_translation();
443  algebra::Vector3D gUnitRB0RB1= gRB1-gRB0;
444  double distRB0RB1= get_magnitude_and_normalize_in_place(gUnitRB0RB1); // distance between centers
445  for (unsigned int i0 = 0; i0 < sites0_.size(); ++i0) {
446  algebra::Vector3D gSite0 = rbi0.tr.get_transformed(sites0_[i0].get_center());
447  algebra::Vector3D gUnitRB0Site0= (gSite0-gRB0)*rbi0.iradius;
448  double cosSigma0 = gUnitRB0Site0*gUnitRB0RB1;
449  if(cosSigma0 < params_.cosSigma1_max) { // not in range... - note the indexing is not an error - sigma0 is equivalent to params_.sigma1
450  continue;
451  }
452  double kFactor0=internal::get_k_factor(cosSigma0, params_.cosSigma1_max); // note the indexing is not an error - sigma0 is equivalent to params_.sigma1
453  algebra::Vector3D gRotSigma0;
454  double dKFactor0;
455  if(da){
456  gRotSigma0 = get_vector_product(gUnitRB0Site0,gUnitRB0RB1);
457  double absSinSigma0 = get_magnitude_and_normalize_in_place(gRotSigma0);
458  dKFactor0=internal::get_derivative_k_factor(absSinSigma0, params_.cosSigma1_max);
459  }
460  for(unsigned int i1 = 0 ; i1 < sites1_.size(); ++i1) {
461  algebra::Vector3D gSite1 = rbi1.tr.get_transformed(sites1_[i1].get_center());
462  IMP_LOG_PROGRESS( "Evaluating sites at global coordinates: " << gSite0
463  << " ; " << gSite1 << std::endl );
464  double cur_score;
465  cur_score =
466  internal::evaluate_pair_of_sites(params_,
467  rbi0, rbi1,
468  gSite1,
469  gUnitRB0RB1, distRB0RB1,
470  gRotSigma0,
471  kFactor0, dKFactor0,
472  da,
473  sphere_derivatives_table,
474  torques_tables);
475  sum += cur_score;
476  if(contacts_accumulator && cur_score!=0.0){
477  n_contacts++;
478  occupied_sites0[i0]++;
479  occupied_sites1[i1]++;
480  }
481  } // j
482  } // i
483  } // is_orientational_score_
484  else
485  {
486  for (unsigned int i = 0; i < sites0_.size(); ++i) {
487  algebra::Vector3D g0 = rbi0.tr.get_transformed(sites0_[i].get_center());
488  for(unsigned int j = 0 ; j < sites1_.size(); ++j) {
489  algebra::Vector3D g1 = rbi1.tr.get_transformed(sites1_[j].get_center());
490  IMP_LOG_PROGRESS( "Evaluating sites at global coordinates: " << g0 << " ; " << g1 << std::endl );
491  double cur_score;
492  // old score
493  cur_score =
494  internal::evaluate_one_site_3(params_.k,
495  params_.r,
496  rbi0, rbi1,
497  sites0_[i], sites1_[j],
498  g0, g1,
499  da,
500  sphere_derivatives_table,
501  torques_tables);
502 
503  sum += cur_score;
504  if(contacts_accumulator && cur_score!=0.0){
505  n_contacts++;
506  occupied_sites0[i]++;
507  occupied_sites1[i]++;
508  }
509  }// j
510  }// i
511  } // else
512  if(contacts_accumulator){
513  double non_specific_range= P::get_range_attraction();
514  double d_spheres= IMP::algebra::get_distance(spheres_table[pip[0].get_index()],
515  spheres_table[pip[1].get_index()]);
516  bool is_nonspecific_interaction= d_spheres < non_specific_range;
517  (*contacts_accumulator)=
518  boost::make_tuple(n_contacts,
519  occupied_sites0,
520  occupied_sites1,
521  is_nonspecific_interaction);
522  }
523 
524  IMP_LOG_PROGRESS( "Sum " << sum << std::endl);
525  return sum;
526 }
527 
528 
529 //!
530 inline double
531 SitesPairScore::evaluate_site_contributions
532 (Model* m,
533  const ParticleIndexPair &pip,
535  boost::tuple< unsigned int, std::vector<unsigned int>, std::vector<unsigned int>, bool >
536  (*contacts_accumulator)
537  ) const
538 {
539  // Get internal tables
540  algebra::Sphere3D const* spheres_table=
541  m->access_spheres_data();
542  double const* quaternions_tables[4];
543  for(unsigned int i = 0; i < 4; i++){
544  quaternions_tables[i]=
545  core::RigidBody::access_quaternion_i_data(m, i);
546  }
547  algebra::Sphere3D* sphere_derivatives_table=
548  m->access_sphere_derivatives_data();
549  double* torques_tables[3];
550  for(unsigned int i = 0; i < 3; i++){
551  torques_tables[i]=
552  core::RigidBody::access_torque_i_data(m, i);
553  }
554  // evaluate:
555  return evaluate_site_contributions_with_internal_tables
556  (spheres_table,
557  quaternions_tables,
558  sphere_derivatives_table,
559  torques_tables,
560  pip,
561  da,
562  contacts_accumulator);
563 }
564 
565 #endif // ifndef SWIG
566 
567 //!
568 inline internal::RigidBodyInfo
569 SitesPairScore::get_rigid_body_info
570 (algebra::Sphere3D const* spheres_table,
571  double const **quaternions_tables,
572  ParticleIndex pi) const
573 {
574  // TODO: add usage check that it has valid quaternions
575  // IMP_USAGE_CHECK(core::RigidBody::get_is_setup(m, pi),
576  // "PI " << pi.get_index() << " not a rigid body");
577  /* if(is_cache_active_){ */
578  /* std::pair<t_particles_rb_cache::iterator, bool> */
579  /* p = particles_rb_cache_.insert */
580  /* (std::make_pair(pi, internal::RigidBodyInfo())); */
581  /* internal::RigidBodyInfo& rbi_cached = p.first->second; */
582  /* bool const rbi_in_cache = !p.second; */
583  /* if(!rbi_in_cache || */
584  /* rbi_cached.cache_id != cur_cache_id_) // = cached version is outdated */
585  /* { */
586  /* rbi_cached.set_particle(spheres_table, */
587  /* quaternions_tables, */
588  /* pi, */
589  /* cur_cache_id_); */
590  /* } */
591  /* return rbi_cached; */
592  /* } */
593  /* else // if is_cache_active_ */
594  /* { */
595  return internal::RigidBodyInfo(spheres_table,
596  quaternions_tables,
597  pi,
598  INVALID_CACHE_ID);
599  /* } */
600 }
601 
602 
603 
604 IMPNPCTRANSPORT_END_NAMESPACE
605 
606 #endif /* IMPNPCTRANSPORT_SITES_PAIR_SCORE_H */
Apply a PairScore to each Pair in a list.
virtual double evaluate_if_good_indexes(Model *m, const ParticleIndexPairs &o, DerivativeAccumulator *da, double max, unsigned int lower_bound, unsigned int upper_bound) const
#define IMP_OBJECT_METHODS(Name)
Define the basic things needed by any Object.
Definition: object_macros.h:25
virtual double evaluate_indexes(Model *m, const ParticleIndexPairs &pips, DerivativeAccumulator *da, unsigned int lower_bound, unsigned int upper_bound) const override
#define IMP_OBJECT_LOG
Set the log level to the object's log level.
Definition: log_macros.h:284
Single variable function.
#define IMP_LOG_PROGRESS(expr)
Definition: log_macros.h:94
A particle with a user-defined type.
Macros to choose the best set or map for different purposes.
Class for storing model, its restraints, constraints, and particles.
Definition: Model.h:86
double get_magnitude_and_normalize_in_place(VT &vt)
Returns the magnitude of vt and turns it to a unit vector in place.
Definition: VectorBaseD.h:282
Apply a function to the distance between two particles with a set of specific binding sites...
Vector3D get_vector_product(const Vector3D &p1, const Vector3D &p2)
Return the vector product (cross product) of two vectors.
Definition: Vector3D.h:31
Ints get_index(const ParticlesTemp &particles, const Subset &subset, const Subsets &excluded)
Define PairScore.
Represent an XYZR particle with a sphere.
Simple 3D transformation class.
A score on the distance between the surfaces of two spheres.
A nullptr-initialized pointer to an IMP Object.
double get_sites_range() const
return the range for site-site attraction
ModelObjectsTemp do_get_inputs(Model *m, const ParticleIndexes &pis) const override
Overload this method to specify the inputs.
double get_sites_k() const
return the k for site-site attraction
VectorD< 3 > Vector3D
Definition: VectorD.h:425
double evaluate_index(algebra::Sphere3D const &s0, algebra::Sphere3D const &s1, algebra::Sphere3D &ds0, algebra::Sphere3D &ds1, DerivativeAccumulator *da) const
Functions to search over vectors.
A Score on the distance between a pair of particles.
A summary of useful information about rigid bodies and their transformation for eg, caching purposes for SitesPairScore.
Decorator for a sphere-like particle.
double get_distance(const Line3D &s, const Vector3D &p)
Get closest distance between a line and a point.
Class for adding derivatives from restraints to the model.
Estimates of various physical quantities.
Compile-time generic restraint and constraint support.