1 /********************************************************************** 2 forcefieldmmff94.h - MMFF94 3 4 Copyright (C) 2006 by Tim Vandermeersch <tim.vandermeersch@gmail.com> 5 6 This file is part of the Open Babel project. 7 For more information, see <http://openbabel.org/> 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation version 2 of the License. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 ***********************************************************************/ 18 19 #include <vector> 20 #include <string> 21 #include <map> 22 23 #include <openbabel/parsmart.h> 24 #include <openbabel/forcefield.h> 25 #include <openbabel/base.h> 26 #include <openbabel/mol.h> 27 28 namespace OpenBabel 29 { 30 class OBFFBondCalculationMMFF94 : public OBFFCalculation2 31 { 32 public: 33 int bt; // bondtype (BTIJ) 34 double kb, r0, rab, delta; 35 36 template<bool> void Compute(); 37 }; 38 39 class OBFFAngleCalculationMMFF94 : public OBFFCalculation3 40 { 41 public: 42 int at; //angletype (ATIJK) 43 bool linear; 44 double ka, theta, theta0, delta; 45 46 template<bool> void Compute(); 47 }; 48 49 class OBFFStrBndCalculationMMFF94 : public OBFFCalculation3 50 { 51 public: 52 int sbt; //strbndtype (SBTIJK) 53 double kbaABC, kbaCBA, theta0, rab0, rbc0, delta_theta, delta_rab, delta_rbc; 54 double theta, rab, rbc; 55 double force_ab_a[3], force_ab_b[3], force_bc_b[3], force_bc_c[3]; 56 double force_abc_a[3], force_abc_b[3], force_abc_c[3]; 57 58 template<bool> void Compute(); 59 }; 60 61 class OBFFTorsionCalculationMMFF94 : public OBFFCalculation4 62 { 63 public: 64 int tt; //torsiontype (TTIJKL) 65 double v1, v2, v3, tor, cosine; 66 67 template<bool> void Compute(); 68 }; 69 70 class OBFFOOPCalculationMMFF94 : public OBFFCalculation4 71 { 72 public: 73 double koop, angle; 74 75 template<bool> void Compute(); 76 }; 77 78 class OBFFVDWCalculationMMFF94 : public OBFFCalculation2 79 { 80 public: 81 int aDA, bDA; // hydrogen donor/acceptor (A=1, D=2, neither=0) 82 double rab, epsilon, alpha_a, alpha_b, Na, Nb, Aa, Ab, Ga, Gb; 83 double R_AB, R_AB7/*, erep, erep7, eattr*/; 84 int pairIndex; // index into iteration using FOR_PAIRS_OF_MOL(..., _mol) 85 86 template<bool> void Compute(); 87 }; 88 89 class OBFFElectrostaticCalculationMMFF94 : public OBFFCalculation2 90 { 91 public: 92 double qq, rab; 93 int pairIndex; // index into iteration using FOR_PAIRS_OF_MOL(..., _mol) 94 95 template<bool> void Compute(); 96 }; 97 98 // Class OBForceFieldMMFF94 99 // class introduction in forcefieldmmff94.cpp 100 class OBForceFieldMMFF94: public OBForceField 101 { 102 protected: 103 //! \return Parses the parameter file 104 bool ParseParamFile(); 105 bool ParseParamProp(std::string &filename); 106 bool ParseParamDef(std::string &filename); 107 bool ParseParamBond(std::string &filename); 108 bool ParseParamBndk(std::string &filename); 109 bool ParseParamAngle(std::string &filename); 110 bool ParseParamStrBnd(std::string &filename); 111 bool ParseParamDfsb(std::string &filename); 112 bool ParseParamOOP(std::string &filename); 113 bool ParseParamTorsion(std::string &filename); 114 bool ParseParamVDW(std::string &filename); 115 bool ParseParamCharge(std::string &filename); 116 bool ParseParamPbci(std::string &filename); 117 //! detect which rings are aromatic 118 bool PerceiveAromatic(); 119 //! \return Get the MMFF94 atom type for atom 120 int GetType(OBAtom *atom); 121 //! \return Sets atomtypes to MMFF94 in _mol 122 bool SetTypes(); 123 //! fill OBFFXXXCalculation vectors 124 bool SetupCalculations(); 125 //! Setup pointers in OBFFXXXCalculation vectors 126 bool SetupPointers(); 127 //! Sets formal charges 128 bool SetFormalCharges(); 129 //! Sets partial charges 130 bool SetPartialCharges(); 131 //! \return The row of the element atom in the periodic table 132 int GetElementRow(OBAtom *atom); 133 //! \return The bond type (BTIJ) 134 int GetBondType(OBAtom* a, OBAtom* b); 135 //! \return The angle type (ATIJK) 136 int GetAngleType(OBAtom* a, OBAtom* b, OBAtom *c); 137 //! \return The stretch-bend type (SBTIJK) 138 int GetStrBndType(OBAtom* a, OBAtom* b, OBAtom *c); 139 //! \return The torsion type (TTIJKL) 140 int GetTorsionType(OBAtom* a, OBAtom* b, OBAtom *c, OBAtom *d); 141 //! \return true if atomtype has sbmb set in mmffprop.par 142 bool HasSbmbSet(int atomtype); 143 //! \return true if atomtype has pilp set in mmffprop.par 144 bool HasPilpSet(int atomtype); 145 //! \return true if atomtype has arom set in mmffprop.par 146 bool HasAromSet(int atomtype); 147 //! \return true if atomtype has lin set in mmffprop.par 148 bool HasLinSet(int atomtype); 149 //! \return the crd value for the atomtype in mmffprop.par 150 int GetCrd(int atomtype); 151 //! \return the val value for the atomtype in mmffprop.par 152 int GetVal(int atomtype); 153 //! \return the mltb value for the atomtype in mmffprop.par 154 int GetMltb(int atomtype); 155 //! \return the level 2 equivalent atom type for type (mmffdef.par) 156 int EqLvl2(int type); 157 //! \return the level 3 equivalent atom type for type (mmffdef.par) 158 int EqLvl3(int type); 159 //! \return the level 4 equivalent atom type for type (mmffdef.par) 160 int EqLvl4(int type); 161 //! \return the level 5 equivalent atom type for type (mmffdef.par) 162 int EqLvl5(int type); 163 //! \return the canonical bond index 164 unsigned int GetCXB(int type, int a, int b); 165 //! \return the canonical angle index 166 unsigned int GetCXA(int type, int a, int b, int c); 167 //! \return the canonical stretch-bend index 168 unsigned int GetCXS(int type, int a, int b, int c); 169 //! \return the canonical out-of-plane index 170 unsigned int GetCXO(int a, int b, int c, int d); 171 //! \return the canonical torsion index 172 unsigned int GetCXT(int type, int a, int b, int c, int d); 173 //! \return the canonical bond-charge-increment index 174 unsigned int GetCXQ(int type, int a, int b); 175 //! \return the U value for the atom from table X page 631 176 double GetUParam(OBAtom* atom); 177 //! \return the Z value for the atom from table VI page 628 178 double GetZParam(OBAtom* atom); 179 //! \return the C value for the atom from table VI page 628 180 double GetCParam(OBAtom* atom); 181 //! \return the V value for the atom from table X page 631 182 double GetVParam(OBAtom* atom); 183 //! return the covalent radius from Blom and Haaland, value from etab if not available 184 double GetCovalentRadius(OBAtom* a); 185 //! return the bond length calculated with a modified version of the Schomaker-Stevenson rule 186 double GetRuleBondLength(OBAtom* a, OBAtom* b); 187 //! return the bond length from mmffbond.par, if not found, one is calculated with a modified version of the Schomaker-Stevenson rule 188 double GetBondLength(OBAtom* a, OBAtom* b); 189 190 //! Same as OBForceField::GetParameter, but takes (bond/angle/torsion) type in account and takes 0 as wildcart. 191 OBFFParameter* GetParameter1Atom(int a, std::vector<OBFFParameter> ¶meter); 192 OBFFParameter* GetParameter2Atom(int a, int b, std::vector<OBFFParameter> ¶meter); 193 OBFFParameter* GetParameter3Atom(int a, int b, int c, std::vector<OBFFParameter> ¶meter); 194 195 //! Same as OBForceField::GetParameter, but takes (bond/angle/torsion) type in account and takes 0 as wildcart. 196 OBFFParameter* GetTypedParameter2Atom(int ffclass, int a, int b, std::vector<OBFFParameter> ¶meter); 197 OBFFParameter* GetTypedParameter3Atom(int ffclass, int a, int b, int c, std::vector<OBFFParameter> ¶meter); 198 OBFFParameter* GetTypedParameter4Atom(int ffclass, int a, int b, int c, int d, std::vector<OBFFParameter> ¶meter); 199 200 201 // OBFFParameter vectors to contain the parameters 202 std::vector<OBFFParameter> _ffbondparams; 203 std::vector<OBFFParameter> _ffbndkparams; 204 std::vector<OBFFParameter> _ffangleparams; 205 std::vector<OBFFParameter> _ffstrbndparams; 206 std::vector<OBFFParameter> _ffdfsbparams; 207 std::vector<OBFFParameter> _fftorsionparams; 208 std::vector<OBFFParameter> _ffoopparams; 209 std::vector<OBFFParameter> _ffvdwparams; 210 std::vector<OBFFParameter> _ffchgparams; 211 std::vector<OBFFParameter> _ffpbciparams; 212 std::vector<OBFFParameter> _ffdefparams; 213 std::vector<OBFFParameter> _ffpropparams; 214 OBBitVec _ffpropPilp; 215 OBBitVec _ffpropArom; 216 OBBitVec _ffpropLin; 217 OBBitVec _ffpropSbmb; 218 219 // OBFFXXXCalculationYYY vectors to contain the calculations 220 std::vector<OBFFBondCalculationMMFF94> _bondcalculations; 221 std::vector<OBFFAngleCalculationMMFF94> _anglecalculations; 222 std::vector<OBFFStrBndCalculationMMFF94> _strbndcalculations; 223 std::vector<OBFFTorsionCalculationMMFF94> _torsioncalculations; 224 std::vector<OBFFOOPCalculationMMFF94> _oopcalculations; 225 std::vector<OBFFVDWCalculationMMFF94> _vdwcalculations; 226 std::vector<OBFFElectrostaticCalculationMMFF94> _electrostaticcalculations; 227 228 bool mmff94s; 229 230 public: 231 //! Constructor OBForceField(ID,IsDefault)232 explicit OBForceFieldMMFF94(const char* ID, bool IsDefault=true) : OBForceField(ID, IsDefault) 233 { 234 _validSetup = false; 235 _init = false; 236 _rvdw = 7.0; 237 _rele = 15.0; 238 _epsilon = 1.0; // default electrostatics 239 _pairfreq = 15; 240 _cutoff = false; 241 _linesearch = LineSearchType::Newton2Num; 242 _gradientPtr = nullptr; 243 _grad1 = nullptr; 244 if (!strncmp(ID, "MMFF94s", 7)) { 245 mmff94s = true; 246 _parFile = std::string("mmff94s.ff"); 247 } else { 248 mmff94s = false; 249 _parFile = std::string("mmff94.ff"); 250 } 251 } 252 253 //! Destructor 254 virtual ~OBForceFieldMMFF94(); 255 256 //! Assignment 257 OBForceFieldMMFF94 &operator = (OBForceFieldMMFF94 &); 258 259 //!Clone the current instance. May be desirable in multithreaded environments MakeNewInstance()260 virtual OBForceFieldMMFF94* MakeNewInstance() 261 { 262 return new OBForceFieldMMFF94(_id, false); 263 } 264 265 //! Get the description for this force field Description()266 const char* Description() 267 { 268 if (mmff94s) 269 return "MMFF94s force field."; 270 else 271 return "MMFF94 force field."; 272 } 273 274 //! Get the unit in which the energy is expressed GetUnit()275 std::string GetUnit() 276 { 277 return std::string("kcal/mol"); 278 } 279 280 //! \return that analytical gradients are implemented for MMFF94 HasAnalyticalGradients()281 bool HasAnalyticalGradients() { return true; } 282 283 //! Returns total energy 284 double Energy(bool gradients = true); 285 //! Returns the bond stretching energy 286 template<bool> double E_Bond(); 287 double E_Bond(bool gradients = true) 288 { 289 return gradients ? E_Bond<true>() : E_Bond<false>(); 290 } 291 //! Returns the angle bending energy 292 template<bool> double E_Angle(); 293 double E_Angle(bool gradients = true) 294 { 295 return gradients ? E_Angle<true>() : E_Angle<false>(); 296 } 297 //! Returns the stretch-bend energy 298 template<bool> double E_StrBnd(); 299 double E_StrBnd(bool gradients = true) 300 { 301 return gradients ? E_StrBnd<true>() : E_StrBnd<false>(); 302 } 303 //! Returns the torsional energy 304 template<bool> double E_Torsion(); 305 double E_Torsion(bool gradients = true) 306 { 307 return gradients ? E_Torsion<true>() : E_Torsion<false>(); 308 } 309 //! Returns the out-of-plane bending energy 310 template<bool> double E_OOP(); 311 double E_OOP(bool gradients = true) 312 { 313 return gradients ? E_OOP<true>() : E_OOP<false>(); 314 } 315 //! Returns the Van der Waals energy (Buckingham potential) 316 template<bool> double E_VDW(); 317 double E_VDW(bool gradients = true) 318 { 319 return gradients ? E_VDW<true>() : E_VDW<false>(); 320 } 321 //! Returns the dipole-dipole interaction energy 322 template<bool> double E_Electrostatic(); 323 double E_Electrostatic(bool gradients = true) 324 { 325 return gradients ? E_Electrostatic<true>() : E_Electrostatic<false>(); 326 } 327 328 //! Validate MMFF94 using validation suite 329 bool Validate(); 330 //! Compare and print the numerical and analytical gradients 331 bool ValidateGradients(); 332 333 }; // class OBForceFieldMM2 334 335 }// namespace OpenBabel 336 337 //! \file forcefieldmmff94.h 338 //! \brief MMFF94 force field 339