00001 // 00002 // Copyright (C) 2004-2006 Rational Discovery LLC 00003 // 00004 // @@ All Rights Reserved @@ 00005 // This file is part of the RDKit. 00006 // The contents are covered by the terms of the BSD license 00007 // which is included in the file license.txt, found at the root 00008 // of the RDKit source tree. 00009 // 00010 #ifndef __RD_FORCEFIELD_H__ 00011 #define __RD_FORCEFIELD_H__ 00012 00013 #include <vector> 00014 #include <boost/smart_ptr.hpp> 00015 #include <Geometry/point.h> 00016 00017 namespace ForceFields { 00018 class ForceFieldContrib; 00019 typedef std::vector<int> INT_VECT; 00020 typedef boost::shared_ptr<ForceFieldContrib> ContribPtr; 00021 typedef std::vector<ContribPtr> ContribPtrVect; 00022 00023 //------------------------------------------------------- 00024 //! A class to store forcefields and handle minimization 00025 /*! 00026 A force field is used like this (schematically): 00027 00028 \verbatim 00029 ForceField ff; 00030 00031 // add contributions: 00032 for contrib in contribs: 00033 ff.contribs().push_back(contrib); 00034 00035 // set up the points: 00036 for positionPtr in positions: 00037 ff.positions().push_back(point); 00038 00039 // initialize: 00040 ff.initialize() 00041 00042 // and minimize: 00043 needsMore = ff.minimize(); 00044 00045 \endverbatim 00046 00047 <b>Notes:</b> 00048 - The ForceField owns its contributions, which are stored using smart 00049 pointers. 00050 - Distance calculations are currently lazy; the full distance matrix is 00051 never generated. In systems where the distance matrix is not sparse, 00052 this is almost certainly inefficient. 00053 00054 */ 00055 class ForceField { 00056 public: 00057 //! construct with a dimension 00058 ForceField(unsigned int dimension=3) : d_dimension(dimension), df_init(false), 00059 d_numPoints(0), dp_distMat(0) {}; 00060 00061 ~ForceField(); 00062 00063 //! does initialization 00064 void initialize(); 00065 00066 00067 //! calculates and returns the energy based on existing positions in the forcefield 00068 /*! 00069 00070 \return the current energy 00071 00072 <b>Note:</b> 00073 This function is less efficient than calcEnergy with postions passed in as double * 00074 the positions need to be converted to double * here 00075 */ 00076 double calcEnergy() const; 00077 00078 // these next two aren't const because they may update our 00079 // distance matrix 00080 00081 //! calculates and returns the energy of the position passed in 00082 /*! 00083 \param pos an array of doubles. Should be \c 3*this->numPoints() long. 00084 00085 \return the current energy 00086 00087 <b>Side effects:</b> 00088 - Calling this resets the current distance matrix 00089 - The individual contributions may further update the distance matrix 00090 */ 00091 double calcEnergy(double *pos); 00092 00093 //! calculates the gradient of the energy at the current position 00094 /*! 00095 00096 \param forces an array of doubles. Should be \c 3*this->numPoints() long. 00097 00098 <b>Note:</b> 00099 This function is less efficient than calcGrad with positions passed in 00100 the positions need to be converted to double * here 00101 */ 00102 void calcGrad(double *forces) const; 00103 00104 //! calculates the gradient of the energy at the provided position 00105 /*! 00106 00107 \param pos an array of doubles. Should be \c 3*this->numPoints() long. 00108 \param forces an array of doubles. Should be \c 3*this->numPoints() long. 00109 00110 <b>Side effects:</b> 00111 - The individual contributions may modify the distance matrix 00112 */ 00113 void calcGrad(double *pos,double *forces); 00114 00115 //! minimizes the energy of the system by following gradients 00116 /*! 00117 \param maxIts the maximum number of iterations to try 00118 \param forceTol the convergence criterion for forces 00119 \param energyTol the convergence criterion for energies 00120 00121 \return an integer value indicating whether or not the convergence 00122 criteria were achieved: 00123 - 0: indicates success 00124 - 1: the minimization did not converge in \c maxIts iterations. 00125 */ 00126 int minimize(unsigned int maxIts=200,double forceTol=1e-4,double energyTol=1e-6); 00127 00128 // --------------------------- 00129 // setters and getters 00130 00131 //! returns a reference to our points (a PointPtrVect) 00132 RDGeom::PointPtrVect &positions() { return d_positions; }; 00133 const RDGeom::PointPtrVect &positions() const { return d_positions; }; 00134 00135 //! returns a reference to our contribs (a ContribPtrVect) 00136 ContribPtrVect &contribs() { return d_contribs; }; 00137 const ContribPtrVect &contribs() const { return d_contribs; }; 00138 00139 //! returns the distance between two points 00140 /*! 00141 \param i point index 00142 \param j point index 00143 \param pos (optional) If this argument is provided, it will be used 00144 to provide the positions of points. \c pos should be 00145 \c 3*this->numPoints() long. 00146 00147 \return the distance 00148 00149 <b>Side effects:</b> 00150 - if the distance between i and j has not previously been calculated, 00151 our internal distance matrix will be updated. 00152 */ 00153 double distance(unsigned int i,unsigned int j,double *pos=0); 00154 00155 //! returns the distance between two points 00156 /*! 00157 \param i point index 00158 \param j point index 00159 \param pos (optional) If this argument is provided, it will be used 00160 to provide the positions of points. \c pos should be 00161 \c 3*this->numPoints() long. 00162 00163 \return the distance 00164 00165 <b>Note:</b> 00166 The internal distance matrix is not updated in this case 00167 */ 00168 double distance(unsigned int i,unsigned int j,double *pos=0) const; 00169 00170 //! returns the dimension of the forcefield 00171 unsigned int dimension() const { 00172 return d_dimension; 00173 } 00174 00175 //! returns the number of points the ForceField is handling 00176 unsigned int numPoints() const { return d_numPoints; }; 00177 00178 INT_VECT &fixedPoints() { return d_fixedPoints; }; 00179 const INT_VECT &fixedPoints() const { return d_fixedPoints; }; 00180 00181 protected: 00182 unsigned int d_dimension; 00183 bool df_init; //!< whether or not we've been initialized 00184 unsigned int d_numPoints; //!< the number of active points 00185 double *dp_distMat; //!< our internal distance matrix 00186 RDGeom::PointPtrVect d_positions; //!< pointers to the points we're using 00187 ContribPtrVect d_contribs; //!< contributions to the energy 00188 INT_VECT d_fixedPoints; 00189 unsigned int d_matSize; 00190 //! scatter our positions into an array 00191 /*! 00192 \param pos should be \c 3*this->numPoints() long; 00193 */ 00194 void scatter(double *pos) const; 00195 00196 //! update our positions from an array 00197 /*! 00198 \param pos should be \c 3*this->numPoints() long; 00199 */ 00200 void gather(double *pos); 00201 00202 //! initializes our internal distance matrix 00203 void initDistanceMatrix(); 00204 }; 00205 } 00206 #endif
1.7.1