Source code for gammapy.astro.source.pwn

# Licensed under a 3-clause BSD style license - see LICENSE.rst
"""Pulsar wind nebula (PWN) source models"""
from __future__ import absolute_import, division, print_function, unicode_literals
import numpy as np
from astropy.units import Quantity
from astropy.utils import lazyproperty
import astropy.constants as const
from ...extern.validator import validate_physical_type
from ..source import Pulsar, SNRTrueloveMcKee

__all__ = [
    'PWN',
]


[docs]class PWN(object): """Simple pulsar wind nebula (PWN) evolution model. Parameters ---------- pulsar : `~gammapy.astro.source.Pulsar` Pulsar model instance. snr : `~gammapy.astro.source.SNRTrueloveMcKee` SNR model instance eta_e : float Fraction of energy going into electrons. eta_B : float Fraction of energy going into magnetic fields. age : `~astropy.units.Quantity` Age of the PWN. morphology : str Morphology model of the PWN """ def __init__(self, pulsar=Pulsar(), snr=SNRTrueloveMcKee(), eta_e=0.999, eta_B=0.001, morphology='Gaussian2D', age=None): self.pulsar = pulsar if not isinstance(snr, SNRTrueloveMcKee): raise ValueError('SNR must be instance of SNRTrueloveMcKee') self.snr = snr self.eta_e = eta_e self.eta_B = eta_B self.morphology = morphology if age is not None: validate_physical_type('age', age, 'time') self.age = age def _radius_free_expansion(self, t): """Radius at age t during free expansion phase. Reference: http://adsabs.harvard.edu/abs/2006ARA%26A..44...17G (Formula 8). """ term1 = (self.snr.e_sn ** 3 * self.pulsar.L_0 ** 2) / (self.snr.m_ejecta ** 5) return (1.44 * term1 ** (1. / 10) * t ** (6. / 5)).cgs @lazyproperty def _collision_time(self): """Time of collision between the PWN and the reverse shock of the SNR. Returns ------- t_coll : `~astropy.units.Quantity` Time of collision. """ from scipy.optimize import fsolve def time_coll(t): t = Quantity(t, 'yr') return (self._radius_free_expansion(t) - self.snr.radius_reverse_shock(t)).value # 4e3 years is a typical value that works for fsolve return Quantity(fsolve(time_coll, 4e3), 'yr')
[docs] def radius(self, t=None): """Radius of the PWN at age t. Reference: http://adsabs.harvard.edu/abs/2006ARA%26A..44...17G (Formula 8). Parameters ---------- t : `~astropy.units.Quantity` Time after birth of the SNR. Notes ----- During the free expansion phase the radius of the PWN evolves like: .. math:: R_{PWN}(t) = 1.44\\text{pc}\\left(\\frac{E_{SN}^3\\dot{E}_0^2} {M_{ej}^5}\\right)^{1/10}t^{6/5} After the collision with the reverse shock of the SNR, the radius is assumed to be constant (See `~gammapy.astro.source.SNRTrueloveMcKee.radius_reverse_shock`) """ if t is not None: validate_physical_type('t', t, 'time') elif hasattr(self, 'age'): t = self.age else: raise ValueError('Need time variable or age attribute.') # Radius at time of collision r_coll = self._radius_free_expansion(self._collision_time) r = np.where(t < self._collision_time, self._radius_free_expansion(t).value, r_coll.value) return Quantity(r, 'cm')
[docs] def magnetic_field(self, t=None): """Estimate of the magnetic field inside the PWN. By assuming that a certain fraction of the spin down energy is converted to magnetic field energy an estimation of the magnetic field can be derived. Parameters ---------- t : `~astropy.units.Quantity` Time after birth of the SNR. """ if t is not None: validate_physical_type('t', t, 'time') elif hasattr(self, 'age'): t = self.age else: raise ValueError('Need time variable or age attribute.') return np.sqrt(2 * const.mu0 * self.eta_B * self.pulsar.energy_integrated(t) / (4. / 3 * np.pi * self.radius(t) ** 3))
[docs] def luminosity_tev(self, t=None, fraction=0.1): """Simple luminosity evolution model. Assumes that the luminosity is just a fraction of the total energy content of the pulsar. No cooling is considered and therefore the estimate is very bad. Parameters ---------- t : `~astropy.units.Quantity` Time after birth of the SNR. """ return fraction * self.pulsar.energy_integrated(t)