GQCP
Loading...
Searching...
No Matches
PrimitiveAngularMomentumIntegralEngine.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
29namespace GQCP {
30
31
37template <typename _Shell>
40public:
41 // The type of shell that this integral engine is related to.
42 using Shell = _Shell;
43
44 // The type of primitive that underlies the type of shell.
45 using Primitive = typename Shell::Primitive;
46
47 // The scalar representation of an angular momentum integral.
49
50
51private:
52 // The angular momentum operator over which the integrals are calculated.
53 AngularMomentumOperator angular_momentum_operator;
54
55
56public:
57 /*
58 * MARK: Constructors
59 */
60
66 angular_momentum_operator {angular_momentum_operator},
68
69
70 /*
71 * MARK: CartesianGTO integrals
72 */
73
82 template <typename Z = Shell>
84
85 // Prepare some variables.
86 const auto i = static_cast<int>(left.cartesianExponents().value(CartesianDirection::x));
87 const auto k = static_cast<int>(left.cartesianExponents().value(CartesianDirection::y));
88 const auto m = static_cast<int>(left.cartesianExponents().value(CartesianDirection::z));
89
90 const auto j = static_cast<int>(right.cartesianExponents().value(CartesianDirection::x));
91 const auto l = static_cast<int>(right.cartesianExponents().value(CartesianDirection::y));
92 const auto n = static_cast<int>(right.cartesianExponents().value(CartesianDirection::z));
93
94 const auto a = left.gaussianExponent();
95 const auto b = right.gaussianExponent();
96
97 const auto K_x = left.center()(CartesianDirection::x);
98 const auto K_y = left.center()(CartesianDirection::y);
99 const auto K_z = left.center()(CartesianDirection::z);
100
101 const auto L_x = right.center()(CartesianDirection::x);
102 const auto L_y = right.center()(CartesianDirection::y);
103 const auto L_z = right.center()(CartesianDirection::z);
104
105
106 // For each component of the angular momentum operator, the integrals can be calculated through overlap integrals, linear momentum integrals and position/dipole integrals.
110
111
112 // The sign factors in the following formulas are required to switch from electronic dipole integrals to position integrals.
113 switch (this->component) {
115 S1.prepareStateForComponent(CartesianDirection::y);
117 const IntegralScalar term1 = -S1.calculate1D(a, K_y, k, b, L_y, l) * T1.calculate1D(a, K_z, m, b, L_z, n);
118
120 S1.prepareStateForComponent(CartesianDirection::z);
121 const IntegralScalar term2 = -T1.calculate1D(a, K_y, k, b, L_y, l) * S1.calculate1D(a, K_z, m, b, L_z, n);
122
123 return S0.calculate1D(a, K_x, i, b, L_x, j) * (term1 - term2); // Calculate a component of the cross product.
124 break;
125 }
126
128 S1.prepareStateForComponent(CartesianDirection::z);
130 const IntegralScalar term1 = -S1.calculate1D(a, K_z, m, b, L_z, n) * T1.calculate1D(a, K_x, i, b, L_x, j);
131
133 S1.prepareStateForComponent(CartesianDirection::x);
134 const IntegralScalar term2 = -T1.calculate1D(a, K_z, m, b, L_z, n) * S1.calculate1D(a, K_x, i, b, L_x, j);
135
136 return S0.calculate1D(a, K_y, k, b, L_y, l) * (term1 - term2); // Calculate a component of the cross product.
137 break;
138 }
139
141 S1.prepareStateForComponent(CartesianDirection::x);
143 const IntegralScalar term1 = -S1.calculate1D(a, K_x, i, b, L_x, j) * T1.calculate1D(a, K_y, k, b, L_y, l);
144
146 S1.prepareStateForComponent(CartesianDirection::y);
147 const IntegralScalar term2 = -T1.calculate1D(a, K_x, i, b, L_x, j) * S1.calculate1D(a, K_y, k, b, L_y, l);
148
149 return S0.calculate1D(a, K_z, m, b, L_z, n) * (term1 - term2); // Calculate a component of the cross product.
150 break;
151 }
152 }
153 }
154
155
156 /*
157 * MARK: London CartesianGTO integrals
158 */
159
168 template <typename Z = Shell>
170
171 // Prepare some variables.
172 const auto i = static_cast<int>(left.cartesianGTO().cartesianExponents().value(CartesianDirection::x));
173 const auto k = static_cast<int>(left.cartesianGTO().cartesianExponents().value(CartesianDirection::y));
174 const auto m = static_cast<int>(left.cartesianGTO().cartesianExponents().value(CartesianDirection::z));
175
176 const auto j = static_cast<int>(right.cartesianGTO().cartesianExponents().value(CartesianDirection::x));
177 const auto l = static_cast<int>(right.cartesianGTO().cartesianExponents().value(CartesianDirection::y));
178 const auto n = static_cast<int>(right.cartesianGTO().cartesianExponents().value(CartesianDirection::z));
179
180 const auto a = left.cartesianGTO().gaussianExponent();
181 const auto b = right.cartesianGTO().gaussianExponent();
182
183 const auto K_x = left.cartesianGTO().center()(CartesianDirection::x);
184 const auto K_y = left.cartesianGTO().center()(CartesianDirection::y);
185 const auto K_z = left.cartesianGTO().center()(CartesianDirection::z);
186
187 const auto L_x = right.cartesianGTO().center()(CartesianDirection::x);
188 const auto L_y = right.cartesianGTO().center()(CartesianDirection::y);
189 const auto L_z = right.cartesianGTO().center()(CartesianDirection::z);
190
191 const auto k_K = left.kVector();
192 const auto k_L = right.kVector();
193 const Vector<double, 3> k1 = right.kVector() - left.kVector(); // The k-vector of the London overlap distribution.
194
195 const auto k_K_x = k_K(CartesianDirection::x);
196 const auto k_K_y = k_K(CartesianDirection::y);
197 const auto k_K_z = k_K(CartesianDirection::z);
198
199 const auto k_L_x = k_L(CartesianDirection::x);
200 const auto k_L_y = k_L(CartesianDirection::y);
201 const auto k_L_z = k_L(CartesianDirection::z);
202
203 const auto k1_x = k1(CartesianDirection::x);
204 const auto k1_y = k1(CartesianDirection::y);
205 const auto k1_z = k1(CartesianDirection::z);
206
207
208 // For each component of the angular momentum operator, the integrals can be calculated through overlap integrals, linear momentum integrals and position/dipole integrals.
212
213
214 // The sign factors in the following formulas are required to switch from electronic dipole integrals to position integrals.
215 switch (this->component) {
217 S1.prepareStateForComponent(CartesianDirection::y);
219 const IntegralScalar term1 = -S1.calculate1D(k1_y, a, K_y, k, b, L_y, l) * T1.calculate1D(k_K_z, a, K_z, m, k_L_z, b, L_z, n);
220
222 S1.prepareStateForComponent(CartesianDirection::z);
223 const IntegralScalar term2 = -T1.calculate1D(k_K_y, a, K_y, k, k_L_y, b, L_y, l) * S1.calculate1D(k1_z, a, K_z, m, b, L_z, n);
224
225 return S0.calculate1D(k1_x, a, K_x, i, b, L_x, j) * (term1 - term2); // Calculate a component of the cross product.
226 break;
227 }
228
230 S1.prepareStateForComponent(CartesianDirection::z);
232 const IntegralScalar term1 = -S1.calculate1D(k1_z, a, K_z, m, b, L_z, n) * T1.calculate1D(k_K_x, a, K_x, i, k_L_x, b, L_x, j);
233
235 S1.prepareStateForComponent(CartesianDirection::x);
236 const IntegralScalar term2 = -T1.calculate1D(k_K_z, a, K_z, m, k_L_z, b, L_z, n) * S1.calculate1D(k1_x, a, K_x, i, b, L_x, j);
237
238 return S0.calculate1D(k1_y, a, K_y, k, b, L_y, l) * (term1 - term2); // Calculate a component of the cross product.
239 break;
240 }
241
243 S1.prepareStateForComponent(CartesianDirection::x);
245 const IntegralScalar term1 = -S1.calculate1D(k1_x, a, K_x, i, b, L_x, j) * T1.calculate1D(k_K_y, a, K_y, k, k_L_y, b, L_y, l);
246
248 S1.prepareStateForComponent(CartesianDirection::y);
249 const IntegralScalar term2 = -T1.calculate1D(k_K_x, a, K_x, i, k_L_x, b, L_x, j) * S1.calculate1D(k1_y, a, K_y, k, b, L_y, l);
250
251 return S0.calculate1D(k1_z, a, K_z, m, b, L_z, n) * (term1 - term2); // Calculate a component of the cross product.
252 break;
253 }
254 }
255 }
256};
257
258
259} // namespace GQCP
Definition: AngularMomentumOperator.hpp:35
const Vector< double, 3 > & reference() const
Definition: BaseReferenceDependentOperator.hpp:66
Definition: BaseVectorPrimitiveIntegralEngine.hpp:32
void prepareStateForComponent(const size_t component)
Definition: BaseVectorPrimitiveIntegralEngine.cpp:60
CartesianDirection component
Definition: BaseVectorPrimitiveIntegralEngine.hpp:36
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: ElectronicDipoleOperator.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: PrimitiveAngularMomentumIntegralEngine.hpp:39
product_t< AngularMomentumOperator::Scalar, typename Primitive::OutputType > IntegralScalar
Definition: PrimitiveAngularMomentumIntegralEngine.hpp:48
_Shell Shell
Definition: PrimitiveAngularMomentumIntegralEngine.hpp:42
typename Shell::Primitive Primitive
Definition: PrimitiveAngularMomentumIntegralEngine.hpp:45
enable_if_t< std::is_same< Z, LondonGTOShell >::value, IntegralScalar > calculate(const LondonCartesianGTO &left, const LondonCartesianGTO &right)
Definition: PrimitiveAngularMomentumIntegralEngine.hpp:169
enable_if_t< std::is_same< Z, GTOShell >::value, IntegralScalar > calculate(const CartesianGTO &left, const CartesianGTO &right)
Definition: PrimitiveAngularMomentumIntegralEngine.hpp:83
PrimitiveAngularMomentumIntegralEngine(const AngularMomentumOperator &angular_momentum_operator, const CartesianDirection component=CartesianDirection::x)
Definition: PrimitiveAngularMomentumIntegralEngine.hpp:65
Definition: PrimitiveElectronicDipoleIntegralEngine.hpp:42
Definition: PrimitiveLinearMomentumIntegralEngine.hpp:38
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: PrimitiveLinearMomentumIntegralEngine.hpp:130
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
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