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