Scine::Sparrow  5.1.0
Library for fast and agile quantum chemical calculations with semiempirical methods.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Pages
AM1PairwiseRepulsion.h
Go to the documentation of this file.
1 
8 #ifndef SPARROW_AM1PAIRWISEREPULSION_H
9 #define SPARROW_AM1PAIRWISEREPULSION_H
10 
13 #include <Utils/Constants.h>
16 #include <Eigen/Core>
17 
18 namespace Scine {
19 namespace Utils {
20 enum class DerivativeOrder;
21 }
22 namespace Sparrow {
23 
24 namespace nddo {
25 
26 // clang-format off
31  public:
33 
34  void calculate(const Eigen::Ref<Eigen::Vector3d>& R, Utils::DerivativeOrder order);
35 
36  double getRepulsionEnergy() const { return repulsionEnergy_; }
37 
38  Eigen::RowVector3d getRepulsionGradient() const { return repulsionGradient_; }
39 
40  Utils::AutomaticDifferentiation::Second3D getRepulsionHessian() const { return repulsionHessian_; }
41  template <Utils::Derivative O> Utils::AutomaticDifferentiation::DerivativeType<O> getDerivative() const;
42 
43  template <Utils::DerivativeOrder O> Utils::AutomaticDifferentiation::Value1DType<O> calculateRepulsion(double R) const;
44  template <Utils::DerivativeOrder O> Utils::AutomaticDifferentiation::Value1DType<O> baseTerm(double R) const;
45  template <Utils::DerivativeOrder O> Utils::AutomaticDifferentiation::Value1DType<O> parenthesisValue(double R) const;
46  template <Utils::DerivativeOrder O> Utils::AutomaticDifferentiation::Value1DType<O> standardParenthesis(double R) const;
47  template <Utils::DerivativeOrder O> Utils::AutomaticDifferentiation::Value1DType<O> gaussianRepulsionTerm(double R) const;
48  template <Utils::DerivativeOrder O> Utils::AutomaticDifferentiation::Value1DType<O> gaussianRepulsion(const AtomicParameters& P, double R) const;
49 
50 
51  private:
52  template <Utils::DerivativeOrder O> Utils::AutomaticDifferentiation::Value1DType<O> radius(double R) const;
53  template <Utils::DerivativeOrder O> Utils::AutomaticDifferentiation::Value1DType<O> integral(double R) const;
54 
55  const AtomicParameters& pA_;
56  const AtomicParameters& pB_;
57 
58  double repulsionEnergy_;
59  Eigen::RowVector3d repulsionGradient_;
61 };
62 // clang-format on
63 
64 template<Utils::DerivativeOrder O>
65 Utils::AutomaticDifferentiation::Value1DType<O> AM1PairwiseRepulsion::calculateRepulsion(double R) const {
66  return baseTerm<O>(R) + gaussianRepulsionTerm<O>(R);
67 }
68 
69 template<Utils::DerivativeOrder O>
70 Utils::AutomaticDifferentiation::Value1DType<O> AM1PairwiseRepulsion::baseTerm(double R) const {
71  auto ssssIntegral = integral<O>(R);
72  return pA_.coreCharge() * pB_.coreCharge() * ssssIntegral * parenthesisValue<O>(R);
73 }
74 
75 template<Utils::DerivativeOrder O>
76 Utils::AutomaticDifferentiation::Value1DType<O> AM1PairwiseRepulsion::parenthesisValue(double R) const {
77  return standardParenthesis<O>(R);
78 }
79 
80 template<Utils::DerivativeOrder O>
81 Utils::AutomaticDifferentiation::Value1DType<O> AM1PairwiseRepulsion::standardParenthesis(double R) const {
82  auto radiusDeriv = radius<O>(R);
83  auto res = 1.0;
84  if (pA_.element() == Utils::ElementType::H &&
85  (pB_.element() == Utils::ElementType::N || pB_.element() == Utils::ElementType::O)) {
86  return res + exp(-pA_.alpha() * radiusDeriv) +
87  radiusDeriv * Utils::Constants::angstrom_per_bohr * exp(-pB_.alpha() * radiusDeriv);
88  }
89  else if (pB_.element() == Utils::ElementType::H &&
90  (pA_.element() == Utils::ElementType::N || pA_.element() == Utils::ElementType::O)) {
91  return res + radiusDeriv * Utils::Constants::angstrom_per_bohr * exp(-pA_.alpha() * radiusDeriv) +
92  exp(-pB_.alpha() * radiusDeriv);
93  }
94  else {
95  return res + exp(-pA_.alpha() * radiusDeriv) + exp(-pB_.alpha() * radiusDeriv);
96  }
97 }
98 
99 template<Utils::DerivativeOrder O>
100 Utils::AutomaticDifferentiation::Value1DType<O> AM1PairwiseRepulsion::gaussianRepulsionTerm(double R) const {
101  auto RD = radius<O>(R);
102  return (gaussianRepulsion<O>(pA_, R) + gaussianRepulsion<O>(pB_, R)) / RD *
103  (pA_.coreCharge() * pB_.coreCharge() / Utils::Constants::ev_per_hartree);
104 }
105 
106 template<Utils::DerivativeOrder O>
107 Utils::AutomaticDifferentiation::Value1DType<O> AM1PairwiseRepulsion::gaussianRepulsion(const AtomicParameters& P,
108  double R) const {
109  if (P.hasGaussianRepulsionParameters()) {
110  const auto& gaussianPar = P.getGaussianRepulsionParameters();
111  auto gaussianRep = Utils::AutomaticDifferentiation::constant1D<O>(0);
112  for (unsigned int i = 0; i < gaussianPar.size(); i += 1) {
113  auto DistC = std::get<2>(gaussianPar[i]);
114  auto RmC = radius<O>(R) - DistC;
115  gaussianRep += std::get<0>(gaussianPar[i]) * exp(-std::get<1>(gaussianPar[i]) * RmC * RmC);
116  };
117  return gaussianRep;
118  };
119 
120  return Utils::AutomaticDifferentiation::constant1D<O>(0);
121 }
122 
123 template<Utils::DerivativeOrder O>
124 inline Utils::AutomaticDifferentiation::Value1DType<O> AM1PairwiseRepulsion::radius(double R) const {
125  return Utils::AutomaticDifferentiation::variableWithUnitDerivative<O>(R);
126 }
127 
128 template<>
129 inline Utils::AutomaticDifferentiation::Value1DType<Utils::DerivativeOrder::Zero>
130 AM1PairwiseRepulsion::integral<Utils::DerivativeOrder::Zero>(double R) const {
131  double pSum = pA_.pCore() + pB_.pCore();
132  double igr = 1.0 / std::sqrt(R * R + pSum * pSum);
133  return igr;
134 }
135 template<>
136 inline Utils::AutomaticDifferentiation::Value1DType<Utils::DerivativeOrder::One>
137 AM1PairwiseRepulsion::integral<Utils::DerivativeOrder::One>(double R) const {
138  double pSum = pA_.pCore() + pB_.pCore();
139  double igr = 1.0 / std::sqrt(R * R + pSum * pSum);
140  Utils::AutomaticDifferentiation::First1D integralD(igr, -igr * igr * igr * R);
141  return integralD;
142 }
143 template<>
144 inline Utils::AutomaticDifferentiation::Value1DType<Utils::DerivativeOrder::Two>
145 AM1PairwiseRepulsion::integral<Utils::DerivativeOrder::Two>(double R) const {
146  double pSum = pA_.pCore() + pB_.pCore();
147  double igr = 1.0 / std::sqrt(R * R + pSum * pSum);
148  double igr3 = igr * igr * igr;
149  Utils::AutomaticDifferentiation::Second1D integralD(igr, -igr3 * R, igr3 * igr * igr * (2 * R * R - pSum * pSum));
150  return integralD;
151 }
152 template<>
153 inline Utils::AutomaticDifferentiation::DerivativeType<Utils::Derivative::First>
154 AM1PairwiseRepulsion::getDerivative<Utils::Derivative::First>() const {
155  return getRepulsionGradient();
156 }
157 template<>
158 inline Utils::AutomaticDifferentiation::DerivativeType<Utils::Derivative::SecondAtomic>
159 AM1PairwiseRepulsion::getDerivative<Utils::Derivative::SecondAtomic>() const {
160  return getRepulsionHessian();
161 }
162 template<>
163 inline Utils::AutomaticDifferentiation::DerivativeType<Utils::Derivative::SecondFull>
164 AM1PairwiseRepulsion::getDerivative<Utils::Derivative::SecondFull>() const {
165  return getRepulsionHessian();
166 }
167 
168 } // namespace nddo
169 
170 } // namespace Sparrow
171 } // namespace Scine
172 #endif // SPARROW_PAIRWISEREPULSION_H
Definition: AtomicParameters.h:29
Definition: AM1PairwiseRepulsion.h:30