Beispiel #1
0
 def _init_defaults_from_pythia_database(self):
     """Init some particle properties from :mod:`particletools.tables`."""
     #: (bool) particle is a nucleus (not yet implemented)
     self.is_nucleus = _pdata.is_nucleus(self.pdg_id[0])
     #: (bool) particle is a hadron
     self.is_hadron = _pdata.is_hadron(self.pdg_id[0])
     #: (bool) particle is a hadron
     self.is_lepton = _pdata.is_lepton(self.pdg_id[0])
     #: Mass, charge, neutron number
     self.A, self.Z, self.N = getAZN(self.pdg_id[0])
     #: (float) ctau in cm
     self.ctau = _pdata.ctau(self.pdg_id[0])
     #: (float) mass in GeV
     self.mass = _pdata.mass(self.pdg_id[0])
     #: (str) species name in string representation
     name = _pname(self.pdg_id[0]) if self.name is None else self.name
     if self.helicity == -1:
         name += '_l'
     elif self.helicity == +1:
         name += '_r'
     self.name = name
     #: (bool) particle is stable
     #: TODO the exclusion of neutron decays is a hotfix
     self.is_stable = (not self.ctau < np.inf or self.pdg_id[0]
                       in config.adv_set['disable_decays'])
Beispiel #2
0
 def init_custom_particle_data(self, name, pdg_id, helicity, ctau, mass,
                               **kwargs):
     """Add custom particle type. (Incomplete and not debugged)"""
     #: (int) Particle Data Group Monte Carlo particle ID
     self.pdg_id = (pdg_id, helicity)
     #: (bool) if it's an electromagnetic particle
     self.is_em = kwargs.pop('is_em', abs(pdg_id) == 11 or pdg_id == 22)
     #: (bool) particle is a nucleus (not yet implemented)
     self.is_nucleus = kwargs.pop('is_nucleus',
                                  _pdata.is_nucleus(self.pdg_id[0]))
     #: (bool) particle is a hadron
     self.is_hadron = kwargs.pop('is_hadron',
                                 _pdata.is_hadron(self.pdg_id[0]))
     #: (bool) particle is a hadron
     self.is_lepton = kwargs.pop('is_lepton',
                                 _pdata.is_lepton(self.pdg_id[0]))
     #: Mass, charge, neutron number
     self.A, self.Z, self.N = getAZN(self.pdg_id[0])
     #: (float) ctau in cm
     self.ctau = ctau
     #: (float) mass in GeV
     self.mass = mass
     #: (str) species name in string representation
     self.name = name
     #: (bool) particle is stable
     self.is_stable = not self.ctau < np.inf
Beispiel #3
0
    def __init__(self,
                 pdg_id,
                 helicity,
                 energy_grid=None,
                 cs_db=None,
                 init_pdata_defaults=True):

        #: (bool) if it's an electromagnetic particle
        self.is_em = abs(pdg_id) == 11 or pdg_id == 22
        #: (int) helicity -1, 0, 1 (0 means undefined or average)
        self.helicity = helicity
        #: (bool) particle is a nucleus (not yet implemented)
        self.is_nucleus = False
        #: (bool) particle is a hadron
        self.is_hadron = False
        #: (bool) particle is a hadron
        self.is_lepton = False
        #: (float) ctau in cm
        self.ctau = None
        #: (float) mass in GeV
        self.mass = None
        #: (str) species name in string representation
        self.name = None
        #: Mass, charge, neutron number
        self.A, self.Z, self.N = getAZN(pdg_id)
        #: (bool) particle has both, hadron and resonance properties
        self.is_mixed = False
        #: (bool) if particle has just resonance behavior
        self.is_resonance = False
        #: (bool) particle is interacting projectile
        self.is_projectile = False
        #: (bool) particle is stable
        self.is_stable = False or pdg_id in config.adv_set['disable_decays']
        #: (bool) can_interact
        self.can_interact = False
        #: (bool) has continuous losses dE/dX defined
        self.has_contloss = False
        #: (np.array) continuous losses in GeV/(g/cm2)
        self.dEdX = None
        #: (bool) is a tracking particle
        self.is_tracking = False
        #: decay channels if any
        self.decay_dists = {}
        #: (int) Particle Data Group Monte Carlo particle ID
        self.pdg_id = (pdg_id, helicity)
        #: (int) Unique PDG ID that is different for tracking particles
        self.unique_pdg_id = (pdg_id, helicity)
        #: (int) MCEq ID
        self.mceqidx = -1

        #: (float) mixing energy, transition between hadron and
        # resonance behavior
        self.E_mix = 0
        #: (int) energy grid index, where transition between
        # hadron and resonance occurs
        self.mix_idx = 0
        #: (float) critical energy in air at the surface
        self.E_crit = 0
        # Energy and cross section dependent inits
        self.current_cross_sections = None
        self._energy_grid = energy_grid

        # Variables for hadronic interaction
        self.current_hadronic_model = None
        self.hadr_secondaries = []
        self.hadr_yields = {}

        # Variables for decays
        self.children = []
        self.decay_dists = {}

        if init_pdata_defaults:
            self._init_defaults_from_pythia_database()

        if self._energy_grid is not None and cs_db is not None:
            #: interaction cross section in 1/cm2
            self.set_cs(cs_db)
Beispiel #4
0
    def set_single_primary_particle(self, E, corsika_id=None, pdg_id=None):
        """Set type and energy of a single primary nucleus to
        calculation of particle yields.

        The functions uses the superposition theorem, where the flux of
        a nucleus with mass A and charge Z is modeled by using Z protons
        and A-Z neutrons at energy :math:`E_{nucleon}= E_{nucleus} / A`
        The nucleus type is defined via :math:`\\text{CORSIKA ID} = A*100 + Z`. For
        example iron has the CORSIKA ID 5226.

        A continuous input energy range is allowed between
        :math:`50*A~ \\text{GeV} < E_\\text{nucleus} < 10^{10}*A \\text{GeV}`.

        Args:
          E (float): (total) energy of nucleus in GeV
          corsika_id (int): ID of nucleus (see text)
        """

        from scipy.linalg import solve
        from MCEq.misc import getAZN_corsika, getAZN

        if corsika_id and pdg_id:
            raise Exception('Provide either corsika or PDG ID')

        info(
            2, 'CORSIKA ID {0}, PDG ID {1}, energy {2:5.3g} GeV'.format(
                corsika_id, pdg_id, E))

        self._restore_initial_condition = (self.set_single_primary_particle, E,
                                           corsika_id, pdg_id)

        egrid = self._energy_grid.c
        ebins = self._energy_grid.b
        ewidths = self._energy_grid.w

        if corsika_id:
            n_nucleons, n_protons, n_neutrons = getAZN_corsika(corsika_id)
        elif pdg_id:
            n_nucleons, n_protons, n_neutrons = getAZN(corsika_id)

        En = E / float(n_nucleons) if n_nucleons > 0 else E

        if En < np.min(self._energy_grid.c):
            raise Exception('energy per nucleon too low for primary ' +
                            str(corsika_id))

        info(3, ('superposition: n_protons={0}, n_neutrons={1}, ' +
                 'energy per nucleon={2:5.3g} GeV').format(
                     n_protons, n_neutrons, En))

        cenbin = np.argwhere(En < ebins)[0][0] - 1

        # Equalize the first three moments for 3 normalizations around the central
        # bin
        emat = np.vstack(
            (ewidths[cenbin - 1:cenbin + 2],
             ewidths[cenbin - 1:cenbin + 2] * egrid[cenbin - 1:cenbin + 2],
             ewidths[cenbin - 1:cenbin + 2] * egrid[cenbin - 1:cenbin + 2]**2))

        self._phi0 *= 0.

        if n_nucleons == 0:
            # This case handles other exotic projectiles
            b_particle = np.array([1., En, En**2])
            lidx = self.pman[pdg_id].lidx
            self._phi0[lidx + cenbin - 1:lidx + cenbin + 2] = solve(
                emat, b_particle)
            return

        if n_protons > 0:
            b_protons = np.array(
                [n_protons, En * n_protons, En**2 * n_protons])
            p_lidx = self.pman[2212].lidx

            self._phi0[p_lidx + cenbin - 1:p_lidx + cenbin + 2] = solve(
                emat, b_protons)
        if n_neutrons > 0:
            b_neutrons = np.array(
                [n_neutrons, En * n_neutrons, En**2 * n_neutrons])
            n_lidx = self.pman[2112].lidx
            self._phi0[n_lidx + cenbin - 1:n_lidx + cenbin + 2] = solve(
                emat, b_neutrons)