29 #ifndef CDPL_FORCEFIELD_UTILITYFUNCTIONS_HPP
30 #define CDPL_FORCEFIELD_UTILITYFUNCTIONS_HPP
44 class MMFF94InteractionData;
63 template <
typename ValueType,
typename CoordsVec>
81 template <
typename ValueType,
typename CoordsVec>
82 ValueType
calcDistance(
const CoordsVec& atom1_pos,
const CoordsVec& atom2_pos);
107 template <
typename ValueType,
typename CoordsVec>
109 ValueType& bond_length1, ValueType& bond_length2);
134 template <
typename ValueType,
typename CoordsVec>
135 ValueType
calcBondLengthsAndAngle(
const CoordsVec& term_atom1_pos,
const CoordsVec& ctr_atom_pos,
const CoordsVec& term_atom2_pos,
136 ValueType& bond_length1, ValueType& bond_length2);
156 template <
typename ValueType,
typename CoordsVec>
157 ValueType
calcBondAngleCos(
const CoordsVec& term_atom1_pos,
const CoordsVec& ctr_atom_pos,
const CoordsVec& term_atom2_pos);
179 template <
typename ValueType,
typename CoordsVec>
180 ValueType
calcBondAngleCos(
const CoordsVec& term_atom1_pos,
const CoordsVec& ctr_atom_pos,
const CoordsVec& term_atom2_pos,
181 const ValueType& r_ij,
const ValueType& r_jk);
201 template <
typename ValueType,
typename CoordsVec>
202 ValueType
calcBondAngle(
const CoordsVec& term_atom1_pos,
const CoordsVec& ctr_atom_pos,
const CoordsVec& term_atom2_pos);
224 template <
typename ValueType,
typename CoordsVec>
225 ValueType
calcBondAngle(
const CoordsVec& term_atom1_pos,
const CoordsVec& ctr_atom_pos,
const CoordsVec& term_atom2_pos,
226 const ValueType& r_ij,
const ValueType& r_jk);
250 template <
typename ValueType,
typename CoordsVec>
252 const CoordsVec& term_atom2_pos,
const CoordsVec& oop_atom_pos);
277 template <
typename ValueType,
typename CoordsVec>
279 const CoordsVec& term_atom2_pos,
const CoordsVec& oop_atom_pos,
280 const ValueType& r_jl);
305 template <
typename ValueType,
typename CoordsVec>
307 const CoordsVec& ctr_atom2_pos,
const CoordsVec& term_atom2_pos);
331 template <
typename ValueType,
typename CoordsVec,
typename GradVec>
333 GradVec& atom1_deriv, GradVec& atom2_deriv);
365 template <
typename ValueType,
typename CoordsVec,
typename GradVec>
367 GradVec& term_atom1_deriv, GradVec& ctr_atom_deriv, GradVec& term_atom2_deriv);
410 template <
typename ValueType,
typename CoordsVec,
typename GradVec>
412 const CoordsVec& ctr_atom2_pos,
const CoordsVec& term_atom2_pos,
413 GradVec& term_atom1_deriv, GradVec& ctr_atom1_deriv,
414 GradVec& ctr_atom2_deriv, GradVec& term_atom2_deriv);
477 template <
typename ValueType,
typename CoordsVec,
typename GradVec>
479 const CoordsVec& term_atom2_pos,
const CoordsVec& oop_atom_pos,
480 GradVec& term_atom1_deriv, GradVec& ctr_atom_deriv,
481 GradVec& term_atom2_deriv, GradVec& oop_atom_deriv);
498 template <
typename VecType1,
typename VecType2,
typename VecType3>
499 void addVectors(
const VecType1& vec1,
const VecType2& vec2, VecType3& res)
501 res[0] = vec2[0] + vec1[0];
502 res[1] = vec2[1] + vec1[1];
503 res[2] = vec2[2] + vec1[2];
506 template <
typename VecType1,
typename VecType2>
507 void subVectors(
const VecType1& vec1,
const VecType1& vec2, VecType2& res)
509 res[0] = vec2[0] - vec1[0];
510 res[1] = vec2[1] - vec1[1];
511 res[2] = vec2[2] - vec1[2];
514 template <
typename ValueType,
typename VecType>
515 ValueType calcDotProduct(
const VecType& vec1,
const VecType& vec2)
517 return (vec1[0] * vec2[0] + vec1[1] * vec2[1] + vec1[2] * vec2[2]);
520 template <
typename VecType,
typename ResVecType>
521 void calcCrossProduct(
const VecType& vec1,
const VecType& vec2, ResVecType& cross_prod)
523 cross_prod[0] = vec1[1] * vec2[2] - vec1[2] * vec2[1];
524 cross_prod[1] = vec1[2] * vec2[0] - vec1[0] * vec2[2];
525 cross_prod[2] = vec1[0] * vec2[1] - vec1[1] * vec2[0];
528 template <
typename VecType1,
typename VecType2>
529 void copyVector(
const VecType1& vec1, VecType2& vec2)
536 template <
typename VecType>
537 void negateVector(VecType&
vec)
544 template <
typename VecType1,
typename VecType2>
545 void negateCopyVector(
const VecType1& vec1, VecType2& vec2)
552 template <
typename VecType,
typename T>
553 void scaleVector(VecType&
vec,
const T& factor)
560 template <
typename VecType,
typename T>
561 void invScaleVector(VecType&
vec,
const T& factor)
568 template <
typename VecType1,
typename VecType2,
typename T>
569 void scaleAddVector(
const VecType1& vec1,
const T& factor, VecType2& vec2)
571 vec2[0] += vec1[0] * factor;
572 vec2[1] += vec1[1] * factor;
573 vec2[2] += vec1[2] * factor;
576 template <
typename VecType1,
typename VecType2,
typename T>
577 void scaleCopyVector(
const VecType1& vec1,
const T& factor, VecType2& vec2)
579 vec2[0] = vec1[0] * factor;
580 vec2[1] = vec1[1] * factor;
581 vec2[2] = vec1[2] * factor;
584 template <
typename VecType1,
typename VecType2,
typename T>
585 void invScaleCopyVector(
const VecType1& vec1,
const T& factor, VecType2& vec2)
587 vec2[0] = vec1[0] / factor;
588 vec2[1] = vec1[1] / factor;
589 vec2[2] = vec1[2] / factor;
592 template <
typename ValueType>
593 ValueType clampCosine(
const ValueType& v)
595 if (v > ValueType(1))
598 if (v < ValueType(-1))
599 return ValueType(-1);
608 template <
typename ValueType,
typename CoordsVec>
611 ValueType pos_diff[3];
613 Detail::subVectors(atom1_pos, atom2_pos, pos_diff);
615 return Detail::calcDotProduct<ValueType>(pos_diff, pos_diff);
618 template <
typename ValueType,
typename CoordsVec>
621 return std::sqrt(calcSquaredDistance<ValueType>(atom1_pos, atom2_pos));
624 template <
typename ValueType,
typename CoordsVec>
626 ValueType& bond_length1, ValueType& bond_length2)
628 ValueType bond_vec1[3];
629 ValueType bond_vec2[3];
631 Detail::subVectors(ctr_atom_pos, term_atom1_pos, bond_vec1);
632 Detail::subVectors(ctr_atom_pos, term_atom2_pos, bond_vec2);
634 bond_length1 = std::sqrt(Detail::calcDotProduct<ValueType>(bond_vec1, bond_vec1));
635 bond_length2 = std::sqrt(Detail::calcDotProduct<ValueType>(bond_vec2, bond_vec2));
637 return Detail::clampCosine(Detail::calcDotProduct<ValueType>(bond_vec1, bond_vec2) / (bond_length1 * bond_length2));
640 template <
typename ValueType,
typename CoordsVec>
642 ValueType& bond_length1, ValueType& bond_length2)
647 template <
typename ValueType,
typename CoordsVec>
655 template <
typename ValueType,
typename CoordsVec>
657 const ValueType& r_ij,
const ValueType& r_jk)
659 ValueType bond_vec1[3];
660 ValueType bond_vec2[3];
662 Detail::subVectors(ctr_atom_pos, term_atom1_pos, bond_vec1);
663 Detail::subVectors(ctr_atom_pos, term_atom2_pos, bond_vec2);
665 return Detail::clampCosine(Detail::calcDotProduct<ValueType>(bond_vec1, bond_vec2) / (r_ij * r_jk));
668 template <
typename ValueType,
typename CoordsVec>
671 return std::acos(calcBondAngleCos<ValueType>(term_atom1_pos, ctr_atom_pos, term_atom2_pos));
674 template <
typename ValueType,
typename CoordsVec>
676 const ValueType& r_ij,
const ValueType& r_jk)
678 return std::acos(calcBondAngleCos<ValueType>(term_atom1_pos, ctr_atom_pos, term_atom2_pos, r_ij, r_jk));
681 template <
typename ValueType,
typename CoordsVec>
683 const CoordsVec& term_atom2_pos,
const CoordsVec& oop_atom_pos)
685 ValueType term_bond1_vec[3];
686 ValueType term_bond2_vec[3];
687 ValueType oop_bond_vec[3];
688 ValueType plane_normal[3];
690 Detail::subVectors(ctr_atom_pos, term_atom1_pos, term_bond1_vec);
691 Detail::subVectors(ctr_atom_pos, term_atom2_pos, term_bond2_vec);
692 Detail::subVectors(ctr_atom_pos, oop_atom_pos, oop_bond_vec);
693 Detail::calcCrossProduct(term_bond1_vec, term_bond2_vec, plane_normal);
695 ValueType pn_len = std::sqrt(Detail::calcDotProduct<ValueType>(plane_normal, plane_normal));
696 ValueType oop_bnd_len = std::sqrt(Detail::calcDotProduct<ValueType>(oop_bond_vec, oop_bond_vec));
697 ValueType ang_cos = Detail::clampCosine(Detail::calcDotProduct<ValueType>(plane_normal, oop_bond_vec) / (pn_len * oop_bnd_len));
699 return (ValueType(M_PI * 0.5) - std::acos(ang_cos));
702 template <
typename ValueType,
typename CoordsVec>
704 const CoordsVec& term_atom2_pos,
const CoordsVec& oop_atom_pos,
705 const ValueType& r_jl)
707 ValueType term_bond1_vec[3];
708 ValueType term_bond2_vec[3];
709 ValueType oop_bond_vec[3];
710 ValueType plane_normal[3];
712 Detail::subVectors(ctr_atom_pos, term_atom1_pos, term_bond1_vec);
713 Detail::subVectors(ctr_atom_pos, term_atom2_pos, term_bond2_vec);
714 Detail::subVectors(ctr_atom_pos, oop_atom_pos, oop_bond_vec);
715 Detail::calcCrossProduct(term_bond1_vec, term_bond2_vec, plane_normal);
717 ValueType pn_len = std::sqrt(Detail::calcDotProduct<ValueType>(plane_normal, plane_normal));
718 ValueType ang_cos = Detail::clampCosine(Detail::calcDotProduct<ValueType>(plane_normal, oop_bond_vec) / (pn_len * r_jl));
720 return (ValueType(M_PI * 0.5) - std::acos(ang_cos));
723 template <
typename ValueType,
typename CoordsVec>
725 const CoordsVec& ctr_atom2_pos,
const CoordsVec& term_atom2_pos)
727 ValueType term_bond1_vec[3];
728 ValueType ctr_bond_vec[3];
729 ValueType term_bond2_vec[3];
730 ValueType plane_normal1[3];
731 ValueType plane_normal2[3];
733 Detail::subVectors(ctr_atom1_pos, term_atom1_pos, term_bond1_vec);
734 Detail::subVectors(ctr_atom1_pos, ctr_atom2_pos, ctr_bond_vec);
735 Detail::subVectors(term_atom2_pos, ctr_atom2_pos, term_bond2_vec);
737 Detail::calcCrossProduct(term_bond1_vec, ctr_bond_vec, plane_normal1);
738 Detail::calcCrossProduct(ctr_bond_vec, term_bond2_vec, plane_normal2);
740 ValueType pn1_len = std::sqrt(Detail::calcDotProduct<ValueType>(plane_normal1, plane_normal1));
741 ValueType pn2_len = std::sqrt(Detail::calcDotProduct<ValueType>(plane_normal2, plane_normal2));
743 return Detail::clampCosine(Detail::calcDotProduct<ValueType>(plane_normal1, plane_normal2) / (pn1_len * pn2_len));
746 template <
typename ValueType,
typename CoordsVec,
typename GradVec>
748 GradVec& atom1_deriv, GradVec& atom2_deriv)
750 Detail::subVectors(atom1_pos, atom2_pos, atom1_deriv);
752 ValueType dist = std::sqrt(Detail::calcDotProduct<ValueType>(atom1_deriv, atom1_deriv));
754 Detail::invScaleVector(atom1_deriv, -dist);
755 Detail::negateCopyVector(atom1_deriv, atom2_deriv);
760 template <
typename ValueType,
typename CoordsVec,
typename GradVec>
762 GradVec& term_atom1_deriv, GradVec& ctr_atom_deriv, GradVec& term_atom2_deriv)
764 ValueType bond_vec1[3];
765 ValueType bond_vec2[3];
767 Detail::subVectors(ctr_atom_pos, term_atom1_pos, bond_vec1);
768 Detail::subVectors(ctr_atom_pos, term_atom2_pos, bond_vec2);
770 ValueType bond_length1 = std::sqrt(Detail::calcDotProduct<ValueType>(bond_vec1, bond_vec1));
771 ValueType bond_length2 = std::sqrt(Detail::calcDotProduct<ValueType>(bond_vec2, bond_vec2));
773 ValueType dot_prod = Detail::calcDotProduct<ValueType>(bond_vec1, bond_vec2);
774 ValueType bl_prod = bond_length1 * bond_length2;
776 Detail::invScaleCopyVector(bond_vec2, bl_prod, term_atom1_deriv);
777 Detail::scaleCopyVector(bond_vec1, dot_prod / (bond_length1 * bond_length1 * bl_prod), ctr_atom_deriv);
778 Detail::subVectors(ctr_atom_deriv, term_atom1_deriv, term_atom1_deriv);
780 Detail::invScaleCopyVector(bond_vec1, bl_prod, term_atom2_deriv);
781 Detail::scaleCopyVector(bond_vec2, dot_prod / (bond_length2 * bond_length2 * bl_prod), ctr_atom_deriv);
782 Detail::subVectors(ctr_atom_deriv, term_atom2_deriv, term_atom2_deriv);
784 Detail::negateCopyVector(term_atom1_deriv, ctr_atom_deriv);
785 Detail::subVectors(term_atom2_deriv, ctr_atom_deriv, ctr_atom_deriv);
787 return Detail::clampCosine(dot_prod / bl_prod);
790 template <
typename ValueType,
typename CoordsVec,
typename GradVec>
792 const CoordsVec& ctr_atom2_pos,
const CoordsVec& term_atom2_pos,
793 GradVec& term_atom1_deriv, GradVec& ctr_atom1_deriv,
794 GradVec& ctr_atom2_deriv, GradVec& term_atom2_deriv)
796 ValueType term_bond1_vec[3];
797 ValueType ctr_bond_vec[3];
798 ValueType term_bond2_vec[3];
799 ValueType term1_ctr2_vec[3];
800 ValueType plane_normal1[3];
801 ValueType plane_normal2[3];
803 Detail::subVectors(ctr_atom1_pos, term_atom1_pos, term_bond1_vec);
804 Detail::subVectors(ctr_atom1_pos, ctr_atom2_pos, ctr_bond_vec);
805 Detail::subVectors(term_atom2_pos, ctr_atom2_pos, term_bond2_vec);
806 Detail::subVectors(ctr_atom2_pos, term_atom1_pos, term1_ctr2_vec);
808 Detail::calcCrossProduct(term_bond1_vec, ctr_bond_vec, plane_normal1);
809 Detail::calcCrossProduct(ctr_bond_vec, term_bond2_vec, plane_normal2);
811 ValueType pn1_len = std::sqrt(Detail::calcDotProduct<ValueType>(plane_normal1, plane_normal1));
812 ValueType pn2_len = std::sqrt(Detail::calcDotProduct<ValueType>(plane_normal2, plane_normal2));
814 Detail::invScaleVector(plane_normal1, pn1_len);
815 Detail::invScaleVector(plane_normal2, pn2_len);
817 ValueType ang_cos = Detail::clampCosine(Detail::calcDotProduct<ValueType>(plane_normal1, plane_normal2));
822 Detail::scaleCopyVector(plane_normal1, -ang_cos, a);
823 Detail::addVectors(a, plane_normal2, a);
824 Detail::invScaleVector(a, pn1_len);
826 Detail::scaleCopyVector(plane_normal2, -ang_cos, b);
827 Detail::addVectors(b, plane_normal1, b);
828 Detail::invScaleVector(b, pn2_len);
830 Detail::calcCrossProduct(ctr_bond_vec, a, term_atom1_deriv);
831 Detail::calcCrossProduct(ctr_bond_vec, b, term_atom2_deriv);
833 Detail::calcCrossProduct(term1_ctr2_vec, a, ctr_atom1_deriv);
834 Detail::calcCrossProduct(term_bond2_vec, b, ctr_atom2_deriv);
836 Detail::subVectors(ctr_atom2_deriv, ctr_atom1_deriv, ctr_atom1_deriv);
838 Detail::addVectors(term_atom1_deriv, ctr_atom1_deriv, ctr_atom2_deriv);
839 Detail::addVectors(ctr_atom2_deriv, term_atom2_deriv, ctr_atom2_deriv);
840 Detail::negateVector(ctr_atom2_deriv);
845 template <
typename ValueType,
typename CoordsVec,
typename GradVec>
847 const CoordsVec& term_atom2_pos,
const CoordsVec& oop_atom_pos,
848 GradVec& term_atom1_deriv, GradVec& ctr_atom_deriv,
849 GradVec& term_atom2_deriv, GradVec& oop_atom_deriv)
851 ValueType term_bond1_vec[3];
852 ValueType term_bond2_vec[3];
853 ValueType oop_bond_vec[3];
854 ValueType term1_oop_vec[3];
855 ValueType term2_oop_vec[3];
858 Detail::subVectors(ctr_atom_pos, term_atom1_pos, term_bond1_vec);
859 Detail::subVectors(ctr_atom_pos, term_atom2_pos, term_bond2_vec);
860 Detail::subVectors(ctr_atom_pos, oop_atom_pos, oop_bond_vec);
861 Detail::subVectors(term_atom2_pos, oop_atom_pos, term2_oop_vec);
862 Detail::subVectors(term_atom1_pos, oop_atom_pos, term1_oop_vec);
864 Detail::calcCrossProduct(term_bond1_vec, term_bond2_vec, ijk_pn);
866 ValueType ijk_pn_len_2 = Detail::calcDotProduct<ValueType>(ijk_pn, ijk_pn);
867 ValueType ijk_pn_len = std::sqrt(ijk_pn_len_2);
868 ValueType oop_bnd_len = std::sqrt(Detail::calcDotProduct<ValueType>(oop_bond_vec, oop_bond_vec));
869 ValueType oop_ijk_pn_len_prod = ijk_pn_len * oop_bnd_len;
870 ValueType oop_ijk_pn_dot_prod = Detail::calcDotProduct<ValueType>(ijk_pn, oop_bond_vec);
871 ValueType ang_cos = Detail::clampCosine(oop_ijk_pn_dot_prod / oop_ijk_pn_len_prod);
876 Detail::calcCrossProduct(term_bond2_vec, oop_bond_vec, kjl_pn);
877 Detail::calcCrossProduct(oop_bond_vec, term_bond1_vec, lji_pn);
879 ctr_atom_deriv[0] = ijk_pn[1] * -term_bond2_vec[2] + ijk_pn[2] * term_bond2_vec[1];
880 ctr_atom_deriv[1] = ijk_pn[0] * term_bond2_vec[2] + ijk_pn[2] * -term_bond2_vec[0];
881 ctr_atom_deriv[2] = ijk_pn[0] * -term_bond2_vec[1] + ijk_pn[1] * term_bond2_vec[0];
883 Detail::scaleVector(ctr_atom_deriv, ang_cos / ijk_pn_len_2);
885 Detail::invScaleCopyVector(kjl_pn, oop_ijk_pn_len_prod, term_atom1_deriv);
886 Detail::subVectors(ctr_atom_deriv, term_atom1_deriv, term_atom1_deriv);
888 ctr_atom_deriv[0] = ijk_pn[1] * term_bond1_vec[2] + ijk_pn[2] * -term_bond1_vec[1];
889 ctr_atom_deriv[1] = ijk_pn[0] * -term_bond1_vec[2] + ijk_pn[2] * term_bond1_vec[0];
890 ctr_atom_deriv[2] = ijk_pn[0] * term_bond1_vec[1] + ijk_pn[1] * -term_bond1_vec[0];
892 Detail::scaleVector(ctr_atom_deriv, ang_cos / ijk_pn_len_2);
894 Detail::invScaleCopyVector(lji_pn, oop_ijk_pn_len_prod, term_atom2_deriv);
895 Detail::subVectors(ctr_atom_deriv, term_atom2_deriv, term_atom2_deriv);
897 Detail::calcCrossProduct(term2_oop_vec, term1_oop_vec, ctr_atom_deriv);
899 Detail::scaleCopyVector(oop_bond_vec, oop_ijk_pn_dot_prod / (oop_bnd_len * oop_bnd_len), oop_atom_deriv);
900 Detail::addVectors(oop_atom_deriv, lji_pn, oop_atom_deriv);
901 Detail::addVectors(oop_atom_deriv, kjl_pn, oop_atom_deriv);
902 Detail::addVectors(oop_atom_deriv, ctr_atom_deriv, oop_atom_deriv);
903 Detail::invScaleVector(oop_atom_deriv, -oop_ijk_pn_len_prod);
905 Detail::copyVector(term_atom1_deriv, ctr_atom_deriv);
906 Detail::addVectors(term_atom2_deriv, ctr_atom_deriv, ctr_atom_deriv);
907 Detail::addVectors(oop_atom_deriv, ctr_atom_deriv, ctr_atom_deriv);
908 Detail::negateVector(ctr_atom_deriv);
915 #endif // CDPL_FORCEFIELD_UTILITYFUNCTIONS_HPP