29 #ifndef CDPL_FORCEFIELD_MMFF94GRADIENTFUNCTIONS_HPP
30 #define CDPL_FORCEFIELD_MMFF94GRADIENTFUNCTIONS_HPP
50 template <
typename ValueType,
typename Iter,
typename CoordsArray,
typename GradVector>
53 template <
typename ValueType,
typename CoordsArray,
typename GradVector>
94 template <
typename ValueType,
typename CoordsVec,
typename GradVec>
96 const ValueType& force_const,
const ValueType& ref_length);
99 template <
typename ValueType,
typename Iter,
typename CoordsArray,
typename GradVector>
102 template <
typename ValueType,
typename CoordsArray,
typename GradVector>
154 template <
typename ValueType,
typename CoordsVec,
typename GradVec>
156 GradVec& term_atom1_grad, GradVec& ctr_atom_grad, GradVec& term_atom2_grad,
bool linear,
157 const ValueType& force_const,
const ValueType& ref_angle);
160 template <
typename ValueType,
typename Iter,
typename CoordsArray,
typename GradVector>
163 template <
typename ValueType,
typename CoordsArray,
typename GradVector>
215 template <
typename ValueType,
typename CoordsVec,
typename GradVec>
218 GradVec& ctr_atom_grad, GradVec& term_atom2_grad,
const ValueType& ijk_force_const,
const ValueType& kji_force_const,
219 const ValueType& ref_angle,
const ValueType& ref_length1,
const ValueType& ref_length2);
222 template <
typename ValueType,
typename Iter,
typename CoordsArray,
typename GradVector>
225 template <
typename ValueType,
typename CoordsArray,
typename GradVector>
265 template <
typename ValueType,
typename CoordsVec,
typename GradVec>
267 const CoordsVec& oop_atom_pos, GradVec& term_atom1_grad, GradVec& ctr_atom_grad, GradVec& term_atom2_grad,
268 GradVec& oop_atom_grad,
const ValueType& force_const);
271 template <
typename ValueType,
typename Iter,
typename CoordsArray,
typename GradVector>
274 template <
typename ValueType,
typename CoordsArray,
typename GradVector>
316 template <
typename ValueType,
typename CoordsVec,
typename GradVec>
318 const CoordsVec& term_atom2_pos, GradVec& term_atom1_grad, GradVec& ctr_atom1_grad, GradVec& ctr_atom2_grad,
319 GradVec& term_atom2_grad,
const ValueType& tor_param1,
const ValueType& tor_param2,
const ValueType& tor_param3);
322 template <
typename ValueType,
typename Iter,
typename CoordsArray,
typename GradVector>
325 template <
typename ValueType,
typename CoordsArray,
typename GradVector>
369 template <
typename ValueType,
typename CoordsVec,
typename GradVec>
371 const ValueType& atom1_chg,
const ValueType& atom2_chg,
const ValueType& scale_fact,
372 const ValueType& de_const,
const ValueType& dist_expo);
375 template <
typename ValueType,
typename Iter,
typename CoordsArray,
typename GradVector>
378 template <
typename ValueType,
typename CoordsArray,
typename GradVector>
436 template <
typename ValueType,
typename CoordsVec,
typename GradVec>
438 const ValueType& e_IJ,
const ValueType& r_IJ,
const ValueType& r_IJ_7);
455 template <
typename ValueType,
typename Iter,
typename CoordsArray,
typename GradVector,
typename FuncType>
456 ValueType calcMMFF94InteractionGradient(Iter& beg,
const Iter& end,
const CoordsArray& coords, GradVector& grad,
const FuncType& func)
458 ValueType e = ValueType();
460 for (; beg != end; ++beg)
461 e += func(*beg, coords, grad);
470 template <
typename ValueType,
typename Iter,
typename CoordsArray,
typename GradVector>
473 return Detail::calcMMFF94InteractionGradient<ValueType>(beg, end, coords, grad,
474 static_cast<ValueType (*)(
const MMFF94BondStretchingInteraction&,
const CoordsArray&, GradVector&)
>(
475 &calcMMFF94BondStretchingGradient<ValueType, CoordsArray, GradVector>));
478 template <
typename ValueType,
typename CoordsArray,
typename GradVector>
481 return calcMMFF94BondStretchingGradient<ValueType>(coords[iaction.getAtom1Index()], coords[iaction.getAtom2Index()], grad[iaction.getAtom1Index()],
482 grad[iaction.getAtom2Index()], iaction.getForceConstant(), iaction.getReferenceLength());
485 template <
typename ValueType,
typename CoordsVec,
typename GradVec>
487 const ValueType& force_const,
const ValueType& ref_length)
489 ValueType dist_atom1_grad[3];
490 ValueType dist_atom2_grad[3];
492 ValueType dr_ij = calcDistanceDerivatives<ValueType>(atom1_pos, atom2_pos, dist_atom1_grad, dist_atom2_grad) - ref_length;
493 ValueType dr_ij_2 = dr_ij * dr_ij;
495 ValueType grad_fact = (ValueType(167.92125 * 4) * dr_ij_2 * dr_ij - ValueType(215.89875 * 2) * dr_ij_2 + ValueType(143.9325) * dr_ij) * force_const;
497 Detail::scaleAddVector(dist_atom1_grad, grad_fact, atom1_grad);
498 Detail::scaleAddVector(dist_atom2_grad, grad_fact, atom2_grad);
500 ValueType e_b = ValueType(143.9325 * 0.5) * force_const * dr_ij_2 * (1 - 2 * dr_ij + 28 * dr_ij_2 / 12);
506 template <
typename ValueType,
typename Iter,
typename CoordsArray,
typename GradVector>
509 return Detail::calcMMFF94InteractionGradient<ValueType>(beg, end, coords, grad,
510 static_cast<ValueType (*)(
const MMFF94AngleBendingInteraction&,
const CoordsArray&, GradVector&)
>(
511 &calcMMFF94AngleBendingGradient<ValueType, CoordsArray, GradVector>));
514 template <
typename ValueType,
typename CoordsArray,
typename GradVector>
517 return calcMMFF94AngleBendingGradient<ValueType>(coords[iaction.getTerminalAtom1Index()], coords[iaction.getCenterAtomIndex()],
518 coords[iaction.getTerminalAtom2Index()], grad[iaction.getTerminalAtom1Index()],
519 grad[iaction.getCenterAtomIndex()], grad[iaction.getTerminalAtom2Index()], iaction.isLinearAngle(),
520 iaction.getForceConstant(), iaction.getReferenceAngle());
523 template <
typename ValueType,
typename CoordsVec,
typename GradVec>
525 GradVec& term_atom1_grad, GradVec& ctr_atom_grad, GradVec& term_atom2_grad,
bool linear,
526 const ValueType& force_const,
const ValueType& ref_angle)
528 ValueType ac_term1_grad[3];
529 ValueType ac_ctr_grad[3];
530 ValueType ac_term2_grad[3];
532 ValueType a_ijk_cos = calcBondAngleCosDerivatives<ValueType>(term_atom1_pos, ctr_atom_pos, term_atom2_pos, ac_term1_grad, ac_ctr_grad, ac_term2_grad);
533 ValueType grad_fact = ValueType(1);
534 ValueType e_a = ValueType(0);
537 grad_fact = ValueType(143.9325) * force_const;
538 e_a = ValueType(143.9325) * force_const * (1 + a_ijk_cos);
541 ValueType a_ijk_cos_2 = a_ijk_cos * a_ijk_cos;
542 ValueType a_ijk = std::acos(a_ijk_cos);
543 ValueType div = std::sqrt(1 - a_ijk_cos_2);
545 if (div < ValueType(0.0000001))
546 div = ValueType(0.0000001);
548 grad_fact = force_const / div *
549 (a_ijk * (ValueType(86.58992538) * a_ijk - ValueType(143.9313616)) -
550 ref_angle * (ValueType(3.022558594) * a_ijk - ValueType(0.02637679965) * ref_angle - ValueType(2.512076157)));
552 ValueType da_ijk = a_ijk * ValueType(180 / M_PI) - ref_angle;
554 e_a = ValueType(0.043844 * 0.5) * force_const * da_ijk * da_ijk * (1 - ValueType(0.007) * da_ijk);
557 Detail::scaleAddVector(ac_term1_grad, grad_fact, term_atom1_grad);
558 Detail::scaleAddVector(ac_ctr_grad, grad_fact, ctr_atom_grad);
559 Detail::scaleAddVector(ac_term2_grad, grad_fact, term_atom2_grad);
565 template <
typename ValueType,
typename Iter,
typename CoordsArray,
typename GradVector>
568 return Detail::calcMMFF94InteractionGradient<ValueType>(beg, end, coords, grad,
569 static_cast<ValueType (*)(
const MMFF94StretchBendInteraction&,
const CoordsArray&, GradVector&)
>(
570 &calcMMFF94StretchBendGradient<ValueType, CoordsArray, GradVector>));
573 template <
typename ValueType,
typename CoordsArray,
typename GradVector>
576 return calcMMFF94StretchBendGradient<ValueType>(coords[iaction.getTerminalAtom1Index()], coords[iaction.getCenterAtomIndex()],
577 coords[iaction.getTerminalAtom2Index()], grad[iaction.getTerminalAtom1Index()],
578 grad[iaction.getCenterAtomIndex()], grad[iaction.getTerminalAtom2Index()], iaction.getIJKForceConstant(),
579 iaction.getKJIForceConstant(), iaction.getReferenceAngle(), iaction.getReferenceLength1(),
580 iaction.getReferenceLength2());
583 template <
typename ValueType,
typename CoordsVec,
typename GradVec>
585 GradVec& term_atom1_grad, GradVec& ctr_atom_grad, GradVec& term_atom2_grad,
586 const ValueType& ijk_force_const,
const ValueType& kji_force_const,
const ValueType& ref_angle,
587 const ValueType& ref_length1,
const ValueType& ref_length2)
589 ValueType ac_term1_grad[3];
590 ValueType ac_ctr_grad[3];
591 ValueType ac_term2_grad[3];
593 ValueType dist_term1_grad[3];
594 ValueType dist_ctr_grad1[3];
595 ValueType dist_ctr_grad2[3];
596 ValueType dist_term2_grad[3];
598 ValueType r_ij = calcDistanceDerivatives<ValueType>(term_atom1_pos, ctr_atom_pos, dist_term1_grad, dist_ctr_grad1);
599 ValueType r_kj = calcDistanceDerivatives<ValueType>(term_atom2_pos, ctr_atom_pos, dist_term2_grad, dist_ctr_grad2);
600 ValueType a_ijk_cos = calcBondAngleCosDerivatives<ValueType>(term_atom1_pos, ctr_atom_pos, term_atom2_pos, ac_term1_grad, ac_ctr_grad, ac_term2_grad);
601 ValueType a_ijk_cos_2 = a_ijk_cos * a_ijk_cos;
602 ValueType a_ijk = std::acos(a_ijk_cos);
604 ValueType dr_ij = r_ij - ref_length1;
605 ValueType dr_kj = r_kj - ref_length2;
606 ValueType da_ijk = a_ijk * ValueType(180 / M_PI) - ref_angle;
607 ValueType div = std::sqrt(1 - a_ijk_cos_2);
609 if (div < ValueType(0.0000001))
610 div = ValueType(0.0000001);
612 ValueType a_ijk_grad_fact = ValueType(-180 * 2.5121 / M_PI) / div * (dr_ij * ijk_force_const + dr_kj * kji_force_const);
614 ValueType r_ij_grad_fact = ValueType(2.5121) * da_ijk * ijk_force_const;
615 ValueType r_kj_grad_fact = ValueType(2.5121) * da_ijk * kji_force_const;
617 Detail::scaleAddVector(dist_term1_grad, r_ij_grad_fact, term_atom1_grad);
618 Detail::scaleAddVector(ac_term1_grad, a_ijk_grad_fact, term_atom1_grad);
620 Detail::scaleAddVector(dist_term2_grad, r_kj_grad_fact, term_atom2_grad);
621 Detail::scaleAddVector(ac_term2_grad, a_ijk_grad_fact, term_atom2_grad);
623 Detail::scaleAddVector(dist_ctr_grad1, r_ij_grad_fact, ctr_atom_grad);
624 Detail::scaleAddVector(dist_ctr_grad2, r_kj_grad_fact, ctr_atom_grad);
625 Detail::scaleAddVector(ac_ctr_grad, a_ijk_grad_fact, ctr_atom_grad);
627 ValueType e_ab = r_ij_grad_fact * dr_ij + r_kj_grad_fact * dr_kj;
633 template <
typename ValueType,
typename Iter,
typename CoordsArray,
typename GradVector>
636 return Detail::calcMMFF94InteractionGradient<ValueType>(beg, end, coords, grad,
637 static_cast<ValueType (*)(
const MMFF94OutOfPlaneBendingInteraction&,
const CoordsArray&,
639 &calcMMFF94OutOfPlaneBendingGradient<ValueType, CoordsArray, GradVector>));
642 template <
typename ValueType,
typename CoordsArray,
typename GradVector>
645 return calcMMFF94OutOfPlaneBendingGradient<ValueType>(coords[iaction.getTerminalAtom1Index()], coords[iaction.getCenterAtomIndex()],
646 coords[iaction.getTerminalAtom2Index()], coords[iaction.getOutOfPlaneAtomIndex()],
647 grad[iaction.getTerminalAtom1Index()], grad[iaction.getCenterAtomIndex()],
648 grad[iaction.getTerminalAtom2Index()], grad[iaction.getOutOfPlaneAtomIndex()],
649 iaction.getForceConstant());
652 template <
typename ValueType,
typename CoordsVec,
typename GradVec>
654 const CoordsVec& oop_atom_pos, GradVec& term_atom1_grad, GradVec& ctr_atom_grad,
655 GradVec& term_atom2_grad, GradVec& oop_atom_grad,
const ValueType& force_const)
657 ValueType ac_term1_grad[3];
658 ValueType ac_term2_grad[3];
659 ValueType ac_ctr_grad[3];
660 ValueType ac_oop_grad[3];
662 ValueType chi_ijkl_cos = calcOutOfPlaneAngleCosDerivatives<ValueType>(term_atom1_pos, ctr_atom_pos, term_atom2_pos, oop_atom_pos, ac_term1_grad,
663 ac_ctr_grad, ac_term2_grad, ac_oop_grad);
664 ValueType chi_ijkl = ValueType(M_PI * 0.5) - std::acos(chi_ijkl_cos);
665 ValueType div = std::sqrt(1 - chi_ijkl_cos * chi_ijkl_cos);
667 if (div < ValueType(0.0000001))
668 div = ValueType(0.0000001);
670 ValueType grad_fact = ValueType(0.043844 * 180 * 180) / div * ValueType(1 / (M_PI * M_PI)) * force_const * chi_ijkl;
672 Detail::scaleAddVector(ac_term1_grad, grad_fact, term_atom1_grad);
673 Detail::scaleAddVector(ac_ctr_grad, grad_fact, ctr_atom_grad);
674 Detail::scaleAddVector(ac_term2_grad, grad_fact, term_atom2_grad);
675 Detail::scaleAddVector(ac_oop_grad, grad_fact, oop_atom_grad);
677 chi_ijkl *= ValueType(180 / M_PI);
679 ValueType e_oop = ValueType(0.5 * 0.043844) * force_const * chi_ijkl * chi_ijkl;
685 template <
typename ValueType,
typename Iter,
typename CoordsArray,
typename GradVector>
688 return Detail::calcMMFF94InteractionGradient<ValueType>(beg, end, coords, grad,
689 static_cast<ValueType (*)(
const MMFF94TorsionInteraction&,
const CoordsArray&, GradVector&)
>(
690 &calcMMFF94TorsionGradient<ValueType, CoordsArray, GradVector>));
693 template <
typename ValueType,
typename CoordsArray,
typename GradVector>
696 return calcMMFF94TorsionGradient<ValueType>(coords[iaction.getTerminalAtom1Index()], coords[iaction.getCenterAtom1Index()],
697 coords[iaction.getCenterAtom2Index()], coords[iaction.getTerminalAtom2Index()],
698 grad[iaction.getTerminalAtom1Index()], grad[iaction.getCenterAtom1Index()], grad[iaction.getCenterAtom2Index()],
699 grad[iaction.getTerminalAtom2Index()], iaction.getTorsionParameter1(), iaction.getTorsionParameter2(),
700 iaction.getTorsionParameter3());
703 template <
typename ValueType,
typename CoordsVec,
typename GradVec>
706 const CoordsVec& term_atom2_pos, GradVec& term_atom1_grad, GradVec& ctr_atom1_grad, GradVec& ctr_atom2_grad,
707 GradVec& term_atom2_grad,
const ValueType& tor_param1,
const ValueType& tor_param2,
const ValueType& tor_param3)
709 ValueType ac_term1_grad[3];
710 ValueType ac_ctr1_grad[3];
711 ValueType ac_ctr2_grad[3];
712 ValueType ac_term2_grad[3];
714 ValueType phi_cos = calcDihedralAngleCosDerivatives<ValueType>(term_atom1_pos, ctr_atom1_pos, ctr_atom2_pos, term_atom2_pos, ac_term1_grad, ac_ctr1_grad,
715 ac_ctr2_grad, ac_term2_grad);
716 ValueType phi = std::acos(phi_cos);
717 ValueType phi_cos_2 = phi_cos * phi_cos;
718 ValueType div = std::sqrt(1 - phi_cos_2);
720 if (div < ValueType(0.0000001))
721 div = ValueType(0.0000001);
723 ValueType grad_fact =
724 ValueType(-1) / div * (tor_param2 * std::sin(2 * phi) - ValueType(0.5) * tor_param1 * std::sin(phi) - ValueType(1.5) * tor_param3 * std::sin(3 * phi));
726 Detail::scaleAddVector(ac_term1_grad, grad_fact, term_atom1_grad);
727 Detail::scaleAddVector(ac_ctr1_grad, grad_fact, ctr_atom1_grad);
728 Detail::scaleAddVector(ac_ctr2_grad, grad_fact, ctr_atom2_grad);
729 Detail::scaleAddVector(ac_term2_grad, grad_fact, term_atom2_grad);
731 ValueType e_t = ValueType(0.5) * (tor_param1 * (1 + phi_cos) + tor_param2 * (1 - std::cos(2 * phi)) + tor_param3 * (1 + std::cos(3 * phi)));
737 template <
typename ValueType,
typename Iter,
typename CoordsArray,
typename GradVector>
740 return Detail::calcMMFF94InteractionGradient<ValueType>(beg, end, coords, grad,
741 static_cast<ValueType (*)(
const MMFF94ElectrostaticInteraction&,
const CoordsArray&, GradVector&)
>(
742 &calcMMFF94ElectrostaticGradient<ValueType, CoordsArray, GradVector>));
745 template <
typename ValueType,
typename CoordsArray,
typename GradVector>
748 return calcMMFF94ElectrostaticGradient<ValueType>(coords[iaction.getAtom1Index()], coords[iaction.getAtom2Index()], grad[iaction.getAtom1Index()],
749 grad[iaction.getAtom2Index()], iaction.getAtom1Charge(), iaction.getAtom2Charge(),
750 iaction.getScalingFactor(), iaction.getDielectricConstant(), iaction.getDistanceExponent());
753 template <
typename ValueType,
typename CoordsVec,
typename GradVec>
755 const ValueType& atom1_chg,
const ValueType& atom2_chg,
const ValueType& scale_fact,
756 const ValueType& de_const,
const ValueType& dist_expo)
758 ValueType dist_atom1_grad[3];
759 ValueType dist_atom2_grad[3];
761 ValueType r_ij = calcDistanceDerivatives<ValueType>(atom1_pos, atom2_pos, dist_atom1_grad, dist_atom2_grad);
763 ValueType tmp1 = r_ij + ValueType(0.05);
764 ValueType tmp2 = std::pow(tmp1, dist_expo);
765 ValueType tmp3 = scale_fact * atom1_chg * atom2_chg / (de_const * tmp2);
767 ValueType grad_fact = ValueType(-332.0716) * dist_expo * tmp3 / tmp1;
769 Detail::scaleAddVector(dist_atom1_grad, grad_fact, atom1_grad);
770 Detail::scaleAddVector(dist_atom2_grad, grad_fact, atom2_grad);
772 double e_q = ValueType(332.0716) * tmp3;
778 template <
typename ValueType,
typename Iter,
typename CoordsArray,
typename GradVector>
781 return Detail::calcMMFF94InteractionGradient<ValueType>(beg, end, coords, grad,
782 static_cast<ValueType (*)(
const MMFF94VanDerWaalsInteraction&,
const CoordsArray&, GradVector&)
>(
783 &calcMMFF94VanDerWaalsGradient<ValueType, CoordsArray, GradVector>));
786 template <
typename ValueType,
typename CoordsArray,
typename GradVector>
789 return calcMMFF94VanDerWaalsGradient<ValueType>(coords[iaction.getAtom1Index()], coords[iaction.getAtom2Index()], grad[iaction.getAtom1Index()],
790 grad[iaction.getAtom2Index()], iaction.getEIJ(), iaction.getRIJ(), iaction.getRIJPow7());
793 template <
typename ValueType,
typename CoordsVec,
typename GradVec>
795 const ValueType& e_IJ,
const ValueType& r_IJ,
const ValueType& r_IJ_7)
797 ValueType dist_atom1_grad[3];
798 ValueType dist_atom2_grad[3];
800 ValueType r_ij = calcDistanceDerivatives<ValueType>(atom1_pos, atom2_pos, dist_atom1_grad, dist_atom2_grad);
801 ValueType r_ij_2 = r_ij * r_ij;
802 ValueType r_ij_6 = r_ij_2 * r_ij_2 * r_ij_2;
803 ValueType r_ij_7 = r_ij_6 * r_ij;
805 ValueType tmp1 = r_ij + ValueType(0.07) * r_IJ;
806 ValueType tmp1_2 = tmp1 * tmp1;
807 ValueType tmp1_4 = tmp1_2 * tmp1_2;
809 ValueType tmp2 = r_ij_7 + ValueType(0.12) * r_IJ_7;
811 ValueType tmp3 = ValueType(1.07) * r_IJ / (r_ij + ValueType(0.07) * r_IJ);
812 ValueType tmp3_2 = tmp3 * tmp3;
813 ValueType tmp3_7 = tmp3_2 * tmp3_2 * tmp3_2 * tmp3;
815 ValueType grad_fact = -r_IJ_7 * e_IJ / (tmp1_4 * tmp1_4 * tmp2 * tmp2) *
816 (ValueType(-22.48094067) * r_ij_7 * r_ij_7 + ValueType(19.78322779) * r_ij_7 * r_IJ_7 +
817 ValueType(0.8812528743) * r_ij_6 * r_IJ_7 * r_IJ + ValueType(1.186993667) * r_IJ_7 * r_IJ_7);
819 Detail::scaleAddVector(dist_atom1_grad, grad_fact, atom1_grad);
820 Detail::scaleAddVector(dist_atom2_grad, grad_fact, atom2_grad);
822 ValueType e_vdw = e_IJ * tmp3_7 * (ValueType(1.12) * r_IJ_7 / tmp2 - 2);
829 #endif // CDPL_FORCEFIELD_MMFF94GRADIENTFUNCTIONS_HPP