GQCP
Loading...
Searching...
No Matches
PrimitiveElectronicQuadrupoleIntegralEngine.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
28#include <boost/math/constants/constants.hpp>
29
30
31namespace GQCP {
32
33
41template <typename _Shell>
44public:
45 // The type of shell that this integral engine is related to.
46 using Shell = _Shell;
47
48 // The type of primitive that underlies the type of shell.
49 using Primitive = typename Shell::Primitive;
50
51 // The scalar representation of an overlap integral.
53
54
55private:
56 // The electronic quadrupole operator over which integrals should be calculated.
57 ElectronicQuadrupoleOperator quadrupole_operator;
58
59
60public:
61 /*
62 * MARK: Constructors
63 */
64
70 quadrupole_operator {quadrupole_operator},
72
73
74 /*
75 * MARK: London CartesianGTO integrals
76 */
77
86 template <typename Z = Shell>
88
89 // Prepare some variables.
90 const auto i = static_cast<int>(left.cartesianGTO().cartesianExponents().value(CartesianDirection::x));
91 const auto k = static_cast<int>(left.cartesianGTO().cartesianExponents().value(CartesianDirection::y));
92 const auto m = static_cast<int>(left.cartesianGTO().cartesianExponents().value(CartesianDirection::z));
93
94 const auto j = static_cast<int>(right.cartesianGTO().cartesianExponents().value(CartesianDirection::x));
95 const auto l = static_cast<int>(right.cartesianGTO().cartesianExponents().value(CartesianDirection::y));
96 const auto n = static_cast<int>(right.cartesianGTO().cartesianExponents().value(CartesianDirection::z));
97
98 const auto a = left.cartesianGTO().gaussianExponent();
99 const auto b = right.cartesianGTO().gaussianExponent();
100
101 const auto K_x = left.cartesianGTO().center()(CartesianDirection::x);
102 const auto K_y = left.cartesianGTO().center()(CartesianDirection::y);
103 const auto K_z = left.cartesianGTO().center()(CartesianDirection::z);
104
105 const auto L_x = right.cartesianGTO().center()(CartesianDirection::x);
106 const auto L_y = right.cartesianGTO().center()(CartesianDirection::y);
107 const auto L_z = right.cartesianGTO().center()(CartesianDirection::z);
108
109 const Vector<double, 3> k1 = right.kVector() - left.kVector(); // The k-vector of the London overlap distribution.
110
111 const auto k1_x = k1(CartesianDirection::x);
112 const auto k1_y = k1(CartesianDirection::y);
113 const auto k1_z = k1(CartesianDirection::z);
114
115
116 // For the current component, the integral can be calculated as a product of three contributions, containing one-dimensional quadrupole integrals, one-dimensional dipole integrals and one-dimensional overlap integrals.
117 // Even though we are working with electronic dipole integrals as opposed to working with position integrals, there is no need to incorporate any sign factors because the dipole integrals always appear in pairs, hence the potential sign factors cancel out.
120
121 switch (this->component) {
123 return this->calculate1D(k1_x, a, K_x, i, b, L_x, j) * S0.calculate1D(k1_y, a, K_y, k, b, L_y, l) * S0.calculate1D(k1_z, a, K_z, m, b, L_z, n);
124 break;
125 }
126
128 return S1.calculate1D(k1_x, a, K_x, i, b, L_x, j) * S1.calculate1D(k1_y, a, K_y, k, b, L_y, l) * S0.calculate1D(k1_z, a, K_z, m, b, L_z, n);
129 break;
130 }
131
133 return S1.calculate1D(k1_x, a, K_x, i, b, L_x, j) * S0.calculate1D(k1_y, a, K_y, k, b, L_y, l) * S1.calculate1D(k1_z, a, K_z, m, b, L_z, n);
134 break;
135 }
136
138 return S1.calculate1D(k1_x, a, K_x, i, b, L_x, j) * S1.calculate1D(k1_y, a, K_y, k, b, L_y, l) * S0.calculate1D(k1_z, a, K_z, m, b, L_z, n);
139 break;
140 }
141
143 return S0.calculate1D(k1_x, a, K_x, i, b, L_x, j) * this->calculate1D(k1_y, a, K_y, k, b, L_y, l) * S0.calculate1D(k1_z, a, K_z, m, b, L_z, n);
144 break;
145 }
146
148 return S0.calculate1D(k1_x, a, K_x, i, b, L_x, j) * S1.calculate1D(k1_y, a, K_y, k, b, L_y, l) * S1.calculate1D(k1_z, a, K_z, m, b, L_z, n);
149 break;
150 }
151
153 return S1.calculate1D(k1_x, a, K_x, i, b, L_x, j) * S0.calculate1D(k1_y, a, K_y, k, b, L_y, l) * S1.calculate1D(k1_z, a, K_z, m, b, L_z, n);
154 break;
155 }
156
158 return S0.calculate1D(k1_x, a, K_x, i, b, L_x, j) * S1.calculate1D(k1_y, a, K_y, k, b, L_y, l) * S1.calculate1D(k1_z, a, K_z, m, b, L_z, n);
159 break;
160 }
161
163 return S0.calculate1D(k1_x, a, K_x, i, b, L_x, j) * S0.calculate1D(k1_y, a, K_y, k, b, L_y, l) * this->calculate1D(k1_z, a, K_z, m, b, L_z, n);
164 break;
165 }
166 }
167 }
168
169
183 template <typename Z = Shell>
184 enable_if_t<std::is_same<Z, LondonGTOShell>::value, IntegralScalar> calculate1D(const complex k1, const double a, const double K, const int i, const double b, const double L, const int j) {
185
186 // Prepare the component X_KC, which is the x-, y- or z-component of the vector between K and the origin of the quadrupole operator.
188 switch (this->component) {
191 break;
192 }
195 break;
196 }
199 break;
200 }
201 default:
202 break;
203 }
204 const auto X_KC = K - this->quadrupole_operator.reference()(component);
205
206
207 // The 1-D electronic quadrupole integral can be calculated completely from overlap integrals.
209 return S0.calculate1D(k1, a, K, i + 2, b, L, j) +
210 2 * X_KC * S0.calculate1D(k1, a, K, i + 1, b, L, j) +
211 std::pow(X_KC, 2) * S0.calculate1D(k1, a, K, i, b, L, j);
212 }
213};
214
215
216} // namespace GQCP
Definition: BaseMatrixPrimitiveIntegralEngine.hpp:32
DyadicCartesianDirection component
Definition: BaseMatrixPrimitiveIntegralEngine.hpp:35
const Vector< double, 3 > & reference() const
Definition: BaseReferenceDependentOperator.hpp:66
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: ElectronicDipoleOperator.hpp:33
Definition: ElectronicQuadrupoleOperator.hpp:33
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: PrimitiveElectronicDipoleIntegralEngine.hpp:42
Definition: PrimitiveElectronicQuadrupoleIntegralEngine.hpp:43
enable_if_t< std::is_same< Z, LondonGTOShell >::value, IntegralScalar > calculate(const LondonCartesianGTO &left, const LondonCartesianGTO &right)
Definition: PrimitiveElectronicQuadrupoleIntegralEngine.hpp:87
_Shell Shell
Definition: PrimitiveElectronicQuadrupoleIntegralEngine.hpp:46
product_t< ElectronicQuadrupoleOperator::Scalar, typename Primitive::OutputType > IntegralScalar
Definition: PrimitiveElectronicQuadrupoleIntegralEngine.hpp:52
typename Shell::Primitive Primitive
Definition: PrimitiveElectronicQuadrupoleIntegralEngine.hpp:49
enable_if_t< std::is_same< Z, LondonGTOShell >::value, IntegralScalar > calculate1D(const complex k1, const double a, const double K, const int i, const double b, const double L, const int j)
Definition: PrimitiveElectronicQuadrupoleIntegralEngine.hpp:184
PrimitiveElectronicQuadrupoleIntegralEngine(const ElectronicQuadrupoleOperator &quadrupole_operator, const DyadicCartesianDirection component=DyadicCartesianDirection::xx)
Definition: PrimitiveElectronicQuadrupoleIntegralEngine.hpp:69
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: 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
DyadicCartesianDirection
Definition: DyadicCartesianDirection.hpp:27
@ zx
Definition: DyadicCartesianDirection.hpp:34
@ xz
Definition: DyadicCartesianDirection.hpp:30
@ yy
Definition: DyadicCartesianDirection.hpp:32
@ yx
Definition: DyadicCartesianDirection.hpp:31
@ xy
Definition: DyadicCartesianDirection.hpp:29
@ xx
Definition: DyadicCartesianDirection.hpp:28
@ yz
Definition: DyadicCartesianDirection.hpp:33
@ zy
Definition: DyadicCartesianDirection.hpp:35
@ zz
Definition: DyadicCartesianDirection.hpp:36
CartesianDirection
Definition: CartesianDirection.hpp:27
@ 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