GQCP
Loading...
Searching...
No Matches
PrimitiveCanonicalKineticEnergyIntegralEngine.hpp
Go to the documentation of this file.
1// This file is part of GQCG-GQCP.
2//
3// Copyright (C) 2017-2020 the GQCG developers
4//
5// GQCG-GQCP is free software: you can redistribute it and/or modify
6// it under the terms of the GNU Lesser General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// GQCG-GQCP is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU Lesser General Public License for more details.
14//
15// You should have received a copy of the GNU Lesser General Public License
16// along with GQCG-GQCP. If not, see <http://www.gnu.org/licenses/>.
17
18#pragma once
19
27#include "Utilities/complex.hpp"
29
30
31namespace GQCP {
32
33
39template <typename _Shell>
42public:
43 // The type of shell that this integral engine is related to.
44 using Shell = _Shell;
45
46 // The type of primitive that underlies the type of shell.
47 using Primitive = typename Shell::Primitive;
48
49 // The scalar representation of a canonical kinetic energy integral.
51
52
53public:
54 /*
55 * MARK: CartesianGTO integrals
56 */
57
66 template <typename Z = Shell>
68
69 // Prepare some variables.
70 const auto i = static_cast<int>(left.cartesianExponents().value(CartesianDirection::x));
71 const auto k = static_cast<int>(left.cartesianExponents().value(CartesianDirection::y));
72 const auto m = static_cast<int>(left.cartesianExponents().value(CartesianDirection::z));
73
74 const auto j = static_cast<int>(right.cartesianExponents().value(CartesianDirection::x));
75 const auto l = static_cast<int>(right.cartesianExponents().value(CartesianDirection::y));
76 const auto n = static_cast<int>(right.cartesianExponents().value(CartesianDirection::z));
77
78 const auto a = left.gaussianExponent();
79 const auto b = right.gaussianExponent();
80
81 const auto K_x = left.center()(CartesianDirection::x);
82 const auto K_y = left.center()(CartesianDirection::y);
83 const auto K_z = left.center()(CartesianDirection::z);
84
85 const auto L_x = right.center()(CartesianDirection::x);
86 const auto L_y = right.center()(CartesianDirection::y);
87 const auto L_z = right.center()(CartesianDirection::z);
88
89
90 // The 3D canonical kinetic energy integral is a sum of three contributions (dx^2, dy^2, dz^2).
91 PrimitiveOverlapIntegralEngine<GTOShell> primitive_overlap_engine;
92
93 IntegralScalar primitive_integral = 1.0;
94 return this->calculate1D(a, K_x, i, b, L_x, j) * primitive_overlap_engine.calculate1D(a, K_y, k, b, L_y, l) * primitive_overlap_engine.calculate1D(a, K_z, m, b, L_z, n) +
95 primitive_overlap_engine.calculate1D(a, K_x, i, b, L_x, j) * this->calculate1D(a, K_y, k, b, L_y, l) * primitive_overlap_engine.calculate1D(a, K_z, m, b, L_z, n) +
96 primitive_overlap_engine.calculate1D(a, K_x, i, b, L_x, j) * primitive_overlap_engine.calculate1D(a, K_y, k, b, L_y, l) * this->calculate1D(a, K_z, m, b, L_z, n);
97 }
98
99
112 template <typename Z = Shell>
113 enable_if_t<std::is_same<Z, GTOShell>::value, IntegralScalar> calculate1D(const double a, const double K, const int i, const double b, const double L, const int j) {
114
115 // The canonical kinetic 1D integral is a sum of three 1D overlap integrals.
116 PrimitiveOverlapIntegralEngine<GTOShell> primitive_overlap_engine;
117
118 return -2 * std::pow(b, 2) * primitive_overlap_engine.calculate1D(a, K, i, b, L, j + 2) +
119 b * (2 * j + 1) * primitive_overlap_engine.calculate1D(a, K, i, b, L, j) -
120 0.5 * j * (j - 1) * primitive_overlap_engine.calculate1D(a, K, i, b, L, j - 2);
121 }
122
123
124 /*
125 * MARK: LondonCartesianGTO integrals
126 */
127
136 template <typename Z = Shell>
138
139 // Prepare some variables.
140 const auto i = static_cast<int>(left.cartesianGTO().cartesianExponents().value(CartesianDirection::x));
141 const auto k = static_cast<int>(left.cartesianGTO().cartesianExponents().value(CartesianDirection::y));
142 const auto m = static_cast<int>(left.cartesianGTO().cartesianExponents().value(CartesianDirection::z));
143
144 const auto j = static_cast<int>(right.cartesianGTO().cartesianExponents().value(CartesianDirection::x));
145 const auto l = static_cast<int>(right.cartesianGTO().cartesianExponents().value(CartesianDirection::y));
146 const auto n = static_cast<int>(right.cartesianGTO().cartesianExponents().value(CartesianDirection::z));
147
148 const auto a = left.cartesianGTO().gaussianExponent();
149 const auto b = right.cartesianGTO().gaussianExponent();
150
151 const auto K_x = left.cartesianGTO().center()(CartesianDirection::x);
152 const auto K_y = left.cartesianGTO().center()(CartesianDirection::y);
153 const auto K_z = left.cartesianGTO().center()(CartesianDirection::z);
154
155 const auto L_x = right.cartesianGTO().center()(CartesianDirection::x);
156 const auto L_y = right.cartesianGTO().center()(CartesianDirection::y);
157 const auto L_z = right.cartesianGTO().center()(CartesianDirection::z);
158
159 const auto k_K = left.kVector();
160 const auto k_L = right.kVector();
161 const Vector<double, 3> k1 = right.kVector() - left.kVector(); // The k-vector of the London overlap distribution.
162
163 const auto k_K_x = k_K(CartesianDirection::x);
164 const auto k_K_y = k_K(CartesianDirection::y);
165 const auto k_K_z = k_K(CartesianDirection::z);
166
167 const auto k_L_x = k_L(CartesianDirection::x);
168 const auto k_L_y = k_L(CartesianDirection::y);
169 const auto k_L_z = k_L(CartesianDirection::z);
170
171 const auto k1_x = k1(CartesianDirection::x);
172 const auto k1_y = k1(CartesianDirection::y);
173 const auto k1_z = k1(CartesianDirection::z);
174
175
176 // The 3D canonical kinetic energy integral is a sum of three contributions (dx^2, dy^2, dz^2).
178
179 IntegralScalar primitive_integral = 1.0;
180 return this->calculate1D(k_K_x, a, K_x, i, k_L_x, b, L_x, j) * S.calculate1D(k1_y, a, K_y, k, b, L_y, l) * S.calculate1D(k1_z, a, K_z, m, b, L_z, n) +
181 S.calculate1D(k1_x, a, K_x, i, b, L_x, j) * this->calculate1D(k_K_y, a, K_y, k, k_L_y, b, L_y, l) * S.calculate1D(k1_z, a, K_z, m, b, L_z, n) +
182 S.calculate1D(k1_x, a, K_x, i, b, L_x, j) * S.calculate1D(k1_y, a, K_y, k, b, L_y, l) * this->calculate1D(k_K_z, a, K_z, m, k_L_z, b, L_z, n);
183 }
184
185
200 template <typename Z = Shell>
201 enable_if_t<std::is_same<Z, LondonGTOShell>::value, IntegralScalar> calculate1D(const complex k_K, const double a, const double K, const int i, const complex k_L, const double b, const double L, const int j) {
202
203 using namespace GQCP::literals;
204
205 // The canonical kinetic 1D integral is a sum of five 1-D overlap integrals. We'll order them from highest to lowest angular momentum.
206 const auto k1 = k_L - k_K; // The (directional component of the) k-vector of the London overlap distribution.
208
209 return -2 * std::pow(b, 2) * S.calculate1D(k1, a, K, i, b, L, j + 2) -
210 2 * b * 1.0_ii * k_L * S.calculate1D(k1, a, K, i, b, L, j + 1) +
211 (b * (2 * j + 1) + 0.5 * std::pow(k_L, 2)) * S.calculate1D(k1, a, K, i, b, L, j) +
212 static_cast<double>(j) * 1.0_ii * k_L * S.calculate1D(k1, a, K, i, b, L, j - 1) -
213 0.5 * j * (j - 1) * S.calculate1D(k1, a, K, i, b, L, j - 2);
214 }
215};
216
217
218} // namespace GQCP
Definition: BaseScalarPrimitiveIntegralEngine.hpp:30
Definition: CartesianGTO.hpp:38
const Vector< double, 3 > & center() const
Definition: CartesianGTO.hpp:129
double gaussianExponent() const
Definition: CartesianGTO.hpp:139
const CartesianExponents & cartesianExponents() const
Definition: CartesianGTO.hpp:112
Definition: LondonCartesianGTO.hpp:38
Vector< double, 3 > kVector() const
Definition: LondonCartesianGTO.cpp:45
const CartesianGTO & cartesianGTO() const
Definition: LondonCartesianGTO.hpp:89
Definition: Matrix.hpp:47
Definition: PrimitiveCanonicalKineticEnergyIntegralEngine.hpp:41
enable_if_t< std::is_same< Z, GTOShell >::value, IntegralScalar > calculate(const CartesianGTO &left, const CartesianGTO &right)
Definition: PrimitiveCanonicalKineticEnergyIntegralEngine.hpp:67
typename Shell::Primitive Primitive
Definition: PrimitiveCanonicalKineticEnergyIntegralEngine.hpp:47
enable_if_t< std::is_same< Z, LondonGTOShell >::value, IntegralScalar > calculate1D(const complex k_K, const double a, const double K, const int i, const complex k_L, const double b, const double L, const int j)
Definition: PrimitiveCanonicalKineticEnergyIntegralEngine.hpp:201
enable_if_t< std::is_same< Z, LondonGTOShell >::value, IntegralScalar > calculate(const LondonCartesianGTO &left, const LondonCartesianGTO &right)
Definition: PrimitiveCanonicalKineticEnergyIntegralEngine.hpp:137
enable_if_t< std::is_same< Z, GTOShell >::value, IntegralScalar > calculate1D(const double a, const double K, const int i, const double b, const double L, const int j)
Definition: PrimitiveCanonicalKineticEnergyIntegralEngine.hpp:113
product_t< KineticOperator::Scalar, typename Primitive::OutputType > IntegralScalar
Definition: PrimitiveCanonicalKineticEnergyIntegralEngine.hpp:50
_Shell Shell
Definition: PrimitiveCanonicalKineticEnergyIntegralEngine.hpp:44
Definition: PrimitiveOverlapIntegralEngine.hpp:43
enable_if_t< std::is_same< Z, GTOShell >::value, IntegralScalar > calculate1D(const double a, const double K, const int i, const double b, const double L, const int j)
Definition: PrimitiveOverlapIntegralEngine.hpp:97
Definition: complex.hpp:57
Definition: BaseOneElectronIntegralBuffer.hpp:25
typename std::enable_if< B, T >::type enable_if_t
Definition: type_traits.hpp:37
decltype(std::declval< T >() *std::declval< U >()) product_t
Definition: aliases.hpp:35
std::complex< double > complex
Definition: complex.hpp:31
@ z
Definition: CartesianDirection.hpp:30
@ x
Definition: CartesianDirection.hpp:28
@ y
Definition: CartesianDirection.hpp:29
size_t value(const CartesianDirection direction) const
Definition: CartesianExponents.hpp:116