{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ " " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 4 - Spin-boson model" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Throughout the first 3 tutorials, we have gradually come to see that a two state system (hereafter abbreviated to `TSS`) interacting with its environment can be modelled as a spin 1/2 particle in a magnetic field interacting with a quantised field of bosons.\n", "\n", "In this tutorial we explore this `spin-boson` model (as it is often called) in more detail and in so doing we'll (as always) discover some new physics along the way 🤓. It is worth noting that the spin-boson model also goes by other names - most notably the [\"dressed atom\"](https://youtu.be/k0X7iSaPM38) model which forms parts of various [university courses](https://ocw.mit.edu/courses/physics/8-422-atomic-and-optical-physics-ii-spring-2013/syllabus/).\n", "\n", "This tutorial is split up into the following sections:\n", "1. Recap\n", "2. Stationary states\n", "3. Structure of the Hamiltonian\n", "4. Parity\n", "5. Down conversion" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [], "source": [ "# Libraries\n", "%matplotlib inline\n", "import matplotlib.pyplot as plt\n", "from IPython.display import Image\n", "import gif\n", "import numpy as np\n", "import pandas as pd\n", "from qutip import *\n", "import warnings\n", "warnings.filterwarnings('ignore')\n", "from itertools import product\n", "import os" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 4.1 - Recap" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's remind ourselves of the Hamiltonian that we built up in the last tutorial ([Tutorial 3](https://nbviewer.jupyter.org/github/project-ida/two-state-quantum-systems/blob/master/03-a-two-state-system-in-a-quantised-field.ipynb#3.6---Spontaneous-emission)):\n", "\n", "$$H = \\overbrace{A \\sigma_z}^{TSS}+ \\overbrace{\\hbar\\omega\\left(a^{\\dagger}a +\\frac{1}{2}\\right)}^{bosons} + \\overbrace{\\frac{\\delta}{2}\\left( a^{\\dagger} + a \\right)\\sigma_x}^{interaction}$$\n", "\n", "The labels A and $\\delta$ were chosen because of the path of discovery that we took to get here. From now on, it will be convenient for us to re-write the Hamiltonian with different labels as:\n", "\n", "$$H = \\frac{\\Delta E}{2} \\sigma_z + \\hbar\\omega\\left(a^{\\dagger}a +\\frac{1}{2}\\right) + U\\left( a^{\\dagger} + a \\right)\\sigma_x$$\n", "\n", "where we recognise $\\Delta E$ as the transition energy of the TSS, $\\hbar\\omega$ the energy of a single boson and $U$ as the strength of the interaction of the TSS with the boson field.\n", "\n", "We will be referring to this Hamiltonian many times in our figures so let's make a variable so it's easier to refer to later." ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [], "source": [ "H_latex = \"$H = (\\Delta E / 2) \\sigma_z + \\hbar\\omega(a^{{\\dagger}}a +1/2) + U( a^{{\\dagger}} + a )\\sigma_x$\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the last tutorial we saw how the physics of spontaneous emission arose from an indirect coupling between the |+> and |-> states of the TSS which was mediated by the interaction with the boson field. This interaction manifested as a Rabi type oscillation between two states of the combined spin boson system (described by |n,±>), namely |0,+> and |1,->.\n", "\n", "In general, the result of such interactions are far more complicated than the Rabi type oscillations we are becoming familiar with. The complexity arises because the combined TSS and field system has many states that interact with each other strongly if their energies are similar.\n", "\n", "We can however still apply the ideas we've learnt about TSS's in some special and interesting situations. That is what we'll explore in this notebook." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 4.2 - Stationary states" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We begin in the same way that we started this tutorial series ([Tutorial 1](https://nbviewer.jupyter.org/github/project-ida/two-state-quantum-systems/blob/master/01-an-isolated-two-state-system.ipynb#1.1---Stationary-state)) by looking for the stationary states of the system. When the system is in one of these states it will remain there for all time. Such states are described by a single constant energy.\n", "\n", "To find the states of constant energy, we'll follow what we did in [Tutorial 2](https://nbviewer.jupyter.org/github/project-ida/two-state-quantum-systems/blob/master/02-perturbing-a-two-state-system.ipynb#2.1-Static-perturbation). Specifically, we will calculate the eigenvalues of the Hamiltonian (i.e the energies) and see how they depend on the TSS transition energy $\\Delta E$.\n", "\n", "What do we expect to find? Let's recall Tutorial 2 - the states of the TSS were directly coupled, mimicking the effect of a classical field. In Fig 3 of that tutorial we discovered an [avoided crossing](https://en.wikipedia.org/wiki/Avoided_crossing) (aka anti-crossing) when the transition energy of the TSS was zero - this was due to the coupling between the states splitting the energy levels apart.\n", "\n", "In the more complicated spin-boson system of this tutorial, the states of the TSS can only couple indirectly through the boson field. Let's see whether we find any similarities - we'll start with no interaction $U=0$ to familiarsie ourselves with the landscape before exploring the full delights of the spin boson system." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Since we will be creating many Hamiltonians with differing parameters, it's helpful to create a function to pre-compute the constant pieces. Specifically, the following function `make_operators` will compute the following:\n", "\n", "- `two_state` = $\\frac{1}{2}\\sigma_z$ \n", "- `bosons` = $a^{\\dagger}a +\\frac{1}{2}$\n", "- `interaction` = $\\left( a^{\\dagger} + a \\right)\\sigma_x$\n", "\n", "so that we can create Hamiltonians with many different TSS transition energies $\\Delta E$, boson frequencies $\\omega$ and interaction strengths $U$ in the following way:\n", "\n", "`H = DeltaE*two_state + omega*bosons + U*interaction`" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [], "source": [ "def make_operators(max_bosons):\n", " \n", " a = tensor(destroy(max_bosons+1), qeye(2)) # tensorised boson destruction operator\n", " sx = tensor(qeye(max_bosons+1), sigmax()) # tensorised sigma_x operator\n", " sz = tensor(qeye(max_bosons+1),sigmaz()) # tensorised sigma_z operator\n", " \n", " two_state = 1/2*sz # two state system energy operator 𝜎𝑧/2\n", " bosons = (a.dag()*a+0.5) # boson energy operator 𝑎†𝑎+1/2\n", " number = a.dag()*a # boson number operator 𝑎†𝑎\n", " interaction = (a.dag() + a) * sx # interaction energy operator (𝑎†+𝑎)𝜎𝑥\n", "\n", " \n", " return two_state, bosons, interaction, number" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If we want to be 100% correct in our description of the spin-boson system, we should allow the possibility of an infinite number of bosons to be present. This is obviously not computationally feasible so we must choose a finite number for the maximum number of bosons we wish to consider.\n", "\n", "For the sake of simplicity in visualisaion outputs, we choose a small number `max_bosons=4`." ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [], "source": [ "max_bosons = 4\n", "two_state, bosons, interaction, number = make_operators(max_bosons)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We now need to prepare a suitable data structure to hold the data about the energies of the stationary states. A [pandas dataframe](https://www.geeksforgeeks.org/python-pandas-dataframe/) (essentially a table) is a suitable choice (which makes plotting easier later).\n", "\n", "We need to specify:\n", "- number of rows - equal to the number of TSS transition energies ($\\Delta E$) that we wish to try\n", "- number of columns - equal to the number of energy levels plus 1 to store the values of $\\Delta E$\n", "- column labels\n", "\n", "Let's create another function for this and then look at an example:" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [], "source": [ "def make_df_for_energy_scan(label_param, min_param, max_param, num_param, num_levels):\n", " \n", " # creates an empty dictionary to store the row/column information\n", " d = {}\n", " \n", " # creates array of parameter values that we want to scan through\n", " param_values = np.linspace(min_param, max_param, num_param)\n", " \n", " # stores the parameter scan label and values (this will soon become the first column in the dataframe)\n", " d[label_param] = param_values\n", " \n", " # creates empty columns to store the eigenvalues for the different levels later on\n", " # num_levels will be the number of rows of H (or any of the operators that make up H)\n", " for i in range(num_levels):\n", " d[f\"level_{i}\"] = np.zeros(num_param)\n", " \n", " # creates the dataframe\n", " df = pd.DataFrame(data=d)\n", " \n", " return df" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", " | $\\Delta E$ | \n", "level_0 | \n", "level_1 | \n", "level_2 | \n", "level_3 | \n", "level_4 | \n", "level_5 | \n", "level_6 | \n", "level_7 | \n", "level_8 | \n", "level_9 | \n", "
---|---|---|---|---|---|---|---|---|---|---|---|
0 | \n", "-4.00 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "
1 | \n", "-3.96 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "
2 | \n", "-3.92 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "
3 | \n", "-3.88 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "
4 | \n", "-3.84 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "