ForceField.h

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

Generated on Tue Oct 7 06:10:10 2008 for RDCode by  doxygen 1.5.5