Flavor Transformations

This notebook produces the figures in the SNEWPY paper showing the effect of the flavor transformation prescriptions upon the nakazato-shen-z0.004-t_rev100ms-s20.0 model

[1]:
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np

from snewpy.neutrino import MassHierarchy, MixingParameters, ThreeFlavorMixingParameters, FourFlavorMixingParameters
import snewpy.flavor_transformation as xforms
from snewpy.flavor import ThreeFlavor, FourFlavor

from snewpy.models.ccsn import Nakazato_2013

from astropy import units as u
from astropy import constants as c
from astropy.coordinates import SkyCoord, EarthLocation, AltAz
from astropy.time import Time

mpl.rc('font', size=18)
%matplotlib inline
[2]:
model = Nakazato_2013(progenitor_mass=20*u.solMass, revival_time=100*u.ms, metallicity=0.004, eos='shen')
model
[2]:

Nakazato_2013 Model: nakazato-shen-z0.004-t_rev100ms-s20.0.fits

Parameter

Value

Progenitor mass

\(20\) \(\mathrm{M_{\odot}}\)

Revival time

\(100\) \(\mathrm{ms}\)

Metallicity

0.004

EOS

shen

Transformed and untransformed energy integrated flux at Earth

Compute and plot the flux at Earth for a SN at 10 kpc with no flavor transformation, and with the chosen flavor transformation.

[3]:
def plot_total_flux(model, xform_nmo, xform_imo):
    """Plot initial and oscillated neutrino luminosities.

    Parameters
    ----------
    model : SupernovaModel
        An input model from a CCSN simulation.
    flav_xform : FlavorTransformation
        A FlavorTransformation subclass; used to create an instance.
    """

    energies = np.linspace(1,60,119) * u.MeV
    d = 10*u.kpc # distance to SN

    times = model.get_time()
    burst_epoch = times <= 0.1*u.s
    accretion_epoch = (times > 0.1*u.s) & (times <= 0.5*u.s)
    cooling_epoch = (times > 0.5*u.s) & (times <= 10*u.s)

    ispec = model.get_flux(times, energies, d)
    ospec_nmo = model.get_flux(times, energies, d, xform_nmo)
    ospec_imo = model.get_flux(times, energies, d, xform_imo)

    ilum = ispec.integrate_or_sum('energy')
    olum_nmo = ospec_nmo.integrate_or_sum('energy')
    olum_imo = ospec_imo.integrate_or_sum('energy')

    # make the figures
    fig, axes = plt.subplots(3,3, figsize=(20,12), tight_layout=True)

    smax = [0.,0.,0.]
    titles = ['Untransformed', 'Transformed (NMO)', 'Transformed (IMO)']
    for i, spec in enumerate([ilum, olum_nmo, olum_imo]):
        for j, phase in enumerate([burst_epoch, accretion_epoch, cooling_epoch]):
            ax = axes[i,j]
            timeunits = 'ms' if j==0 else 's'
            x_values = times[phase].to(timeunits)
            for flavor in ThreeFlavor:
                y_values = spec.array.squeeze()[flavor][phase].to('1/(cm2 s)')
                if i == 0:
                    smax[j] = np.maximum(smax[j], 1.1*np.max(y_values))

                ax.plot(x_values, y_values, label=flavor.to_tex(), lw=3,
                        color={'E':'C0','MU':'C1','TAU':'C2'}[flavor.lepton],
                        ls='-' if flavor.is_neutrino else ':')

            ax.set(xlim=(x_values[0].value, x_values[-1].value),
                   ylim=(0, smax[j].value))

            if j==0:
                ax.set(ylabel=f'flux [{y_values.unit._repr_latex_()}]')
                ax.legend(loc='upper right', ncol=1, fontsize=18)
            if j==1:
                ax.set(title=titles[i])
            if i < 2:
                ax.set(xticklabels=[])
            else:
                ax.set(xlabel='time [{}]'.format(timeunits))

            ax.grid(ls=':')


    return fig

Untransformed and Transformed Spectra at Earth

Compute and plot the spectra at Earth for a SN at 10 kpc with no flavor transformation, and with the chosen flavor transformation.

[4]:
def plot_spectra(model, xform_nmo, xform_imo, t):
    """Plot initial and oscillated neutrino luminosities.

    Parameters
    ----------
    model : SupernovaModel
        An input model from a CCSN simulation.
    flav_xform : FlavorTransformation
        A FlavorTransformation subclass; used to create an instance.
    t : astropy.Quantity
        Time to compute the spectrum.
    """

    energies = np.linspace(1,60,119) * u.MeV
    d = 10*u.kpc # distance to SN

    #get the spectra
    ispec = model.get_flux(t, energies, d)
    ospec_nmo = model.get_flux(t, energies, d, xform_nmo)
    ospec_imo = model.get_flux(t, energies, d, xform_imo)

    fig, axes = plt.subplots(2,2, figsize=(18,15), sharex=True, sharey=True, tight_layout=True)

    for idx_mixing, ospec in enumerate([ospec_nmo, ospec_imo]):
        for idx_nu, flavors in enumerate([ThreeFlavor['NU'], ThreeFlavor['NU_BAR']]):
            for idx_spec, spec in enumerate([ispec, ospec_nmo]):
                spec_val = spec.array.squeeze()
                spec_val = spec_val.to('1e16/(erg s cm2)')
                for flavor in flavors:
                    ax = axes[idx_nu][idx_mixing]
                    ax.plot(energies, spec_val[flavor],
                            label = ('Untransformed','Transformed')[idx_spec]+' '+flavor.to_tex(),
                            color={'E':'C0','MU':'C1','TAU':'C2'}[flavor.lepton],
                            ls=('-',':')[idx_spec],
                            lw=2,  alpha=0.7
                           )

        ax.set(title='{Nu}eutrinos in the {mixing}: $t = ${t:.1f}'.format(Nu=['N','Antin'][idx_nu],
                                                                          mixing=['NMO','IMO'][idx_mixing],
                                                                          t=t)
              )
    for ax in axes.flatten():
        ax.grid()
        ax.legend(loc='upper right', ncol=2, fontsize=16)
    for ax in axes[:,0]:
        ax.set(ylabel=f'flux {spec_val.unit._repr_latex_()}')#[$10^{16}$ erg$^{-1}$ cm$^{-2}$ s$^{-1}$]')

    return fig
[5]:
mixpars_nmo = MixingParameters('NORMAL')
mixpars_imo = MixingParameters('INVERTED')

xform_nmo = xforms.AdiabaticMSW(mixpars_nmo)
xform_imo = xforms.AdiabaticMSW(mixpars_imo)

fig = plot_total_flux(model, xform_nmo, xform_imo)
fig.show()
# fig.savefig('flux_adiabaticmsw.pdf')
fig = plot_spectra(model, xform_nmo, xform_imo, 100*u.ms)
fig.show()
# fig.savefig('spectra_adiabaticmsw.pdf')
../_images/nb_FlavorTransformation_7_0.png
../_images/nb_FlavorTransformation_7_1.png
[6]:
# set 1 degree as the mixing angle theta14
mixpars_nmo = FourFlavorMixingParameters(**MixingParameters('NORMAL'), theta14=1*u.deg)
xf_nmo = xforms.AdiabaticMSWes(mixpars_nmo)

mixpars_imo = FourFlavorMixingParameters(**MixingParameters('INVERTED'), theta14=1*u.deg)
xf_imo = xforms.AdiabaticMSWes(mixpars_imo)

fig = plot_total_flux(model, xf_nmo, xf_imo)
fig.show()
# fig.savefig('flux_adiabaticmswes.pdf')
fig = plot_spectra(model, xf_nmo, xf_imo, 100*u.ms)
fig.show()
# fig.savefig('spectra_adiabaticmswes.pdf')
../_images/nb_FlavorTransformation_8_0.png
../_images/nb_FlavorTransformation_8_1.png
[ ]: