/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> ¶meter); |
463 | | //! see GetParameter(int a, int b, int c, int d, std::vector<OBFFParameter> ¶meter) |
464 | | OBFFParameter* GetParameter(const char* a, const char* b, const char* c, const char* d, |
465 | | std::vector<OBFFParameter> ¶meter); |
466 | | //! Get index for vector<OBFFParameter> ... |
467 | | int GetParameterIdx(int a, int b, int c, int d, std::vector<OBFFParameter> ¶meter); |
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 |