Coverage Report

Created: 2026-04-09 06:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openbabel/src/forcefields/forcefieldmmff94.h
Line
Count
Source
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() override;
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() override;
123
      //! fill OBFFXXXCalculation vectors
124
      bool SetupCalculations() override;
125
      //! Setup pointers in OBFFXXXCalculation vectors
126
      bool SetupPointers() override;
127
      //!  Sets formal charges
128
      bool SetFormalCharges() override;
129
      //!  Sets partial charges
130
      bool SetPartialCharges() override;
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
232
12
      explicit OBForceFieldMMFF94(const char* ID, bool IsDefault=true) : OBForceField(ID, IsDefault)
233
12
      {
234
12
        _validSetup = false;
235
12
        _init = false;
236
12
        _rvdw = 7.0;
237
12
        _rele = 15.0;
238
12
        _epsilon = 1.0; // default electrostatics
239
12
        _pairfreq = 15;
240
12
        _cutoff = false;
241
12
        _linesearch = LineSearchType::Newton2Num;
242
12
        _gradientPtr = nullptr;
243
12
        _grad1 = nullptr;
244
12
  if (!strncmp(ID, "MMFF94s", 7)) {
245
6
          mmff94s = true;
246
6
          _parFile = std::string("mmff94s.ff");
247
6
  } else {
248
6
          mmff94s = false;
249
6
          _parFile = std::string("mmff94.ff");
250
6
  }
251
12
      }
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
260
      OBForceFieldMMFF94* MakeNewInstance() override
261
0
      {
262
0
        return new OBForceFieldMMFF94(_id, false);
263
0
      }
264
265
      //! Get the description for this force field
266
      const char* Description() override
267
0
      {
268
0
        if (mmff94s)
269
0
          return "MMFF94s force field.";
270
0
  else
271
0
          return "MMFF94 force field.";
272
0
      }
273
274
      //! Get the unit in which the energy is expressed
275
      std::string GetUnit() override
276
0
      {
277
0
        return std::string("kcal/mol");
278
0
      }
279
280
      //! \return that analytical gradients are implemented for MMFF94
281
0
      bool HasAnalyticalGradients() override { return true; }
282
283
      //! Returns total energy
284
      double Energy(bool gradients = true) override;
285
      //! Returns the bond stretching energy
286
      template<bool> double E_Bond();
287
      double E_Bond(bool gradients = true) override
288
0
      {
289
0
        return gradients ? E_Bond<true>() : E_Bond<false>();
290
0
      }
291
      //! Returns the angle bending energy
292
      template<bool> double E_Angle();
293
      double E_Angle(bool gradients = true) override
294
0
      {
295
0
        return gradients ? E_Angle<true>() : E_Angle<false>();
296
0
      }
297
      //! Returns the stretch-bend energy
298
      template<bool> double E_StrBnd();
299
      double E_StrBnd(bool gradients = true) override
300
0
      {
301
0
        return gradients ? E_StrBnd<true>() : E_StrBnd<false>();
302
0
      }
303
      //! Returns the torsional energy
304
      template<bool> double E_Torsion();
305
      double E_Torsion(bool gradients = true) override
306
0
      {
307
0
        return gradients ? E_Torsion<true>() : E_Torsion<false>();
308
0
      }
309
      //! Returns the out-of-plane bending energy
310
      template<bool> double E_OOP();
311
      double E_OOP(bool gradients = true) override
312
0
      {
313
0
        return gradients ? E_OOP<true>() : E_OOP<false>();
314
0
      }
315
      //! Returns the Van der Waals energy (Buckingham potential)
316
      template<bool> double E_VDW();
317
      double E_VDW(bool gradients = true) override
318
0
      {
319
0
        return gradients ? E_VDW<true>() : E_VDW<false>();
320
0
      }
321
      //! Returns the dipole-dipole interaction energy
322
      template<bool> double E_Electrostatic();
323
      double E_Electrostatic(bool gradients = true) override
324
0
      {
325
0
        return gradients ? E_Electrostatic<true>() : E_Electrostatic<false>();
326
0
      }
327
328
      //! Validate MMFF94 using validation suite
329
      bool Validate() override;
330
      //! Compare and print the numerical and analytical gradients
331
      bool ValidateGradients() override;
332
333
  }; // class OBForceFieldMM2
334
335
}// namespace OpenBabel
336
337
//! \file forcefieldmmff94.h
338
//! \brief MMFF94 force field