GQCP
Loading...
Searching...
No Matches
USQTwoElectronOperator.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
20
34
35
36namespace GQCP {
37
38
45template <typename _Scalar, typename _Vectorizer>
47 public DoublySpinResolvedBase<PureUSQTwoElectronOperatorComponent<_Scalar, _Vectorizer>, MixedUSQTwoElectronOperatorComponent<_Scalar, _Vectorizer>, USQTwoElectronOperator<_Scalar, _Vectorizer>>,
48 public DoublySpinResolvedBasisTransformable<USQTwoElectronOperator<_Scalar, _Vectorizer>>,
49 public DoublySpinResolvedJacobiRotatable<USQTwoElectronOperator<_Scalar, _Vectorizer>>,
50 public VectorSpaceArithmetic<USQTwoElectronOperator<_Scalar, _Vectorizer>, _Scalar> {
51public:
52 // The scalar type used for a single parameter: real or complex.
53 using Scalar = _Scalar;
54
55 // The type of the vectorizer that relates a one-dimensional storage of matrices to the tensor structure of two-electron operators. This distinction is carried over from `USQOneElectronOperator`.
56 using Vectorizer = _Vectorizer;
57
58 // The type of 'this'.
60
61 // The type of the transformation that is naturally related to an unrestricted two-electron operator.
63
64 // The type of Jacobi rotation that is naturally related to an unrestricted two-electron operator.
66
67 // The spinor tag corresponding to a `USQTwoElectronOperator`.
69
70 // The type components this spin resolved object is made of.
73
74
75public:
76 /*
77 * MARK: Constructors
78 */
79
80 // Inherit `DoublySpinResolvedBase`'s constructors.
82
83
95 template <size_t N>
96 USQTwoElectronOperator(const std::array<SquareRankFourTensor<Scalar>, N>& gs_aa, const std::array<SquareRankFourTensor<Scalar>, N>& gs_ab, const std::array<SquareRankFourTensor<Scalar>, N>& gs_ba, const std::array<SquareRankFourTensor<Scalar>, N>& gs_bb, const Vectorizer& vectorizer) :
97
98 // Encapsulate the array of matrix representations in the different spin-components components, and put them together to form the `USQTwoElectronOperator`.
102 MixedUSQTwoElectronOperatorComponent<Scalar, Vectorizer> {StorageArray<SquareRankFourTensor<Scalar>, Vectorizer> {gs_ba, vectorizer}},
103 PureUSQTwoElectronOperatorComponent<Scalar, Vectorizer> {StorageArray<SquareRankFourTensor<Scalar>, Vectorizer> {gs_bb, vectorizer}}) {
104
105 // Check if the given tensor representations have the same dimensions, for each spin part.
106 const auto dimension_of_first_aa = gs_aa[0].dimension();
107 const auto dimension_of_first_ab = gs_ab[0].dimension();
108 const auto dimension_of_first_ba = gs_ba[0].dimension();
109 const auto dimension_of_first_bb = gs_bb[0].dimension();
110
111 for (size_t i = 1; i < N; i++) {
112
113 const auto dimension_of_ith_aa = gs_aa[i].dimension();
114 const auto dimension_of_ith_ab = gs_ab[i].dimension();
115 const auto dimension_of_ith_ba = gs_ba[i].dimension();
116 const auto dimension_of_ith_bb = gs_bb[i].dimension();
117
118 if ((dimension_of_first_aa != dimension_of_ith_aa) || (dimension_of_first_ab != dimension_of_ith_ab) || (dimension_of_first_ba != dimension_of_ith_ba) || (dimension_of_first_bb != dimension_of_ith_bb)) {
119 throw std::invalid_argument("USQTwoElectronOperator(const std::array<SquareRankFourTensor<Scalar>, N>&, const std::array<SquareRankFourTensor<Scalar>, N>&, const std::array<SquareRankFourTensor<Scalar>, N>&, const std::array<SquareRankFourTensor<Scalar>, N>&): The given tensor representations do not have the same dimensions for either the alpha, beta or one of the mixed components.");
120 }
121 }
122 }
123
124
135 template <typename Z = Vectorizer>
137 typename std::enable_if<std::is_same<Z, ScalarVectorizer>::value>::type* = 0) :
138 USQTwoElectronOperator(std::array<SquareRankFourTensor<Scalar>, 1> {g_aa}, std::array<SquareRankFourTensor<Scalar>, 1> {g_ab}, std::array<SquareRankFourTensor<Scalar>, 1> {g_ba}, std::array<SquareRankFourTensor<Scalar>, 1> {g_bb}, ScalarVectorizer()) {}
139
140
146
147
148 /*
149 * MARK: Named constructors
150 */
151
158
159 const auto zero_component_pure = PureUSQTwoElectronOperatorComponent<Scalar, Vectorizer>::Zero(dim);
160 const auto zero_component_mixed = MixedUSQTwoElectronOperatorComponent<Scalar, Vectorizer>::Zero(dim);
161
162 return USQTwoElectronOperator<Scalar, Vectorizer> {zero_component_pure, zero_component_mixed, zero_component_mixed, zero_component_pure};
163 }
164
165
172
173 return USQTwoElectronOperator<Scalar, Vectorizer> {g_restricted.alphaAlpha(), g_restricted.alphaBeta(), g_restricted.betaAlpha(), g_restricted.betaBeta()};
174 }
175
176
177 /*
178 * MARK: Calculations
179 */
180
189
190 // Calculate the sum of all spin contributions.
191 // Unfortunately, we can't give `StorageArray` out-of-the-box vector-space arithmetic (since the default scalar type for scalar multiplication is unknown), so we'll have to do the summation ourselves.
192 const auto expectation_value_elements_aa = this->alphaAlpha().calculateExpectationValue(d.alphaAlpha()).elements();
193 const auto expectation_value_elements_ab = this->alphaBeta().calculateExpectationValue(d.alphaBeta()).elements();
194 const auto expectation_value_elements_ba = this->betaAlpha().calculateExpectationValue(d.betaAlpha()).elements();
195 const auto expectation_value_elements_bb = this->betaBeta().calculateExpectationValue(d.betaBeta()).elements();
196
197 auto result_elements = expectation_value_elements_aa;
198 const auto vectorizer = this->alphaAlpha().vectorizer();
199 for (size_t i = 0; i < vectorizer.numberOfElements(); i++) {
200 result_elements[i] += expectation_value_elements_ab[i] + expectation_value_elements_ba[i] + expectation_value_elements_bb[i];
201 }
202
203 return StorageArray<Scalar, Vectorizer> {result_elements, vectorizer};
204 }
205
206
207 /*
208 * MARK: General information
209 */
210
217 size_t numberOfOrbitals(const Spin sigma, const Spin tau) const {
218
219 if (sigma == Spin::alpha && tau == Spin::beta) {
220 return this->alphaAlpha().numberOfOrbitals();
221 } else if (sigma == Spin::alpha && tau == Spin::beta) {
222 return this->alphaBeta().numberOfOrbitals();
223 } else if (sigma == Spin::beta && tau == Spin::alpha) {
224 return this->betaAlpha().numberOfOrbitals();
225 } else {
226 return this->betaBeta().numberOfOrbitals();
227 }
228 }
229
230
231 /*
232 * @return The number of orbital related to the alpha-alpha part of the unrestricted two-electron operator.
233 *
234 * @note It is advised to only use this API when it is known that all spin-components of the two-electron operator are equal.
235 */
236 size_t numberOfOrbitals() const { return this->alphaAlpha().numberOfOrbitals(); }
237
238
243 // Since `rotate` and `rotated` are both defined in `DoublySpinResolvedBasisTransformable` and `DoublySpinResolvedJacobiRotatable`, we have to explicitly enable these methods here.
244
245 // Allow the `rotate` method from `DoublySpinResolvedBasisTransformable`, since there's also a `rotate` from `DoublySpinResolvedJacobiRotatable`.
247
248 // Allow the `rotated` method from `DoublySpinResolvedBasisTransformable`, since there's also a `rotated` from `DoublySpinResolvedJacobiRotatable`.
250
251 // Allow the `rotate` method from `DoublySpinResolvedJacobiRotatable`, since there's also a `rotate` from `DoublySpinResolvedBasisTransformable`.
253
254 // Allow the `rotated` method from `DoublySpinResolvedJacobiRotatable`, since there's also a `rotated` from `DoublySpinResolvedBasisTransformable`.
256
257
258 /*
259 * MARK: Conforming to VectorSpaceArithmetic
260 */
261
265 Self& operator+=(const Self& rhs) override {
266
267 // Add the spin-components.
268 this->alphaAlpha() += rhs.alphaAlpha();
269 this->alphaBeta() += rhs.alphaBeta();
270 this->betaAlpha() += rhs.betaAlpha();
271 this->betaBeta() += rhs.betaBeta();
272
273 return *this;
274 }
275
276
280 Self& operator*=(const Scalar& a) override {
281
282 // Multiply the spin-components with the scalar.
283 this->alphaAlpha() *= a;
284 this->alphaBeta() *= a;
285 this->betaAlpha() *= a;
286 this->betaBeta() *= a;
287
288 return *this;
289 }
290};
291
292
293/*
294 * MARK: Convenience aliases
295 */
296
297// A scalar-like USQTwoElectronOperator, i.e. with scalar-like access.
298template <typename Scalar>
300
301// A vector-like USQTwoElectronOperator, i.e. with vector-like access.
302template <typename Scalar>
304
305// A matrix-like USQTwoElectronOperator, i.e. with matrix-like access.
306template <typename Scalar>
308
309// A tensor-like USQTwoElectronOperator, i.e. with tensor-like access.
310template <typename Scalar, size_t N>
312
313
320template <typename Scalar, typename Vectorizer>
321struct OperatorTraits<USQTwoElectronOperator<Scalar, Vectorizer>> {
322
323 // A type that corresponds to the scalar version of the associated unrestricted one-electron operator type.
325
326 // The type of transformation that is naturally associated to an unrestricted two-electron operator.
328
329 // The type of the one-particle density matrix that is naturally associated an unrestricted two-electron operator.
331
332 // The type of the two-particle density matrix that is naturally associated an unrestricted two-electron operator.
334};
335
336
337/*
338 * MARK: BasisTransformableTraits
339 */
340
344template <typename Scalar, typename Vectorizer>
346
347 // The type of transformation that is naturally related to a `USQTwoElectronOperator`.
349};
350
351
352/*
353 * MARK: JacobiRotatableTraits
354 */
355
359template <typename Scalar, typename Vectorizer>
361
362 // The type of Jacobi rotation for which the Jacobi rotation should be defined.
364};
365
366
367/*
368 * MARK: One-electron operator products
369 */
370
376template <typename _Scalar>
378 public VectorSpaceArithmetic<ScalarUSQOneElectronOperatorProduct<_Scalar>, _Scalar>,
379 public BasisTransformable<ScalarUSQOneElectronOperatorProduct<_Scalar>>,
380 public JacobiRotatable<ScalarUSQOneElectronOperatorProduct<_Scalar>> {
381public:
382 // The scalar type of one of the matrix elements: real or complex.
383 using Scalar = _Scalar;
384
385 // The type of 'this'.
387
388
389private:
390 // The one-electron part of the product.
392
393 // The two-electron part of the product. Since it is expressed as a `SQTwoElectronOperator`.
395
396
397public:
398 /*
399 * MARK: Constructors
400 */
401
409 o {o},
410 t {t} {}
411
412
413 /*
414 * MARK: Access
415 */
416
420 const ScalarUSQOneElectronOperator<Scalar>& oneElectron() const { return this->o; }
421
425 const ScalarUSQTwoElectronOperator<Scalar>& twoElectron() const { return this->t; }
426
431
436
437
438 /*
439 * MARK: Conforming to `VectorSpaceArithmetic`
440 */
441
446
447 // Add the one- and two-electron operator parts.
448 this->oneElectron() += rhs.oneElectron();
449 this->twoElectron() += rhs.twoElectron();
450
451 return *this;
452 }
453
454
459
460 // Multiply the one- and two-electron operator parts with the scalar.
461 this->oneElectron() *= a;
462 this->twoElectron() *= a;
463
464 return *this;
465 }
466
467
468 /*
469 * MARK: Conforming to BasisTransformable
470 */
471
479 Self transformed(const UTransformation<Scalar>& T) const override {
480
481 auto result = *this;
482
483 // Transform the one- and two-electron contributions.
484 result.oneElectron().transform(T);
485 result.twoElectron().transform(T);
486
487 return result;
488 }
489
490
491 // Allow the `rotate` method from `BasisTransformable`, since there's also a `rotate` from `JacobiRotatable`.
493
494 // Allow the `rotated` method from `BasisTransformable`, since there's also a `rotated` from `JacobiRotatable`.
496
497
498 /*
499 * MARK: Conforming to JacobiRotatable
500 */
501
509 Self rotated(const UJacobiRotation& jacobi_rotation) const override {
510
511 auto result = *this;
512
513 // Transform the total one- and two-electron contributions.
514 result.oneElectron().rotate(jacobi_rotation);
515 result.twoElectron().rotate(jacobi_rotation);
516
517 return result;
518 }
519
520 // Allow the `rotate` method from `JacobiRotatable`, since there's also a `rotate` from `BasisTransformable`.
522
523
524 /*
525 * MARK: Expectation value
526 */
527
537
538 // We can access the expectation value of a scalar operator using an empty call.
539 return this->oneElectron().calculateExpectationValue(D)() + this->twoElectron().calculateExpectationValue(d)();
540 }
541};
542
543
544/*
545 * MARK: `BasisTransformableTraits` for `ScalarUSQOneElectronOperatorProduct`.
546 */
547
553template <typename Scalar>
555
556 // The type of transformation matrix that is naturally associated to a `ScalarUSQOneElectronOperatorProduct`.
558};
559
560
561/*
562 * MARK: `JacobiRotatableTraits` for `ScalarUSQOneElectronOperatorProduct`.
563 */
564
570template <typename Scalar>
572
573 // The type of Jacobi rotation for which the Jacobi rotation should be defined.
575};
576
577
578} // namespace GQCP
Definition: BasisTransformable.hpp:50
void rotate(const Transformation &U)
Definition: BasisTransformable.hpp:107
Definition: DoublySpinResolvedBase.hpp:36
Definition: DoublySpinResolvedBasisTransformable.hpp:35
Definition: DoublySpinResolvedJacobiRotatable.hpp:35
USQTwoElectronOperator< _Scalar, _Vectorizer > rotated(const JacobiRotationType &jacobi_rotation) const override
Definition: DoublySpinResolvedJacobiRotatable.hpp:54
Definition: JacobiRotatable.hpp:50
Definition: MixedUSQTwoElectronOperatorComponent.hpp:40
StorageArray< Scalar, Vectorizer > calculateExpectationValue(const MixedSpinResolved2DMComponent< Scalar > &d) const
Definition: MixedUSQTwoElectronOperatorComponent.hpp:72
Definition: PureUSQTwoElectronOperatorComponent.hpp:39
Definition: RSQTwoElectronOperator.hpp:43
PureUSQTwoElectronOperatorComponent< Scalar, Vectorizer > alphaAlpha() const
Definition: RSQTwoElectronOperator.hpp:71
MixedUSQTwoElectronOperatorComponent< Scalar, Vectorizer > alphaBeta() const
Definition: RSQTwoElectronOperator.hpp:82
MixedUSQTwoElectronOperatorComponent< Scalar, Vectorizer > betaAlpha() const
Definition: RSQTwoElectronOperator.hpp:93
PureUSQTwoElectronOperatorComponent< Scalar, Vectorizer > betaBeta() const
Definition: RSQTwoElectronOperator.hpp:103
size_t numberOfOrbitals() const
Definition: SQOperatorStorageBase.hpp:277
const Vectorizer & vectorizer() const
Definition: SQOperatorStorageBase.hpp:282
static FinalOperator Zero(const size_t dim, const Vectorizer &vectorizer)
Definition: SQOperatorStorageBase.hpp:145
Definition: USQTwoElectronOperator.hpp:380
ScalarUSQOneElectronOperatorProduct< Scalar > Self
Definition: USQTwoElectronOperator.hpp:386
Self rotated(const UJacobiRotation &jacobi_rotation) const override
Definition: USQTwoElectronOperator.hpp:509
Scalar calculateExpectationValue(const SpinResolved1DM< Scalar > &D, const SpinResolved2DM< Scalar > &d) const
Definition: USQTwoElectronOperator.hpp:536
ScalarUSQOneElectronOperatorProduct(const ScalarUSQOneElectronOperator< Scalar > &o, const ScalarUSQTwoElectronOperator< Scalar > &t)
Definition: USQTwoElectronOperator.hpp:408
Self transformed(const UTransformation< Scalar > &T) const override
Definition: USQTwoElectronOperator.hpp:479
ScalarUSQOneElectronOperatorProduct & operator+=(const ScalarUSQOneElectronOperatorProduct &rhs) override
Definition: USQTwoElectronOperator.hpp:445
ScalarUSQOneElectronOperator< Scalar > & oneElectron()
Definition: USQTwoElectronOperator.hpp:430
ScalarUSQOneElectronOperatorProduct & operator*=(const Scalar &a) override
Definition: USQTwoElectronOperator.hpp:458
const ScalarUSQOneElectronOperator< Scalar > & oneElectron() const
Definition: USQTwoElectronOperator.hpp:420
ScalarUSQTwoElectronOperator< Scalar > & twoElectron()
Definition: USQTwoElectronOperator.hpp:435
const ScalarUSQTwoElectronOperator< Scalar > & twoElectron() const
Definition: USQTwoElectronOperator.hpp:425
_Scalar Scalar
Definition: USQTwoElectronOperator.hpp:383
StorageArray< Scalar, Vectorizer > calculateExpectationValue(const Derived2DM &d) const
Definition: SimpleSQTwoElectronOperator.hpp:104
Definition: SpinResolved1DM.hpp:44
Definition: SpinResolved2DM.hpp:44
Definition: SquareRankFourTensor.hpp:36
Definition: StorageArray.hpp:38
Definition: UJacobiRotation.hpp:32
Definition: USQOneElectronOperator.hpp:48
Definition: USQTwoElectronOperator.hpp:50
static USQTwoElectronOperator< Scalar, Vectorizer > FromRestricted(const RSQTwoElectronOperator< Scalar, Vectorizer > &g_restricted)
Definition: USQTwoElectronOperator.hpp:171
static USQTwoElectronOperator< Scalar, Vectorizer > Zero(const size_t dim)
Definition: USQTwoElectronOperator.hpp:157
USQTwoElectronOperator< Scalar, Vectorizer > Self
Definition: USQTwoElectronOperator.hpp:59
Self & operator+=(const Self &rhs) override
Definition: USQTwoElectronOperator.hpp:265
size_t numberOfOrbitals(const Spin sigma, const Spin tau) const
Definition: USQTwoElectronOperator.hpp:217
_Scalar Scalar
Definition: USQTwoElectronOperator.hpp:53
typename DoublySpinResolvedBase< PureUSQTwoElectronOperatorComponent< Scalar, Vectorizer >, MixedUSQTwoElectronOperatorComponent< Scalar, Vectorizer >, USQTwoElectronOperator< Scalar, Vectorizer > >::Pure PureComponentType
Definition: USQTwoElectronOperator.hpp:71
USQTwoElectronOperator()
Definition: USQTwoElectronOperator.hpp:144
_Vectorizer Vectorizer
Definition: USQTwoElectronOperator.hpp:56
size_t numberOfOrbitals() const
Definition: USQTwoElectronOperator.hpp:236
USQTwoElectronOperator(const SquareRankFourTensor< Scalar > &g_aa, const SquareRankFourTensor< Scalar > &g_ab, const SquareRankFourTensor< Scalar > &g_ba, const SquareRankFourTensor< Scalar > &g_bb, typename std::enable_if< std::is_same< Z, ScalarVectorizer >::value >::type *=0)
Definition: USQTwoElectronOperator.hpp:136
typename DoublySpinResolvedBase< PureUSQTwoElectronOperatorComponent< Scalar, Vectorizer >, MixedUSQTwoElectronOperatorComponent< Scalar, Vectorizer >, USQTwoElectronOperator< Scalar, Vectorizer > >::Mixed MixedComponentType
Definition: USQTwoElectronOperator.hpp:72
USQTwoElectronOperator(const std::array< SquareRankFourTensor< Scalar >, N > &gs_aa, const std::array< SquareRankFourTensor< Scalar >, N > &gs_ab, const std::array< SquareRankFourTensor< Scalar >, N > &gs_ba, const std::array< SquareRankFourTensor< Scalar >, N > &gs_bb, const Vectorizer &vectorizer)
Definition: USQTwoElectronOperator.hpp:96
StorageArray< Scalar, Vectorizer > calculateExpectationValue(const SpinResolved2DM< Scalar > &d) const
Definition: USQTwoElectronOperator.hpp:188
Self & operator*=(const Scalar &a) override
Definition: USQTwoElectronOperator.hpp:280
Definition: spinor_tags.hpp:37
Definition: VectorSpaceArithmetic.hpp:35
Definition: BaseOneElectronIntegralBuffer.hpp:25
UnrestrictedSpinorTag UnrestrictedSpinOrbitalTag
Definition: spinor_tags.hpp:42
DenseVectorizer< 0 > ScalarVectorizer
Definition: DenseVectorizer.hpp:203
Spin
Definition: Spin.hpp:27
@ beta
Definition: Spin.hpp:29
@ alpha
Definition: Spin.hpp:28
Definition: BasisTransformable.hpp:37
Definition: JacobiRotatable.hpp:37
Definition: OperatorTraits.hpp:28