A Supernova Lightcurve

A Supernova Lightcurve#

ReacLib provides the beta-decay constants for radioactive nuclei, and these can be treated like any other rate. So we can build a network with \({}^{56}\mathrm{Ni}\) and compute its decay.

import pynucastro as pyna

import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import solve_ivp

We’ll look at \({}^{56}\mathrm{Ni} \rightarrow {}^{56}\mathrm{Co} \rightarrow {}^{56}\mathrm{Fe}\)

nuclei = ["ni56", "co56", "fe56"]
rl = pyna.ReacLibLibrary()
lib = rl.linking_nuclei(nuclei)

We see that we pull in 2 rates, which are simple decays.

lib
Co56 ⟶ Fe56 + e⁺ + 𝜈           [Q =   4.57 MeV] (Co56 --> Fe56 <wc12_reaclib_weak_>)
Ni56 ⟶ Co56 + e⁺ + 𝜈           [Q =   2.13 MeV] (Ni56 --> Co56 <wc12_reaclib_weak_>)
net = pyna.PythonNetwork(libraries=[lib])

We can write out the network to solve.

net.write_network("decay.py")
#%pycat decay.py
import decay

We’ll start out with pure \({}^{56}\mathrm{Ni}\) and convert to molar fractions, since that’s what we integrate.

X = np.zeros(len(net.unique_nuclei))
X[decay.jni56] = 1.0
Y0 = X / decay.A

Even though the rates have no density or temperature dependence, we still need to pass in a \((\rho, T)\), so we’ll just set them to arbitrary values.

rho0 = 1.0
T0 = 1.0

We’ll integrate for 400 days

seconds_per_day = 24 * 3600
tmax = 400 * seconds_per_day

We can use the default integrator in solve_ivp() since this system is not stiff.

sol = solve_ivp(decay.rhs, [0, tmax], Y0,
                dense_output=True, args=(rho0, T0), rtol=1.e-8, atol=1.e-10)

Now we can look at the evolution of the composition

fig, ax = plt.subplots()
for n in range(len(net.unique_nuclei)):
    ax.semilogy(sol.t / seconds_per_day, decay.A[n] * sol.y[n, :], label=f"X({decay.names[n].capitalize()})")
ax.set_ylim(1.e-6, 2)
ax.legend()
ax.set_xlabel("time (days)")
ax.set_ylabel("X")
Text(0, 0.5, 'X')
../_images/5af0ff0c37fc057d5463088506feb658b3e4f2c588237b0aa44d071c5fecd7a1.png

If we want the luminosity, we can compute that as the instantaneous energy release. Note: this assumes that all of the energy release is given to photons. For this, we need the rates, which we can get these by iterating over the solution

L = []
for n in range(sol.y.shape[-1]):
    Y = sol.y[:, n]
    dYdt = decay.rhs(sol.t[n], Y, rho0, T0)
    L.append(decay.energy_release(dYdt))

L is now in erg/g/s, so we should multiply by the initial \({}^{56}\mathrm{Ni}\) mass.

M_sun = 2.e33
L_sun = 4.e33

# initial mass
M_Ni56 = 1.0 * M_sun
L = np.array(L) * M_sun

Now we can plot the lightcurve.

fig, ax = plt.subplots()
ax.semilogy(sol.t / seconds_per_day, L / L_sun)
ax.set_xlabel("time (days)")
ax.set_ylabel("luminosity (solar)")
Text(0, 0.5, 'luminosity (solar)')
../_images/13d2cb811e2f027adbc136c04042853306f7af7363c388609fa7d02477da085f.png