Scine::Sparrow  5.0.0
Library for fast and agile quantum chemical calculations with semiempirical methods.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Pages
PM6PairwiseRepulsion.h
Go to the documentation of this file.
1 
8 #ifndef SPARROW_PAIRWISEREPULSION_H
9 #define SPARROW_PAIRWISEREPULSION_H
10 
13 #include <Utils/Constants.h>
17 #include <Eigen/Core>
18 
19 namespace Scine {
20 
21 namespace Sparrow {
22 
23 namespace nddo {
24 
25 // clang-format off
30  public:
32 
33  void calculate(const Eigen::Vector3d& R, Utils::DerivativeOrder order);
34 
35  double getRepulsionEnergy() const { return repulsionEnergy_; }
36 
37  Eigen::RowVector3d getRepulsionGradient() const { return repulsionGradient_; }
38 
39  Utils::AutomaticDifferentiation::Second3D getRepulsionHessian() const { return repulsionHessian_; }
40  template <Utils::Derivative O> Utils::AutomaticDifferentiation::DerivativeType<O> getDerivative() const;
41 
42  template <Utils::DerivativeOrder O> Utils::AutomaticDifferentiation::Value1DType<O> calculateRepulsion(double R) const;
43  template <Utils::DerivativeOrder O> Utils::AutomaticDifferentiation::Value1DType<O> baseTerm(double R) const;
44  template <Utils::DerivativeOrder O> Utils::AutomaticDifferentiation::Value1DType<O> additionalTerm(double R) const;
45  template <Utils::DerivativeOrder O> Utils::AutomaticDifferentiation::Value1DType<O> gaussianRepulsionTerm(double R) const;
46  template <Utils::DerivativeOrder O> Utils::AutomaticDifferentiation::Value1DType<O> gaussianRepulsion(const AtomicParameters& P, double R) const;
47 
48  template <Utils::DerivativeOrder O> Utils::AutomaticDifferentiation::Value1DType<O> parenthesisValue(double R) const;
49  template <Utils::DerivativeOrder O> Utils::AutomaticDifferentiation::Value1DType<O> standardParenthesis(double R) const;
50  template <Utils::DerivativeOrder O> Utils::AutomaticDifferentiation::Value1DType<O> NHOHParenthesis(double R) const;
51  template <Utils::DerivativeOrder O> Utils::AutomaticDifferentiation::Value1DType<O> CCParenthesis(double R) const;
52  template <Utils::DerivativeOrder O> Utils::AutomaticDifferentiation::Value1DType<O> SiOParenthesis(double R) const;
53 
54 
55  private:
56  template <Utils::DerivativeOrder O> Utils::AutomaticDifferentiation::Value1DType<O> radius(double R) const;
57  template <Utils::DerivativeOrder O> Utils::AutomaticDifferentiation::Value1DType<O> integral(double R) const;
58 
59  const double cOfAdditiveTerm; // NB: The value of c = 1e-8 described in the paper is transformed from Angstrom^12 to bohr^12.
60  const double exponentCoefficient; // NB: The value of 0.0003 described in the paper is transformed from Angstrom^-5 to bohr^-5.
61  const double furtherExponentCC; // NB: The value of 5.98 described in the paper is transformed from Angstrom^-1 to bohr^-1.
62  const double distanceSiO; // NB: The value of 2.9 described in the paper is transformed from Angstrom to bohr.
63  const double factorCC;
64  const double factorSiO;
65 
66  const AtomicParameters& pA_;
67  const AtomicParameters& pB_;
68  const PM6DiatomicParameters& pAB_;
69 
70  double repulsionEnergy_;
71  Eigen::RowVector3d repulsionGradient_;
73 };
74 // clang-format on
75 
76 template<Utils::DerivativeOrder O>
77 Utils::AutomaticDifferentiation::Value1DType<O> PM6PairwiseRepulsion::calculateRepulsion(double R) const {
78  return baseTerm<O>(R) + additionalTerm<O>(R) + gaussianRepulsionTerm<O>(R);
79 }
80 
81 template<Utils::DerivativeOrder O>
82 Utils::AutomaticDifferentiation::Value1DType<O> PM6PairwiseRepulsion::baseTerm(double R) const {
83  auto ssssIntegral = integral<O>(R);
84  return pA_.coreCharge() * pB_.coreCharge() * ssssIntegral * parenthesisValue<O>(R);
85 }
86 
87 template<Utils::DerivativeOrder O>
88 Utils::AutomaticDifferentiation::Value1DType<O> PM6PairwiseRepulsion::parenthesisValue(double R) const {
89  if ((pA_.element() == Utils::ElementType::H && (pB_.element() == Utils::ElementType::O || pB_.element() == Utils::ElementType::N ||
90  pB_.element() == Utils::ElementType::C)) ||
91  (pB_.element() == Utils::ElementType::H && (pA_.element() == Utils::ElementType::O || pA_.element() == Utils::ElementType::N ||
92  pA_.element() == Utils::ElementType::C)))
93  return NHOHParenthesis<O>(R);
94  if (pA_.element() == Utils::ElementType::C && pB_.element() == Utils::ElementType::C)
95  return CCParenthesis<O>(R);
96  if ((pA_.element() == Utils::ElementType::Si && pB_.element() == Utils::ElementType::O) ||
97  (pA_.element() == Utils::ElementType::O && pB_.element() == Utils::ElementType::Si))
98  return SiOParenthesis<O>(R);
99 
100  return standardParenthesis<O>(R);
101 }
102 
103 template<Utils::DerivativeOrder O>
104 Utils::AutomaticDifferentiation::Value1DType<O> PM6PairwiseRepulsion::additionalTerm(double R) const {
105  auto RD = radius<O>(R);
106  double za13 = std::pow(Utils::ElementInfo::Z(pA_.element()), 1.0 / 3.0);
107  double zb13 = std::pow(Utils::ElementInfo::Z(pB_.element()), 1.0 / 3.0);
108  auto v = Utils::AutomaticDifferentiation::constant1D<O>(za13 + zb13);
109  v /= RD;
110  auto v2 = v * v;
111  auto v6 = v2 * v2 * v2;
112  return cOfAdditiveTerm * v6 * v6 / Utils::Constants::ev_per_hartree;
113 }
114 
115 template<Utils::DerivativeOrder O>
116 Utils::AutomaticDifferentiation::Value1DType<O> PM6PairwiseRepulsion::gaussianRepulsionTerm(double R) const {
117  auto RD = radius<O>(R);
118  return (gaussianRepulsion<O>(pA_, R) + gaussianRepulsion<O>(pB_, R)) / RD *
119  (pA_.coreCharge() * pB_.coreCharge() / Utils::Constants::ev_per_hartree);
120 }
121 
122 template<Utils::DerivativeOrder O>
123 Utils::AutomaticDifferentiation::Value1DType<O> PM6PairwiseRepulsion::gaussianRepulsion(const AtomicParameters& P,
124  double R) const {
125  if (P.hasGaussianRepulsionParameters()) {
126  const auto& gaussianPar = P.getGaussianRepulsionParameters();
127  for (unsigned int i = 0; i < gaussianPar.size(); i += 1) {
128  auto DistC = std::get<2>(gaussianPar[i]);
129  auto RmC = radius<O>(R) - DistC;
130  return std::get<0>(gaussianPar[i]) * exp(-std::get<1>(gaussianPar[i]) * RmC * RmC);
131  };
132  };
133 
134  return Utils::AutomaticDifferentiation::constant1D<O>(0);
135 }
136 
137 template<Utils::DerivativeOrder O>
138 Utils::AutomaticDifferentiation::Value1DType<O> PM6PairwiseRepulsion::standardParenthesis(double R) const {
139  auto RD = radius<O>(R);
140  auto R2 = RD * RD;
141  auto R6 = R2 * R2 * R2;
142  auto res = 1.0;
143  return res + (2 * pAB_.x()) * exp(-pAB_.alpha() * (RD + exponentCoefficient * R6));
144 }
145 
146 template<Utils::DerivativeOrder O>
147 Utils::AutomaticDifferentiation::Value1DType<O> PM6PairwiseRepulsion::NHOHParenthesis(double R) const {
148  auto RD = radius<O>(R);
149  auto res = 1.0;
150  return res + 2 * pAB_.x() * exp(-pAB_.alpha() * (RD * RD));
151 }
152 
153 template<Utils::DerivativeOrder O>
154 Utils::AutomaticDifferentiation::Value1DType<O> PM6PairwiseRepulsion::CCParenthesis(double R) const {
155  return standardParenthesis<O>(R) + factorCC * exp(-furtherExponentCC * radius<O>(R));
156 }
157 
158 template<Utils::DerivativeOrder O>
159 Utils::AutomaticDifferentiation::Value1DType<O> PM6PairwiseRepulsion::SiOParenthesis(double R) const {
160  auto r1 = radius<O>(R) - distanceSiO;
161  return standardParenthesis<O>(R) + factorSiO * exp(-r1 * r1);
162 }
163 
164 template<Utils::DerivativeOrder O>
165 inline Utils::AutomaticDifferentiation::Value1DType<O> PM6PairwiseRepulsion::radius(double R) const {
166  return Utils::AutomaticDifferentiation::variableWithUnitDerivative<O>(R);
167 }
168 
169 template<>
170 inline Utils::AutomaticDifferentiation::Value1DType<Utils::DerivativeOrder::Zero>
171 PM6PairwiseRepulsion::integral<Utils::DerivativeOrder::Zero>(double R) const {
172  double pSum = pA_.pCore() + pB_.pCore();
173  double igr = 1.0 / std::sqrt(R * R + pSum * pSum);
174  return igr;
175 }
176 template<>
177 inline Utils::AutomaticDifferentiation::Value1DType<Utils::DerivativeOrder::One>
178 PM6PairwiseRepulsion::integral<Utils::DerivativeOrder::One>(double R) const {
179  double pSum = pA_.pCore() + pB_.pCore();
180  double igr = 1.0 / std::sqrt(R * R + pSum * pSum);
181  Utils::AutomaticDifferentiation::First1D integralD(igr, -igr * igr * igr * R);
182  return integralD;
183 }
184 template<>
185 inline Utils::AutomaticDifferentiation::Value1DType<Utils::DerivativeOrder::Two>
186 PM6PairwiseRepulsion::integral<Utils::DerivativeOrder::Two>(double R) const {
187  double pSum = pA_.pCore() + pB_.pCore();
188  double igr = 1.0 / std::sqrt(R * R + pSum * pSum);
189  double igr3 = igr * igr * igr;
190  Utils::AutomaticDifferentiation::Second1D integralD(igr, -igr3 * R, igr3 * igr * igr * (2 * R * R - pSum * pSum));
191  return integralD;
192 }
193 template<>
194 inline Utils::AutomaticDifferentiation::DerivativeType<Utils::Derivative::First>
195 PM6PairwiseRepulsion::getDerivative<Utils::Derivative::First>() const {
196  return getRepulsionGradient();
197 }
198 template<>
199 inline Utils::AutomaticDifferentiation::DerivativeType<Utils::Derivative::SecondAtomic>
200 PM6PairwiseRepulsion::getDerivative<Utils::Derivative::SecondAtomic>() const {
201  return getRepulsionHessian();
202 }
203 template<>
204 inline Utils::AutomaticDifferentiation::DerivativeType<Utils::Derivative::SecondFull>
205 PM6PairwiseRepulsion::getDerivative<Utils::Derivative::SecondFull>() const {
206  return getRepulsionHessian();
207 }
208 
209 } // namespace nddo
210 
211 } // namespace Sparrow
212 } // namespace Scine
213 #endif // PAIRWISEREPULSION_H
Definition: PM6DiatomicParameters.h:23
Definition: PM6PairwiseRepulsion.h:29
static constexpr unsigned Z(const ElementType e) noexcept
Definition: AtomicParameters.h:29