Vibronic spectra

Technical details are available in the API documentation: sf.apps.vibronic

Here we study how GBS can be used to compute vibronic spectra. So let’s start from the beginning: what is a vibronic spectrum? Molecules absorb light at frequencies that depend on the allowed transitions between different electronic states. These electronic transitions can be accompanied by changes in the vibrational energy of the molecules. In this case, the absorption lines that represent the frequencies at which light is more strongly absorbed are referred to as the vibronic spectrum. The term vibronic refers to the simultaneous vibrational and electronic transitions of a molecule upon absorption of light.

It is possible to determine vibronic spectra by running clever and careful spectroscopy experiments. However, this can be slow and expensive, in which case it is valuable to predict vibronic spectra using theoretical calculations. To model molecular vibronic transitions with GBS, we need only a few relevant molecular parameters:

  1. \(\Omega\): diagonal matrix whose entries are the square-roots of the frequencies of the normal modes of the electronic initial state.

  2. \(\Omega'\): diagonal matrix whose entries are the square-roots of the frequencies of the normal modes of the electronic final state.

  3. \(U_\text{D}\): Duschinsky matrix.

  4. \(\delta\): displacement vector.

  5. \(T\): temperature.

The Duschinsky matrix and displacement vector encode information regarding how vibrational modes are transformed when the molecule changes from the initial to final electronic state. At zero temperature, all initial modes are in the vibrational ground state. At finite temperature, other vibrational states are also populated.

In the GBS algorithm for computing vibronic spectra [45], these chemical parameters are sufficient to determine the configuration of a GBS device. As opposed to other applications that involve only single-mode squeezing and linear interferometry, in vibronic spectra we prepare a Gaussian state using two-mode squeezing, linear interferometry, single-mode squeezing, and displacements.

The function gbs_params() of the vibronic module can be used to obtain the squeezing, interferometer, and displacement parameters from the input chemical parameters listed above. In this page, we study the vibronic spectrum of formic acid 🐜. Its chemical parameters, obtained from [45], can be found in the data module:

from strawberryfields.apps import vibronic, data
import numpy as np
formic = data.Formic()
w = formic.w  # ground state frequencies
wp = formic.wp  # excited state frequencies
Ud = formic.Ud  # Duschinsky matrix
delta = formic.delta  # displacement vector
T = 0  # temperature

We can now map this chemical information to GBS parameters using the function gbs_params():

t, U1, r, U2, alpha = vibronic.gbs_params(w, wp, Ud, delta, T)

Note that since two-mode squeezing operators are involved, if we have \(N\) vibrational modes, the Gaussian state prepared is a \(2N\)-mode Gaussian state and the samples are vectors of length \(2N\). The first \(N\) modes are those of the final electronic state; the remaining \(N\) modes are those of the ground state. From above, \(t\) is a vector of two-mode squeezing parameters, \(U_1\) and \(U_2\) are the interferometer unitaries (we need two interferometers), \(r\) is a vector of single-mode squeezing parameters, and alpha is a vector of displacements.

Photons detected at the output of the GBS device correspond to a specific transition energy. The GBS algorithm for vibronic spectra works because the programmed device provides samples in such a way that the energies that are sampled with high probability are the peaks of the vibronic spectrum. The function energies() can be used to compute the energies for a set of samples. In this case we show the energy of the first five samples:

e = vibronic.energies(formic, w, wp)
print(np.around(e[:5], 4))  # 4 decimal precision

Out:

[1566.4602 4699.3806 1566.4602 4699.3806 4699.3806]

Once the GBS parameters have been obtained, it is straightforward to run the GBS algorithm: we generate many samples, compute their energies, and make a histogram of the observed energies. The sample module contains the function vibronic(), which is tailored for use in vibronic spectra applications. Similarly, the plot module includes a spectrum() function that generates the vibronic spectrum from the GBS samples. Let’s see how this is done for just a few samples:

from strawberryfields.apps import sample, plot
import plotly
nr_samples = 10
s = sample.vibronic(t, U1, r, U2, alpha, nr_samples)
e = vibronic.energies(s, w, wp)
spectrum = plot.spectrum(e, xmin=-1000, xmax=8000)
plotly.offline.plot(spectrum, filename="spectrum.html")