Coverage Report

Created: 2025-08-29 06:47

/src/openbabel/include/openbabel/forcefield.h
Line
Count
Source (jump to first uncovered line)
1
/**********************************************************************
2
forcefield.h - Handle OBForceField class.
3
4
Copyright (C) 2006-2007 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
#ifndef OB_FORCEFIELD_H
20
#define OB_FORCEFIELD_H
21
22
#include <vector>
23
#include <string>
24
25
#include <openbabel/babelconfig.h>
26
#include <openbabel/mol.h>  // TODO: Move OBMol code out of the header (use OBMol*)
27
#include <openbabel/atom.h> // TODO: Move OBAtom code out of the header
28
#include <openbabel/plugin.h>
29
#include <openbabel/bitvec.h>
30
#include <float.h>
31
32
namespace OpenBabel
33
{
34
  class OBGridData;
35
36
  // log levels
37
0
#define OBFF_LOGLVL_NONE  0   //!< no output
38
0
#define OBFF_LOGLVL_LOW   1   //!< SteepestDescent progress... (no output from Energy())
39
0
#define OBFF_LOGLVL_MEDIUM  2   //!< individual energy terms
40
0
#define OBFF_LOGLVL_HIGH  3   //!< individual calculations and parameters
41
42
  // terms
43
0
#define OBFF_ENERGY   (1 << 0)   //!< all terms
44
0
#define OBFF_EBOND    (1 << 1)   //!< bond term
45
0
#define OBFF_EANGLE   (1 << 2)   //!< angle term
46
0
#define OBFF_ESTRBND    (1 << 3)   //!< strbnd term
47
0
#define OBFF_ETORSION   (1 << 4)   //!< torsion term
48
0
#define OBFF_EOOP   (1 << 5)   //!< oop term
49
0
#define OBFF_EVDW   (1 << 6)   //!< vdw term
50
0
#define OBFF_EELECTROSTATIC (1 << 7)   //!< electrostatic term
51
52
  // constraint types
53
0
#define OBFF_CONST_IGNORE (1 << 0)   //!< ignore the atom while setting up calculations
54
0
#define OBFF_CONST_ATOM   (1 << 1)   //!< fix the atom position
55
0
#define OBFF_CONST_ATOM_X (1 << 2)   //!< fix the x coordinate of the atom position
56
0
#define OBFF_CONST_ATOM_Y (1 << 3)   //!< fix the y coordinate of the atom position
57
0
#define OBFF_CONST_ATOM_Z (1 << 4)   //!< fix the z coordinate of the atom position
58
0
#define OBFF_CONST_DISTANCE (1 << 5)   //!< constrain distance length
59
0
#define OBFF_CONST_ANGLE  (1 << 6)   //!< constrain angle
60
0
#define OBFF_CONST_TORSION  (1 << 7)   //!< constrain torsion
61
#define OBFF_CONST_CHIRAL (1 << 8)   //!< constrain chiral volume
62
63
  // mode arguments for SteepestDescent, ConjugateGradients, ...
64
#define OBFF_NUMERICAL_GRADIENT   (1 << 0)  //!< use numerical gradients
65
#define OBFF_ANALYTICAL_GRADIENT  (1 << 1)  //!< use analytical gradients
66
67
const double KCAL_TO_KJ = 4.1868;
68
const double GAS_CONSTANT = 8.31446261815324e-3 / KCAL_TO_KJ;  //!< kcal mol^-1 K^-1 (2018 CODATA recommended value)
69
70
  // inline if statements for logging.
71
0
#define IF_OBFF_LOGLVL_LOW    if(_loglvl >= OBFF_LOGLVL_LOW)
72
0
#define IF_OBFF_LOGLVL_MEDIUM if(_loglvl >= OBFF_LOGLVL_MEDIUM)
73
0
#define IF_OBFF_LOGLVL_HIGH   if(_loglvl >= OBFF_LOGLVL_HIGH)
74
75
  //! The type of line search to be used for optimization -- simple or Newton numeric
76
  struct LineSearchType
77
  {
78
    enum {
79
      Simple, Newton2Num
80
    };
81
  };
82
  /*
83
  struct ConstraintType
84
  {
85
    enum {
86
      Ignore, Atom, AtomX, AtomY, AtomZ, Distance, Angle, Torsion, Chiral
87
    };
88
  };
89
  */
90
91
  //! \class OBFFParameter forcefield.h <openbabel/forcefield.h>
92
  //! \brief Internal class for OBForceField to hold forcefield parameters
93
  class OBFPRT OBFFParameter {
94
  public:
95
    //! Used to store integer atom types
96
    int         a, b, c, d;
97
    //! used to store string atom types
98
    std::string _a, _b, _c, _d;
99
100
    //! Used to store integer type parameters (bondtypes, multiplicity, ...)
101
    std::vector<int>    _ipar;
102
    //! Used to store double type parameters (force constants, bond lengths, angles, ...)
103
    std::vector<double> _dpar;
104
105
    //! Assignment
106
    OBFFParameter& operator=(const OBFFParameter &ai)
107
0
      {
108
0
        if (this != &ai) {
109
0
          a = ai.a;
110
0
          b = ai.b;
111
0
          c = ai.c;
112
0
          d = ai.d;
113
0
          _a = ai._a;
114
0
          _b = ai._b;
115
0
          _c = ai._c;
116
0
          _d = ai._d;
117
0
          _ipar = ai._ipar;
118
0
          _dpar = ai._dpar;
119
0
        }
120
121
0
        return *this;
122
0
      }
123
124
    //! Reset the atom types and set all parameters to zero
125
    void clear ()
126
0
    {
127
0
      a = b = c = d = 0;
128
0
      _ipar.clear();
129
0
      _dpar.clear();
130
0
    }
131
  }; // class OBFFParameter
132
133
  // specific class introductions in forcefieldYYYY.cpp (for YYYY calculations)
134
135
  //! \class OBFFCalculation2 forcefield.h <openbabel/forcefield.h>
136
  //! \brief Internal class for OBForceField to hold energy and gradient calculations on specific force fields
137
  class OBFPRT OBFFCalculation2
138
  {
139
  public:
140
    //! Used to store the energy for this OBFFCalculation
141
    double energy;
142
    //! Used to store the atoms for this OBFFCalculation
143
    OBAtom *a, *b;
144
    //! Used to store the index of atoms for this OBFFCalculation
145
    int idx_a, idx_b;
146
    //! Pointer to atom coordinates as double[3]
147
    double *pos_a, *pos_b;
148
    //! Pointer to atom forces
149
    double force_a[3], force_b[3];
150
    //! Destructor
151
    virtual ~OBFFCalculation2()
152
0
    {
153
0
    }
154
    //! \return Setup pointers to atom positions and forces (To be called
155
    //!  while setting up calculations). Sets optimized to true.
156
    virtual void SetupPointers()
157
0
    {
158
0
      if (!a || !b) return;
159
0
      pos_a = a->GetCoordinate();
160
0
      idx_a = a->GetIdx();
161
0
      pos_b = b->GetCoordinate();
162
0
      idx_b = b->GetIdx();
163
0
    }
164
  };
165
166
  //! \class OBFFCalculation3 forcefield.h <openbabel/forcefield.h>
167
  //! \brief Internal class for OBForceField to hold energy and gradient calculations on specific force fields
168
  class OBFPRT OBFFCalculation3: public OBFFCalculation2
169
  {
170
  public:
171
    //! Used to store the atoms for this OBFFCalculation
172
    OBAtom *c;
173
    //! Used to store the index of atoms for this OBFFCalculation
174
    int idx_c;
175
    //! Pointer to atom coordinates as double[3]
176
    double *pos_c;
177
    //! Pointer to atom forces
178
    double force_c[3];
179
    //! Destructor
180
    virtual ~OBFFCalculation3()
181
0
    {
182
0
    }
183
    //! \return Setup pointers to atom positions and forces (To be called
184
    //!  while setting up calculations). Sets optimized to true.
185
    void SetupPointers() override
186
0
    {
187
0
      if (!a || !b || !c) return;
188
0
      pos_a = a->GetCoordinate();
189
0
      idx_a = a->GetIdx();
190
0
      pos_b = b->GetCoordinate();
191
0
      idx_b = b->GetIdx();
192
0
      pos_c = c->GetCoordinate();
193
0
      idx_c = c->GetIdx();
194
0
    }
195
  };
196
197
  //! \class OBFFCalculation4 forcefield.h <openbabel/forcefield.h>
198
  //! \brief Internal class for OBForceField to hold energy and gradient calculations on specific force fields
199
  class OBFPRT OBFFCalculation4: public OBFFCalculation3
200
  {
201
  public:
202
    //! Used to store the atoms for this OBFFCalculation
203
    OBAtom *d;
204
    //! Used to store the index of atoms for this OBFFCalculation
205
    int idx_d;
206
    //! Pointer to atom coordinates as double[3]
207
    double *pos_d;
208
    //! Pointer to atom forces
209
    double force_d[3];
210
    //! Destructor
211
    virtual ~OBFFCalculation4()
212
0
    {
213
0
    }
214
    //! \return Setup pointers to atom positions and forces (To be called
215
    //!  while setting up calculations). Sets optimized to true.
216
    void SetupPointers()
217
0
    {
218
0
      if (!a || !b || !c || !d) return;
219
0
      pos_a = a->GetCoordinate();
220
0
      idx_a = a->GetIdx();
221
0
      pos_b = b->GetCoordinate();
222
0
      idx_b = b->GetIdx();
223
0
      pos_c = c->GetCoordinate();
224
0
      idx_c = c->GetIdx();
225
0
      pos_d = d->GetCoordinate();
226
0
      idx_d = d->GetIdx();
227
0
    }
228
  };
229
230
  //! \class OBFFConstraint forcefield.h <openbabel/forcefield.h>
231
  //! \brief Internal class for OBForceField to hold constraints
232
  //! \since version 2.2
233
  class OBFPRT OBFFConstraint
234
  {
235
  public:
236
    //! Used to store the contraint energy for this OBFFConstraint
237
    double factor, constraint_value;
238
    double rab0, rbc0;
239
    //! Used to store the contraint type for this OBFFConstraint
240
    int type, ia, ib, ic, id;
241
    //! Used to store the atoms for this OBFFCostraint
242
    OBAtom *a, *b, *c, *d;
243
    //! Used to store the gradients for this OBFFCalculation
244
    vector3 grada, gradb, gradc, gradd;
245
246
    //! Constructor
247
    OBFFConstraint()
248
0
      {
249
0
        a = b = c = d = nullptr;
250
0
        ia = ib = ic = id = 0;
251
0
        constraint_value = 0.0;
252
0
        factor = 0.0;
253
0
      }
254
    //! Destructor
255
    ~OBFFConstraint()
256
0
      {
257
0
      }
258
259
    vector3 GetGradient(int a)
260
0
    {
261
0
      if (a == ia)
262
0
        return grada;
263
0
      else if (a == ib)
264
0
        return gradb;
265
0
      else if (a == ic)
266
0
        return gradc;
267
0
      else if (a == id)
268
0
        return gradd;
269
0
      else
270
0
        return  VZero;
271
0
    }
272
  };
273
274
  //! \class OBFFConstraints forcefield.h <openbabel/forcefield.h>
275
  //! \brief Internal class for OBForceField to handle constraints
276
  //! \since version 2.2
277
  class OBFPRT OBFFConstraints
278
  {
279
  public:
280
    //! Constructor
281
    OBFFConstraints();
282
    //! Destructor
283
    ~OBFFConstraints()
284
0
      {
285
0
        _constraints.clear();
286
0
        _ignored.Clear();
287
0
        _fixed.Clear();
288
0
        _Xfixed.Clear();
289
0
        _Yfixed.Clear();
290
0
        _Zfixed.Clear();
291
0
      }
292
    //! Clear all constraints
293
    void Clear();
294
    //! Get the constraint energy
295
    double GetConstraintEnergy();
296
    //! Get the constraint gradient for atom with index a
297
    vector3 GetGradient(int a);
298
    //! Get the constrain gradient for the atom
299
    OBFFConstraints& operator=(const OBFFConstraints &ai)
300
0
      {
301
0
        if (this != &ai) {
302
0
          _constraints = ai._constraints;
303
0
          _ignored = ai._ignored;
304
0
          _fixed = ai._fixed;
305
0
          _Xfixed = ai._Xfixed;
306
0
          _Yfixed = ai._Yfixed;
307
0
          _Zfixed = ai._Zfixed;
308
0
        }
309
0
        return *this;
310
0
      }
311
312
    /*! Translate indices to OBAtom* objects, this function is called from OBForceField::Setup,
313
     *  this function doesn't have to be called from anywhere else.
314
     */
315
    void Setup(OBMol &mol);
316
317
    /////////////////////////////////////////////////////////////////////////
318
    // Set Constraints                                                     //
319
    /////////////////////////////////////////////////////////////////////////
320
    //! \name Methods to set constraints
321
    //@{
322
    //! Set Constraint factor
323
    void SetFactor(double factor);
324
    //! Ignore the atom while setting up calculations
325
    void AddIgnore(int a);
326
    //! Fix the position of an atom
327
    void AddAtomConstraint(int a);
328
    //! Fix the x coordinate of the atom position
329
    void AddAtomXConstraint(int a);
330
    //! Fix the y coordinate of the atom position
331
    void AddAtomYConstraint(int a);
332
    //! Fix the z coordinate of the atom position
333
    void AddAtomZConstraint(int a);
334
    //! Constrain the bond length a-b
335
    void AddDistanceConstraint(int a, int b, double length);
336
    //! Constrain the angle a-b-c
337
    void AddAngleConstraint(int a, int b, int c, double angle);
338
    //! Constrain the torsion angle a-b-c-d
339
    void AddTorsionConstraint(int a, int b, int c, int d, double torsion);
340
    //! Delete a constraint
341
    //! \par index constraint index
342
    void DeleteConstraint(int index);
343
    //@}
344
    /////////////////////////////////////////////////////////////////////////
345
    // Get Constraints                                                     //
346
    /////////////////////////////////////////////////////////////////////////
347
    //! \name Methods to get information about set constraints
348
    //@{
349
    //! Get Constraint factor
350
    double GetFactor();
351
    //! \returns the number of set constraints
352
    int Size() const;
353
    /*! The following constraint types are known: OBFF_CONST_IGNORE (ignore
354
     *  the atom while setting up calculations, forcefield implementations
355
     *  need to check this value in their setup function), OBFF_CONST_ATOM
356
     *  (fix atom position), OBFF_CONST_ATOM_X (fix x coordinate),
357
     *  OBFF_CONST_ATOM_Y (fix y coordinate), OBFF_CONST_ATOM_Z (fix z
358
     *  coordinate), OBFF_CONST_BOND (constrain bond length), OBFF_CONST_ANGLE
359
     *  (constrain angle), OBFF_CONST_TORSION (constrain torsion angle)
360
     *  \return the constraint type
361
     */
362
    int GetConstraintType(int index) const;
363
    /*! \return The constraint value, this can be a bond length, angle or
364
     *   torsion angle depending on the constraint type.
365
     */
366
    double GetConstraintValue(int index) const;
367
    //! \return The constraint atom a (or fixed atom)
368
    //! \par index constraint index
369
    int GetConstraintAtomA(int index) const;
370
    //! \return The constraint atom b
371
    //! \par index constraint index
372
    int GetConstraintAtomB(int index) const;
373
    //! \return The constraint atom c
374
    //! \par index constraint index
375
    int GetConstraintAtomC(int index) const;
376
    //! \return The constraint atom d
377
    //! \par index constraint index
378
    int GetConstraintAtomD(int index) const;
379
    //! \return true if this atom is ignored
380
    //! \par a atom index
381
    bool IsIgnored(int a);
382
    //! \return true if this atom is fixed
383
    //! \par a atom index
384
    bool IsFixed(int a);
385
    //! \return true if the x coordinate for this atom is fixed
386
    //! \par a atom index
387
    bool IsXFixed(int a);
388
    //! \return true if the y coordinate for this atom is fixed
389
    //! \par a atom index
390
    bool IsYFixed(int a);
391
    //! \return true if the z coordinate for this atom is fixed
392
    //! \par a atom index
393
    bool IsZFixed(int a);
394
    //! \return the ignored atom indexes as bitvec. (used in
395
    //! OBForceField::Setup() to determine if a call to
396
    //! OBForceField::SetupCalculations() is needed)
397
0
    OBBitVec GetIgnoredBitVec() { return _ignored; }
398
    //! \return the fixed atom indexes as bitvec. (used in
399
    //! OBForceField::SystematicRotorSearch() and similar)
400
0
    OBBitVec GetFixedBitVec() { return _fixed; }
401
    //@}
402
403
  private:
404
    std::vector<OBFFConstraint> _constraints;
405
    OBBitVec  _ignored;
406
    OBBitVec  _fixed;
407
    OBBitVec  _Xfixed;
408
    OBBitVec  _Yfixed;
409
    OBBitVec  _Zfixed;
410
    double _factor;
411
  };
412
413
  // Class OBForceField
414
  // class introduction in forcefield.cpp
415
  class OBFPRT OBForceField : public OBPlugin
416
  {
417
    MAKE_PLUGIN(OBForceField)
418
419
    protected:
420
421
      /*!
422
      Get the correct OBFFParameter from a OBFFParameter vector.
423
424
      \code vector<OBFFParameter> parameters; \endcode
425
426
      this vector is filled with entries (as OBFFParameter) from
427
      a parameter file. This happens in the Setup() function.
428
429
      \code GetParameter(a, 0, 0, 0, parameters); \endcode
430
431
      returns the first OBFFParameter from vector<OBFFParameter>
432
      parameters where: pa = a (pa = parameter.a)
433
434
      use: vdw parameters, ...
435
436
      \code GetParameter(a, b, 0, 0, parameters); \endcode
437
438
      returns the first OBFFParameter from vector<OBFFParameter>
439
      parameters where: pa = a & pb = b      (ab)
440
      or: pa = b & pb = a      (ba)
441
442
      use: bond parameters, vdw parameters (pairs), ...
443
444
      \code GetParameter(a, b, c, 0, parameters); \endcode
445
446
      returns the first OBFFParameter from vector<OBFFParameter>
447
      parameters where: pa = a & pb = b & pc = c     (abc)
448
      or: pa = c & pb = b & pc = a     (cba)
449
450
      use: angle parameters, ...
451
452
      \code GetParameter(a, b, c, d, parameters); \endcode
453
454
      returns the first OBFFParameter from vector<OBFFParameter>
455
      parameters where: pa = a & pb = b & pc = c & pd = d    (abcd)
456
      or: pa = d & pb = b & pc = c & pd = a    (dbca)
457
      or: pa = a & pb = c & pc = b & pd = d    (acbd)
458
      or: pa = d & pb = c & pc = b & pd = a    (dcba)
459
460
      use: torsion parameters, ...
461
    */
462
    OBFFParameter* GetParameter(int a, int b, int c, int d, std::vector<OBFFParameter> &parameter);
463
    //! see GetParameter(int a, int b, int c, int d, std::vector<OBFFParameter> &parameter)
464
    OBFFParameter* GetParameter(const char* a, const char* b, const char* c, const char* d,
465
        std::vector<OBFFParameter> &parameter);
466
    //! Get index for vector<OBFFParameter> ...
467
    int GetParameterIdx(int a, int b, int c, int d, std::vector<OBFFParameter> &parameter);
468
469
    /*! Calculate the potential energy function derivative numerically with
470
     *  repect to the coordinates of atom with index a (this vector is the gradient)
471
     *
472
     * \param a  provides coordinates
473
     * \param terms OBFF_ENERGY, OBFF_EBOND, OBFF_EANGLE, OBFF_ESTRBND, OBFF_ETORSION,
474
     * OBFF_EOOP, OBFF_EVDW, OBFF_ELECTROSTATIC
475
     * \return the negative gradient of atom a
476
     */
477
    vector3 NumericalDerivative(OBAtom *a, int terms = OBFF_ENERGY);
478
    //! OB 3.0
479
    vector3 NumericalSecondDerivative(OBAtom *a, int terms = OBFF_ENERGY);
480
481
    /*
482
     *   NEW gradients functions
483
     */
484
485
    /*! Set the gradient for atom with index idx to grad
486
     */
487
    void SetGradient(double *grad, int idx)
488
0
    {
489
0
      const int coordIdx = (idx - 1) * 3;
490
0
      for (unsigned int i = 0; i < 3; ++i) {
491
0
        _gradientPtr[coordIdx + i] = grad[i];
492
0
      }
493
0
    }
494
495
    /*! Add grad to the gradient for atom with index idx
496
     */
497
    void AddGradient(double *grad, int idx)
498
0
    {
499
0
      const int coordIdx = (idx - 1) * 3;
500
0
      for (unsigned int i = 0; i < 3; ++i) {
501
0
        _gradientPtr[coordIdx + i] += grad[i];
502
0
      }
503
0
    }
504
505
    /*! Set all gradients to zero
506
     */
507
    virtual void ClearGradients()
508
0
    {
509
      // We cannot use memset because IEEE floating point representations
510
      // are not guaranteed by C/C++ standard, but this loop can be
511
      // unrolled or vectorized by compilers
512
0
      for (unsigned int i = 0; i < _ncoords; ++i)
513
0
        _gradientPtr[i] = 0.0;
514
      //      memset(_gradientPtr, '\0', sizeof(double)*_ncoords);
515
0
    }
516
517
    /*! Check if two atoms are in the same ring. [NOTE: this function uses SSSR,
518
     *  this means that not all rings are found for bridged rings. This causes
519
     *  some problems with the MMFF94 validation.]
520
     *  \param a atom a
521
     *  \param b atom b
522
     *  \return true if atom a and b are in the same ring
523
     */
524
    bool IsInSameRing(OBAtom* a, OBAtom* b);
525
526
    // general variables
527
    OBMol   _mol; //!< Molecule to be evaluated or minimized
528
    bool  _init; //!< Used to make sure we only parse the parameter file once, when needed
529
    std::string _parFile; //!< parameter file name
530
    bool  _validSetup; //!< was the last call to Setup successful
531
    double  *_gradientPtr; //!< pointer to the gradients (used by AddGradient(), minimization functions, ...)
532
    // logging variables
533
    std::ostream* _logos; //!< Output for logfile
534
    char  _logbuf[BUFF_SIZE+1]; //!< Temporary buffer for logfile output
535
    int   _loglvl; //!< Log level for output
536
    int   _origLogLevel;
537
    // conformer genereation (rotor search) variables
538
    int   _current_conformer; //!< used to hold i for current conformer (needed by UpdateConformers)
539
    std::vector<double> _energies; //!< used to hold the energies for all conformers
540
    // minimization variables
541
    double  _econv, _gconv, _e_n1; //!< Used for conjugate gradients and steepest descent(Initialize and TakeNSteps)
542
    int   _cstep, _nsteps; //!< Used for conjugate gradients and steepest descent(Initialize and TakeNSteps)
543
    double  *_grad1; //!< Used for conjugate gradients and steepest descent(Initialize and TakeNSteps)
544
    unsigned int _ncoords; //!< Number of coordinates for conjugate gradients
545
    int         _linesearch; //!< LineSearch type
546
    // molecular dynamics variables
547
    double  _timestep; //!< Molecular dynamics time step in picoseconds
548
    double  _temp; //!< Molecular dynamics temperature in Kelvin
549
    double  *_velocityPtr; //!< pointer to the velocities
550
    // contraint varibles
551
    static OBFFConstraints _constraints; //!< Constraints
552
    static unsigned int _fixAtom; //!< SetFixAtom()/UnsetFixAtom()
553
    static unsigned int _ignoreAtom; //!< SetIgnoreAtom()/UnsetIgnoreAtom()
554
    // cut-off variables
555
    bool  _cutoff; //!< true = cut-off enabled
556
    double  _rvdw; //!< VDW cut-off distance
557
    double  _rele; //!< Electrostatic cut-off distance
558
    double _epsilon; //!< Dielectric constant for electrostatics
559
    OBBitVec  _vdwpairs; //!< VDW pairs that should be calculated
560
    OBBitVec  _elepairs; //!< Electrostatic pairs that should be calculated
561
    int   _pairfreq; //!< The frequence to update non-bonded pairs
562
    // group variables
563
    std::vector<OBBitVec> _intraGroup; //!< groups for which intra-molecular interactions should be calculated
564
    std::vector<OBBitVec> _interGroup; //!< groups for which intra-molecular interactions should be calculated
565
    std::vector<std::pair<OBBitVec, OBBitVec> > _interGroups; //!< groups for which intra-molecular
566
                                                              //!< interactions should be calculated
567
  public:
568
    /*! Clone the current instance. May be desirable in multithreaded environments,
569
     *  Should be deleted after use
570
     */
571
    virtual OBForceField* MakeNewInstance()=0;
572
573
    //! Destructor
574
    virtual ~OBForceField()
575
0
    {
576
0
      if (_grad1 != nullptr) {
577
0
        delete [] _grad1;
578
0
        _grad1 = nullptr;
579
0
      }
580
0
      if (_gradientPtr != nullptr) {
581
0
        delete [] _gradientPtr;
582
0
  _gradientPtr = nullptr;
583
0
      }
584
0
    }
585
586
    //! \return Plugin type ("forcefields")
587
    const char* TypeID() override
588
10
    {
589
10
      return "forcefields";
590
10
    }
591
592
    /*! \param ID forcefield id (Ghemical, MMFF94, UFF, ...).
593
     *  \return A pointer to a forcefield (the default if ID is empty), or NULL if not available.
594
     */
595
    static OBForceField* FindForceField(const std::string& ID)
596
0
    {
597
0
      return FindType(ID.c_str());
598
0
    }
599
    /*! \param ID forcefield id (Ghemical, MMFF94, UFF, ...).
600
     *  \return A pointer to a forcefield (the default if ID is empty), or NULL if not available.
601
     */
602
    static OBForceField* FindForceField(const char *ID)
603
0
    {
604
0
      return FindType(ID);
605
0
    }
606
    /*
607
     *
608
     */
609
    void SetParameterFile(const std::string &filename)
610
0
    {
611
0
      _parFile = filename;
612
0
      _init = false;
613
0
    }
614
    /*! \return The unit (kcal/mol, kJ/mol, ...) in which the energy is expressed as std::string.
615
     */
616
0
    virtual std::string GetUnit() { return std::string("au"); }
617
    /* Does this force field have analytical gradients defined for all
618
     * calculation components (bonds, angles, non-bonded, etc.)
619
     * If this is true, code should default to using OBFF_ANALYTICAL_GRADIENT
620
     * for SteepestDescent() or ConjugateGradients().
621
     * \return True if all analytical gradients are implemented.
622
     */
623
0
    virtual bool HasAnalyticalGradients() { return false; }
624
    /*! Setup the forcefield for mol (assigns atom types, charges, etc.). Keep current constraints.
625
     *  \param mol The OBMol object that contains the atoms and bonds.
626
     *  \return True if successful.
627
     */
628
    bool Setup(OBMol &mol);
629
    /*! Setup the forcefield for mol (assigns atom types, charges, etc.). Use new constraints.
630
     *  \param mol The OBMol object that contains the atoms and bonds.
631
     *  \param constraints The OBFFConstraints object that contains the constraints.
632
     *  \return True if successful.
633
     */
634
    bool Setup(OBMol &mol, OBFFConstraints &constraints);
635
    /*! Load the parameters (this function is overloaded by the individual forcefields,
636
     *  and is called autoamically from OBForceField::Setup()).
637
     */
638
    // move to protected in future version
639
0
    virtual bool ParseParamFile() { return false; }
640
    /*! Set the atom types (this function is overloaded by the individual forcefields,
641
     *  and is called autoamically from OBForceField::Setup()).
642
     */
643
    // move to protected in future version
644
0
    virtual bool SetTypes() { return false; }
645
    /*! Set the formal charges (this function is overloaded by the individual forcefields,
646
     *  and is called autoamically from OBForceField::Setup()).
647
     */
648
    // move to protected in future version
649
0
    virtual bool SetFormalCharges() { return false; }
650
    /*! Set the partial charges (this function is overloaded by the individual forcefields,
651
     *  and is called autoamically from OBForceField::Setup()).
652
     */
653
    // move to protected in future version
654
0
    virtual bool SetPartialCharges() { return false; }
655
    /*! Setup the calculations (this function is overloaded by the individual forcefields,
656
     *  and is called autoamically from OBForceField::Setup()).
657
     */
658
    // move to protected in future version
659
0
    virtual bool SetupCalculations() { return false; }
660
    /*! Setup the pointers to the atom positions in the OBFFCalculation objects. This method
661
     *  will iterate over all the calculations and call SetupPointers for each one. (This
662
     *  function should be implemented by the individual force field implementations).
663
     */
664
    // move to protected in future version
665
0
    virtual bool SetupPointers() { return false; }
666
    /*! Compare the internal forcefield OBMol object to mol. If the two have the
667
     *  same number of atoms and bonds, and all atomic numbers are the same,
668
     *  this function returns false, and no call to Setup is needed.
669
     *  \return True if Setup needs to be called.
670
     */
671
    bool IsSetupNeeded(OBMol &mol);
672
    /*! Get the force atom types. The atom types will be added to
673
     *  the atoms of mol as OBPairData. The attribute will be "FFAtomType".
674
     *
675
     *  \code
676
     *  ...
677
     *  pFF->Setup(&mol);
678
     *  pFF->GetAtomTypes(&mol);
679
     *  FOR_ATOMS_OF_MOL (atom, mol) {
680
     *    OBPairData *type = (OBPairData*) atom->GetData("FFAtomType");
681
     *    if (type)
682
     *      cout << "atom " << atom->GetIdx() << " : " << type->GetValue() << endl;
683
     *  }
684
     *  ...
685
     *  \endcode
686
     */
687
    bool GetAtomTypes(OBMol &mol);
688
    /*! Get the force field formal charges. The formal charges will be added to
689
     *  the atoms of mol as OBPairData. The attribute will be "FFPartialCharge".
690
     *
691
     *  \code
692
     *  ...
693
     *  pFF->Setup(&mol);
694
     *  pFF->GetPartialCharges(&mol);
695
     *  FOR_ATOMS_OF_MOL (atom, mol) {
696
     *    OBPairData *chg = (OBPairData*) atom->GetData("FFPartialCharge");
697
     *    if (chg)
698
     *      cout << "atom " << atom->GetIdx() << " : " << chg->GetValue() << endl;
699
     *  }
700
     *  ...
701
     *  \endcode
702
     */
703
    bool GetPartialCharges(OBMol &mol);
704
705
706
707
    /*! Get coordinates for current conformer and attach OBConformerData with energies, forces, ... to mol.
708
     *  \param mol The OBMol object to copy the coordinates to (from OBForceField::_mol).
709
     *  \return True if successful.
710
     */
711
    bool GetCoordinates(OBMol &mol);
712
    //! \deprecated Use GetCooordinates instead.
713
    OB_DEPRECATED_MSG("Use GetCooordinates instead.")
714
0
    bool UpdateCoordinates(OBMol &mol) {return GetCoordinates(mol); }
715
    /*! Get coordinates for all conformers and attach OBConformerData with energies, forces, ... to mol.
716
     *  \param mol The OBMol object to copy the coordinates to (from OBForceField::_mol).
717
     *  \return True if successful.
718
     */
719
    bool GetConformers(OBMol &mol);
720
    //! \deprecated Use GetConformers instead.
721
    OB_DEPRECATED_MSG("Use GetConformers instead.")
722
0
    bool UpdateConformers(OBMol &mol) { return GetConformers(mol); }
723
    /*! Set coordinates for current conformer.
724
     *  \param mol the OBMol object to copy the coordinates from (to OBForceField::_mol).
725
     *  \return true if successful.
726
     */
727
    bool SetCoordinates(OBMol &mol);
728
    /*! Set coordinates for all conformers.
729
     *  \param mol The OBMol object to copy the coordinates from (to OBForceField::_mol).
730
     *  \return True if successful.
731
     */
732
    bool SetConformers(OBMol &mol);
733
    /*! Create a grid with spacing @p step and @p padding. Place a probe atom of type probe at every grid point,
734
     *  calculate the energy and store it in the grid. These grids can then be used to create isosurfaces to
735
     *  identify locations where the probe atom has favourable interactions with the molecule.
736
     *  \param step The grid step size in A..
737
     *  \param padding The padding for the grid in A.
738
     *  \param type The force field atom type for the probe.
739
     *  \param pchg The partial charge for the probe atom.
740
     *  \return Pointer to the grid constaining the results.
741
     */
742
    OBGridData *GetGrid(double step, double padding, const char *type, double pchg);
743
744
    /////////////////////////////////////////////////////////////////////////
745
    // Interacting groups                                                  //
746
    /////////////////////////////////////////////////////////////////////////
747
748
    //! \name Methods for specifying interaction groups
749
    //@{
750
    /*! Enable intra-molecular interactions for group (bonds, angles, strbnd, torsions, oop).
751
     *  This function should be called before Setup().
752
     *  \param group OBBitVec with bits set for the indexes of the atoms which make up the group.
753
     */
754
    void AddIntraGroup(OBBitVec &group);
755
    /*! Enable inter-molecular interactions for group (non-bonded: vdw & ele).
756
     *  This function should be called before Setup().
757
     *  \param group OBBitVec with bits set for the indexes of the atoms which make up the group.
758
     */
759
    void AddInterGroup(OBBitVec &group);
760
    /*! Enable inter-molecular interactions between group1 and group2 (non-bonded: vdw & ele).
761
     *  Note that this function doesn't enable bonded interactions in either group. Non-bonded
762
     *  interactions in the groups itself are also not enabled.
763
     *  This function should be called before Setup().
764
     *  \param group1 OBBitVec with bits set for the indexes of the atoms which make up the first group.
765
     *  \param group2 OBBitVec with bits set for the indexes of the atoms which make up the second group.
766
     */
767
    void AddInterGroups(OBBitVec &group1, OBBitVec &group2);
768
    /*! Clear all previously specified groups.
769
     */
770
    void ClearGroups();
771
    /*! \return true if there are groups.
772
     */
773
    bool HasGroups();
774
    //@}
775
776
    /////////////////////////////////////////////////////////////////////////
777
    // Cut-off                                                             //
778
    /////////////////////////////////////////////////////////////////////////
779
780
    //! \name Methods for Cut-off distances
781
    //@{
782
    /*! Enable or disable Cut-offs. Cut-offs are disabled by default.
783
     *  \param enable Enable when true, disable when false.
784
     */
785
    void EnableCutOff(bool enable)
786
0
    {
787
0
      _cutoff = enable;
788
0
    }
789
    /*! \return True if Cut-off distances are used.
790
     */
791
    bool IsCutOffEnabled()
792
0
    {
793
0
      return _cutoff;
794
0
    }
795
    /*! Set the VDW cut-off distance to r. Note that this does not enable cut-off distances.
796
     *  \param r The VDW cut-off distance to be used in A.
797
     */
798
    void SetVDWCutOff(double r)
799
0
    {
800
0
      _rvdw = r;
801
0
    }
802
    /*! Get the VDW cut-off distance.
803
     *  \return The VDW cut-off distance in A.
804
     */
805
    double GetVDWCutOff()
806
0
    {
807
0
      return _rvdw;
808
0
    }
809
    /*! Set the Electrostatic cut-off distance to r. Note that this does not
810
     *  enable cut-off distances.
811
     *  \param r The electrostatic cut-off distance to be used in A.
812
     */
813
    void SetElectrostaticCutOff(double r)
814
0
    {
815
0
      _rele = r;
816
0
    }
817
    /*! Get the Electrostatic cut-off distance.
818
     *  \return The electrostatic cut-off distance in A.
819
     */
820
    double GetElectrostaticCutOff()
821
0
    {
822
0
      return _rele;
823
0
    }
824
    /*! Set the dielectric constant for electrostatic SetupCalculations
825
     * \param epsilon The relative permittivity to use (default = 1.0)
826
     */
827
     void SetDielectricConstant(double epsilon)
828
0
     {
829
0
       _epsilon = epsilon;
830
0
     }
831
     /* Get the dielectric permittivity used for electrostatic calculations
832
     * \rreturn The current relative permittivity
833
     */
834
     double GetDielectricConstant()
835
0
     {
836
0
       return _epsilon;
837
0
     }
838
    /*! Set the frequency by which non-bonded pairs are updated. Values from 10 to 20
839
     *  are recommended. Too low will decrease performance, too high will cause
840
     *  non-bonded interactions within cut-off not to be calculated.
841
     *  \param f The pair list update frequency.
842
     */
843
    void SetUpdateFrequency(int f)
844
0
    {
845
0
      _pairfreq = f;
846
0
    }
847
    /*! Get the frequency by which non-bonded pairs are updated.
848
     *  \return The pair list update frequency.
849
     */
850
    int GetUpdateFrequency()
851
0
    {
852
0
      return _pairfreq;
853
0
    }
854
    /*! Set the bits in _vdwpairs and _elepairs to 1 for interactions that
855
     *  are within cut-off distance. This function is called in minimizing
856
     *  algorithms such as SteepestDescent and ConjugateGradients.
857
     */
858
    void UpdatePairsSimple();
859
860
    //void UpdatePairsGroup(); TODO
861
862
    /*! Get the number of non-bonded pairs in _mol.
863
     *  \return The number of atom pairs (ignores cutoff)
864
     */
865
    unsigned int GetNumPairs();
866
    /*! Get the number of enabled electrostatic pairs in _mol.
867
     *  \return The number of pairs currently enabled (within cut-off distance)
868
     */
869
    unsigned int GetNumElectrostaticPairs();
870
    /*! Get the number of enabled VDW pairs in _mol.
871
     *  \return The number of pairs currently enabled (within cut-off distance)
872
     */
873
    unsigned int GetNumVDWPairs();
874
    /*! Set bits in range 0..._numpairs-1 to 1. Using this means there will
875
     *  be no cut-off. (not-working: see code for more information.
876
     */
877
    void EnableAllPairs()
878
0
    {
879
0
      // TODO: OBBitVec doesn't seem to be allocating it's memory correctly
880
0
      //_vdwpairs.SetRangeOn(0, _numpairs-1);
881
0
      //_elepairs.SetRangeOn(0, _numpairs-1);
882
0
    }
883
    //@}
884
885
    /*! Get the pointer to the gradients
886
     */
887
    virtual vector3 GetGradient(OBAtom *a, int /*terms*/ = OBFF_ENERGY)
888
0
    {
889
0
      const int coordIdx = (a->GetIdx() - 1) * 3;
890
0
      return _gradientPtr + coordIdx;
891
0
    }
892
893
    /*! Get the pointer to the gradients
894
     */
895
    double* GetGradientPtr()
896
0
    {
897
0
      return _gradientPtr;
898
0
    }
899
900
    /////////////////////////////////////////////////////////////////////////
901
    // Energy Evaluation                                                   //
902
    /////////////////////////////////////////////////////////////////////////
903
904
    //! \name Methods for energy evaluation
905
    //@{
906
    /*! \param gradients Set to true when the gradients need to be calculated
907
     *  (needs to be done before calling GetGradient()).
908
     *  \return Total energy.
909
     *   \par Output to log:
910
     *    OBFF_LOGLVL_NONE:   none \n
911
     *    OBFF_LOGLVL_LOW:    none \n
912
     *    OBFF_LOGLVL_MEDIUM: energy for individual energy terms \n
913
     *    OBFF_LOGLVL_HIGH:   energy for individual energy interactions \n
914
     */
915
0
    virtual double Energy(bool UNUSED(gradients) = true) { return 0.0f; }
916
    /*! \param gradients Set to true when the gradients need to be calculated
917
     *  (needs to be done before calling GetGradient()).
918
     *  \return Bond stretching energy.
919
     *   \par Output to log:
920
     *    see Energy()
921
     */
922
0
    virtual double E_Bond(bool UNUSED(gradients) = true) { return 0.0f; }
923
    /*! \param gradients Set to true when the gradients need to be calculated
924
     *  (needs to be done before calling GetGradient()).
925
     *  \return Angle bending energy.
926
     *  \par Output to log:
927
     *   see Energy()
928
     */
929
0
    virtual double E_Angle(bool UNUSED(gradients) = true) { return 0.0f; }
930
    /*! \param gradients Set to true when the gradients need to be calculated
931
     *  (needs to be done before calling GetGradient()).
932
     *  \return Stretch bending energy.
933
     *   \par Output to log:
934
     *    see Energy()
935
     */
936
0
    virtual double E_StrBnd(bool UNUSED(gradients) = true) { return 0.0f; }
937
    /*! \param gradients Set to true when the gradients need to be calculated
938
     *  (needs to be done before calling GetGradient()).
939
     *  \return Torsional energy.
940
     *    \par Output to log:
941
     *    see Energy()
942
     */
943
0
    virtual double E_Torsion(bool UNUSED(gradients) = true) { return 0.0f; }
944
    /*! \param gradients Set to true when the gradients need to be calculated
945
     *  (needs to be done before calling GetGradient()).
946
     *  \return Out-Of-Plane bending energy.
947
     *   \par Output to log:
948
     *    see Energy()
949
     */
950
0
    virtual double E_OOP(bool UNUSED(gradients) = true) { return 0.0f; }
951
    /*! \param gradients Set to true when the gradients need to be calculated
952
     *  (needs to be done before calling GetGradient()).
953
     *  \return Van der Waals energy.
954
     *   \par Output to log:
955
     *    see Energy()
956
     */
957
0
    virtual double E_VDW(bool UNUSED(gradients) = true) { return 0.0f; }
958
    /*! \param gradients Set to true when the gradients need to be calculated
959
     *  (needs to be done before calling GetGradient()).
960
     *  \return Electrostatic energy.
961
     *   \par Output to log:
962
     *    see Energy()
963
     */
964
0
    virtual double E_Electrostatic(bool UNUSED(gradients) = true) { return 0.0f; }
965
    //@}
966
967
    /////////////////////////////////////////////////////////////////////////
968
    // Logging                                                             //
969
    /////////////////////////////////////////////////////////////////////////
970
971
    //! \name Methods for logging
972
    //@{
973
    /*! Print the atom types to the log.
974
     */
975
    void PrintTypes();
976
    /*! Print the formal charges to the log (atom.GetPartialCharge(),
977
     *  MMFF94 FC's are not always int).
978
     */
979
    void PrintFormalCharges();
980
    /*! Print the partial charges to the log.
981
     */
982
    void PrintPartialCharges();
983
    /*! Print the velocities to the log.
984
     */
985
    void PrintVelocities();
986
    /*! Set the stream for logging (can also be &cout for logging to screen).
987
     *  \param pos Stream (when pos is 0, std::cout wil be used).
988
     *  \return True if successful.
989
     */
990
    bool SetLogFile(std::ostream *pos);
991
    /*! Set the log level (OBFF_LOGLVL_NONE, OBFF_LOGLVL_LOW, OBFF_LOGLVL_MEDIUM, OBFF_LOGLVL_HIGH).
992
     *  Inline if statements for logging are available:
993
     *  \code
994
     *  #define IF_OBFF_LOGLVL_LOW    if(_loglvl >= OBFF_LOGLVL_LOW)
995
     *  #define IF_OBFF_LOGLVL_MEDIUM if(_loglvl >= OBFF_LOGLVL_MEDIUM)
996
     *  #define IF_OBFF_LOGLVL_HIGH   if(_loglvl >= OBFF_LOGLVL_HIGH)
997
     *  \endcode
998
     *
999
     *  example:
1000
     *  \code
1001
     *  SetLogLevel(OBFF_LOGLVL_MEDIUM);
1002
     *  IF_OBFF_LOGLVL_HIGH {
1003
     *    OBFFLog("this text will NOT be logged...\n");
1004
     *  }
1005
     *
1006
     *  IF_OBFF_LOGLVL_LOW {
1007
     *    OBFFLog"this text will be logged...\n");
1008
     *  }
1009
     *
1010
     *  IF_OBFF_LOGLVL_MEDIUM {
1011
     *    OBFFLog("this text will also be logged...\n");
1012
     *  }
1013
     *  \endcode
1014
     */
1015
    bool SetLogLevel(int level);
1016
    /*! \return The log level.
1017
     */
1018
0
    int GetLogLevel() { return _loglvl; }
1019
    /*! Print msg to the logfile.
1020
     *  \param msg The message to print.
1021
     */
1022
    void OBFFLog(std::string msg)
1023
0
    {
1024
0
      if (!_logos)
1025
0
        return;
1026
0
1027
0
      *_logos << msg;
1028
0
    }
1029
    /*! Print msg to the logfile.
1030
     *  \param msg The message to print.
1031
     */
1032
    void OBFFLog(const char *msg)
1033
0
    {
1034
0
      if (!_logos)
1035
0
        return;
1036
1037
0
      *_logos << msg;
1038
0
    }
1039
    //@}
1040
1041
    /////////////////////////////////////////////////////////////////////////
1042
    // Structure Generation                                                //
1043
    /////////////////////////////////////////////////////////////////////////
1044
1045
    //! \name Methods for structure generation
1046
    //@{
1047
    //! Generate coordinates for the molecule (distance geometry)
1048
    //! \deprecated Use OBDistanceGeometry class instead
1049
    OB_DEPRECATED_MSG("Use OBDistanceGeometry class instead")
1050
    void DistanceGeometry();
1051
    /*! Generate conformers for the molecule (systematicaly rotating torsions).
1052
     *
1053
     *  The initial starting structure here is important, this structure should be
1054
     *  minimized for the best results. SystematicRotorSearch works by rotating around
1055
     *  the rotatable bond in a molecule (see OBRotamerList class). This rotating generates
1056
     *  multiple conformers. The energy for all these conformers is then evaluated and the
1057
     *  lowest energy conformer is selected.
1058
     *
1059
     *  \param geomSteps The number of steps to take during geometry optimization.
1060
     *  \param sampleRingBonds Whether to sample ring torsions.
1061
     *
1062
     *  \par Output to log:
1063
     *  This function should only be called with the log level set to OBFF_LOGLVL_NONE or OBFF_LOGLVL_LOW. Otherwise
1064
     *  too much information about the energy calculations needed for this function will interfere with the output for
1065
     *  this function. \n\n
1066
     *  OBFF_LOGLVL_NONE:   None. \n
1067
     *  OBFF_LOGLVL_LOW:    Number of rotatable bonds, energies for the conformers, which one is the lowest, ... \n
1068
     *  OBFF_LOGLVL_MEDIUM: See note above. \n
1069
     *  OBFF_LOGLVL_HIGH:   See note above. \n
1070
     */
1071
    void SystematicRotorSearch(unsigned int geomSteps = 2500, bool sampleRingBonds = false);
1072
    /*! Generate conformers for the molecule by systematicaly rotating torsions. To be used in combination with
1073
     *  SystematicRotorSearchNexConformer().
1074
     *
1075
     *  example:
1076
     *  \code
1077
     *  // pFF is a pointer to a OBForceField class
1078
     *  pFF->SystematicRotorSearchInitialize(300);
1079
     *  while (pFF->SystematicRotorSearchNextConformer(300)) {
1080
     *    // do some updating in your program (show last generated conformer, ...)
1081
     *  }
1082
     *  \endcode
1083
     *
1084
     *  If you don't need any updating in your program, SystematicRotorSearch() is recommended.
1085
     *
1086
     *  \param geomSteps The number of steps to take during geometry optimization.
1087
     *  \param sampleRingBonds Whether to sample ring torsions.
1088
     *  \return The number of conformers.
1089
     */
1090
    int SystematicRotorSearchInitialize(unsigned int geomSteps = 2500, bool sampleRingBonds = false);
1091
    /*! Evaluate the next conformer.
1092
     *  \param geomSteps The number of steps to take during geometry optimization.
1093
     *  \return True if there are more conformers.
1094
     */
1095
    bool SystematicRotorSearchNextConformer(unsigned int geomSteps = 2500);
1096
    /*! Generate conformers for the molecule (randomly rotating torsions).
1097
     *
1098
     *  The initial starting structure here is important, this structure should be
1099
     *  minimized for the best results. RandomRotorSearch works by randomly rotating around
1100
     *  the rotatable bonds in a molecule (see OBRotamerList class). This rotating generates
1101
     *  multiple conformers. The energy for all these conformers is then evaluated and the
1102
     *  lowest energy conformer is selected.
1103
     *
1104
     *  \param conformers The number of random conformers to consider during the search.
1105
     *  \param geomSteps The number of steps to take during geometry optimization for each conformer.
1106
     *  \param sampleRingBonds Whether to sample ring torsions.
1107
     *
1108
     *  \par Output to log:
1109
     *  This function should only be called with the log level set to OBFF_LOGLVL_NONE or OBFF_LOGLVL_LOW. Otherwise
1110
     *  too much information about the energy calculations needed for this function will interfere with the output for
1111
     *  this function. \n\n
1112
     *  OBFF_LOGLVL_NONE:   None. \n
1113
     *  OBFF_LOGLVL_LOW:    Number of rotatable bonds, energies for the conformers, which one is the lowest, ... \n
1114
     *  OBFF_LOGLVL_MEDIUM: See note above. \n
1115
     *  OBFF_LOGLVL_HIGH:   See note above. \n
1116
     */
1117
    void RandomRotorSearch(unsigned int conformers, unsigned int geomSteps = 2500,
1118
                           bool sampleRingBonds = false);
1119
    /*! Generate conformers for the molecule by randomly rotating torsions. To be used in combination with
1120
     *  RandomRotorSearchNexConformer().
1121
     *
1122
     *  example:
1123
     *  \code
1124
     *  // pFF is a pointer to a OBForceField class
1125
     *  pFF->RandomRotorSearchInitialize(300);
1126
     *  while (pFF->RandomRotorSearchNextConformer(300)) {
1127
     *    // do some updating in your program (show last generated conformer, ...)
1128
     *  }
1129
     *  \endcode
1130
     *
1131
     *  If you don't need any updating in your program, RandomRotorSearch() is recommended.
1132
     *
1133
     *  \param conformers The number of random conformers to consider during the search
1134
     *  \param geomSteps The number of steps to take during geometry optimization
1135
     *  \param sampleRingBonds Whether to sample ring torsions.
1136
     */
1137
    void RandomRotorSearchInitialize(unsigned int conformers, unsigned int geomSteps = 2500,
1138
                                     bool sampleRingBonds = false);
1139
    /*! Evaluate the next conformer.
1140
     *  \param geomSteps The number of steps to take during geometry optimization.
1141
     *  \return True if there are more conformers.
1142
     */
1143
    bool RandomRotorSearchNextConformer(unsigned int geomSteps = 2500);
1144
    /*! Generate conformers for the molecule (randomly rotating torsions).
1145
     *
1146
     *  The initial starting structure here is important, this structure should be
1147
     *  minimized for the best results. WeightedRotorSearch works by randomly rotating around
1148
     *  the rotatable bonds in a molecule (see OBRotamerList class). Unlike RandomRotorSearch()
1149
     *  the random choice of torsions is reweighted based on the energy of the generated conformer.
1150
     *  Over time, the generated conformers for each step should become increasingly better.
1151
     *  The lowest energy conformer is selected.
1152
     *
1153
     * \param conformers The number of random conformers to consider during the search.
1154
     * \param geomSteps The number of steps to take during geometry optimization for each conformer.
1155
     *  \param sampleRingBonds Whether to sample ring torsions.
1156
     *
1157
     *  \par Output to log:
1158
     *  This function should only be called with the log level set to OBFF_LOGLVL_NONE or OBFF_LOGLVL_LOW. Otherwise
1159
     *  too much information about the energy calculations needed for this function will interfere with the output for
1160
     *  this function. \n\n
1161
     *  OBFF_LOGLVL_NONE:   None. \n
1162
     *  OBFF_LOGLVL_LOW:    Number of rotatable bonds, energies for the conformers, which one is the lowest, ... \n
1163
     *  OBFF_LOGLVL_MEDIUM: See note above. \n
1164
     *  OBFF_LOGLVL_HIGH:   See note above. \n
1165
     */
1166
    void WeightedRotorSearch(unsigned int conformers, unsigned int geomSteps,
1167
                             bool sampleRingBonds = false);
1168
    /**
1169
     * @brief A fast rotor search to find low energy conformations
1170
     *
1171
     * Iterate over each of the rotors, and set the
1172
     * torsion angle to that which minimizes the energy (while keeping the rest of the molecule
1173
     * fixed). In general (for molecules with more than
1174
     * one rotatable bond), this procedure will not find
1175
     * the global minimum, but it will at least get rid of any bad
1176
     * clashes, and it do so quickly.
1177
     *
1178
     * Torsions closer to the center
1179
     * of the molecule will be optimized first as these most likely
1180
     * to generate large clashes.
1181
     *
1182
     * One possible use of this procedure is to prepare a reasonable 3D structure
1183
     * of a molecule for viewing. Another is to prepare the starting structure
1184
     * for a more systematic rotor search (in which case you should geometry
1185
     * optimize the final structure).
1186
     *
1187
     * @param permute Whether or not to permute the order of the 4 most central rotors.
1188
     *                Default is true. This does a more thorough search, but takes 4! = 24 times
1189
     *                as long.
1190
     * @since version 2.4
1191
     */
1192
    int FastRotorSearch(bool permute = true);
1193
1194
#ifdef HAVE_EIGEN
1195
    //! \since version 2.4
1196
    int DiverseConfGen(double rmsd, unsigned int nconfs = 0, double energy_gap = 50, bool verbose = false);
1197
#endif
1198
1199
    /////////////////////////////////////////////////////////////////////////
1200
    // Energy Minimization                                                 //
1201
    /////////////////////////////////////////////////////////////////////////
1202
1203
    //! \name Methods for energy minimization
1204
    //@{
1205
    /*! Set the LineSearchType. The default type is LineSearchType::Newton2Num.
1206
     *  \param type The LineSearchType to be used in SteepestDescent and ConjugateGradients.
1207
     */
1208
    void SetLineSearchType(int type)
1209
0
    {
1210
0
      _linesearch = type;
1211
0
    }
1212
    /*! Get the LineSearchType.
1213
     *  \return The current LineSearchType.
1214
     */
1215
    int GetLineSearchType()
1216
0
    {
1217
0
      return _linesearch;
1218
0
    }
1219
    /*! Perform a linesearch starting at atom in direction direction.
1220
     * \deprecated Current code should use LineSearch(double *, double*) instead.
1221
     */
1222
    OB_DEPRECATED_MSG("Current code should use LineSearch(double *, double*) instead.")
1223
    vector3 LineSearch(OBAtom *atom, vector3 &direction);
1224
    /*! Perform a linesearch for the entire molecule in direction @p direction.
1225
     *  This function is called when using LineSearchType::Simple.
1226
     *
1227
     *  \param currentCoords Start coordinates.
1228
     *  \param direction The search direction.
1229
     *  \return alpha, The scale of the step we moved along the direction vector.
1230
     *
1231
     *  \par Output to log:
1232
     *  OBFF_LOGLVL_NONE:   none \n
1233
     *  OBFF_LOGLVL_LOW:    none \n
1234
     *  OBFF_LOGLVL_MEDIUM: none \n
1235
     *  OBFF_LOGLVL_HIGH:   none \n
1236
     */
1237
    double LineSearch(double *currentCoords, double *direction);
1238
    /*! Perform a linesearch for the entire molecule.
1239
     *  This function is called when using LineSearchType::Newton2Num.
1240
     *
1241
     *  \param direction The search direction.
1242
     *  \return alpha, The scale of the step we moved along the direction vector.
1243
     *
1244
     *  \par Output to log:
1245
     *  OBFF_LOGLVL_NONE:   none \n
1246
     *  OBFF_LOGLVL_LOW:    none \n
1247
     *  OBFF_LOGLVL_MEDIUM: none \n
1248
     *  OBFF_LOGLVL_HIGH:   none \n
1249
     */
1250
    double Newton2NumLineSearch(double *direction);
1251
    /*! Set the coordinates of the atoms to origCoord + step.
1252
     *  \param origCoords Start coordinates.
1253
     *  \param direction The search direction.
1254
     *  \param step The step to take.
1255
     */
1256
    void   LineSearchTakeStep(double *origCoords, double *direction, double step);
1257
    /*! Perform steepest descent optimalization for steps steps or until convergence criteria is reached.
1258
     *
1259
     *  \param steps The number of steps.
1260
     *  \param econv Energy convergence criteria. (defualt is 1e-6)
1261
     *  \param method Deprecated. (see HasAnalyticalGradients())
1262
     *
1263
     *  \par Output to log:
1264
     *  This function should only be called with the log level set to OBFF_LOGLVL_NONE or OBFF_LOGLVL_LOW. Otherwise
1265
     *  too much information about the energy calculations needed for the minimization will interfere with the list
1266
     *  of energies for succesive steps. \n\n
1267
     *  OBFF_LOGLVL_NONE:   none \n
1268
     *  OBFF_LOGLVL_LOW:    header including number of steps and first step \n
1269
     *  OBFF_LOGLVL_MEDIUM: see note above \n
1270
     *  OBFF_LOGLVL_HIGH:   see note above \n
1271
     */
1272
    void SteepestDescent(int steps, double econv = 1e-6f, int method = OBFF_ANALYTICAL_GRADIENT);
1273
    /*! Initialize steepest descent optimalization, to be used in combination with SteepestDescentTakeNSteps().
1274
     *
1275
     *  example:
1276
     *  \code
1277
     *  // pFF is a pointer to a OBForceField class
1278
     *  pFF->SteepestDescentInitialize(100, 1e-5f);
1279
     *  while (pFF->SteepestDescentTakeNSteps(5)) {
1280
     *    // do some updating in your program (redraw structure, ...)
1281
     *  }
1282
     *  \endcode
1283
     *
1284
     *  If you don't need any updating in your program, SteepestDescent() is recommended.
1285
     *
1286
     *  \param steps The number of steps.
1287
     *  \param econv Energy convergence criteria. (defualt is 1e-6)
1288
     *  \param method Deprecated. (see HasAnalyticalGradients())
1289
     *
1290
     *  \par Output to log:
1291
     *  This function should only be called with the log level set to OBFF_LOGLVL_NONE or OBFF_LOGLVL_LOW. Otherwise
1292
     *  too much information about the energy calculations needed for the minimization will interfere with the list
1293
     *  of energies for succesive steps. \n\n
1294
     *  OBFF_LOGLVL_NONE:   none \n
1295
     *  OBFF_LOGLVL_LOW:    header including number of steps \n
1296
     *  OBFF_LOGLVL_MEDIUM: see note above \n
1297
     *  OBFF_LOGLVL_HIGH:   see note above \n
1298
     */
1299
    void SteepestDescentInitialize(int steps = 1000, double econv = 1e-6f, int method = OBFF_ANALYTICAL_GRADIENT);
1300
    /*! Take n steps in a steepestdescent optimalization that was previously initialized with SteepestDescentInitialize().
1301
     *
1302
     *  \param n The number of steps to take.
1303
     *  \return False if convergence or the number of steps given by SteepestDescentInitialize() has been reached.
1304
     *
1305
     *  \par Output to log:
1306
     *  This function should only be called with the log level set to OBFF_LOGLVL_NONE or OBFF_LOGLVL_LOW. Otherwise
1307
     *  too much information about the energy calculations needed for the minimization will interfere with the list
1308
     *  of energies for succesive steps. \n\n
1309
     *  OBFF_LOGLVL_NONE:   none \n
1310
     *  OBFF_LOGLVL_LOW:    step number, energy and energy for the previous step \n
1311
     *  OBFF_LOGLVL_MEDIUM: see note above \n
1312
     *  OBFF_LOGLVL_HIGH:   see note above \n
1313
     */
1314
    bool SteepestDescentTakeNSteps(int n);
1315
    /*! Perform conjugate gradient optimalization for steps steps or until convergence criteria is reached.
1316
     *
1317
     *  \param steps The number of steps.
1318
     *  \param econv Energy convergence criteria. (defualt is 1e-6)
1319
     *  \param method Deprecated. (see HasAnalyticalGradients())
1320
     *
1321
     *  \par Output to log:
1322
     *  This function should only be called with the log level set to OBFF_LOGLVL_NONE or OBFF_LOGLVL_LOW. Otherwise
1323
     *  too much information about the energy calculations needed for the minimization will interfere with the list
1324
     *  of energies for succesive steps. \n\n
1325
     *  OBFF_LOGLVL_NONE:   none \n
1326
     *  OBFF_LOGLVL_LOW:    information about the progress of the minimization \n
1327
     *  OBFF_LOGLVL_MEDIUM: see note above \n
1328
     *  OBFF_LOGLVL_HIGH:   see note above \n
1329
     */
1330
    void ConjugateGradients(int steps, double econv = 1e-6f, int method = OBFF_ANALYTICAL_GRADIENT);
1331
    /*! Initialize conjugate gradient optimalization and take the first step, to be
1332
     *  used in combination with ConjugateGradientsTakeNSteps().
1333
     *
1334
     *  example:
1335
     *  \code
1336
     *  // pFF is a pointer to a OBForceField class
1337
     *  pFF->ConjugateGradientsInitialize(100, 1e-5f);
1338
     *  while (pFF->ConjugateGradientsTakeNSteps(5)) {
1339
     *    // do some updating in your program (redraw structure, ...)
1340
     *  }
1341
     *  \endcode
1342
     *
1343
     *  If you don't need any updating in your program, ConjugateGradients() is recommended.
1344
     *
1345
     *  \param steps The number of steps.
1346
     *  \param econv Energy convergence criteria. (defualt is 1e-6)
1347
     *  \param method Deprecated. (see HasAnalyticalGradients())
1348
     *
1349
     *  \par Output to log:
1350
     *  This function should only be called with the log level set to OBFF_LOGLVL_NONE or OBFF_LOGLVL_LOW. Otherwise
1351
     *  too much information about the energy calculations needed for the minimization will interfere with the list
1352
     *  of energies for succesive steps. \n\n
1353
     *  OBFF_LOGLVL_NONE:   none \n
1354
     *  OBFF_LOGLVL_LOW:    header including number of steps and first step \n
1355
     *  OBFF_LOGLVL_MEDIUM: see note above \n
1356
     *  OBFF_LOGLVL_HIGH:   see note above \n
1357
     */
1358
    void ConjugateGradientsInitialize(int steps = 1000, double econv = 1e-6f, int method = OBFF_ANALYTICAL_GRADIENT);
1359
    /*! Take n steps in a conjugate gradient optimalization that was previously
1360
     *  initialized with ConjugateGradientsInitialize().
1361
     *
1362
     *  \param n The number of steps to take.
1363
     *  \return False if convergence or the number of steps given by ConjugateGradientsInitialize() has been reached.
1364
     *
1365
     *  \par Output to log:
1366
     *  This function should only be called with the log level set to OBFF_LOGLVL_NONE or OBFF_LOGLVL_LOW. Otherwise
1367
     *  too much information about the energy calculations needed for the minimization will interfere with the list
1368
     *  of energies for succesive steps. \n\n
1369
     *  OBFF_LOGLVL_NONE:   none \n
1370
     *  OBFF_LOGLVL_LOW:    step number, energy and energy for the previous step \n
1371
     *  OBFF_LOGLVL_MEDIUM: see note above \n
1372
     *  OBFF_LOGLVL_HIGH:   see note above \n
1373
    */
1374
    bool ConjugateGradientsTakeNSteps(int n);
1375
    //@}
1376
1377
    /////////////////////////////////////////////////////////////////////////
1378
    // Molecular Dynamics                                                  //
1379
    /////////////////////////////////////////////////////////////////////////
1380
1381
    //! \name Methods for molecular dynamics
1382
    //@{
1383
    /*! Generate starting velocities with a Maxwellian distribution.
1384
     */
1385
    void GenerateVelocities();
1386
    /*! Correct the velocities so that the following is true:
1387
     *
1388
     *  \code
1389
     *        3N
1390
     *       ----
1391
     *  0.5  \    m_i * v_i^2 = 0.5 * Ndf * R * T = E_kin
1392
     *       /
1393
     *       ----
1394
     *       i=1
1395
     *
1396
     *  E_kin : kinetic energy
1397
     *  m_i : mass of atom i
1398
     *  v_i : velocity of atom i
1399
     *  Ndf : number of degrees of freedom (3 * number of atoms)
1400
     *  R : gas constant
1401
     *  T : temperature
1402
     *  \endcode
1403
     *
1404
     */
1405
    void CorrectVelocities();
1406
    /*! Take n steps at temperature T. If no velocities are set, they will be generated.
1407
     *
1408
     *  example:
1409
     *  \code
1410
     *  // pFF is a pointer to a OBForceField class
1411
     *  while (pFF->MolecularDynamicsTakeNSteps(5, 300)) {
1412
     *    // do some updating in your program (redraw structure, ...)
1413
     *  }
1414
     * \endcode
1415
     *
1416
     *  \param n The number of steps to take.
1417
     *  \param T Absolute temperature in Kelvin.
1418
     *  \param timestep The time step in picoseconds. (10e-12 s)
1419
     *  \param method OBFF_ANALYTICAL_GRADIENTS (default) or OBFF_NUMERICAL_GRADIENTS
1420
     */
1421
    void MolecularDynamicsTakeNSteps(int n, double T, double timestep = 0.001, int method = OBFF_ANALYTICAL_GRADIENT);
1422
    //@}
1423
1424
    /////////////////////////////////////////////////////////////////////////
1425
    // Constraints                                                         //
1426
    /////////////////////////////////////////////////////////////////////////
1427
1428
    //! \name Methods for constraints
1429
    //@{
1430
    /*! Get the current constraints.
1431
     *  \return The current constrains stored in the force field.
1432
     */
1433
    OBFFConstraints& GetConstraints();
1434
    /*! Set the constraints.
1435
     *  \param constraints The new constraints to be used.
1436
     */
1437
    void SetConstraints(OBFFConstraints& constraints);
1438
    /*! Fix the atom position until UnsetFixAtom() is called. This function
1439
     *  can be used in programs that allow the user to interact with a molecule
1440
     *  that is being minimized without having to check if the atom is already
1441
     *  fixed in the constraints set by Setup() or SetConstraints(). Using this
1442
     *  makes sure the selected atom follows the mouse cursur.
1443
     *  \param index The index for the atom to fix.
1444
     */
1445
    void SetFixAtom(int index);
1446
    /*! Undo last SetFixAtom. This function will not remove the fix atom
1447
     *  constraint for this atom if set by Setup() or SetConstraints().
1448
     */
1449
    void UnsetFixAtom();
1450
    /*! Ignore the atom until UnsetIgnoreAtom() is called. This function
1451
     *  can be used in programs that allow the user to interact with a molecule
1452
     *  that is being minimized without having to check if the atom is already
1453
     *  ignored in the constraints set by Setup() or SetConstraints(). Using this
1454
     *  makes sure, in drawing mode, you can close rings without your newly
1455
     *  created puching the other atoms away.
1456
     *  \param index The index for the atom to ignore.
1457
     */
1458
    void SetIgnoreAtom(int index);
1459
    /*! Undo last SetIgnoreAtom. This function will not remove the ignore atom
1460
     *  constraint for this atom if set by Setup() or SetConstraints().
1461
     */
1462
    void UnsetIgnoreAtom();
1463
1464
    //! internal function
1465
    static bool IgnoreCalculation(int a, int b);
1466
    //! internal function
1467
    static bool IgnoreCalculation(int a, int b, int c);
1468
    //! internal function
1469
    static bool IgnoreCalculation(int a, int b, int c, int d);
1470
    //@}
1471
1472
1473
    /////////////////////////////////////////////////////////////////////////
1474
    // Validation                                                          //
1475
    /////////////////////////////////////////////////////////////////////////
1476
1477
    //! \name Methods for forcefield validation
1478
    //@{
1479
    //! (debugging)
1480
    bool DetectExplosion();
1481
    //! (debugging)
1482
    vector3 ValidateLineSearch(OBAtom *atom, vector3 &direction);
1483
    //! (debugging)
1484
    void ValidateSteepestDescent(int steps);
1485
    //! (debugging)
1486
    void ValidateConjugateGradients(int steps);
1487
    //! Validate the force field implementation (debugging)
1488
0
    virtual bool Validate() { return false; }
1489
    /*!
1490
      Validate the analytical gradients by comparing them to numerical ones. This function has to
1491
      be implemented force field specific. (debugging)
1492
    */
1493
0
    virtual bool ValidateGradients() { return false; }
1494
    /*!
1495
      Calculate the error of the analytical gradient (debugging)
1496
      \return  error = fabs(numgrad - anagrad) / anagrad * 100%
1497
    */
1498
    vector3 ValidateGradientError(vector3 &numgrad, vector3 &anagrad);
1499
    //@}
1500
1501
    /////////////////////////////////////////////////////////////////////////
1502
    // Vector Analysis                                                     //
1503
    /////////////////////////////////////////////////////////////////////////
1504
1505
    //! \name Methods for vector analysis (used by OBFFXXXXCalculationYYYY)
1506
    //@{
1507
    /*! Calculate the derivative of a vector length. The vector is given by a - b,
1508
     * the length of this vector rab = sqrt(ab.x^2 + ab.y^2 + ab.z^2).
1509
     * \param pos_a atom a (coordinates)
1510
     * \param pos_b atom b (coordinates)
1511
     * \param force_a - return value for the force on atom a
1512
     * \param force_b - return value for the force on atom b
1513
     * \return The distance between a and b (bondlength for bond stretching, separation for vdw, electrostatic)
1514
     */
1515
    static double VectorBondDerivative(double *pos_a, double *pos_b,
1516
                                       double *force_a, double *force_b);
1517
    /*! To be used for VDW or Electrostatic interactions. This
1518
     *  is faster than VectorBondDerivative, but does no error checking.
1519
     */
1520
    static double VectorDistanceDerivative(const double* const pos_i, const double* const pos_j,
1521
                                           double *force_i, double *force_j);
1522
    //! \deprecated
1523
    OB_DEPRECATED
1524
    static double VectorLengthDerivative(vector3 &a, vector3 &b);
1525
1526
    /*! Calculate the derivative of a angle a-b-c. The angle is given by dot(ab,cb)/rab*rcb.
1527
     *  Used for harmonic (cubic) angle potentials.
1528
     * \param pos_a atom a (coordinates)
1529
     * \param pos_b atom b (coordinates)
1530
     * \param pos_c atom c (coordinates)
1531
     * \param force_a - return value for the force on atom a
1532
     * \param force_b - return value for the force on atom b
1533
     * \param force_c - return value for the force on atom c
1534
     * \return The angle between a-b-c
1535
     */
1536
    static double VectorAngleDerivative(double *pos_a, double *pos_b, double *pos_c,
1537
                                        double *force_a, double *force_b, double *force_c);
1538
    //! \deprecated
1539
    OB_DEPRECATED
1540
    static double VectorAngleDerivative(vector3 &a, vector3 &b, vector3 &c);
1541
    /*! Calculate the derivative of a OOP angle a-b-c-d. b is the central atom, and a-b-c is the plane.
1542
     * The OOP angle is given by 90° - arccos(dot(corss(ab,cb),db)/rabbc*rdb).
1543
     * \param pos_a atom a (coordinates)
1544
     * \param pos_b atom b (coordinates)
1545
     * \param pos_c atom c (coordinates)
1546
     * \param pos_d atom d (coordinates)
1547
     * \param force_a - return value for the force on atom a
1548
     * \param force_b - return value for the force on atom b
1549
     * \param force_c - return value for the force on atom c
1550
     * \param force_d - return value for the force on atom d
1551
     * \return The OOP angle for a-b-c-d
1552
     */
1553
    static double VectorOOPDerivative(double *pos_a, double *pos_b, double *pos_c, double *pos_d,
1554
                                      double *force_a, double *force_b, double *force_c, double *force_d);
1555
    //! \deprecated
1556
    OB_DEPRECATED
1557
    static double VectorOOPDerivative(vector3 &a, vector3 &b, vector3 &c, vector3 &d);
1558
    /*! Calculate the derivative of a torsion angle a-b-c-d. The torsion angle is given by arccos(dot(corss(ab,bc),cross(bc,cd))/rabbc*rbccd).
1559
     * \param pos_a atom a (coordinates)
1560
     * \param pos_b atom b (coordinates)
1561
     * \param pos_c atom c (coordinates)
1562
     * \param pos_d atom d (coordinates)
1563
     * \param force_a - return value for the force on atom a
1564
     * \param force_b - return value for the force on atom b
1565
     * \param force_c - return value for the force on atom c
1566
     * \param force_d - return value for the force on atom d
1567
     * \return The tosion angle for a-b-c-d
1568
     */
1569
    static double VectorTorsionDerivative(double *pos_a, double *pos_b, double *pos_c, double *pos_d,
1570
                                          double *force_a, double *force_b, double *force_c, double *force_d);
1571
    //! \deprecated
1572
    OB_DEPRECATED
1573
    static double VectorTorsionDerivative(vector3 &a, vector3 &b, vector3 &c, vector3 &d);
1574
1575
    /*! inline fuction to speed up minimization speed
1576
     * \param i pointer to i[3]
1577
     * \param j pointer to j[3]
1578
     * \param result pointer to result[3], will be set to i - j
1579
     */
1580
    static void VectorSubtract(double *i, double *j, double *result)
1581
0
    {
1582
0
      for (unsigned int c = 0; c < 3; ++c)
1583
0
        result[c] = i[c] - j[c];
1584
0
    }
1585
1586
    static void VectorSubtract(const double* const i, const double* const j, double *result)
1587
0
    {
1588
0
      for (unsigned int c = 0; c < 3; ++c)
1589
0
        result[c] = i[c] - j[c];
1590
0
    }
1591
1592
    /*! inline fuction to speed up minimization speed
1593
     * \param i pointer to i[3]
1594
     * \param j pointer to j[3]
1595
     * \param result pointer to result[3], will be set to i + j
1596
     */
1597
    static void VectorAdd(double *i, double *j, double *result)
1598
0
    {
1599
0
      for (unsigned int c = 0; c < 3; ++c)
1600
0
        result[c] = i[c] + j[c];
1601
0
    }
1602
1603
    /*! inline fuction to speed up minimization speed
1604
     * \param i pointer to i[3]
1605
     * \param n divide x,y,z with n
1606
     * \param result pointer to result[3]
1607
     */
1608
    static void VectorDivide(double *i, double n, double *result)
1609
0
    {
1610
0
      for (unsigned int c = 0; c < 3; ++c)
1611
0
        result[c] = i[c] / n;
1612
0
    }
1613
1614
    /*! inline fuction to speed up minimization speed
1615
     * \param i pointer to i[3]
1616
     * \param n multiply x,y,z with n
1617
     * \param result pointer to result[3]
1618
     */
1619
    static void VectorMultiply(double *i, double n, double *result)
1620
0
    {
1621
0
      for (unsigned int c = 0; c < 3; ++c)
1622
0
        result[c] = i[c] * n;
1623
0
    }
1624
1625
    static void VectorMultiply(const double* const i, const double n, double *result)
1626
0
    {
1627
0
      for (unsigned int c = 0; c < 3; ++c)
1628
0
        result[c] = i[c] * n;
1629
0
    }
1630
1631
    /*! inline fuction to speed up minimization speed
1632
     * \param i pointer to i[3], multiply this vector by n and set this vector to the result.
1633
     * \param n the scalar value to be multipled
1634
     */
1635
    static void VectorSelfMultiply(double *i, double n)
1636
0
    {
1637
0
      for (unsigned int c = 0; c < 3; ++c)
1638
0
        i[c] *= n;
1639
0
    }
1640
1641
    /*! inline fuction to speed up minimization speed
1642
     * \param i pointer to i[3] to be normalized
1643
     */
1644
    static void VectorNormalize(double *i)
1645
0
    {
1646
0
      double length = VectorLength(i);
1647
0
      for (unsigned int c = 0; c < 3; ++c)
1648
0
        i[c] /= length;
1649
0
    }
1650
1651
    /*! inline fuction to speed up minimization speed
1652
     * \param from pointer to i[3] to be copied from
1653
     * \param to pointer to j[3] to be copied to
1654
     */
1655
    static void VectorCopy(double *from, double *to)
1656
0
    {
1657
0
      for (unsigned int c = 0; c < 3; ++c)
1658
0
        to[c] = from[c];
1659
0
    }
1660
1661
    /*! inline fuction to speed up minimization speed
1662
     * \param i pointer to i[3]
1663
     * \return the vector length
1664
     */
1665
    static double VectorLength(double *i)
1666
0
    {
1667
0
      return sqrt( i[0]*i[0] + i[1]*i[1] + i[2]*i[2] );
1668
0
    }
1669
1670
    static double VectorDistance(double *pos_i, double *pos_j)
1671
0
    {
1672
0
      double ij[3];
1673
0
      VectorSubtract(pos_i, pos_j, ij);
1674
0
      const double rij = VectorLength(ij);
1675
0
      return rij;
1676
0
    }
1677
1678
    /*! inline fuction to speed up minimization speed
1679
     * \param i pointer to i[3]
1680
     * \param j pointer to j[3]
1681
     * \param k pointer to k[3]
1682
     * \return the vector angle ijk (deg)
1683
     */
1684
    static double VectorAngle(double *i, double *j, double *k);
1685
1686
    /*! inline fuction to speed up minimization speed
1687
     * \param i pointer to i[3]
1688
     * \param j pointer to j[3]
1689
     * \param k pointer to k[3]
1690
     * \param l pointer to l[3]
1691
     * \return the vector torson ijkl (deg)
1692
     */
1693
    static double VectorTorsion(double *i, double *j, double *k, double *l);
1694
1695
    /*! inline fuction to speed up minimization speed
1696
     * \param i pointer to i[3]
1697
     * \param j pointer to j[3]
1698
     * \param k pointer to k[3]
1699
     * \param l pointer to l[3]
1700
     * \return the vector torson ijkl (deg)
1701
     */
1702
    static double VectorOOP(double *i, double *j, double *k, double *l);
1703
1704
    /*! inline fuction to speed up minimization speed
1705
     * \param i pointer to i[3], will set x,y,z to 0,0,0
1706
     */
1707
    static void VectorClear(double *i)
1708
0
    {
1709
0
      for (unsigned int c = 0; c < 3; ++c)
1710
0
        i[c] = 0.0;
1711
0
    }
1712
1713
    /*! inline fuction to speed up minimization speed
1714
     * \param i pointer to i[3]
1715
     * \param j pointer to j[3]
1716
     * \return the dot product
1717
     */
1718
    static double VectorDot(double *i, double *j)
1719
0
    {
1720
0
      double result = 0.0;
1721
      // Written as a loop for vectorization
1722
      // Loop will be unrolled by compiler otherwise
1723
0
      for (unsigned int c = 0; c < 3; ++c)
1724
0
        result += i[c]*j[c];
1725
0
      return result;
1726
0
    }
1727
1728
    /*! inline fuction to speed up minimization speed
1729
     * \param i pointer to i[3]
1730
     * \param j pointer to j[3]
1731
     * \param result the dot product (as a return value double[3])
1732
     */
1733
    static void VectorCross(double *i, double *j, double *result)
1734
0
    {
1735
0
      result[0] =   i[1]*j[2] - i[2]*j[1];
1736
0
      result[1] = - i[0]*j[2] + i[2]*j[0];
1737
0
      result[2] =   i[0]*j[1] - i[1]*j[0];
1738
0
    }
1739
1740
    static void PrintVector(double *i)
1741
0
    {
1742
0
      std::cout << "<" << i[0] << ", " << i[1] << ", " << i[2] << ">" << std::endl;
1743
0
    }
1744
    //@}
1745
1746
  }; // class OBForceField
1747
1748
}// namespace OpenBabel
1749
1750
#endif   // OB_FORCEFIELD_H
1751
1752
//! \file forcefield.h
1753
//! \brief Handle forcefields