00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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/babelconfig.h>
00029 #include <openbabel/base.h>
00030 #include <openbabel/mol.h>
00031 #include <openbabel/plugin.h>
00032 #include <openbabel/grid.h>
00033 #include <openbabel/griddata.h>
00034 #include <float.h>
00035
00036 namespace OpenBabel
00037 {
00038
00039 #define OBFF_LOGLVL_NONE 0
00040 #define OBFF_LOGLVL_LOW 1
00041 #define OBFF_LOGLVL_MEDIUM 2
00042 #define OBFF_LOGLVL_HIGH 3
00043
00044
00045 #define OBFF_ENERGY (1 << 0)
00046 #define OBFF_EBOND (1 << 1)
00047 #define OBFF_EANGLE (1 << 2)
00048 #define OBFF_ESTRBND (1 << 3)
00049 #define OBFF_ETORSION (1 << 4)
00050 #define OBFF_EOOP (1 << 5)
00051 #define OBFF_EVDW (1 << 6)
00052 #define OBFF_EELECTROSTATIC (1 << 7)
00053
00054
00055 #define OBFF_CONST_IGNORE (1 << 0)
00056 #define OBFF_CONST_ATOM (1 << 1)
00057 #define OBFF_CONST_ATOM_X (1 << 2)
00058 #define OBFF_CONST_ATOM_Y (1 << 3)
00059 #define OBFF_CONST_ATOM_Z (1 << 4)
00060 #define OBFF_CONST_DISTANCE (1 << 5)
00061 #define OBFF_CONST_ANGLE (1 << 6)
00062 #define OBFF_CONST_TORSION (1 << 7)
00063 #define OBFF_CONST_CHIRAL (1 << 8)
00064
00065
00066 #define OBFF_NUMERICAL_GRADIENT (1 << 0)
00067 #define OBFF_ANALYTICAL_GRADIENT (1 << 1)
00068
00069 #define KCAL_TO_KJ 4.1868
00070
00071
00072 #define IF_OBFF_LOGLVL_LOW if(_loglvl >= OBFF_LOGLVL_LOW)
00073 #define IF_OBFF_LOGLVL_MEDIUM if(_loglvl >= OBFF_LOGLVL_MEDIUM)
00074 #define IF_OBFF_LOGLVL_HIGH if(_loglvl >= OBFF_LOGLVL_HIGH)
00075
00077 struct LineSearchType
00078 {
00079 enum {
00080 Simple, Newton2Num
00081 };
00082 };
00083
00084
00085
00086
00087
00088
00089
00090
00091
00094 class OBFPRT OBFFParameter {
00095 public:
00097 int a, b, c, d;
00099 std::string _a, _b, _c, _d;
00100
00102 std::vector<int> _ipar;
00104 std::vector<double> _dpar;
00105
00107 OBFFParameter& operator=(const OBFFParameter &ai)
00108 {
00109 if (this != &ai) {
00110 a = ai.a;
00111 b = ai.b;
00112 c = ai.c;
00113 d = ai.d;
00114 _a = ai._a;
00115 _b = ai._b;
00116 _c = ai._c;
00117 _d = ai._d;
00118 _ipar = ai._ipar;
00119 _dpar = ai._dpar;
00120 }
00121
00122 return *this;
00123 }
00124
00126 void clear ()
00127 {
00128 a = b = c = d = 0;
00129 _ipar.clear();
00130 _dpar.clear();
00131 }
00132 };
00133
00134
00135
00138 class OBFPRT OBFFCalculation2
00139 {
00140 public:
00142 double energy;
00144 OBAtom *a, *b;
00146 int idx_a, idx_b;
00148 double *pos_a, *pos_b;
00150 double force_a[3], force_b[3];
00152 virtual ~OBFFCalculation2()
00153 {
00154 }
00157 virtual void SetupPointers()
00158 {
00159 if (!a || !b) return;
00160 pos_a = a->GetCoordinate();
00161 idx_a = a->GetIdx();
00162 pos_b = b->GetCoordinate();
00163 idx_b = b->GetIdx();
00164 }
00165 };
00166
00169 class OBFPRT OBFFCalculation3: public OBFFCalculation2
00170 {
00171 public:
00173 OBAtom *c;
00175 int idx_c;
00177 double *pos_c;
00179 double force_c[3];
00181 virtual ~OBFFCalculation3()
00182 {
00183 }
00186 virtual void SetupPointers()
00187 {
00188 if (!a || !b || !c) return;
00189 pos_a = a->GetCoordinate();
00190 idx_a = a->GetIdx();
00191 pos_b = b->GetCoordinate();
00192 idx_b = b->GetIdx();
00193 pos_c = c->GetCoordinate();
00194 idx_c = c->GetIdx();
00195 }
00196 };
00197
00200 class OBFPRT OBFFCalculation4: public OBFFCalculation3
00201 {
00202 public:
00204 OBAtom *d;
00206 int idx_d;
00208 double *pos_d;
00210 double force_d[3];
00212 virtual ~OBFFCalculation4()
00213 {
00214 }
00217 void SetupPointers()
00218 {
00219 if (!a || !b || !c || !d) return;
00220 pos_a = a->GetCoordinate();
00221 idx_a = a->GetIdx();
00222 pos_b = b->GetCoordinate();
00223 idx_b = b->GetIdx();
00224 pos_c = c->GetCoordinate();
00225 idx_c = c->GetIdx();
00226 pos_d = d->GetCoordinate();
00227 idx_d = d->GetIdx();
00228 }
00229 };
00230
00234 class OBFPRT OBFFConstraint
00235 {
00236 public:
00238 double factor, constraint_value;
00239 double rab0, rbc0;
00241 int type, ia, ib, ic, id;
00243 OBAtom *a, *b, *c, *d;
00245 vector3 grada, gradb, gradc, gradd;
00246
00248 OBFFConstraint()
00249 {
00250 a = b = c = d = NULL;
00251 ia = ib = ic = id = 0;
00252 constraint_value = 0.0;
00253 factor = 0.0;
00254 }
00256 ~OBFFConstraint()
00257 {
00258 }
00259
00260 vector3 GetGradient(int a)
00261 {
00262 if (a == ia)
00263 return grada;
00264 else if (a == ib)
00265 return gradb;
00266 else if (a == ic)
00267 return gradc;
00268 else if (a == id)
00269 return gradd;
00270 else
00271 return VZero;
00272 }
00273 };
00274
00278 class OBFPRT OBFFConstraints
00279 {
00280 public:
00282 OBFFConstraints();
00284 ~OBFFConstraints()
00285 {
00286 _constraints.clear();
00287 _ignored.Clear();
00288 _fixed.Clear();
00289 _Xfixed.Clear();
00290 _Yfixed.Clear();
00291 _Zfixed.Clear();
00292 }
00294 void Clear();
00296 double GetConstraintEnergy();
00298 vector3 GetGradient(int a);
00300 OBFFConstraints& operator=(const OBFFConstraints &ai)
00301 {
00302 if (this != &ai) {
00303 _constraints = ai._constraints;
00304 _ignored = ai._ignored;
00305 _fixed = ai._fixed;
00306 _Xfixed = ai._Xfixed;
00307 _Yfixed = ai._Yfixed;
00308 _Zfixed = ai._Zfixed;
00309 }
00310 return *this;
00311 }
00312
00316 void Setup(OBMol &mol);
00317
00319
00322
00323
00324 void SetFactor(double factor);
00326 void AddIgnore(int a);
00328 void AddAtomConstraint(int a);
00330 void AddAtomXConstraint(int a);
00332 void AddAtomYConstraint(int a);
00334 void AddAtomZConstraint(int a);
00336 void AddDistanceConstraint(int a, int b, double length);
00338 void AddAngleConstraint(int a, int b, int c, double angle);
00340 void AddTorsionConstraint(int a, int b, int c, int d, double torsion);
00343 void DeleteConstraint(int index);
00345
00346
00349
00350
00351 double GetFactor();
00353 int Size() const;
00363 int GetConstraintType(int index) const;
00367 double GetConstraintValue(int index) const;
00370 int GetConstraintAtomA(int index) const;
00373 int GetConstraintAtomB(int index) const;
00376 int GetConstraintAtomC(int index) const;
00379 int GetConstraintAtomD(int index) const;
00382 bool IsIgnored(int a);
00385 bool IsFixed(int a);
00388 bool IsXFixed(int a);
00391 bool IsYFixed(int a);
00394 bool IsZFixed(int a);
00398 OBBitVec GetIgnoredBitVec() { return _ignored; }
00400
00401 private:
00402 std::vector<OBFFConstraint> _constraints;
00403 OBBitVec _ignored;
00404 OBBitVec _fixed;
00405 OBBitVec _Xfixed;
00406 OBBitVec _Yfixed;
00407 OBBitVec _Zfixed;
00408 double _factor;
00409 };
00410
00411
00412
00413 class OBFPRT OBForceField : public OBPlugin
00414 {
00415 MAKE_PLUGIN(OBForceField)
00416
00417 protected:
00418
00460 OBFFParameter* GetParameter(int a, int b, int c, int d, std::vector<OBFFParameter> ¶meter);
00462 OBFFParameter* GetParameter(const char* a, const char* b, const char* c, const char* d,
00463 std::vector<OBFFParameter> ¶meter);
00465 int GetParameterIdx(int a, int b, int c, int d, std::vector<OBFFParameter> ¶meter);
00466
00475 vector3 NumericalDerivative(OBAtom *a, int terms = OBFF_ENERGY);
00477 vector3 NumericalSecondDerivative(OBAtom *a, int terms = OBFF_ENERGY);
00478
00479
00480
00481
00482
00485 void SetGradient(double *grad, int idx)
00486 {
00487 const int coordIdx = (idx - 1) * 3;
00488 for (unsigned int i = 0; i < 3; ++i) {
00489 _gradientPtr[coordIdx + i] = grad[i];
00490 }
00491 }
00492
00495 void AddGradient(double *grad, int idx)
00496 {
00497 const int coordIdx = (idx - 1) * 3;
00498 for (unsigned int i = 0; i < 3; ++i) {
00499 _gradientPtr[coordIdx + i] += grad[i];
00500 }
00501 }
00502
00505 virtual vector3 GetGradient(OBAtom *a, int = OBFF_ENERGY)
00506 {
00507 const int coordIdx = (a->GetIdx() - 1) * 3;
00508 return _gradientPtr + coordIdx;
00509 }
00510
00513 double* GetGradientPtr()
00514 {
00515 return _gradientPtr;
00516 }
00517
00520 virtual void ClearGradients()
00521 {
00522
00523
00524
00525 for (unsigned int i = 0; i < _ncoords; ++i)
00526 _gradientPtr[i] = 0.0;
00527
00528 }
00529
00537 bool IsInSameRing(OBAtom* a, OBAtom* b);
00538
00539
00540 OBMol _mol;
00541 bool _init;
00542 std::string _parFile;
00543 bool _validSetup;
00544 double *_gradientPtr;
00545
00546 std::ostream* _logos;
00547 char _logbuf[BUFF_SIZE+1];
00548 int _loglvl;
00549 int _origLogLevel;
00550
00551 int _current_conformer;
00552 std::vector<double> _energies;
00553
00554 double _econv, _e_n1;
00555 int _cstep, _nsteps;
00556 double *_grad1;
00557 unsigned int _ncoords;
00558 int _linesearch;
00559
00560 double _timestep;
00561 double _temp;
00562 double *_velocityPtr;
00563
00564 static OBFFConstraints _constraints;
00565 static int _fixAtom;
00566 static int _ignoreAtom;
00567
00568 bool _cutoff;
00569 double _rvdw;
00570 double _rele;
00571 OBBitVec _vdwpairs;
00572 OBBitVec _elepairs;
00573 int _pairfreq;
00574
00575 std::vector<OBBitVec> _intraGroup;
00576 std::vector<OBBitVec> _interGroup;
00577 std::vector<std::pair<OBBitVec, OBBitVec> > _interGroups;
00578
00579 public:
00583 virtual OBForceField* MakeNewInstance()=0;
00584
00586 virtual ~OBForceField()
00587 {
00588 if (_grad1 != NULL) {
00589 delete [] _grad1;
00590 _grad1 = NULL;
00591 }
00592 }
00593
00595 const char* TypeID()
00596 {
00597 return "forcefields";
00598 }
00599
00603 static OBForceField* FindForceField(const std::string& ID)
00604 {
00605 return FindType(ID.c_str());
00606 }
00610 static OBForceField* FindForceField(const char *ID)
00611 {
00612 return FindType(ID);
00613 }
00614
00615
00616
00617 void SetParameterFile(const std::string &filename)
00618 {
00619 _parFile = filename;
00620 _init = false;
00621 }
00624 virtual std::string GetUnit() { return std::string("au"); }
00625
00626
00627
00628
00629
00630
00631 virtual bool HasAnalyticalGradients() { return false; }
00636 bool Setup(OBMol &mol);
00642 bool Setup(OBMol &mol, OBFFConstraints &constraints);
00646
00647 virtual bool ParseParamFile() { return false; }
00651
00652 virtual bool SetTypes() { return false; }
00656
00657 virtual bool SetFormalCharges() { return false; }
00661
00662 virtual bool SetPartialCharges() { return false; }
00666
00667 virtual bool SetupCalculations() { return false; }
00672
00673 virtual bool SetupPointers() { return false; }
00679 bool IsSetupNeeded(OBMol &mol);
00695 bool GetAtomTypes(OBMol &mol);
00711 bool GetPartialCharges(OBMol &mol);
00712
00713
00714
00719 bool GetCoordinates(OBMol &mol);
00721 bool UpdateCoordinates(OBMol &mol) {return GetCoordinates(mol); }
00726 bool GetConformers(OBMol &mol);
00728 bool UpdateConformers(OBMol &mol) { return GetConformers(mol); }
00733 bool SetCoordinates(OBMol &mol);
00738 bool SetConformers(OBMol &mol);
00748 OBGridData *GetGrid(double step, double padding, const char *type, double pchg);
00749
00751
00753
00755
00756
00760 void AddIntraGroup(OBBitVec &group);
00765 void AddInterGroup(OBBitVec &group);
00773 void AddInterGroups(OBBitVec &group1, OBBitVec &group2);
00776 void ClearGroups();
00779 bool HasGroups();
00781
00783
00785
00787
00788
00791 void EnableCutOff(bool enable)
00792 {
00793 _cutoff = enable;
00794 }
00797 bool IsCutOffEnabled()
00798 {
00799 return _cutoff;
00800 }
00804 void SetVDWCutOff(double r)
00805 {
00806 _rvdw = r;
00807 }
00811 double GetVDWCutOff()
00812 {
00813 return _rvdw;
00814 }
00819 void SetElectrostaticCutOff(double r)
00820 {
00821 _rele = r;
00822 }
00826 double GetElectrostaticCutOff()
00827 {
00828 return _rele;
00829 }
00835 void SetUpdateFrequency(int f)
00836 {
00837 _pairfreq = f;
00838 }
00842 int GetUpdateFrequency()
00843 {
00844 return _pairfreq;
00845 }
00850 void UpdatePairsSimple();
00851
00852
00853
00857 unsigned int GetNumPairs();
00861 void EnableAllPairs()
00862 {
00863
00864
00865
00866 }
00868
00870
00872
00874
00875
00884 virtual double Energy(bool = true) { return 0.0f; }
00891 virtual double E_Bond(bool = true) { return 0.0f; }
00898 virtual double E_Angle(bool = true) { return 0.0f; }
00905 virtual double E_StrBnd(bool = true) { return 0.0f; }
00912 virtual double E_Torsion(bool = true) { return 0.0f; }
00919 virtual double E_OOP(bool = true) { return 0.0f; }
00926 virtual double E_VDW(bool = true) { return 0.0f; }
00933 virtual double E_Electrostatic(bool = true) { return 0.0f; }
00935
00937
00939
00941
00942
00944 void PrintTypes();
00948 void PrintFormalCharges();
00951 void PrintPartialCharges();
00954 void PrintVelocities();
00959 bool SetLogFile(std::ostream *pos);
00984 bool SetLogLevel(int level);
00987 int GetLogLevel() { return _loglvl; }
00991 void OBFFLog(std::string msg)
00992 {
00993 if (!_logos)
00994 return;
00995
00996 *_logos << msg;
00997 }
01001 void OBFFLog(const char *msg)
01002 {
01003 if (!_logos)
01004 return;
01005
01006 *_logos << msg;
01007 }
01009
01011
01013
01015
01016
01017 void DistanceGeometry();
01037 void SystematicRotorSearch(unsigned int geomSteps = 2500);
01055 int SystematicRotorSearchInitialize(unsigned int geomSteps = 2500);
01060 bool SystematicRotorSearchNextConformer(unsigned int geomSteps = 2500);
01081 void RandomRotorSearch(unsigned int conformers, unsigned int geomSteps = 2500);
01099 void RandomRotorSearchInitialize(unsigned int conformers, unsigned int geomSteps = 2500);
01104 bool RandomRotorSearchNextConformer(unsigned int geomSteps = 2500);
01126 void WeightedRotorSearch(unsigned int conformers, unsigned int geomSteps);
01127
01129
01131
01133
01134
01137 void SetLineSearchType(int type)
01138 {
01139 _linesearch = type;
01140 }
01144 int GetLineSearchType()
01145 {
01146 return _linesearch;
01147 }
01151 vector3 LineSearch(OBAtom *atom, vector3 &direction);
01165 double LineSearch(double *currentCoords, double *direction);
01178 double Newton2NumLineSearch(double *direction);
01184 void LineSearchTakeStep(double *origCoords, double *direction, double step);
01200 void SteepestDescent(int steps, double econv = 1e-6f, int method = OBFF_ANALYTICAL_GRADIENT);
01227 void SteepestDescentInitialize(int steps = 1000, double econv = 1e-6f, int method = OBFF_ANALYTICAL_GRADIENT);
01242 bool SteepestDescentTakeNSteps(int n);
01258 void ConjugateGradients(int steps, double econv = 1e-6f, int method = OBFF_ANALYTICAL_GRADIENT);
01286 void ConjugateGradientsInitialize(int steps = 1000, double econv = 1e-6f, int method = OBFF_ANALYTICAL_GRADIENT);
01302 bool ConjugateGradientsTakeNSteps(int n);
01304
01306
01308
01310
01311
01313 void GenerateVelocities();
01333 void CorrectVelocities();
01349 void MolecularDynamicsTakeNSteps(int n, double T, double timestep = 0.001, int method = OBFF_ANALYTICAL_GRADIENT);
01351
01353
01355
01357
01358
01361 OBFFConstraints& GetConstraints();
01365 void SetConstraints(OBFFConstraints& constraints);
01373 void SetFixAtom(int index);
01377 void UnsetFixAtom();
01386 void SetIgnoreAtom(int index);
01390 void UnsetIgnoreAtom();
01391
01393 static bool IgnoreCalculation(int a, int b);
01395 static bool IgnoreCalculation(int a, int b, int c);
01397 static bool IgnoreCalculation(int a, int b, int c, int d);
01399
01400
01402
01404
01406
01407
01408 bool DetectExplosion();
01410 vector3 ValidateLineSearch(OBAtom *atom, vector3 &direction);
01412 void ValidateSteepestDescent(int steps);
01414 void ValidateConjugateGradients(int steps);
01416 virtual bool Validate() { return false; }
01421 virtual bool ValidateGradients() { return false; }
01426 vector3 ValidateGradientError(vector3 &numgrad, vector3 &anagrad);
01428
01430
01432
01434
01435
01443 static double VectorBondDerivative(double *pos_a, double *pos_b,
01444 double *force_a, double *force_b);
01448 static double VectorDistanceDerivative(const double* const pos_i, const double* const pos_j,
01449 double *force_i, double *force_j);
01451 static double VectorLengthDerivative(vector3 &a, vector3 &b);
01452
01463 static double VectorAngleDerivative(double *pos_a, double *pos_b, double *pos_c,
01464 double *force_a, double *force_b, double *force_c);
01466 static double VectorAngleDerivative(vector3 &a, vector3 &b, vector3 &c);
01479 static double VectorOOPDerivative(double *pos_a, double *pos_b, double *pos_c, double *pos_d,
01480 double *force_a, double *force_b, double *force_c, double *force_d);
01482 static double VectorOOPDerivative(vector3 &a, vector3 &b, vector3 &c, vector3 &d);
01494 static double VectorTorsionDerivative(double *pos_a, double *pos_b, double *pos_c, double *pos_d,
01495 double *force_a, double *force_b, double *force_c, double *force_d);
01497 static double VectorTorsionDerivative(vector3 &a, vector3 &b, vector3 &c, vector3 &d);
01498
01504 static void VectorSubtract(double *i, double *j, double *result)
01505 {
01506 for (unsigned int c = 0; c < 3; ++c)
01507 result[c] = i[c] - j[c];
01508 }
01509
01510 static void VectorSubtract(const double* const i, const double* const j, double *result)
01511 {
01512 for (unsigned int c = 0; c < 3; ++c)
01513 result[c] = i[c] - j[c];
01514 }
01515
01521 static void VectorAdd(double *i, double *j, double *result)
01522 {
01523 for (unsigned int c = 0; c < 3; ++c)
01524 result[c] = i[c] + j[c];
01525 }
01526
01532 static void VectorDivide(double *i, double n, double *result)
01533 {
01534 for (unsigned int c = 0; c < 3; ++c)
01535 result[c] = i[c] / n;
01536 }
01537
01543 static void VectorMultiply(double *i, double n, double *result)
01544 {
01545 for (unsigned int c = 0; c < 3; ++c)
01546 result[c] = i[c] * n;
01547 }
01548
01549 static void VectorMultiply(const double* const i, const double n, double *result)
01550 {
01551 for (unsigned int c = 0; c < 3; ++c)
01552 result[c] = i[c] * n;
01553 }
01554
01559 static void VectorSelfMultiply(double *i, double n)
01560 {
01561 for (unsigned int c = 0; c < 3; ++c)
01562 i[c] *= n;
01563 }
01564
01568 static void VectorNormalize(double *i)
01569 {
01570 double length = VectorLength(i);
01571 for (unsigned int c = 0; c < 3; ++c)
01572 i[c] /= length;
01573 }
01574
01579 static void VectorCopy(double *from, double *to)
01580 {
01581 for (unsigned int c = 0; c < 3; ++c)
01582 to[c] = from[c];
01583 }
01584
01589 static double VectorLength(double *i)
01590 {
01591 return sqrt( i[0]*i[0] + i[1]*i[1] + i[2]*i[2] );
01592 }
01593
01594 static double VectorDistance(double *pos_i, double *pos_j)
01595 {
01596 double ij[3];
01597 VectorSubtract(pos_i, pos_j, ij);
01598 const double rij = VectorLength(ij);
01599 return rij;
01600 }
01601
01608 static double VectorAngle(double *i, double *j, double *k);
01609
01617 static double VectorTorsion(double *i, double *j, double *k, double *l);
01618
01626 static double VectorOOP(double *i, double *j, double *k, double *l);
01627
01631 static void VectorClear(double *i)
01632 {
01633 for (unsigned int c = 0; c < 3; ++c)
01634 i[c] = 0.0;
01635 }
01636
01642 static double VectorDot(double *i, double *j)
01643 {
01644 double result = 0.0;
01645
01646
01647 for (unsigned int c = 0; c < 3; ++c)
01648 result += i[c]*j[c];
01649 return result;
01650 }
01651
01657 static void VectorCross(double *i, double *j, double *result)
01658 {
01659 result[0] = i[1]*j[2] - i[2]*j[1];
01660 result[1] = - i[0]*j[2] + i[2]*j[0];
01661 result[2] = i[0]*j[1] - i[1]*j[0];
01662 }
01663
01664 static void PrintVector(double *i)
01665 {
01666 std::cout << "<" << i[0] << ", " << i[1] << ", " << i[2] << ">" << std::endl;
01667 }
01669
01670 };
01671
01672 }
01673
01674 #endif // OB_FORCEFIELD_H
01675