forcefield.h

Go to the documentation of this file.
00001 /**********************************************************************
00002 forcefield.h - Handle OBForceField class.
00003  
00004 Copyright (C) 2006-2007 by Tim Vandermeersch <[email protected]>
00005  
00006 This file is part of the Open Babel project.
00007 For more information, see <http://openbabel.sourceforge.net/>
00008  
00009 This program is free software; you can redistribute it and/or modify
00010 it under the terms of the GNU General Public License as published by
00011 the Free Software Foundation version 2 of the License.
00012  
00013 This program is distributed in the hope that it will be useful,
00014 but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 GNU General Public License for more details.
00017 ***********************************************************************/
00018 
00019 #ifndef OB_FORCEFIELD_H
00020 #define OB_FORCEFIELD_H
00021 
00022 #include <vector>
00023 #include <string>
00024 #include <map>
00025 
00026 #include <list>
00027 #include <set>
00028 #include <openbabel/base.h>
00029 #include <openbabel/mol.h>
00030 #include <openbabel/pluginiter.h>
00031 
00032 namespace OpenBabel
00033 {
00034   // log levels
00035 #define OBFF_LOGLVL_NONE        0   
00036 #define OBFF_LOGLVL_LOW 1     
00037 #define OBFF_LOGLVL_MEDIUM      2 
00038 #define OBFF_LOGLVL_HIGH        3   
00039 
00040   // terms
00041 #define OBFF_ENERGY             (1 << 0)   
00042 #define OBFF_EBOND              (1 << 1)   
00043 #define OBFF_EANGLE             (1 << 2)   
00044 #define OBFF_ESTRBND            (1 << 3) 
00045 #define OBFF_ETORSION           (1 << 4) 
00046 #define OBFF_EOOP               (1 << 5)     
00047 #define OBFF_EVDW               (1 << 6)     
00048 #define OBFF_EELECTROSTATIC     (1 << 7) 
00049 
00050   // mode arguments for SteepestDescent, ConjugateGradients, ...
00051 #define OBFF_NUMERICAL_GRADIENT   (1 << 0)  
00052 #define OBFF_ANALYTICAL_GRADIENT        (1 << 1)  
00053 
00054 #define KCAL_TO_KJ      4.1868
00055 
00056   // inline if statements for logging.
00057 #define IF_OBFF_LOGLVL_LOW    if(loglvl >= OBFF_LOGLVL_LOW)
00058 #define IF_OBFF_LOGLVL_MEDIUM if(loglvl >= OBFF_LOGLVL_MEDIUM)
00059 #define IF_OBFF_LOGLVL_HIGH   if(loglvl >= OBFF_LOGLVL_HIGH)
00060   
00063   class OBFFParameter {
00064   public:
00066     int         a, b, c, d;
00068     std::string _a, _b, _c, _d; 
00069 
00071     int       ipar1, ipar2, ipar3, ipar4, ipar5;
00073     double    dpar1, dpar2, dpar3, dpar4, dpar5;
00074 
00076     OBFFParameter& operator=(const OBFFParameter &ai) 
00077     {
00078       if (this != &ai) {
00079         a = ai.a;
00080         b = ai.b;
00081         c = ai.c;
00082         d = ai.d;
00083         _a = ai._a;
00084         _b = ai._b;
00085         _c = ai._c;
00086         _d = ai._d;
00087         ipar1 = ai.ipar1;
00088         ipar2 = ai.ipar2;
00089         ipar3 = ai.ipar3;
00090         ipar4 = ai.ipar4;
00091         ipar5 = ai.ipar5;
00092         dpar1 = ai.dpar1;
00093         dpar2 = ai.dpar2;
00094         dpar3 = ai.dpar3;
00095         dpar4 = ai.dpar4;
00096         dpar5 = ai.dpar5;
00097       }
00098         
00099       return *this;
00100     }
00101 
00103     void clear () 
00104     {
00105       a = 0;
00106       b = 0;
00107       c = 0;
00108       d = 0;
00109       ipar1 = 0;
00110       ipar2 = 0;
00111       ipar3 = 0;
00112       ipar4 = 0;
00113       ipar5 = 0;
00114       dpar1 = 0.0f;
00115       dpar2 = 0.0f;
00116       dpar3 = 0.0f;
00117       dpar4 = 0.0f;
00118       dpar5 = 0.0f;
00119     }
00120   }; // class OBFFParameter
00121   
00122   // specific class introductions in forcefieldYYYY.cpp (for YYYY calculations)
00125   class OBFFCalculation
00126   {
00127     public:
00129       double energy;
00131       vector3 grada, gradb, gradc, gradd;
00133       OBAtom *a, *b, *c, *d;
00134 
00136       OBFFCalculation() 
00137         {
00138           a = NULL;
00139           b = NULL;
00140           c = NULL;
00141           d = NULL;
00142           energy = 0.0f;
00143           grada = VZero;
00144           gradb = VZero;
00145           gradc = VZero;
00146           gradd = VZero;
00147         }
00149       virtual ~OBFFCalculation()
00150         {
00151         }
00152       
00154       virtual void Compute(bool gradients = true) 
00155         {
00156         }
00158       virtual double GetEnergy() 
00159       {
00160         if (!energy)
00161           Compute(false);
00162 
00163         return energy; 
00164       }
00166       virtual vector3 GetGradient(OBAtom *atom) 
00167       {
00168         if (atom == a)
00169           return grada;
00170         else if (atom == b)
00171           return gradb;
00172         else if (atom == c)
00173           return gradc;
00174         else if (atom == d)
00175           return gradd;
00176         else 
00177           return  VZero;
00178       }
00179   };
00180 
00181   // Class OBForceField
00182   // class introduction in forcefield.cpp
00183   class OBAPI OBForceField
00184   {
00185   
00186   MAKE_PLUGIN(OBForceField)
00187   
00188     protected:
00230     OBFFParameter* GetParameter(int a, int b, int c, int d, std::vector<OBFFParameter> &parameter);
00232     OBFFParameter* GetParameter(const char* a, const char* b, const char* c, const char* d, std::vector<OBFFParameter> &parameter);
00233            
00235 
00240     vector3 NumericalDerivative(OBAtom *a, int terms = OBFF_ENERGY);
00242     vector3 NumericalSecondDerivative(OBAtom *a, int terms = OBFF_ENERGY);
00252     virtual vector3 GetGradient(OBAtom *a, int terms = OBFF_ENERGY) 
00253     { 
00254       return -NumericalDerivative(a, terms); 
00255     }
00261     bool IsInSameRing(OBAtom* a, OBAtom* b);
00262  
00263     OBMol _mol; 
00264 
00266     std::ostream* logos;
00267     char logbuf[200];
00268     int loglvl; 
00269 
00271     int current_conformer;
00272 
00274     double _econv, _e_n1;
00275     int _method, _cstep, _nsteps;
00276     std::vector<vector3> _grad1, _dir1;
00277 
00278   public:
00280     virtual ~OBForceField()
00281       {
00282       }
00284     //virtual std::string Description()=0;
00288     static OBForceField* FindForceField(const std::string& ID)
00289     { 
00290       return Iter().FindType(ID);
00291     } 
00295     static OBForceField* FindForceField(const char *ID)
00296     {
00297       std::string ffname(ID);
00298       return FindForceField(ffname);
00299     }
00301     virtual std::string GetUnit() { return std::string("au"); }
00306     virtual bool Setup(OBMol &mol) { return false; }
00311     bool UpdateCoordinates(OBMol &mol);
00316     bool UpdateConformers(OBMol &mol);
00320     void OBFFLog(std::string msg)
00321     {
00322       if (!logos)
00323         return;
00324       
00325       *logos << msg;
00326     }
00330     void OBFFLog(const char *msg)
00331     {
00332       if (!logos)
00333         return;
00334       
00335       *logos << msg;
00336     }
00337 
00339     // Energy Evaluation                                                   //
00341       
00343 
00344 
00352     virtual double Energy(bool gradients = true) { return 0.0f; }
00358     virtual double E_Bond(bool gradients = true) { return 0.0f; }
00364     virtual double E_Angle(bool gradients = true) { return 0.0f; }
00370     virtual double E_StrBnd(bool gradients = true) { return 0.0f; }
00376     virtual double E_Torsion(bool gradients = true) { return 0.0f; }
00382     virtual double E_OOP(bool gradients = true) { return 0.0f; }
00388     virtual double E_VDW(bool gradients = true) { return 0.0f; }
00394     virtual double E_Electrostatic(bool gradients = true) { return 0.0f; }
00396      
00398     // Logging                                                             //
00400       
00402 
00403 
00407     bool SetLogFile(std::ostream *pos);
00436     bool SetLogLevel(int level);
00438     int GetLogLevel() { return loglvl; }
00440      
00442     // Structure Generation                                                //
00444       
00446 
00447 
00464     void SystematicRotorSearch();
00465       
00467     // Energy Minimization                                                 //
00469       
00471 
00472 
00484     vector3 LineSearch(OBAtom *atom, vector3 &direction);
00499     void SteepestDescent(int steps, double econv = 1e-6f, int method = OBFF_ANALYTICAL_GRADIENT);
00527     void SteepestDescentInitialize(int steps = 1000, double econv = 1e-6f, int method = OBFF_ANALYTICAL_GRADIENT);
00543     bool SteepestDescentTakeNSteps(int n);
00559     void ConjugateGradients(int steps, double econv = 1e-6f, int method = OBFF_ANALYTICAL_GRADIENT);
00586     void ConjugateGradientsInitialize(int steps = 1000, double econv = 1e-6f, int method = OBFF_ANALYTICAL_GRADIENT);
00601     bool ConjugateGradientsTakeNSteps(int n);
00603       
00605     // Validation                                                          //
00607       
00609 
00610 
00611     virtual bool Validate() { return false; }
00616     virtual bool ValidateGradients() { return false; }
00621     vector3 ValidateGradientError(vector3 &numgrad, vector3 &anagrad);
00623      
00625     // Vector Analysis                                                     //
00627       
00629 
00630 
00636     static double VectorLengthDerivative(vector3 &a, vector3 &b);
00643     static double VectorAngleDerivative(vector3 &a, vector3 &b, vector3 &c);
00651     static double VectorTorsionDerivative(vector3 &a, vector3 &b, vector3 &c, vector3 &d);
00653 
00658     void kludge()
00659     {
00660       PluginIter<OBForceField> it;
00661       (++it)->SetLogLevel(1);
00662       if(it)it.ID();
00663     }
00664 
00665   }; // class OBForceField
00666 
00667 }// namespace OpenBabel
00668 
00669 #endif   // OB_FORCEFIELD_H
00670