Old habits

Or: Recombination dynamics in a coupled two-level system with strong nonradiative contribution (an ipython notebook)

One of my students investigates the transient behavior of the photoluminescence emitted by (In,Ga)N quantum heterostructures after being irradiated by a short laser pulse. The characteristic feature of the transients he observes for these structures is a power-law decay of the photoluminescence intensity with time at low temperatures (10 K), which changes into an exponential decay at higher temperatures (150 K).

His results reminded me of ones I acquired myself ages ago, during my own time as a PhD student. I didn't have a sensible interpretation then, but I do have one now. Hence, to the surprise of my student, I nonchalantly wrote down the following two coupled differential equations as if they had just occurred to me:

${\dot n_b} = -n_b/\tau_{rel} - n_b/\tau_{nr} + n_w \exp(-\frac{E_b}{k_B T})/\tau_e$

${\dot n_w} = n_b/\tau_{rel} - t^{b-1} n_w/\tau_{w} - n_w \exp(-\frac{E_b}{k_B T})/\tau_e$

with the second term in the second equation ($t^{b-1} n_w/\tau_{w}$) being the experimental observable. The form of this term is giving rise to what is known as a stretched exponential, which for $b \rightarrow 0$ approaches a power law for long times.

Using Mathematica, it takes 7 lines of code to solve this system and to plot it for several temperatures $T$ (or, equivalently and as done here, for different energies $k_B T$):

from IPython.display import Image
Image(filename='/home/cobra/ownCloud/MyStuff/Documents/pdes-net.org/files/images/deqs.png')

Mathematica

As I had hoped, this simple model reproduces the behavior observed in the experiment fairly well. My student was also pleased, but only with the result, not with the method: he's familiar with Matlab, but not with Mathematica. Well, I suspect that he's also not too familiar with Matlab, since he could otherwise have easily solved the equations himself.

In any case, his admission reminded me that I actually wanted to migrate my computational activities to free software whenever possible. It's not easy to get rid of old habits, and as I'm using Mathematica since 23 years, the code above just came naturally, while the one below still required an explicit intellectual effort. But that's essentially the same lame excuse which I'm tired to hear from users of, for example, Microsoft Office when asked to prepare a document with LibreOffice.

So let's get moving. Here's the above differential equation system solved and plotted using numpy, scipy, and matplotlib in an ipython notebook. Note how the notebook integrates the actual code with comments, links, pictures and equations. Editing this notebook is a real treat thanks to the use of markdown and LaTeX syntax.

#Initialize
%matplotlib inline
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
from scipy.integrate import odeint 

mpl.rcParams['figure.figsize'] = (6, 4)
mpl.rcParams['font.size'] = 16
mpl.rcParams['text.usetex'] = True
mpl.rcParams['font.family'] = 'Serif'
mpl.rcParams['lines.linewidth'] = 2
mpl.rcParams['xtick.major.pad'] = 7
# Parameters
taurel = 0.1       # capture time
taue = 0.1         # emission time
taunr = 0.01       # nonradiative lifetime
tauw = 1.65        # radiative lifetime
eb = 20            # activation energy (in meV)
b = 0              # stretching parameter (approaches power law for b -> 0)
# solve the system dn/dt = f(n,t) and plot the solution
fig = plt.figure()
#for kt in np.linspace(1,13,7):          # approximate temperatures
for T in [10,30,50,70,100,150]:          # exact temperatures

    kt = 0.086173324*T                   # in meV

    def f(n,t):
            nbt = n[0]
            nwt = n[1]
            # the model equations
            f0 = - nbt/taurel - nbt/taunr + nwt*np.exp(-eb/kt)/taue
            f1 = nbt/taurel - nwt*np.exp(-eb/kt)/taue - t**(b-1)*nwt/tauw
            return [f0, f1]

    # initial conditions
    nb0 = 1.                            # initial population in barrier
    nw0 = 0                             # initial population in well
    n0 = [nb0, nw0]                     # initial condition vector
    t  = np.logspace(-2,2,1000)         # logarithmic time grid

    # solve the DES
    soln = odeint(f, n0, t)
    nb = soln[:, 0]
    nw = soln[:, 1]

    # plot results
    plt.loglog(t, t**(b-1)*nw/tauw/max(t**(b-1)*nw/tauw), label=r'%.0f K' %T)
    plt.xlabel('Time (ns)')
    plt.ylabel('Intensity (arb. units)')
    plt.axis([7e-3,40,1e-5,2]);
    plt.legend(loc='lower left', frameon=False, prop={'size':15}, labelspacing=0.15)

ipython

fig.savefig('transients.pdf')

The above command saves this plot as a publication-ready figure in pdf format. There are many other available formats, including eps (for the traditional LaTeX/dvipdf toolchain), svg (for further editing with inkscape, or publishing in the web) and png (for insertion in a Powerpoint/Impress presentation).