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> &parameter);
192       OBFFParameter* GetParameter2Atom(int a, int b, std::vector<OBFFParameter> &parameter);
193       OBFFParameter* GetParameter3Atom(int a, int b, int c, std::vector<OBFFParameter> &parameter);
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> &parameter);
197       OBFFParameter* GetTypedParameter3Atom(int ffclass, int a, int b, int c, std::vector<OBFFParameter> &parameter);
198       OBFFParameter* GetTypedParameter4Atom(int ffclass, int a, int b, int c, int d, std::vector<OBFFParameter> &parameter);
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