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'])
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
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)
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)