Orbital rotations#
Reference state parameterization#
In time-dependent Hartree–Fock, the variations of orbitals in the time-independent reference state, \(| 0 \rangle = | \Psi_\mathrm{HF} \rangle\), can be introduced by means of an exponential parameterization
where
It is convenient to organize the electron transfer amplitudes into the virtual–occupied (vo) and occupied–virtual (ov) blocks of a molecular orbital (MO) matrix. In the vo- and ov-blocks, we put amplitudes \(\kappa_{ai}\) and \(\kappa_{ai}^\ast \equiv \kappa_{ia}\), respectively.
The \(\kappa\)-matrix is Hermitian and so is the \(\hat{\kappa}\)-operator.
Generator of orbital rotations#
For an \(N\)-electron system, we have
Since
we have
where we have introduced time-transformed creation operators
From the algebra of creation and annihilation operators, we find that
and therefore
where we have introduced the unitary matrix
Following the determinant property of linearity, this transformation of creation operators translates directly into a transformation of orbitals in the wave function
where
This transformation preserves orthonormality among the orbitals and the \(\hat{\kappa}\)-operator can be thought of as a generator of rotations in the space of molecular orbitals.
Phase isolation#
The phase is preserved in the orbital transformation in the sense that the overall phase of the reference state does not change, or in terms of orbitals
It can therefore be used for the parameterization of phase-isolated wave functions as indicated with the overbar in \(| \bar{\Psi}(t) \rangle\).
Spin symmetry#
If we wish to preserve the singlet spin symmetry of a closed-shell reference state, we use spin-adapted electron-transfer operators
where
Summations here run over molecular orbitals (MOs) instead of spin orbitals, and consequently, the number of parameters is reduced by a factor of four.
We get
where
with
Illustrations#
import numpy as np
from scipy.linalg import expm
Let us consider a system of two-electrons in two MOs (or four spin orbitals).
Multi-electron excited determinants#
The generator of rotations includes only single electron excitation operators but the range of the transformation includes all determinants, also multi-electron excited determinants.
We reach the doubly excited determinant with
k31, k32, k41, k42 = (np.pi * 0.5j, 0, 0, np.pi * 0.5j)
k13, k23, k14, k24 = np.conjugate((k31, k32, k41, k42))
kappa = np.array(
[[0, 0, k13, k14], [0, 0, k23, k24], [k31, k32, 0, 0], [k41, k42, 0, 0]]
)
U = expm(-1j * kappa)
print("Occupied orbitals:\n", U.real[:, :2])
Occupied orbitals:
[[0. 0.]
[0. 0.]
[1. 0.]
[0. 1.]]
Phase isolation#
Let us create a random generator of orbital rotations on the form
np.set_printoptions(precision=6, suppress=True, linewidth=170)
np.random.seed(20240208)
kappa = np.zeros((4, 4), dtype=complex)
kappa[2:, :2] = np.random.rand(2, 2) + 1j * np.random.rand(2, 2)
kappa = kappa + np.conjugate(kappa).T
The transformed orbitals become
U = expm(-1j * kappa)
print("Transformed orbitals:\n", U)
Transformed orbitals:
[[ 0.414314+0.j -0.272098-0.000049j -0.063249-0.357053j -0.609038-0.501889j]
[-0.272098+0.000049j 0.784682+0.j -0.400653-0.136519j -0.138307-0.334586j]
[ 0.063249-0.357053j 0.400653-0.136519j 0.78434 +0.j -0.265899+0.058835j]
[ 0.609038-0.501889j 0.138307-0.334586j -0.265899-0.058835j 0.414656+0.j ]]
We note that the diagonal elements are real, i.e.
Spin symmetry#
The singlet spin symmetry of the closed-shell reference state, \(|\psi_1, \psi_2 \rangle\), is preserved by requiring that \(\kappa_{42} = \kappa_{31}\) and \(\kappa_{41} = \kappa_{32} = 0\).
As an example, let us consider
k31, k32, k41, k42 = (np.pi * 0.25j, 0, 0, np.pi * 0.25j)
k13, k23, k14, k24 = np.conjugate((k31, 0, 0, k42))
kappa = np.array(
[[0, 0, k13, k14], [0, 0, k23, k24], [k31, k32, 0, 0], [k41, k42, 0, 0]]
)
U = expm(-1j * kappa)
print("Occupied orbitals:\n", U.real[:, :2])
Occupied orbitals:
[[0.707107 0. ]
[0. 0.707107]
[0.707107 0. ]
[0. 0.707107]]
The resulting state can be written
where we identify the reference state and the doubly excited determinant alongside the singly excited spin-adapted configuration of singlet spin symmetry.
Finally, let us consider a somewhat larger system with four electrons in six MOs (or 12 spin orbitals). In the spin-orbital basis, it is convenient to organize parameters in spin blocks.
Let us perform a random transformation of the spin orbitals and print out \(\tilde{\psi}_1\) and \(\tilde{\psi}_\bar{1}\) as examples.
k31, k41, k51, k61, k32, k42, k52, k62 = np.random.rand(8) + 1j * np.random.rand(8)
k13, k14, k15, k16, k23, k24, k25, k26 = np.conjugate(
(k31, k41, k51, k61, k32, k42, k52, k62)
)
kappa = np.array(
[
[0, 0, 0, 0, k13, k14, k15, k16, 0, 0, 0, 0],
[0, 0, 0, 0, k23, k24, k25, k26, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, k13, k14, k15, k16],
[0, 0, 0, 0, 0, 0, 0, 0, k23, k24, k25, k26],
[k31, k32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[k41, k42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[k51, k52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[k61, k62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, k31, k32, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, k41, k42, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, k51, k52, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, k61, k62, 0, 0, 0, 0, 0, 0, 0, 0],
]
)
U = expm(-1j * kappa)
print("Lowest occupied alpha-spin orbital:\n", U[:,0])
print("Lowest occupied beta-spin orbital:\n", U[:,2])
Lowest occupied alpha-spin orbital:
[ 0.195145-0.j -0.674738-0.007566j 0. +0.j 0. +0.j 0.272185-0.364692j 0.150157-0.219078j -0.077445-0.261337j 0.390656+0.045347j
0. +0.j 0. +0.j 0. +0.j 0. +0.j ]
Lowest occupied beta-spin orbital:
[ 0. +0.j 0. +0.j 0.195145-0.j -0.674738-0.007566j 0. +0.j 0. +0.j 0. +0.j 0. +0.j
0.272185-0.364692j 0.150157-0.219078j -0.077445-0.261337j 0.390656+0.045347j]
We note that the spatial parts of the two spin orbitals are identical.
If we instead implement the transformation in the MO-basis, the dimension of the \(\kappa\)-matrix becomes reduced by a factor of two.
kappa = np.array(
[
[0, 0, k13, k14, k15, k16],
[0, 0, k23, k24, k25, k26],
[k31, k32, 0, 0, 0, 0],
[k41, k42, 0, 0, 0, 0],
[k51, k52, 0, 0, 0, 0],
[k61, k62, 0, 0, 0, 0],
]
)
U = expm(-1j * kappa)
print("Lowest occupied molecular orbital:\n", U[:,0])
Lowest occupied molecular orbital:
[ 0.195145-0.j -0.674738-0.007566j 0.272185-0.364692j 0.150157-0.219078j -0.077445-0.261337j 0.390656+0.045347j]
We note that this molecular orbital is identical to the spatial parts of the spin orbitals in the previous example.