RDCode: ForceField.h Source File

- Main Page
- Namespaces
- Classes
- Files
- Directories

# 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