RDKit
Open-source cheminformatics and machine learning.
Loading...
Searching...
No Matches
MMFF/Params.h
Go to the documentation of this file.
1//
2// Copyright (C) 2004-2024 Paolo Tosco and other RDKit contributors
3//
4// @@ All Rights Reserved @@
5// This file is part of the RDKit.
6// The contents are covered by the terms of the BSD license
7// which is included in the file license.txt, found at the root
8// of the RDKit source tree.
9//
10//
11#include <RDGeneral/export.h>
12#ifndef RD_MMFFPARAMS_H
13#define RD_MMFFPARAMS_H
14
15#include <memory>
16#include <RDGeneral/Invariant.h>
17#include <cmath>
18#include <string>
19#include <vector>
20#include <algorithm>
21#include <map>
22#include <cstdint>
23
24#ifndef M_PI
25#define M_PI 3.14159265358979323846
26#endif
27
28// binary searches are slightly faster than std::map;
29// however when I moved to binary searches I had already
30// written the code for std::map, so the two methods
31// can be toggled defining RDKIT_MMFF_PARAMS_USE_STD_MAP
32
33// #define RDKIT_MMFF_PARAMS_USE_STD_MAP 1
34
35namespace ForceFields {
36namespace MMFF {
37
38constexpr double DEG2RAD = M_PI / 180.0;
39constexpr double RAD2DEG = 180.0 / M_PI;
40constexpr double MDYNE_A_TO_KCAL_MOL = 143.9325;
41inline bool isDoubleZero(const double x) {
42 return ((x < 1.0e-10) && (x > -1.0e-10));
43}
44inline void clipToOne(double &x) { x = std::clamp(x, -1.0, 1.0); }
45
46//! class to store MMFF atom type equivalence levels
48 public:
49 std::uint8_t eqLevel[4];
50};
51
52//! class to store MMFF Properties
54 public:
55 std::uint8_t atno;
56 std::uint8_t crd;
57 std::uint8_t val;
58 std::uint8_t pilp;
59 std::uint8_t mltb;
60 std::uint8_t arom;
61 std::uint8_t linh;
62 std::uint8_t sbmb;
63};
64
65//! class to store MMFF Partial Bond Charge Increments
67 public:
68 double pbci;
69 double fcadj;
70};
71
72//! class to store MMFF bond-charge-increment parameters used to
73//! construct MMFF partial atomic charges
75 public:
76 double bci;
77};
78
79//! class to store MMFF parameters for bond stretching
81 public:
82 double kb;
83 double r0;
84};
85
86//! class to store parameters for Herschbach-Laurie's version
87//! of Badger's rule
89 public:
90 double a_ij;
91 double d_ij;
92 double dp_ij;
93};
94
95//! class to store covalent radius and Pauling electronegativity
96//! values for MMFF bond stretching empirical rule
98 public:
99 double r0;
100 double chi;
101};
102
103//! class to store MMFF parameters for angle bending
105 public:
106 double ka;
107 double theta0;
108};
109
110//! class to store MMFF parameters for stretch-bending
112 public:
113 double kbaIJK;
114 double kbaKJI;
115};
116
117//! class to store MMFF parameters for out-of-plane bending
119 public:
120 double koop;
121};
122
123//! class to store MMFF parameters for torsions
125 public:
126 double V1;
127 double V2;
128 double V3;
129};
130
131//! class to store MMFF parameters for non-bonded Van der Waals
133 public:
134 double alpha_i;
135 double N_i;
136 double A_i;
137 double G_i;
138 double R_star;
139 std::uint8_t DA;
140};
141
149
151 public:
152 //! Looks up the parameters for a particular key and returns them.
153 /*!
154 \return a pointer to the MMFFArom object, NULL on failure.
155 */
156 bool isMMFFAromatic(const unsigned int atomType) const {
157 return std::find(d_params.begin(), d_params.end(), atomType) !=
158 d_params.end();
159 }
160
161 MMFFAromCollection(const std::vector<std::uint8_t> *mmffArom = nullptr);
162 std::vector<std::uint8_t> d_params; //!< the aromatic type vector
163};
164
166 public:
167 //! Looks up the parameters for a particular key and returns them.
168 /*!
169 \return a pointer to the MMFFDef object, NULL on failure.
170 */
171 const MMFFDef *operator()(const unsigned int atomType) const {
172#ifdef RDKIT_MMFF_PARAMS_USE_STD_MAP
173 const auto res = d_params.find(atomType);
174 return ((res != d_params.end()) ? &((*res).second) : NULL);
175#else
176 return ((atomType && (atomType <= d_params.size()))
177 ? &d_params[atomType - 1]
178 : nullptr);
179#endif
180 }
181
182 MMFFDefCollection(std::string mmffDef = "");
183
184#ifdef RDKIT_MMFF_PARAMS_USE_STD_MAP
185 std::map<const unsigned int, MMFFDef> d_params; //!< the parameter map
186#else
187 std::vector<MMFFDef> d_params; //!< the parameter vector
188#endif
189};
190
192 public:
193 //! Looks up the parameters for a particular key and returns them.
194 /*!
195 \return a pointer to the MMFFProp object, NULL on failure.
196 */
197 const MMFFProp *operator()(const unsigned int atomType) const {
198#ifdef RDKIT_MMFF_PARAMS_USE_STD_MAP
199 const auto res = d_params.find(atomType);
200 return ((res != d_params.end()) ? &((*res).second) : NULL);
201#else
202 auto bounds =
203 std::equal_range(d_iAtomType.begin(), d_iAtomType.end(), atomType);
204 return ((bounds.first != bounds.second)
205 ? &d_params[bounds.first - d_iAtomType.begin()]
206 : nullptr);
207#endif
208 }
209
210 MMFFPropCollection(std::string mmffProp = "");
211#ifdef RDKIT_MMFF_PARAMS_USE_STD_MAP
212 std::map<const unsigned int, MMFFProp> d_params; //!< the parameter map
213#else
214 std::vector<MMFFProp> d_params;
215 std::vector<std::uint8_t> d_iAtomType; //!< the parameter vector
216#endif
217};
218
220 public:
221 //! Looks up the parameters for a particular key and returns them.
222 /*!
223 \return a pointer to the MMFFPBCI object, NULL on failure.
224 */
225 const MMFFPBCI *operator()(const unsigned int atomType) const {
226#ifdef RDKIT_MMFF_PARAMS_USE_STD_MAP
227 const auto res = d_params.find(atomType);
228 return ((res != d_params.end()) ? &((*res).second) : NULL);
229#else
230 return ((atomType && (atomType <= d_params.size()))
231 ? &d_params[atomType - 1]
232 : nullptr);
233#endif
234 }
235
236 MMFFPBCICollection(std::string mmffPBCI = "");
237
238#ifdef RDKIT_MMFF_PARAMS_USE_STD_MAP
239 std::map<const unsigned int, MMFFPBCI> d_params; //!< the parameter map
240#else
241 std::vector<MMFFPBCI> d_params; //!< the parameter vector
242#endif
243};
244
246 public:
247 //! Looks up the parameters for a particular key and returns them.
248 /*!
249 \return a pointer to the MMFFChg object, NULL on failure.
250 */
251 const std::pair<int, const MMFFChg *> getMMFFChgParams(
252 const unsigned int bondType, const unsigned int iAtomType,
253 const unsigned int jAtomType) const {
254 int sign = -1;
255 const MMFFChg *mmffChgParams = nullptr;
256 unsigned int canIAtomType = iAtomType;
257 unsigned int canJAtomType = jAtomType;
258 if (iAtomType > jAtomType) {
259 canIAtomType = jAtomType;
260 canJAtomType = iAtomType;
261 sign = 1;
262 }
263#ifdef RDKIT_MMFF_PARAMS_USE_STD_MAP
264 const auto res1 = d_params[bondType].find(canIAtomType);
265 if (res1 != d_params[bondType].end()) {
266 const auto res2 = ((*res1).second).find(canJAtomType);
267 if (res2 != ((*res1).second).end()) {
268 mmffChgParams = &((*res2).second);
269 }
270 }
271#else
272 auto bounds =
273 std::equal_range(d_iAtomType.begin(), d_iAtomType.end(), canIAtomType);
274 if (bounds.first != bounds.second) {
275 bounds = std::equal_range(
276 d_jAtomType.begin() + (bounds.first - d_iAtomType.begin()),
277 d_jAtomType.begin() + (bounds.second - d_iAtomType.begin()),
278 canJAtomType);
279 if (bounds.first != bounds.second) {
280 bounds = std::equal_range(
281 d_bondType.begin() + (bounds.first - d_jAtomType.begin()),
282 d_bondType.begin() + (bounds.second - d_jAtomType.begin()),
283 bondType);
284 if (bounds.first != bounds.second) {
285 mmffChgParams = &d_params[bounds.first - d_bondType.begin()];
286 }
287 }
288 }
289#endif
290
291 return std::make_pair(sign, mmffChgParams);
292 }
293
294 MMFFChgCollection(std::string mmffChg = "");
295
296//!< the parameter 3D-map
297#ifdef RDKIT_MMFF_PARAMS_USE_STD_MAP
298 std::map<const unsigned int,
299 std::map<const unsigned int, std::map<const unsigned int, MMFFChg>>>
300 d_params; //!< the parameter 3D-map
301#else
302 std::vector<MMFFChg> d_params; //!< the parameter vector
303 std::vector<std::uint8_t> d_iAtomType; //!< atom type vector for atom i
304 std::vector<std::uint8_t> d_jAtomType; //!< atom type vector for atom j
305 std::vector<std::uint8_t> d_bondType; //!< bond type vector for bond i-j
306#endif
307};
308
310 public:
311 //! Looks up the parameters for a particular key and returns them.
312 /*!
313 \return a pointer to the MMFFBond object, NULL on failure.
314 */
315 const MMFFBond *operator()(const unsigned int bondType,
316 const unsigned int atomType,
317 const unsigned int nbrAtomType) const {
318 const MMFFBond *mmffBondParams = nullptr;
319 unsigned int canAtomType = atomType;
320 unsigned int canNbrAtomType = nbrAtomType;
321 if (atomType > nbrAtomType) {
322 canAtomType = nbrAtomType;
323 canNbrAtomType = atomType;
324 }
325#ifdef RDKIT_MMFF_PARAMS_USE_STD_MAP
326 const auto res1 = d_params.find(bondType);
327 std::map<const unsigned int,
328 std::map<const unsigned int, MMFFBond>>::const_iterator res2;
329 std::map<const unsigned int, MMFFBond>::const_iterator res3;
330 if (res1 != d_params.end()) {
331 res2 = ((*res1).second).find(canAtomType);
332 if (res2 != ((*res1).second).end()) {
333 res3 = ((*res2).second).find(canNbrAtomType);
334 if (res3 != ((*res2).second).end()) {
335 mmffBondParams = &((*res3).second);
336 }
337 }
338 }
339#else
340 auto bounds =
341 std::equal_range(d_iAtomType.begin(), d_iAtomType.end(), canAtomType);
342 if (bounds.first != bounds.second) {
343 bounds = std::equal_range(
344 d_jAtomType.begin() + (bounds.first - d_iAtomType.begin()),
345 d_jAtomType.begin() + (bounds.second - d_iAtomType.begin()),
346 canNbrAtomType);
347 if (bounds.first != bounds.second) {
348 bounds = std::equal_range(
349 d_bondType.begin() + (bounds.first - d_jAtomType.begin()),
350 d_bondType.begin() + (bounds.second - d_jAtomType.begin()),
351 bondType);
352 if (bounds.first != bounds.second) {
353 mmffBondParams = &d_params[bounds.first - d_bondType.begin()];
354 }
355 }
356 }
357#endif
358
359 return mmffBondParams;
360 }
361
362 MMFFBondCollection(std::string mmffBond = "");
363#ifdef RDKIT_MMFF_PARAMS_USE_STD_MAP
364 std::map<const unsigned int,
365 std::map<const unsigned int, std::map<const unsigned int, MMFFBond>>>
366 d_params; //!< the parameter 3D-map
367#else
368 std::vector<MMFFBond> d_params; //!< the parameter vector
369 std::vector<std::uint8_t> d_iAtomType; //!< atom type vector for atom i
370 std::vector<std::uint8_t> d_jAtomType; //!< atom type vector for atom j
371 std::vector<std::uint8_t> d_bondType; //!< bond type vector for bond i-j
372#endif
373};
374
376 public:
377 //! Looks up the parameters for a particular key and returns them.
378 /*!
379 \return a pointer to the MMFFBndk object, NULL on failure.
380 */
381 const MMFFBond *operator()(const int atomicNum,
382 const int nbrAtomicNum) const {
383 const MMFFBond *mmffBndkParams = nullptr;
384 unsigned int canAtomicNum = atomicNum;
385 unsigned int canNbrAtomicNum = nbrAtomicNum;
386 if (atomicNum > nbrAtomicNum) {
387 canAtomicNum = nbrAtomicNum;
388 canNbrAtomicNum = atomicNum;
389 }
390#ifdef RDKIT_MMFF_PARAMS_USE_STD_MAP
391 const auto res1 = d_params.find(canAtomicNum);
392 std::map<const unsigned int, MMFFBond>::const_iterator res2;
393 if (res1 != d_params.end()) {
394 res2 = ((*res1).second).find(canNbrAtomicNum);
395 if (res2 != ((*res1).second).end()) {
396 mmffBndkParams = &((*res2).second);
397 }
398 }
399#else
400 auto bounds = std::equal_range(d_iAtomicNum.begin(), d_iAtomicNum.end(),
401 canAtomicNum);
402 if (bounds.first != bounds.second) {
403 bounds = std::equal_range(
404 d_jAtomicNum.begin() + (bounds.first - d_iAtomicNum.begin()),
405 d_jAtomicNum.begin() + (bounds.second - d_iAtomicNum.begin()),
406 canNbrAtomicNum);
407 if (bounds.first != bounds.second) {
408 mmffBndkParams = &d_params[bounds.first - d_jAtomicNum.begin()];
409 }
410 }
411#endif
412
413 return mmffBndkParams;
414 }
415
416 MMFFBndkCollection(std::string mmffBndk = "");
417#ifdef RDKIT_MMFF_PARAMS_USE_STD_MAP
418 std::map<const unsigned int, std::map<const unsigned int, MMFFBond>>
419 d_params; //!< the parameter 2D-map
420#else
421 std::vector<MMFFBond> d_params; //!< the parameter vector
422 std::vector<std::uint8_t> d_iAtomicNum; //!< atomic number vector for atom i
423 std::vector<std::uint8_t> d_jAtomicNum; //!< atomic number vector for atom j
424#endif
425};
426
428 public:
429 //! Looks up the parameters for a particular key and returns them.
430 /*!
431 \return a pointer to the MMFFHerschbachLaurie object, NULL on failure.
432 */
433 const MMFFHerschbachLaurie *operator()(const int iRow, const int jRow) const {
434 const MMFFHerschbachLaurie *mmffHerschbachLaurieParams = nullptr;
435 unsigned int canIRow = iRow;
436 unsigned int canJRow = jRow;
437 if (iRow > jRow) {
438 canIRow = jRow;
439 canJRow = iRow;
440 }
441#ifdef RDKIT_MMFF_PARAMS_USE_STD_MAP
442 const auto res1 = d_params.find(canIRow);
443 std::map<const unsigned int, MMFFHerschbachLaurie>::const_iterator res2;
444 if (res1 != d_params.end()) {
445 res2 = ((*res1).second).find(canJRow);
446 if (res2 != ((*res1).second).end()) {
447 mmffHerschbachLaurieParams = &((*res2).second);
448 }
449 }
450#else
451 auto bounds = std::equal_range(d_iRow.begin(), d_iRow.end(), canIRow);
452 if (bounds.first != bounds.second) {
453 bounds = std::equal_range(
454 d_jRow.begin() + (bounds.first - d_iRow.begin()),
455 d_jRow.begin() + (bounds.second - d_iRow.begin()), canJRow);
456 if (bounds.first != bounds.second) {
457 mmffHerschbachLaurieParams = &d_params[bounds.first - d_jRow.begin()];
458 }
459 }
460#endif
461
462 return mmffHerschbachLaurieParams;
463 }
464
465 MMFFHerschbachLaurieCollection(std::string mmffHerschbachLaurie = "");
466
467#ifdef RDKIT_MMFF_PARAMS_USE_STD_MAP
468 std::map<const unsigned int,
469 std::map<const unsigned int, MMFFHerschbachLaurie>>
470 d_params; //!< the parameter 2D-map
471#else
472 std::vector<MMFFHerschbachLaurie> d_params; //!< the parameter vector
473 std::vector<std::uint8_t> d_iRow; //!< periodic row number vector for atom i
474 std::vector<std::uint8_t> d_jRow; //!< periodic row number vector for atom j
475#endif
476};
477
479 public:
480 //! Looks up the parameters for a particular key and returns them.
481 /*!
482 \return a pointer to the MMFFCovRadPauEle object, NULL on failure.
483 */
484 const MMFFCovRadPauEle *operator()(const unsigned int atomicNum) const {
485#ifdef RDKIT_MMFF_PARAMS_USE_STD_MAP
486 const auto res = d_params.find(atomicNum);
487 return ((res != d_params.end()) ? &((*res).second) : NULL);
488#else
489 auto bounds =
490 std::equal_range(d_atomicNum.begin(), d_atomicNum.end(), atomicNum);
491 return ((bounds.first != bounds.second)
492 ? &d_params[bounds.first - d_atomicNum.begin()]
493 : nullptr);
494#endif
495 }
496
497 MMFFCovRadPauEleCollection(std::string mmffCovRadPauEle = "");
498#ifdef RDKIT_MMFF_PARAMS_USE_STD_MAP
499 std::map<const unsigned int, MMFFCovRadPauEle>
500 d_params; //!< the parameter map
501#else
502 std::vector<MMFFCovRadPauEle> d_params; //!< the parameter vector
503 std::vector<std::uint8_t> d_atomicNum; //!< the atomic number vector
504#endif
505};
506
508 public:
509 //! Looks up the parameters for a particular key and returns them.
510 /*!
511 \return a pointer to the MMFFAngle object, NULL on failure.
512 */
514 const unsigned int angleType,
515 const unsigned int iAtomType,
516 const unsigned int jAtomType,
517 const unsigned int kAtomType) const {
518 const MMFFAngle *mmffAngleParams = nullptr;
519 unsigned int iter = 0;
520
521// For bending of the i-j-k angle, a five-stage process based
522// in the level combinations 1-1-1,2-2-2,3-2-3,4-2-4, and
523// 5-2-5 is used. (MMFF.I, note 68, page 519)
524// We skip 1-1-1 since Level 2 === Level 1
525#ifdef RDKIT_MMFF_PARAMS_USE_STD_MAP
526 while ((iter < 4) && (!mmffAngleParams)) {
527 unsigned int canIAtomType = (*mmffDef)(iAtomType)->eqLevel[iter];
528 unsigned int canKAtomType = (*mmffDef)(kAtomType)->eqLevel[iter];
529 if (canIAtomType > canKAtomType) {
530 std::swap(canIAtomType, canKAtomType);
531 }
532 const auto res1 = d_params.find(angleType);
533 if (res1 != d_params.end()) {
534 const auto res2 = ((*res1).second).find(canIAtomType);
535 if (res2 != ((*res1).second).end()) {
536 const auto res3 = ((*res2).second).find(jAtomType);
537 if (res3 != ((*res2).second).end()) {
538 const auto res4 = ((*res3).second).find(canKAtomType);
539 if (res4 != ((*res3).second).end()) {
540 mmffAngleParams = &((*res4).second);
541 }
542 }
543 }
544 }
545 ++iter;
546 }
547#else
548 auto jBounds =
549 std::equal_range(d_jAtomType.begin(), d_jAtomType.end(), jAtomType);
550 if (jBounds.first != jBounds.second) {
551 while ((iter < 4) && (!mmffAngleParams)) {
552 unsigned int canIAtomType = (*mmffDef)(iAtomType)->eqLevel[iter];
553 unsigned int canKAtomType = (*mmffDef)(kAtomType)->eqLevel[iter];
554 if (canIAtomType > canKAtomType) {
555 std::swap(canIAtomType, canKAtomType);
556 }
557
558 auto bounds = std::equal_range(
559 d_iAtomType.begin() + (jBounds.first - d_jAtomType.begin()),
560 d_iAtomType.begin() + (jBounds.second - d_jAtomType.begin()),
561 canIAtomType);
562 if (bounds.first != bounds.second) {
563 bounds = std::equal_range(
564 d_kAtomType.begin() + (bounds.first - d_iAtomType.begin()),
565 d_kAtomType.begin() + (bounds.second - d_iAtomType.begin()),
566 canKAtomType);
567 if (bounds.first != bounds.second) {
568 bounds = std::equal_range(
569 d_angleType.begin() + (bounds.first - d_kAtomType.begin()),
570 d_angleType.begin() + (bounds.second - d_kAtomType.begin()),
571 angleType);
572 if (bounds.first != bounds.second) {
573 mmffAngleParams = &d_params[bounds.first - d_angleType.begin()];
574 }
575 }
576 }
577 ++iter;
578 }
579 }
580#endif
581
582 return mmffAngleParams;
583 }
584
585 MMFFAngleCollection(std::string mmffAngle = "");
586#ifdef RDKIT_MMFF_PARAMS_USE_STD_MAP
587 std::map<const unsigned int,
588 std::map<const unsigned int,
589 std::map<const unsigned int,
590 std::map<const unsigned int, MMFFAngle>>>>
591 d_params; //!< the parameter 4D-map
592#else
593 std::vector<MMFFAngle> d_params; //!< the parameter vector
594 std::vector<std::uint8_t> d_iAtomType; //!< atom type vector for atom i
595 std::vector<std::uint8_t> d_jAtomType; //!< atom type vector for atom j
596 std::vector<std::uint8_t> d_kAtomType; //!< atom type vector for atom k
597 std::vector<std::uint8_t> d_angleType; //!< angle type vector for angle i-j-k
598#endif
599};
600
602 public:
603 //! Looks up the parameters for a particular key and returns them.
604 /*!
605 \return a pointer to the MMFFStbn object, NULL on failure.
606 */
607 const std::pair<bool, const MMFFStbn *> getMMFFStbnParams(
608 const unsigned int stretchBendType, const unsigned int bondType1,
609 const unsigned int bondType2, const unsigned int iAtomType,
610 const unsigned int jAtomType, const unsigned int kAtomType) const {
611 const MMFFStbn *mmffStbnParams = nullptr;
612 bool swap = false;
613 unsigned int canIAtomType = iAtomType;
614 unsigned int canKAtomType = kAtomType;
615 unsigned int canStretchBendType = stretchBendType;
616 if (iAtomType > kAtomType) {
617 canIAtomType = kAtomType;
618 canKAtomType = iAtomType;
619 swap = true;
620 } else if (iAtomType == kAtomType) {
621 swap = (bondType1 < bondType2);
622 }
623#ifdef RDKIT_MMFF_PARAMS_USE_STD_MAP
624 const auto res1 = d_params.find(canStretchBendType);
625 if (res1 != d_params.end()) {
626 const auto res2 = ((*res1).second).find(canIAtomType);
627 if (res2 != ((*res1).second).end()) {
628 const auto res3 = ((*res2).second).find(jAtomType);
629 if (res3 != ((*res2).second).end()) {
630 const auto res4 = ((*res3).second).find(canKAtomType);
631 if (res4 != ((*res3).second).end()) {
632 mmffStbnParams = &((*res4).second);
633 }
634 }
635 }
636 }
637#else
638 auto jBounds =
639 std::equal_range(d_jAtomType.begin(), d_jAtomType.end(), jAtomType);
640 if (jBounds.first != jBounds.second) {
641 auto bounds = std::equal_range(
642 d_iAtomType.begin() + (jBounds.first - d_jAtomType.begin()),
643 d_iAtomType.begin() + (jBounds.second - d_jAtomType.begin()),
644 canIAtomType);
645 if (bounds.first != bounds.second) {
646 bounds = std::equal_range(
647 d_kAtomType.begin() + (bounds.first - d_iAtomType.begin()),
648 d_kAtomType.begin() + (bounds.second - d_iAtomType.begin()),
649 canKAtomType);
650 if (bounds.first != bounds.second) {
651 bounds = std::equal_range(
652 d_stretchBendType.begin() + (bounds.first - d_kAtomType.begin()),
653 d_stretchBendType.begin() + (bounds.second - d_kAtomType.begin()),
654 canStretchBendType);
655 if (bounds.first != bounds.second) {
656 mmffStbnParams =
657 &d_params[bounds.first - d_stretchBendType.begin()];
658 }
659 }
660 }
661 }
662#endif
663
664 return std::make_pair(swap, mmffStbnParams);
665 }
666
667 MMFFStbnCollection(std::string mmffStbn = "");
668#ifdef RDKIT_MMFF_PARAMS_USE_STD_MAP
669 std::map<const unsigned int,
670 std::map<const unsigned int,
671 std::map<const unsigned int,
672 std::map<const unsigned int, MMFFStbn>>>>
673 d_params; //!< the parameter 4D-map
674#else
675 std::vector<MMFFStbn> d_params; //!< the parameter vector
676 std::vector<std::uint8_t> d_iAtomType; //!< atom type vector for atom i
677 std::vector<std::uint8_t> d_jAtomType; //!< atom type vector for atom j
678 std::vector<std::uint8_t> d_kAtomType; //!< atom type vector for atom k
679 std::vector<std::uint8_t>
680 d_stretchBendType; //!< stretch-bend type vector for angle i-j-k
681#endif
682};
683
685 public:
686 //! Looks up the parameters for a particular key and returns them.
687 /*!
688 \return a pointer to the MMFFStbn object, NULL on failure.
689 */
690 const std::pair<bool, const MMFFStbn *> getMMFFDfsbParams(
691 const unsigned int periodicTableRow1,
692 const unsigned int periodicTableRow2,
693 const unsigned int periodicTableRow3) const {
694 const MMFFStbn *mmffDfsbParams = nullptr;
695 bool swap = false;
696 unsigned int canPeriodicTableRow1 = periodicTableRow1;
697 unsigned int canPeriodicTableRow3 = periodicTableRow3;
698 if (periodicTableRow1 > periodicTableRow3) {
699 canPeriodicTableRow1 = periodicTableRow3;
700 canPeriodicTableRow3 = periodicTableRow1;
701 swap = true;
702 }
703 const auto res1 = d_params.find(canPeriodicTableRow1);
704 if (res1 != d_params.end()) {
705 const auto res2 = ((*res1).second).find(periodicTableRow2);
706 if (res2 != ((*res1).second).end()) {
707 const auto res3 = ((*res2).second).find(canPeriodicTableRow3);
708 if (res3 != ((*res2).second).end()) {
709 mmffDfsbParams = &((*res3).second);
710 }
711 }
712 }
713
714 return std::make_pair(swap, mmffDfsbParams);
715 }
716
717 MMFFDfsbCollection(std::string mmffDfsb = "");
718 std::map<const unsigned int,
719 std::map<const unsigned int, std::map<const unsigned int, MMFFStbn>>>
720 d_params; //!< the parameter 3D-map
721};
722
724 public:
725 //! Looks up the parameters for a particular key and returns them.
726 /*!
727 \return a pointer to the MMFFOop object, NULL on failure.
728 */
729 const MMFFOop *operator()(const MMFFDefCollection *mmffDef,
730 const unsigned int iAtomType,
731 const unsigned int jAtomType,
732 const unsigned int kAtomType,
733 const unsigned int lAtomType) const {
734 const MMFFOop *mmffOopParams = nullptr;
735 unsigned int iter = 0;
736 std::vector<unsigned int> canIKLAtomType(3);
737// For out-of-plane bending ijk; I , where j is the central
738// atom [cf. eq. (511, the five-stage protocol 1-1-1; 1, 2-2-2; 2,
739// 3-2-3;3, 4-2-4;4, 5-2-5;5 is used. The final stage provides
740// wild-card defaults for all except the central atom.
741#ifdef RDKIT_MMFF_PARAMS_USE_STD_MAP
742 while ((iter < 4) && (!mmffOopParams)) {
743 canIKLAtomType[0] = (*mmffDef)(iAtomType)->eqLevel[iter];
744 unsigned int canJAtomType = jAtomType;
745 canIKLAtomType[1] = (*mmffDef)(kAtomType)->eqLevel[iter];
746 canIKLAtomType[2] = (*mmffDef)(lAtomType)->eqLevel[iter];
747 std::sort(canIKLAtomType.begin(), canIKLAtomType.end());
748 const auto res1 = d_params.find(canIKLAtomType[0]);
749 if (res1 != d_params.end()) {
750 const auto res2 = ((*res1).second).find(canJAtomType);
751 if (res2 != ((*res1).second).end()) {
752 const auto res3 = ((*res2).second).find(canIKLAtomType[1]);
753 if (res3 != ((*res2).second).end()) {
754 const auto res4 = ((*res3).second).find(canIKLAtomType[2]);
755 if (res4 != ((*res3).second).end()) {
756 mmffOopParams = &((*res4).second);
757 }
758 }
759 }
760 }
761 ++iter;
762 }
763#else
764 auto jBounds =
765 std::equal_range(d_jAtomType.begin(), d_jAtomType.end(), jAtomType);
766 if (jBounds.first != jBounds.second) {
767 while ((iter < 4) && (!mmffOopParams)) {
768 canIKLAtomType[0] = (*mmffDef)(iAtomType)->eqLevel[iter];
769 canIKLAtomType[1] = (*mmffDef)(kAtomType)->eqLevel[iter];
770 canIKLAtomType[2] = (*mmffDef)(lAtomType)->eqLevel[iter];
771 std::sort(canIKLAtomType.begin(), canIKLAtomType.end());
772 auto bounds = std::equal_range(
773 d_iAtomType.begin() + (jBounds.first - d_jAtomType.begin()),
774 d_iAtomType.begin() + (jBounds.second - d_jAtomType.begin()),
775 canIKLAtomType[0]);
776 if (bounds.first != bounds.second) {
777 bounds = std::equal_range(
778 d_kAtomType.begin() + (bounds.first - d_iAtomType.begin()),
779 d_kAtomType.begin() + (bounds.second - d_iAtomType.begin()),
780 canIKLAtomType[1]);
781 if (bounds.first != bounds.second) {
782 bounds = std::equal_range(
783 d_lAtomType.begin() + (bounds.first - d_kAtomType.begin()),
784 d_lAtomType.begin() + (bounds.second - d_kAtomType.begin()),
785 canIKLAtomType[2]);
786 if (bounds.first != bounds.second) {
787 mmffOopParams = &d_params[bounds.first - d_lAtomType.begin()];
788 }
789 }
790 }
791 ++iter;
792 }
793 }
794#endif
795
796 return mmffOopParams;
797 }
798
799 MMFFOopCollection(const bool isMMFFs, std::string mmffOop = "");
800
801#ifdef RDKIT_MMFF_PARAMS_USE_STD_MAP
802 std::map<const unsigned int,
803 std::map<const unsigned int,
804 std::map<const unsigned int,
805 std::map<const unsigned int, MMFFOop>>>>
806 d_params; //!< the parameter 4D-map
807#else
808 std::vector<MMFFOop> d_params; //!< the parameter vector
809 std::vector<std::uint8_t> d_iAtomType; //!< atom type vector for atom i
810 std::vector<std::uint8_t> d_jAtomType; //!< atom type vector for atom j
811 std::vector<std::uint8_t> d_kAtomType; //!< atom type vector for atom k
812 std::vector<std::uint8_t> d_lAtomType; //!< atom type vector for atom l
813#endif
814};
815
817 public:
818 //! Looks up the parameters for a particular key and returns them.
819 /*!
820 \return a pointer to the MMFFTor object, NULL on failure.
821 */
822 const std::pair<const unsigned int, const MMFFTor *> getMMFFTorParams(
823 const MMFFDefCollection *mmffDef,
824 const std::pair<unsigned int, unsigned int> torType,
825 const unsigned int iAtomType, const unsigned int jAtomType,
826 const unsigned int kAtomType, const unsigned int lAtomType) const {
827 const MMFFTor *mmffTorParams = nullptr;
828 unsigned int iter = 0;
829 unsigned int iWildCard = 0;
830 unsigned int lWildCard = 0;
831 unsigned int canTorType = torType.first;
832 unsigned int maxIter = 5;
833// For i-j-k-2 torsion interactions, a five-stage
834// process based on level combinations 1-1-1-1, 2-2-2-2,
835// 3-2-2-5, 5-2-2-3, and 5-2-2-5 is used, where stages 3
836// and 4 correspond to "half-default" or "half-wild-card" entries.
837#ifdef RDKIT_MMFF_PARAMS_USE_STD_MAP
838#else
839#endif
840
841 while (((iter < maxIter) && ((!mmffTorParams) || (maxIter == 4))) ||
842 ((iter == 4) && (torType.first == 5) && torType.second)) {
843 // The rule of setting the torsion type to the value it had
844 // before being set to 5 as a last resort in case parameters
845 // could not be found is not mentioned in MMFF.IV; it was
846 // empirically discovered due to a number of tests in the
847 // MMFF validation suite otherwise failing
848 if ((maxIter == 5) && (iter == 4)) {
849 maxIter = 4;
850 iter = 0;
851 canTorType = torType.second;
852 }
853 iWildCard = iter;
854 lWildCard = iter;
855 if (iter == 1) {
856 iWildCard = 1;
857 lWildCard = 3;
858 } else if (iter == 2) {
859 iWildCard = 3;
860 lWildCard = 1;
861 }
862 unsigned int canIAtomType = (*mmffDef)(iAtomType)->eqLevel[iWildCard];
863 unsigned int canJAtomType = jAtomType;
864 unsigned int canKAtomType = kAtomType;
865 unsigned int canLAtomType = (*mmffDef)(lAtomType)->eqLevel[lWildCard];
866 if (canJAtomType > canKAtomType) {
867 unsigned int temp = canKAtomType;
868 canKAtomType = canJAtomType;
869 canJAtomType = temp;
870 temp = canLAtomType;
871 canLAtomType = canIAtomType;
872 canIAtomType = temp;
873 } else if ((canJAtomType == canKAtomType) &&
874 (canIAtomType > canLAtomType)) {
875 unsigned int temp = canLAtomType;
876 canLAtomType = canIAtomType;
877 canIAtomType = temp;
878 }
879#ifdef RDKIT_MMFF_PARAMS_USE_STD_MAP
880 const auto res1 = d_params.find(canTorType);
881 if (res1 != d_params.end()) {
882 const auto res2 = ((*res1).second).find(canIAtomType);
883 if (res2 != ((*res1).second).end()) {
884 const auto res3 = ((*res2).second).find(canJAtomType);
885 if (res3 != ((*res2).second).end()) {
886 const auto res4 = ((*res3).second).find(canKAtomType);
887 if (res4 != ((*res3).second).end()) {
888 const auto res5 = ((*res4).second).find(canLAtomType);
889 if (res5 != ((*res4).second).end()) {
890 mmffTorParams = &((*res5).second);
891 if (maxIter == 4) {
892 break;
893 }
894 }
895 }
896 }
897 }
898 }
899#else
900 auto jBounds = std::equal_range(d_jAtomType.begin(), d_jAtomType.end(),
901 canJAtomType);
902 if (jBounds.first != jBounds.second) {
903 auto bounds = std::equal_range(
904 d_kAtomType.begin() + (jBounds.first - d_jAtomType.begin()),
905 d_kAtomType.begin() + (jBounds.second - d_jAtomType.begin()),
906 canKAtomType);
907 if (bounds.first != bounds.second) {
908 bounds = std::equal_range(
909 d_iAtomType.begin() + (bounds.first - d_kAtomType.begin()),
910 d_iAtomType.begin() + (bounds.second - d_kAtomType.begin()),
911 canIAtomType);
912 if (bounds.first != bounds.second) {
913 bounds = std::equal_range(
914 d_lAtomType.begin() + (bounds.first - d_iAtomType.begin()),
915 d_lAtomType.begin() + (bounds.second - d_iAtomType.begin()),
916 canLAtomType);
917 if (bounds.first != bounds.second) {
918 bounds = std::equal_range(
919 d_torType.begin() + (bounds.first - d_lAtomType.begin()),
920 d_torType.begin() + (bounds.second - d_lAtomType.begin()),
921 canTorType);
922 if (bounds.first != bounds.second) {
923 mmffTorParams = &d_params[bounds.first - d_torType.begin()];
924 if (maxIter == 4) {
925 break;
926 }
927 }
928 }
929 }
930 }
931 }
932#endif
933 ++iter;
934 }
935
936 return std::make_pair(canTorType, mmffTorParams);
937 }
938
939 MMFFTorCollection(const bool isMMFFs, std::string mmffTor = "");
940#ifdef RDKIT_MMFF_PARAMS_USE_STD_MAP
941 std::map<
942 const unsigned int,
943 std::map<
944 const unsigned int,
945 std::map<const unsigned int,
946 std::map<const unsigned int, std::map<const unsigned int,
947 MMFFTor>>>>>
948 d_params; //!< the parameter 5D-map
949#else
950 std::vector<MMFFTor> d_params; //!< the parameter vector
951 std::vector<std::uint8_t> d_iAtomType; //!< atom type vector for atom i
952 std::vector<std::uint8_t> d_jAtomType; //!< atom type vector for atom j
953 std::vector<std::uint8_t> d_kAtomType; //!< atom type vector for atom k
954 std::vector<std::uint8_t> d_lAtomType; //!< atom type vector for atom l
955 std::vector<std::uint8_t>
956 d_torType; //!< torsion type vector for angle i-j-k-l
957#endif
958};
959
961 public:
962 //! gets a pointer to the singleton MMFFVdWCollection
963 double power;
964 double B;
965 double Beta;
966 double DARAD;
967 double DAEPS;
968 //! Looks up the parameters for a particular key and returns them.
969 /*!
970 \return a pointer to the MMFFVdW object, NULL on failure.
971 */
972 const MMFFVdW *operator()(const unsigned int atomType) const {
973#ifdef RDKIT_MMFF_PARAMS_USE_STD_MAP
974 const auto res = d_params.find(atomType);
975 return (res != d_params.end() ? &((*res).second) : NULL);
976#else
977 auto bounds =
978 std::equal_range(d_atomType.begin(), d_atomType.end(), atomType);
979 return ((bounds.first != bounds.second)
980 ? &d_params[bounds.first - d_atomType.begin()]
981 : nullptr);
982#endif
983 }
984
985 MMFFVdWCollection(std::string mmffVdW = "");
986#ifdef RDKIT_MMFF_PARAMS_USE_STD_MAP
987 std::map<const unsigned int, MMFFVdW> d_params; //!< the parameter map
988#else
989 std::vector<MMFFVdW> d_params; //!< the parameter vector
990 std::vector<std::uint8_t> d_atomType; //!< atom type vector
991#endif
992};
993} // namespace MMFF
994} // namespace ForceFields
995
996#endif
#define M_PI
Definition MMFF/Params.h:25
const MMFFAngle * operator()(const MMFFDefCollection *mmffDef, const unsigned int angleType, const unsigned int iAtomType, const unsigned int jAtomType, const unsigned int kAtomType) const
Looks up the parameters for a particular key and returns them.
std::vector< MMFFAngle > d_params
the parameter vector
std::vector< std::uint8_t > d_angleType
angle type vector for angle i-j-k
MMFFAngleCollection(std::string mmffAngle="")
std::vector< std::uint8_t > d_kAtomType
atom type vector for atom k
std::vector< std::uint8_t > d_jAtomType
atom type vector for atom j
std::vector< std::uint8_t > d_iAtomType
atom type vector for atom i
class to store MMFF parameters for angle bending
MMFFAromCollection(const std::vector< std::uint8_t > *mmffArom=nullptr)
std::vector< std::uint8_t > d_params
the aromatic type vector
bool isMMFFAromatic(const unsigned int atomType) const
Looks up the parameters for a particular key and returns them.
MMFFBndkCollection(std::string mmffBndk="")
std::vector< std::uint8_t > d_jAtomicNum
atomic number vector for atom j
std::vector< std::uint8_t > d_iAtomicNum
atomic number vector for atom i
std::vector< MMFFBond > d_params
the parameter vector
const MMFFBond * operator()(const int atomicNum, const int nbrAtomicNum) const
Looks up the parameters for a particular key and returns them.
std::vector< std::uint8_t > d_jAtomType
atom type vector for atom j
std::vector< std::uint8_t > d_bondType
bond type vector for bond i-j
std::vector< std::uint8_t > d_iAtomType
atom type vector for atom i
MMFFBondCollection(std::string mmffBond="")
const MMFFBond * operator()(const unsigned int bondType, const unsigned int atomType, const unsigned int nbrAtomType) const
Looks up the parameters for a particular key and returns them.
std::vector< MMFFBond > d_params
the parameter vector
class to store MMFF parameters for bond stretching
Definition MMFF/Params.h:80
std::vector< MMFFChg > d_params
the parameter vector
std::vector< std::uint8_t > d_jAtomType
atom type vector for atom j
MMFFChgCollection(std::string mmffChg="")
the parameter 3D-map
const std::pair< int, const MMFFChg * > getMMFFChgParams(const unsigned int bondType, const unsigned int iAtomType, const unsigned int jAtomType) const
Looks up the parameters for a particular key and returns them.
std::vector< std::uint8_t > d_iAtomType
atom type vector for atom i
std::vector< std::uint8_t > d_bondType
bond type vector for bond i-j
const MMFFCovRadPauEle * operator()(const unsigned int atomicNum) const
Looks up the parameters for a particular key and returns them.
std::vector< MMFFCovRadPauEle > d_params
the parameter vector
std::vector< std::uint8_t > d_atomicNum
the atomic number vector
MMFFCovRadPauEleCollection(std::string mmffCovRadPauEle="")
const MMFFDef * operator()(const unsigned int atomType) const
Looks up the parameters for a particular key and returns them.
std::vector< MMFFDef > d_params
the parameter vector
MMFFDefCollection(std::string mmffDef="")
class to store MMFF atom type equivalence levels
Definition MMFF/Params.h:47
std::uint8_t eqLevel[4]
Definition MMFF/Params.h:49
const std::pair< bool, const MMFFStbn * > getMMFFDfsbParams(const unsigned int periodicTableRow1, const unsigned int periodicTableRow2, const unsigned int periodicTableRow3) const
Looks up the parameters for a particular key and returns them.
MMFFDfsbCollection(std::string mmffDfsb="")
std::map< const unsigned int, std::map< const unsigned int, std::map< const unsigned int, MMFFStbn > > > d_params
the parameter 3D-map
const MMFFHerschbachLaurie * operator()(const int iRow, const int jRow) const
Looks up the parameters for a particular key and returns them.
std::vector< std::uint8_t > d_iRow
periodic row number vector for atom i
std::vector< std::uint8_t > d_jRow
periodic row number vector for atom j
MMFFHerschbachLaurieCollection(std::string mmffHerschbachLaurie="")
std::vector< MMFFHerschbachLaurie > d_params
the parameter vector
MMFFOopCollection(const bool isMMFFs, std::string mmffOop="")
std::vector< std::uint8_t > d_iAtomType
atom type vector for atom i
std::vector< std::uint8_t > d_kAtomType
atom type vector for atom k
std::vector< MMFFOop > d_params
the parameter vector
const MMFFOop * operator()(const MMFFDefCollection *mmffDef, const unsigned int iAtomType, const unsigned int jAtomType, const unsigned int kAtomType, const unsigned int lAtomType) const
Looks up the parameters for a particular key and returns them.
std::vector< std::uint8_t > d_jAtomType
atom type vector for atom j
std::vector< std::uint8_t > d_lAtomType
atom type vector for atom l
class to store MMFF parameters for out-of-plane bending
const MMFFPBCI * operator()(const unsigned int atomType) const
Looks up the parameters for a particular key and returns them.
MMFFPBCICollection(std::string mmffPBCI="")
std::vector< MMFFPBCI > d_params
the parameter vector
class to store MMFF Partial Bond Charge Increments
Definition MMFF/Params.h:66
const MMFFProp * operator()(const unsigned int atomType) const
Looks up the parameters for a particular key and returns them.
std::vector< MMFFProp > d_params
MMFFPropCollection(std::string mmffProp="")
std::vector< std::uint8_t > d_iAtomType
the parameter vector
class to store MMFF Properties
Definition MMFF/Params.h:53
const std::pair< bool, const MMFFStbn * > getMMFFStbnParams(const unsigned int stretchBendType, const unsigned int bondType1, const unsigned int bondType2, const unsigned int iAtomType, const unsigned int jAtomType, const unsigned int kAtomType) const
Looks up the parameters for a particular key and returns them.
MMFFStbnCollection(std::string mmffStbn="")
std::vector< std::uint8_t > d_jAtomType
atom type vector for atom j
std::vector< std::uint8_t > d_stretchBendType
stretch-bend type vector for angle i-j-k
std::vector< MMFFStbn > d_params
the parameter vector
std::vector< std::uint8_t > d_kAtomType
atom type vector for atom k
std::vector< std::uint8_t > d_iAtomType
atom type vector for atom i
class to store MMFF parameters for stretch-bending
std::vector< std::uint8_t > d_jAtomType
atom type vector for atom j
MMFFTorCollection(const bool isMMFFs, std::string mmffTor="")
std::vector< std::uint8_t > d_kAtomType
atom type vector for atom k
std::vector< std::uint8_t > d_torType
torsion type vector for angle i-j-k-l
const std::pair< const unsigned int, const MMFFTor * > getMMFFTorParams(const MMFFDefCollection *mmffDef, const std::pair< unsigned int, unsigned int > torType, const unsigned int iAtomType, const unsigned int jAtomType, const unsigned int kAtomType, const unsigned int lAtomType) const
Looks up the parameters for a particular key and returns them.
std::vector< std::uint8_t > d_lAtomType
atom type vector for atom l
std::vector< MMFFTor > d_params
the parameter vector
std::vector< std::uint8_t > d_iAtomType
atom type vector for atom i
class to store MMFF parameters for torsions
double power
gets a pointer to the singleton MMFFVdWCollection
std::vector< MMFFVdW > d_params
the parameter vector
MMFFVdWCollection(std::string mmffVdW="")
std::vector< std::uint8_t > d_atomType
atom type vector
const MMFFVdW * operator()(const unsigned int atomType) const
Looks up the parameters for a particular key and returns them.
class to store MMFF parameters for non-bonded Van der Waals
#define RDKIT_FORCEFIELD_EXPORT
Definition export.h:201
constexpr double RAD2DEG
Definition MMFF/Params.h:39
constexpr double MDYNE_A_TO_KCAL_MOL
Definition MMFF/Params.h:40
bool isDoubleZero(const double x)
Definition MMFF/Params.h:41
constexpr double DEG2RAD
Definition MMFF/Params.h:38
void clipToOne(double &x)
Definition MMFF/Params.h:44