示例#1
0
    def __init__(self, costh,
                 pmodel=(pm.HillasGaisser2012, 'H3a'),
                 hadr='SIBYLL2.3c', barr_mods=(), depth=1950*Units.m,
                 density=('CORSIKA', ('SouthPole', 'December')),
                 debug_level=1):
        """Initializes the nuVeto object for a particular costheta, CR Flux,
        hadronic model, barr parameters, and depth

        Note:
            A separate MCEq instance needs to be created for each
            combination of __init__'s arguments. To access pmodel and hadr,
            use mceq.pm_params and mceq.yields_params
        Args:
            costh (float): Cos(theta), the cosine of the neutrino zenith at the detector
            pmodel (tuple(CR model class, arguments)): CR Flux
            hadr (str): hadronic interaction model
            barr_mods: barr parameters
            depth (float): the depth at which the veto probability is computed below the ice
        """
        self.costh = costh
        self.pmodel = pmodel
        self.geom = Geometry(depth)
        theta = np.degrees(np.arccos(self.geom.cos_theta_eff(self.costh)))

        config.debug_level = debug_level
        # config.enable_em = False
        config.enable_muon_energy_loss = False
        config.return_as = 'total energy'
        config.adv_set['allowed_projectiles'] = [2212, 2112,
                                                 211, -211,
                                                 321, -321,
                                                 130,
                                                 -2212, -2112]#, 11, 22]
        config.ctau = 2.5
        self.mceq = MCEqRun(
            # provide the string of the interaction model
            interaction_model=hadr,
            # primary cosmic ray flux model
            # support a tuple (primary model class (not instance!), arguments)
            primary_model=pmodel,
            # zenith angle \theta in degrees, measured positively from vertical direction at surface
            theta_deg=theta,
            # atmospheric density model
            density_model=density)


        if len(barr_mods) > 0:
            for barr_mod in barr_mods:
                # Modify proton-air -> mod[0]
                self.mceq.set_mod_pprod(2212, BARR[barr_mod[0]].pdg, barr_unc, barr_mod)
            # Populate the modifications to the matrices by re-filling the interaction matrix
            self.mceq.regenerate_matrices(skip_decay_matrix=True)

        X_vec = np.logspace(np.log10(2e-3),
                            np.log10(self.mceq.density_model.max_X), 12)
        self.dX_vec = np.diff(X_vec)
        self.X_vec = 10**centers(np.log10(X_vec))
示例#2
0
    def __init__(self,
                 costh,
                 pmodel=(pm.HillasGaisser2012, 'H3a'),
                 hadr='SIBYLL2.3c',
                 barr_mods=(),
                 depth=1950 * Units.m,
                 density=('CORSIKA', ('SouthPole', 'June'))):
        """Initializes the nuVeto object for a particular costheta, CR Flux,
        hadronic model, barr parameters, and depth

        Note:
            A separate MCEq instance needs to be created for each
            combination of __init__'s arguments. To access pmodel and hadr,
            use mceq.pm_params and mceq.yields_params
        Args:
            costh (float): Cos(theta), the cosine of the neutrino zenith at the detector
            pmodel (tuple(CR model class, arguments)): CR Flux
            hadr (str): hadronic interaction model
            barr_mods: barr parameters
            depth (float): the depth at which the veto probability is computed below the ice
        """
        self.costh = costh
        self.pmodel = pmodel
        self.geom = Geometry(depth)
        theta = np.degrees(np.arccos(self.geom.cos_theta_eff(self.costh)))

        MCEq.core.dbg = 0
        MCEq.kernels.dbg = 0
        MCEq.density_profiles.dbg = 0
        MCEq.data.dbg = 0
        self.mceq = MCEqRun(
            # provide the string of the interaction model
            interaction_model=hadr,
            # atmospheric density model
            density_model=density,
            # primary cosmic ray flux model
            # support a tuple (primary model class (not instance!), arguments)
            primary_model=pmodel,
            # zenith angle \theta in degrees, measured positively from vertical direction
            theta_deg=theta,
            enable_muon_energy_loss=False,
            **mceq_config_without(['enable_muon_energy_loss',
                                   'density_model']))

        for barr_mod in barr_mods:
            # Modify proton-air -> mod[0]
            self.mceq.set_mod_pprod(2212, BARR[barr_mod[0]].pdg, barr_unc,
                                    barr_mod)
        # Populate the modifications to the matrices by re-filling the interaction matrix
        self.mceq._init_default_matrices(skip_D_matrix=True)

        X_vec = np.logspace(np.log10(2e-3),
                            np.log10(self.mceq.density_model.max_X), 12)
        self.dX_vec = np.diff(X_vec)
        self.X_vec = 10**centers(np.log10(X_vec))
示例#3
0
def test_some_angles():
    import mceq_config as config
    from MCEq.core import MCEqRun
    import crflux.models as pm
    import numpy as np

    config.debug_level = 5
    config.kernel_config = 'numpy'
    config.cuda_gpu_id = 0
    config.mkl_threads = 2

    mceq = MCEqRun(interaction_model='SIBYLL23C',
                   theta_deg=0.,
                   primary_model=(pm.HillasGaisser2012, 'H3a'))

    nmu = []
    for theta in [0., 30., 60., 90]:
        mceq.set_theta_deg(theta)
        mceq.solve()
        nmu.append(
            np.sum(
                mceq.get_solution('mu+', 0, integrate=True) +
                mceq.get_solution('mu-', 0, integrate=True)))
    print(nmu)
    assert np.allclose(nmu, [
        59787.31805017808, 60908.05990627792, 66117.91267025097,
        69664.26521920023
    ])
示例#4
0
    def __init__(self, interaction_model='SIBYLL23C', 
            theta_angles=np.rad2deg(np.arccos(np.linspace(0.5,0,3))), 
            ):
        r'''
        '''

        self._mceq = MCEqRun(
            interaction_model=interaction_model,
            theta_deg=0.,
            primary_model=(pm.GlobalSplineFitBeta,
                 '/Users/mhuber/AtmosphericShowers/Data/GSF_spline_20171007.pkl.bz2')
            )

        self.e_grid = self._mceq.e_grid
        # get the flux estimates
        self.flux_keys =  ['numu_conv','numu_pr','numu_total',
                           'mu_conv','mu_pr','mu_total',
                           'nue_conv','nue_pr','nue_total',
                           'nutau_pr']

        self.fluxes = self._calc_fluxes(theta_angles)
        self.flux_tcks = dict()
示例#5
0
def run_MCEq(
    primary_model,
    interaction_model="SIBYLL2.3c",
    density_profiles=[
        ("MSIS00_IC", ("SouthPole", "January")),
        ("MSIS00_IC", ("SouthPole", "July")),
    ],
    particle_ids=["total_numu", "total_antinumu"],
    cosz_lim=[-1.0, 1.0],
    cosz_steps=50,
    emag=3,
):

    # define equidistant grid in cos(theta) with cosz_steps steps
    theta_grid = np.arccos(np.linspace(cosz_lim[0], cosz_lim[1], cosz_steps))
    theta_grid *= 180.0 / np.pi

    # temporarily result dict
    flux_for_density = {}

    ## loop over all density profiles
    #for density in density_profiles:
    for density in tqdm(density_profiles, desc="Density"):
        print "=" * 60
        print "Current atmosphere model:", density[0], "--", density[1][
            0], density[1][1]
        print "-" * 60

        # set atmosphere model string for result dictionary
        if density[1][1] is not None:
            density_str = density[0] + density[1][0] + density[1][1]
        else:
            density_str = density[0] + density[1][0]

        # update mceq_config with the current atmosphere model
        config["density_model"] = density

        # create instance of MCEqRun class
        mceq_run = MCEqRun(
            interaction_model=interaction_model,
            primary_model=primary_model,
            theta_deg=0.0,  # updated later
            **config)

        # obtain energy grid (fixed) of the solution for the x-axis of the plots
        e_grid = mceq_run.e_grid

        # update dictionary
        flux_for_density[density_str] = {}
        for flux_str in particle_ids:
            flux_for_density[density_str][flux_str] = np.zeros(
                (len(theta_grid), len(e_grid)))

        ## loop over all theta bins
        #for theta_id, theta in enumerate(theta_grid):
        for theta_id, theta in enumerate(tqdm(theta_grid, desc="Theta")):
            print "-" * 60
            print "Current theta:", theta

            # Set/update the zenith angle
            mceq_run.set_theta_deg(theta)
            # Run the solver
            mceq_run.solve()

            # get fluxes
            flux_solutions = get_solutions(mceq_run, particle_ids, mag=emag)

            # store fluxes in result dictionary'
            for flux_str in particle_ids:
                flux_for_density[density_str][flux_str][
                    theta_id, :] = flux_solutions[flux_str]
                #print flux_for_density[density_str][flux_str][theta_id,:]

    # average density models:
    fluxes = {}
    for flux_str in particle_ids:
        fluxes[flux_str] = np.zeros((len(theta_grid), len(e_grid)))

    for flux_str in particle_ids:
        for density in flux_for_density.keys():  # loop over all density models
            fluxes[flux_str] += flux_for_density[density][flux_str]
        fluxes[flux_str] /= len(flux_for_density.keys()) * 1.0

    # add e_grid and theta_grid
    #fluxes["e_grid"] = e_grid
    #fluxes["theta_grid"] = theta_grid

    return fluxes
示例#6
0
def get_angle_flux(angle, mag=0):
    """
    angle should be in degrees! 
    
    returns a dicitionary with the energies and the fluxes for each neutrino type 
    """

    if not (isinstance(angle, float) or isinstance(angle, int)):
        raise TypeError("Arg 'angle' should be {}, got {}".format(
            float, type(angle)))

    if not (angle <= 180. and angle >= 0.):
        raise ValueError("Invalid zenith angle {} deg".format(angle))

    flux = {}

    mceq = MCEqRun(
        interaction_model='SIBYLL23C',
        primary_model=(HawkBPL, 0.),
        #        primary_model = (crf.HillasGaisser2012, 'H3a'),
        theta_deg=angle)
    mceq.solve()

    flux['e_grid'] = mceq.e_grid

    flux['nue_flux'] = mceq.get_solution('nue', mag) + mceq.get_solution(
        'pr_nue', mag)
    flux['nue_bar_flux'] = mceq.get_solution(
        'antinue', mag) + mceq.get_solution('pr_antinue', mag)
    flux['numu_flux'] = mceq.get_solution('numu', mag) + mceq.get_solution(
        'pr_numu', mag)
    flux['numu_bar_flux'] = mceq.get_solution(
        'antinumu', mag) + mceq.get_solution('pr_antinumu', mag)
    flux['nutau_flux'] = mceq.get_solution('nutau', mag) + mceq.get_solution(
        'pr_nutau', mag)
    flux['nutau_bar_flux'] = mceq.get_solution(
        'antinutau', mag) + mceq.get_solution('pr_antinutau', mag)

    obj = open("temp_mceq_flux.dat".format(angle), 'w')
    #     obj.write("# E[Gev] Phi_nue[Gev/cm2/s/sr] Phi_numu[Gev/cm2/s/sr] Phi_nutau[Gev/cm2/s/sr] Phi_nue_bar Phi_numu_bar Phi_nutau_bar\n")
    for i in range(len(flux['e_grid'])):
        obj.write(str(flux['e_grid'][i]))
        obj.write(' ')
        obj.write(str(flux['nue_flux'][i]))
        obj.write(' ')
        obj.write(str(flux['numu_flux'][i]))
        obj.write(' ')
        obj.write(str(flux['nutau_flux'][i]))
        obj.write(' ')
        obj.write(str(flux['nue_bar_flux'][i]))
        obj.write(' ')
        obj.write(str(flux['numu_bar_flux'][i]))
        obj.write(' ')
        obj.write(str(flux['nutau_bar_flux'][i]))
        obj.write('\n')
    obj.close()
示例#7
0
    e = numpy.sqrt(p**2 + m**2) - m  # Kinetic energy (GeV)
    j = (e + m) / p  # Jacobian factor for going from dphi / dp
    #   to dphi / dE (almost 1 ...)
    f = (data[:, 3] + data[:, 7]) * j  # Flux (1/(GeV m^2 s sr))

    df = numpy.sqrt(data[:, 4]**2 + data[:, 5]**2 +  # Flux uncertainty
                    data[:, 8]**2 + data[:, 9]**2) * j

    return ExperimentalData(e, f * 1E-04, df * 1E-04)


bess = load_bess('BESS_TEV.txt')

# Simulate the flux using MCEq
mceq = MCEqRun(interaction_model='SIBYLL23C',
               primary_model=(crf.GlobalSplineFitBeta, None),
               density_model=('MSIS00', ('Tokyo', 'October')),
               theta_deg=0)

cos_theta = 0.95
theta = numpy.arccos(cos_theta) * 180 / numpy.pi
mceq.set_theta_deg(theta)

altitude = numpy.array((30., ))
X_grid = mceq.density_model.h2X(altitude * 1E+02)


def weight(xmat, egrid, name, c):
    return (1 + c) * numpy.ones_like(xmat)


mceq.set_mod_pprod(2212, 211, weight, ('a', 0.141))  # Coefficients taken
示例#8
0
    def _compute_outputs(self, inputs=None):
        """Compute histograms for output channels."""
        logging.debug('Entering mceq._compute_outputs')

        primary_model = split(self.params['primary_model'].value, ',')
        if len(primary_model) != 2:
            raise ValueError('primary_model is not of length 2, instead is of '
                             'length {0}'.format(len(primary_model)))
        primary_model[0] = eval('pm.' + primary_model[0])
        density_model = (self.params['density_model'].value,
                         (self.params['location'].value,
                          self.params['season'].value))

        mceq_run = MCEqRun(
            interaction_model=str(self.params['interaction_model'].value),
            primary_model=primary_model,
            theta_deg=0.0,
            density_model=density_model,
            **mceq_config.mceq_config_without(['density_model']))

        # Power of energy to scale the flux (the results will be returned as E**mag * flux)
        mag = 0

        # Obtain energy grid (fixed) of the solution for the x-axis of the plots
        e_grid = mceq_run.e_grid

        # Dictionary for results
        flux = OrderedDict()
        for nu in self.output_names:
            flux[nu] = []

        binning = self.output_binning
        cz_binning = binning.dims[binning.index('coszen', use_basenames=True)]
        en_binning = binning.dims[binning.index('energy', use_basenames=True)]
        cz_centers = cz_binning.weighted_centers.m
        angles = (np.arccos(cz_centers) * ureg.radian).m_as('degrees')

        for theta in angles:
            mceq_run.set_theta_deg(theta)
            mceq_run.solve()

            flux['nue'].append(mceq_run.get_solution('total_nue', mag))
            flux['nuebar'].append(mceq_run.get_solution('total_antinue', mag))
            flux['numu'].append(mceq_run.get_solution('total_numu', mag))
            flux['numubar'].append(mceq_run.get_solution(
                'total_antinumu', mag))

        for nu in flux.iterkeys():
            flux[nu] = np.array(flux[nu])

        smoothing = self.params['smoothing'].value.m
        en_centers = en_binning.weighted_centers.m_as('GeV')
        spline_flux = self.bivariate_spline(flux,
                                            cz_centers,
                                            e_grid,
                                            smooth=smoothing)
        ev_flux = self.bivariate_evaluate(spline_flux, cz_centers, en_centers)

        for nu in ev_flux:
            ev_flux[nu] = ev_flux[nu] * ureg('cm**-2 s**-1 sr**-1 GeV**-1')

        mapset = []
        for nu in ev_flux.iterkeys():
            mapset.append(Map(name=nu, hist=ev_flux[nu], binning=binning))

        return MapSet(mapset)
def generate_table(interaction_model=None,
                   primary_model=None,
                   density_model=None):

    interaction_model = interaction_model or 'SIBYLL23C'
    primary_model = primary_model or 'H3a'
    density_model = density_model or 'USStd'
    tag = '-'.join((interaction_model.lower(), primary_model.lower(),
                    density_model.lower()))

    weights = None
    if interaction_model == 'YFM':
        # Use weights from Yanez et al., 2019 (https://arxiv.org/abs/1909.08365)
        interaction_model = 'SIBYLL23C'
        weights = {211: 0.141, -211: 0.116, 321: 0.402, -321: 0.583}

    if primary_model == 'GSF':
        primary_model = (crf.GlobalSplineFitBeta, None)
    elif primary_model == 'H3a':
        primary_model = (crf.HillasGaisser2012, 'H3a')
    elif primary_model == 'PolyGonato':
        primary_model = (crf.PolyGonato, None)
    else:
        raise ValueError(f'Invalid primary model: {primary_model}')

    if density_model == 'USStd':
        density_model = ('CORSIKA', ('USStd', None))
    elif density_model.startswith('MSIS00'):
        density_model = ('MSIS00', density_model.split('-')[1:])
    else:
        raise ValueError(f'Invalid density model: {density_model}')

    config.e_min = 1E-01
    config.enable_default_tracking = False
    config.enable_muon_energy_loss = True

    mceq = MCEqRun(interaction_model=interaction_model,
                   primary_model=primary_model,
                   density_model=density_model,
                   theta_deg=0)

    if weights:

        def weight(xmat, egrid, name, c):
            return (1 + c) * numpy.ones_like(xmat)

        for pid, w in weights.items():
            mceq.set_mod_pprod(2212, pid, weight, ('a', w))
        mceq.regenerate_matrices(skip_decay_matrix=True)

    energy = mceq.e_grid
    cos_theta = numpy.linspace(0, 1, 51)
    altitude = numpy.linspace(0, 9E+03, 10)

    data = numpy.zeros((altitude.size, cos_theta.size, energy.size, 2))
    for ic, ci in enumerate(cos_theta):
        print(f'processing {ci:.2f}')

        theta = numpy.arccos(ci) * 180 / numpy.pi
        mceq.set_theta_deg(theta)
        X_grid = mceq.density_model.h2X(altitude[::-1] * 1E+02)
        mceq.solve(int_grid=X_grid)

        for index, _ in enumerate(altitude):
            mu_m = mceq.get_solution('mu-', grid_idx=index) * 1E+04
            mu_p = mceq.get_solution('mu+', grid_idx=index) * 1E+04
            K = (mu_m > 0) & (mu_p > 0)
            data[altitude.size - 1 - index, ic, K, 0] = mu_m[K]
            data[altitude.size - 1 - index, ic, K, 1] = mu_p[K]

    # Dump the data grid to a litle endian binary file
    data = data.astype('f4').flatten()
    with open(f'data/simulated/flux-mceq-{tag}.table', 'wb') as f:
        numpy.array((energy.size, cos_theta.size, altitude.size),
                    dtype='i8').astype('<i8').tofile(f)
        numpy.array((energy[0], energy[-1], cos_theta[0], cos_theta[-1],
                     altitude[0], altitude[-1]),
                    dtype='f8').astype('<f8').tofile(f)
        data.astype('<f4').tofile(f)
示例#10
0
    def __get_spline__(
        interaction_model,
        primary_model,
        months,
        theta_grid,
        theta_grid_cos,
    ):
        """Get MCEq spline for the provided settings

        Parameters
        ----------
        interaction_model : str
            The interaction model. This is passed on to `MCEqRun`.
        primary_model : str
            The primary model to use. Must be one of:
                GST_3-gen, GST_4-gen, H3a, H4a, poly-gonato, TIG, ZS, ZSP, GH
        months : list of str
            The months for which to solve the cascade equations. These must be
            provided as a list of month names, e.g. ['January', 'August']. A
            list of splines will be returned of the same length as `months`.
        theta_grid : array_like
            The grid points in theta to evaluate on in degrees.
            If `theta_grid_cos` is True, this is instead cos(theta).
        theta_grid_cos : bool
            If True, `theta_grid` is interpreted as cos(theta),
            i.e. arccos() is applied first.

        Returns
        -------
        dict
            The result of MCEq together with the fitted splines.
            See documentation of `get_spline()` for more details.

        Raises
        ------
        AttributeError
            If the provided `primary_model` is unknown.
        """
        log.info('\tCalculating \'{}\' \'{}\''.format(interaction_model,
                                                      primary_model))

        import mceq_config
        from MCEq import version
        from MCEq.core import MCEqRun
        import crflux.models as pm

        config_updates = {
            'h_obs': 1000.,
            'debug_level': 1,
        }
        if 'MKL_PATH' in os.environ:
            config_updates['MKL_path'] = os.environ['MKL_PATH']

        splines = {}
        pmodels = {
            "GST_3-gen": (pm.GaisserStanevTilav, "3-gen"),
            "GST_4-gen": (pm.GaisserStanevTilav, "4-gen"),
            "H3a": (pm.HillasGaisser2012, "H3a"),
            "H4a": (pm.HillasGaisser2012, "H4a"),
            "poly-gonato": (pm.PolyGonato, False),
            "TIG": (pm.Thunman, None),
            "ZS": (pm.ZatsepinSokolskaya, 'default'),
            "ZSP": (pm.ZatsepinSokolskaya, 'pamela'),
            "GH": (pm.GaisserHonda, None),
        }

        for i, month in enumerate(months):
            config_updates['density_model'] = ('MSIS00_IC', ('SouthPole',
                                                             month))

            # update settings in mceq_config
            # Previous method mceq_config.config is deprecated and resulted
            # in pickle errors for deepcopy.
            for name, value in config_updates.items():
                setattr(mceq_config, name, value)

            try:
                pmodel = pmodels[primary_model]
            except KeyError:
                raise AttributeError(
                    'primary_model {} unknown. options: {}'.format(
                        primary_model, pmodels.keys()))
            mceq_run = MCEqRun(interaction_model=interaction_model,
                               primary_model=pmodel,
                               theta_deg=0.0,
                               **config_updates)
            e_grid = np.log10(deepcopy(mceq_run.e_grid))
            spline_dicts, flux_dicts = __solve_month__(mceq_run, e_grid,
                                                       theta_grid,
                                                       theta_grid_cos)

            splines[i] = {}
            splines[i]['total_spline_dict'] = spline_dicts[0]
            splines[i]['conv_spline_dict'] = spline_dicts[1]
            splines[i]['pr_spline_dict'] = spline_dicts[2]
            splines[i]['total_flux_dict'] = flux_dicts[0]
            splines[i]['conv_flux_dict'] = flux_dicts[1]
            splines[i]['pr_flux_dict'] = flux_dicts[2]
            splines[i]['config_updates'] = deepcopy(config_updates)
            splines[i]['mceq_version'] = version.__version__
            splines[i]['ic3_labels_version'] = ic3_labels.__version__
            splines[i]['e_grid'] = e_grid
            splines[i]['theta_grid'] = theta_grid
        return splines
示例#11
0
def get_initial_state(energies, zeniths, n_nu, kwargs):
    """
    This either loads the initial state, or generates it.
    Loading it is waaaay quicker.

    Possible issue! If you run a bunch of jobs and don't already have this flux generated, bad stuff can happen. 
    I'm imagining issues where a bunch of jobs waste time making this, and then all try to write to the same file
    Very bad. Big crash. Very Fail 
    """
    path = os.path.join(config["datapath"], config["mceq_flux"])
    if os.path.exists(path):
        #        print("Loading MCEq Flux")
        f = open(path, 'rb')
        inistate = pickle.load(f)
        f.close()
    else:
        #        print("Generating MCEq Flux")
        inistate = np.zeros(shape=(angular_bins, energy_bins, 2, n_nu))
        mceq = MCEqRun(interaction_model=config["interaction_model"],
                       primary_model=(crf.HillasGaisser2012, 'H3a'),
                       theta_deg=0.)

        r_e = 6.378e6  # meters
        ic_depth = 1.5e3  # meters
        mag = 0.  # power energy is raised to and then used to scale the flux
        for angle_bin in range(angular_bins):
            # get the MCEq angle from the icecube zenith angle
            angle_deg = asin(
                sin(pi - acos(zeniths[angle_bin])) * (r_e - ic_depth) / r_e)
            angle_deg = angle_deg * 180. / pi
            if angle_deg > 180.:
                angle_deg = 180.

            print("Evaluating {} deg Flux".format(angle_deg))
            # for what it's worth, if you try just making a new MCEqRun for each angle, you get a memory leak.
            # so you need to manually set the angle
            mceq.set_theta_deg(angle_deg)
            mceq.solve()

            flux = {}
            flux['e_grid'] = mceq.e_grid

            flux['nue_flux'] = mceq.get_solution(
                'nue', mag) + mceq.get_solution('pr_nue', mag)
            flux['nue_bar_flux'] = mceq.get_solution(
                'antinue', mag) + mceq.get_solution('pr_antinue', mag)
            flux['numu_flux'] = mceq.get_solution(
                'numu', mag) + mceq.get_solution('pr_numu', mag)
            flux['numu_bar_flux'] = mceq.get_solution(
                'antinumu', mag) + mceq.get_solution('pr_antinumu', mag)
            flux['nutau_flux'] = mceq.get_solution(
                'nutau', mag) + mceq.get_solution('pr_nutau', mag)
            flux['nutau_bar_flux'] = mceq.get_solution(
                'antinutau', mag) + mceq.get_solution('pr_antinutau', mag)

            for neut_type in range(2):
                for flavor in range(n_nu):
                    flav_key = get_key(flavor, neut_type)
                    if flav_key == "":
                        continue

                    for energy_bin in range(energy_bins):
                        # (account for the difference in units between mceq and nusquids! )
                        inistate[angle_bin][energy_bin][neut_type][
                            flavor] = get_closest(
                                energies[energy_bin] / un.GeV, flux['e_grid'],
                                flux[flav_key])

        if np.min(inistate) < 0:
            raise ValueError(
                "Found negative value in the input from MCEq {}".format(
                    np.min(inistate)))
        # save it now
        f = open(path, 'wb')
        pickle.dump(inistate, f, -1)
        f.close()

    return (inistate)
示例#12
0
from __future__ import print_function

import mceq_config as config
from MCEq.core import MCEqRun
import crflux.models as pm
import numpy as np

config.debug_level = 1
config.kernel_config = 'numpy'
config.cuda_gpu_id = 0
config.set_mkl_threads(4)

mceq = MCEqRun(
    interaction_model='SIBYLL23C',
    theta_deg=0.,
    primary_model=(pm.HillasGaisser2012, 'H3a'))


def test_config_and_file_download():
    import mceq_config as config
    import os
    # Import of config triggers data download
    assert config.mceq_db_fname in os.listdir(config.data_dir)


def test_some_angles():

    nmu = []
    for theta in [0., 30., 60., 90]:
        mceq.set_theta_deg(theta)
        mceq.solve()
示例#13
0
def make_plots():
    Emin = 1 * un.GeV
    Emax = 10 * un.PeV

    energies = nsq.logspace(Emin, Emax, 100)
    angles = nsq.linspace(-0.99, -0.98, 2)

    # just look at straight up/down
    # get MCEq flux there

    mag = 0.
    angle = 0.  #degrees

    mceq = MCEqRun(interaction_model='SIBYLL23C',
                   primary_model=(crf.HillasGaisser2012, 'H3a'),
                   theta_deg=0.)

    mceq.solve()

    n_nu = 3
    inistate = np.zeros(shape=(2, len(energies), 2, n_nu))
    flux = {}

    flux['e_grid'] = mceq.e_grid
    flux['nue_flux'] = mceq.get_solution('nue', mag) + mceq.get_solution(
        'pr_nue', mag)
    flux['nue_bar_flux'] = mceq.get_solution(
        'antinue', mag) + mceq.get_solution('pr_antinue', mag)
    flux['numu_flux'] = mceq.get_solution('numu', mag) + mceq.get_solution(
        'pr_numu', mag)
    flux['numu_bar_flux'] = mceq.get_solution(
        'antinumu', mag) + mceq.get_solution('pr_antinumu', mag)
    flux['nutau_flux'] = mceq.get_solution('nutau', mag) + mceq.get_solution(
        'pr_nutau', mag)
    flux['nutau_bar_flux'] = mceq.get_solution(
        'antinutau', mag) + mceq.get_solution('pr_antinutau', mag)

    # propagate it with nusquids
    for neut_type in range(2):
        for flavor in range(n_nu):
            flav_key = get_key(flavor, neut_type)
            if flav_key == "":
                continue
            for energy_bin in range(len(energies)):
                inistate[0][energy_bin][neut_type][flavor] = get_closest(
                    energies[energy_bin] / un.GeV, flux['e_grid'],
                    flux[flav_key])

                inistate[1][energy_bin][neut_type][flavor] = get_closest(
                    energies[energy_bin] / un.GeV, flux['e_grid'],
                    flux[flav_key])

    nus_atm = nsq.nuSQUIDSAtm(angles, energies, n_nu, nsq.NeutrinoType.both,
                              True)

    nus_atm.Set_MixingAngle(0, 1, 0.563942)
    nus_atm.Set_MixingAngle(0, 2, 0.154085)
    nus_atm.Set_MixingAngle(1, 2, 0.785398)

    nus_atm.Set_SquareMassDifference(1, 7.65e-05)
    nus_atm.Set_SquareMassDifference(2, 0.00247)

    nus_atm.SetNeutrinoCrossSections(xs)

    #settting some zenith angle stuff
    nus_atm.Set_rel_error(1.0e-6)
    nus_atm.Set_abs_error(1.0e-6)
    #nus_atm.Set_GSL_step(gsl_odeiv2_step_rk4)
    nus_atm.Set_GSL_step(nsq.GSL_STEP_FUNCTIONS.GSL_STEP_RK4)

    # we load in the initial state. Generating or Loading from a file
    nus_atm.Set_initial_state(inistate, nsq.Basis.flavor)
    print("Done setting initial state")

    # we turn off the progress bar for jobs run on the cobalts
    nus_atm.Set_ProgressBar(False)
    nus_atm.Set_IncludeOscillations(True)

    print("Evolving State")
    nus_atm.EvolveState()

    # Evaluate the flux at the energies, flavors, and shit we care about

    eval_flux = {}
    for flavor in range(3):
        for nute in range(2):
            key = get_key(flavor, nute)
            if key == "":
                continue
            eval_flux[key] = np.zeros(len(energies))

            for energy in range(len(energies)):
                powed = energies[energy]

                eval_flux[key][energy] = nus_atm.EvalFlavor(
                    flavor, -0.985, powed, nute)

    # multiply the fluxes with total cross sections at that energy

    conv_flux = {}
    for flavor in flavors.keys():
        if flavor == "electron":
            i_flav = 0
        elif flavor == "muon":
            i_flav = 1
        else:
            i_flav = 2
        for neut_type in neut_types.keys():
            if neut_type == "neutrino":
                i_neut = 0
            else:
                i_neut = 1

            eval_key = get_key(i_flav, i_neut)
            for current in currents.keys():
                conv_key = "_".join([flavor, neut_type, current])
                conv_flux[conv_key] = np.zeros(len(energies))
                for energy in range(len(energies)):
                    powed = energies[energy]

                    conv_flux[conv_key][
                        energy] = eval_flux[eval_key][energy] * get_total_flux(
                            powed, flavors[flavor], neut_types[neut_type],
                            currents[current])

    # sum up the cascades and compare them with the cross sections

    casc_fluxes = np.zeros(len(energies))
    track_fluxes = np.zeros(len(energies))
    for key in conv_flux:
        if is_cascade(key):
            casc_fluxes += conv_flux[key]
        else:
            track_fluxes += conv_flux[key]

    plt.plot(energies / un.GeV, casc_fluxes, label="Cascades")
    plt.plot(energies / un.GeV, track_fluxes, label="Tracks")
    plt.xscale('log')
    plt.xlim([10**2, 10**7])
    plt.yscale('log')
    plt.legend()
    plt.xlabel("Energy [GeV]", size=14)
    plt.ylabel(r"Flux$\cdot\sigma_{total}$ [s GeV sr]$^{-1}$", size=14)
    plt.show()
示例#14
0
def SetupMCEq(rawpositions, rawdensities, Settings={}):

    ad = den_p.GeneralizedTarget()
    densities = []
    positions = []
    if (rawpositions[0] > 0):
        positions.append(0)
        densities.append(rawdensities[0])
    for i in range(0, len(rawdensities)):
        if not np.isnan(rawdensities[i]):
            densities.append(rawdensities[i])
            positions.append(rawpositions[i])
#   ad.len_target=positions[-1]
    ad.set_length(positions[-1] - positions[0])
    for i in range(0, len(densities) - 1):
        ad.add_material(positions[i], densities[i], 'Layer' + str(i))
    ad.print_table()

    if Settings['PrimaryModel'] == 'HillasGaisser_H3a':
        PrimaryObject = pm.HillasGaisser2012
        PrimaryString = 'H3a'

    if Settings['PrimaryModel'] == 'HillasGaisser_H4a':
        PrimaryObject = pm.HillasGaisser2012
        PrimaryString = 'H4a'

    if Settings['PrimaryModel'] == 'GaisserHonda':
        PrimaryObject = pm.GaisserHonda
        PrimaryString = None

    if Settings['PrimaryModel'] == 'CombinedGHAndHG_H3a':
        PrimaryObject = pm.CombinedGHandHG
        PrimaryString = "H3a"

    if Settings['PrimaryModel'] == 'CombinedGHAndHG_H4a':
        PrimaryObject = pm.CombinedGHandHG
        PrimaryString = "H4a"

    if Settings['PrimaryModel'] == 'PolyGonato':
        PrimaryObject = pm.PolyGonato
        PrimaryString = None

    if Settings['PrimaryModel'] == 'Thunman':
        PrimaryObject = pm.Thunman
        PrimaryString = None

    if Settings['PrimaryModel'] == 'ZatsepinSokolskaya':
        PrimaryObject = pm.ZatsepinSokolskaya
        PrimaryString = None

    mceq_run = MCEqRun(
        interaction_model=Settings['HadronicModel'],
        primary_model=(PrimaryObject, PrimaryString),
        #Do not provide any default values to avoid unnecessary initilizations
        theta_deg=0.,
        density_model=('GeneralizedTarget', None),
        # Expand the rest of parameters
        **mceq_config_without(['density_model', 'integrator']))
    #    config['integrator'] = 'odepack'

    mceq_run.density_model = ad
    res_group = [
        "mu+", "mu-", "pi_mu+", "pi_mu-", "k_mu+", "k_mu-", "pr_mu+", "pr_mu-"
    ]
    mceq_run.set_obs_particles(res_group)
    return [mceq_run, ad]
示例#15
0
    assert issubclass(
        CRModel, crf.PrimaryFlux), "Unknown primary cosmic ray spectrum model"

    # define CR model parameters
    if args.cosmic_ray_model == "HillasGaisser2012":
        CR_vers = "H3a"
    elif args.cosmic_ray_model == "GaisserStanevTilav":
        CR_vers = "4-gen"
    else:
        CR_vers = None

    mceq_run = MCEqRun(
        #provide the string of the interaction model
        interaction_model=interaction_model,
        #primary cosmic ray flux model
        #support a tuple (primary model class (not instance!), arguments)
        primary_model=(CRModel, CR_vers),
        # Zenith angle in degrees. 0=vertical, 90=horizontal
        theta_deg=0.,
        #GPU device id
        **config)

    # Some global settings. One can play around with them, but there
    # is currently no good reason why

    # Primary proton projectile (neutron is included automatically
    # vie isospin symmetries)
    primary_particle = 2212
    # The parameter delta for finite differences computation
    delta = 0.001
    # Energy grid will be truncated below this value (saves some
    # memory and interpolation speed, but not really needed, I think)
示例#16
0
    r += MCEq_obj.set_mod_pprod(2112, 311, mod_linear, (fac_k0,), delay_init=True)
    r += MCEq_obj.set_mod_pprod(2112, -311, mod_linear, (fac_k0,), delay_init=True)
    r += MCEq_obj.set_mod_pprod(2112, 130, mod_linear, (fac_k0l,), delay_init=True)
    r += MCEq_obj.set_mod_pprod(2112, 310, mod_linear, (fac_k0s,), delay_init=True)


    if r > 0:
        MCEq_obj._init_default_matrices(skip_D_matrix=True)




#pmodel = (pm.HillasGaisser2012, "H3a")  #  (pm.Thunman, None)   # (pm.GaisserStanevTilav, "3-gen") # (PolyGonato, False)
pmodel = (pm.HillasGaisser2012, "H3a")  #  (pm.Thunman, None)   # (pm.GaisserStanevTilav, "3-gen") # (PolyGonato, False)

mceq_run_January = MCEqRun(interaction_model='DPMJET-III', density_model=('MSIS00_IC',('SouthPole','January')),
                       primary_model=pmodel, theta_deg=theta_use, **mceq_config_without(['density_model']) )

mceq_run_January.unset_mod_pprod(dont_fill=False)
#Power of energy to scale the flux
mag = 3

#obtain energy grid (nver changes) of the solution for the x-axis of the plots
e_grid_January = mceq_run_January.e_grid

#e_grid = mceq_run_January.y.e_grid
#mceq_run.unset_mod_pprod()

#mod_0 = (0.0,0.0,0.0,0.0,0.0,0.0,0.0,mceq_run_January )
mod_0 = (-1.0,-1.0, mceq_run_January )
apply_mod_p(*mod_0)
mceq_run_January.y.print_mod_pprod()
示例#17
0
class nuVeto(object):
    """Class for computing the neutrino passing fraction i.e. (1-(Veto probability))"""
    def __init__(self,
                 costh,
                 pmodel=(pm.HillasGaisser2012, 'H3a'),
                 hadr='SIBYLL2.3c',
                 barr_mods=(),
                 depth=1950 * Units.m,
                 density=('CORSIKA', ('SouthPole', 'December')),
                 debug_level=1):
        """Initializes the nuVeto object for a particular costheta, CR Flux,
        hadronic model, barr parameters, and depth

        Note:
            A separate MCEq instance needs to be created for each
            combination of __init__'s arguments. To access pmodel and hadr,
            use mceq.pm_params and mceq.yields_params
        Args:
            costh (float): Cos(theta), the cosine of the neutrino zenith at the detector
            pmodel (tuple(CR model class, arguments)): CR Flux
            hadr (str): hadronic interaction model
            barr_mods: barr parameters
            depth (float): the depth at which the veto probability is computed below the ice
        """
        self.costh = costh
        self.pmodel = pmodel
        self.geom = Geometry(depth)
        theta = np.degrees(np.arccos(self.geom.cos_theta_eff(self.costh)))
        if density[0] == 'MSIS00_IC':
            print('Passing "MSIS00_IC" assumes IceCube-centered coordinates, '
                  'which obviates the depth used here. Switching to "MSIS00" '
                  'for identical results.')
            density = ('MSIS00', density[1])

        config.debug_level = debug_level
        # config.enable_em = False
        config.enable_muon_energy_loss = False
        config.return_as = 'total energy'
        config.adv_set['allowed_projectiles'] = [
            2212, 2112, 211, -211, 321, -321, 130, -2212, -2112
        ]  #, 11, 22]
        config.ctau = 2.5
        self.mceq = MCEqRun(
            # provide the string of the interaction model
            interaction_model=hadr,
            # primary cosmic ray flux model
            # support a tuple (primary model class (not instance!), arguments)
            primary_model=pmodel,
            # zenith angle \theta in degrees, measured positively from vertical direction at surface
            theta_deg=theta,
            # atmospheric density model
            density_model=density)

        if len(barr_mods) > 0:
            for barr_mod in barr_mods:
                # Modify proton-air -> mod[0]
                self.mceq.set_mod_pprod(2212, BARR[barr_mod[0]].pdg, barr_unc,
                                        barr_mod)
            # Populate the modifications to the matrices by re-filling the interaction matrix
            self.mceq.regenerate_matrices(skip_decay_matrix=True)

        X_vec = np.logspace(np.log10(2e-3),
                            np.log10(self.mceq.density_model.max_X), 12)
        self.dX_vec = np.diff(X_vec)
        self.X_vec = 10**centers(np.log10(X_vec))

    @staticmethod
    def categ_to_mothers(categ, daughter):
        """Get the parents for this category"""
        rcharge = '-' if 'bar' in daughter else '+'
        lcharge = '+' if 'bar' in daughter else '-'
        rbar = 'bar' if 'bar' in daughter else ''
        lbar = '' if 'bar' in daughter else 'bar'
        if categ == 'conv':
            mothers = ['pi' + rcharge, 'K' + rcharge, 'K_L0']
            if 'nu_tau' in daughter:
                mothers = []
            elif 'nu_e' in daughter:
                mothers.extend(['K_S0', 'mu' + rcharge])
            elif 'nu_mu' in daughter:
                mothers.extend(['mu' + lcharge])
        elif categ == 'pr':
            if 'nu_tau' in daughter:
                mothers = ['D' + rcharge, 'D_s' + rcharge]
            else:
                mothers = ['D' + rcharge, 'D_s' + rcharge, 'D' + rbar + '0'
                           ]  #, 'Lambda'+lbar+'0']#, 'Lambda_c'+rcharge]
        elif categ == 'total':
            mothers = nuVeto.categ_to_mothers(
                'conv', daughter) + nuVeto.categ_to_mothers('pr', daughter)
        else:
            mothers = [
                categ,
            ]
        return mothers

    @staticmethod
    def esamp(enu, accuracy):
        """ returns the sampling of parent energies for a given enu
        """
        # TODO: replace 1e8 with MMC-prpl interpolated bounds
        return np.logspace(np.log10(enu), np.log10(enu + 1e8),
                           int(1000 * accuracy))

    @staticmethod
    def projectiles():
        """Get allowed pimaries"""
        pdg_ids = config.adv_set['allowed_projectiles']
        namer = ParticleProperties.modtab.pdg2modname
        allowed = []
        for pdg_id in pdg_ids:
            allowed.append(namer[pdg_id])
            try:
                allowed.append(namer[-pdg_id])
            except KeyError:
                continue
        return allowed

    @staticmethod
    def nbody(fpath, esamp, enu, fn, l_ice):
        with np.load(fpath) as dfile:
            xmus = centers(dfile['xedges'])
            xnus = np.concatenate([xmus, [1]])
            vals = np.nan_to_num(dfile['histograms'])

            ddec = interpolate.RegularGridInterpolator((xnus, xmus),
                                                       vals,
                                                       bounds_error=False,
                                                       fill_value=None)
            emu_mat = xmus[:, None] * esamp[None, :] * Units.GeV
            pmu_mat = ddec(np.stack(np.meshgrid(enu / esamp, xmus), axis=-1))
            reaching = 1 - np.sum(pmu_mat * fn.prpl(
                np.stack([emu_mat, np.ones(emu_mat.shape) * l_ice], axis=-1)),
                                  axis=0)
            reaching[reaching < 0.] = 0.
            return reaching

    @staticmethod
    @lru_cache(2**12)
    def psib(l_ice, mother, enu, accuracy, prpl):
        """ returns the suppression factor due to the sibling muon
        """
        esamp = nuVeto.esamp(enu, accuracy)
        fn = MuonProb(prpl)
        if mother in ['D0', 'D0-bar']:
            reaching = nuVeto.nbody(
                resource_filename('nuVeto',
                                  'data/decay_distributions/D0_numu.npz'),
                esamp, enu, fn, l_ice)
        elif mother in ['D+', 'D-']:
            reaching = nuVeto.nbody(
                resource_filename('nuVeto',
                                  'data/decay_distributions/D+_numu.npz'),
                esamp, enu, fn, l_ice)
        elif mother in ['Ds+', 'Ds-']:
            reaching = nuVeto.nbody(
                resource_filename('nuVeto',
                                  'data/decay_distributions/Ds_numu.npz'),
                esamp, enu, fn, l_ice)
        elif mother == 'K0L':
            reaching = nuVeto.nbody(
                resource_filename('nuVeto',
                                  'data/decay_distributions/K0L_numu.npz'),
                esamp, enu, fn, l_ice)
        else:
            # Assuming muon energy is E_parent - E_nu
            reaching = 1. - fn.prpl(
                list(zip((esamp - enu) * Units.GeV, [l_ice] * len(esamp))))
        return reaching

    @lru_cache(maxsize=2**12)
    def get_dNdEE(self, mother, daughter):
        """Differential parent-->neutrino (mother--daughter) yield"""
        ihijo = 20
        e_grid = self.mceq.e_grid
        delta = self.mceq.e_widths
        x_range = e_grid[ihijo] / e_grid
        rr = ParticleProperties.rr(mother, daughter)
        dNdEE_edge = ParticleProperties.br_2body(mother, daughter) / (1 - rr)
        dN_mat = self.mceq._decays.get_matrix(
            (ParticleProperties.pdg_id[mother], 0),
            (ParticleProperties.pdg_id[daughter], 0))
        dNdEE = dN_mat[ihijo] * e_grid / delta
        logx = np.log10(x_range)
        logx_width = -np.diff(logx)[0]
        good = (logx + logx_width / 2 < np.log10(1 - rr)) & (x_range >= 5.e-2)

        x_low = x_range[x_range < 5e-2]
        dNdEE_low = np.array([dNdEE[good][-1]] * x_low.size)
        dNdEE_interp = lambda x_: interpolate.pchip(
            np.concatenate([[1 - rr], x_range[good], x_low])[::-1],
            np.concatenate([[dNdEE_edge], dNdEE[good], dNdEE_low])[::-1],
            extrapolate=True)(x_) * np.heaviside(1 - rr - x_, 1)
        return x_range, dNdEE, dNdEE_interp

    @lru_cache(maxsize=2**12)
    def grid_sol(self, ecr=None, particle=None):
        """MCEq grid solution for \\frac{dN_{CR,p}}_{dE_p}"""
        if ecr is not None:
            self.mceq.set_single_primary_particle(ecr, particle)
        else:
            self.mceq.set_primary_model(*self.pmodel)
        self.mceq.solve(int_grid=self.X_vec, grid_var="X")
        return self.mceq.grid_sol

    @lru_cache(maxsize=2**12)
    def nmu(self, ecr, particle, prpl='ice_allm97_step_1'):
        """Poisson probability of getting no muons"""
        grid_sol = self.grid_sol(ecr, particle)
        l_ice = self.geom.overburden(self.costh)
        mu = np.abs(self.get_solution('mu-', grid_sol)) + np.abs(
            self.get_solution(
                'mu+', grid_sol))  # np.abs hack to prevent negative fluxes
        fn = MuonProb(prpl)
        coords = list(
            zip(self.mceq.e_grid * Units.GeV, [l_ice] * len(self.mceq.e_grid)))
        ### DEBUG ###
        # if np.trapz(mu*fn.prpl(coords)*self.mceq.e_grid, np.log(self.mceq.e_grid)) < 0:
        #     import pdb
        #     pdb.set_trace()
        ###
        return np.trapz(mu * fn.prpl(coords) * self.mceq.e_grid,
                        np.log(self.mceq.e_grid))

    @lru_cache(maxsize=2**12)
    def get_rescale_phi(self, mother, ecr=None, particle=None):
        """Flux of the mother at all heights"""
        grid_sol = self.grid_sol(
            ecr, particle
        )  # MCEq solution (fluxes tabulated as a function of height)
        dX = self.dX_vec * Units.gr / Units.cm**2
        rho = self.mceq.density_model.X2rho(
            self.X_vec) * Units.gr / Units.cm**3
        inv_decay_length_array = (
            ParticleProperties.mass_dict[mother] /
            (self.mceq.e_grid[:, None] * Units.GeV)) / (
                ParticleProperties.lifetime_dict[mother] * rho[None, :])
        rescale_phi = dX[None, :] * inv_decay_length_array * self.get_solution(
            mother, grid_sol, grid_idx=False).T
        return rescale_phi

    def get_integrand(self,
                      categ,
                      daughter,
                      enu,
                      accuracy,
                      prpl,
                      ecr=None,
                      particle=None):
        """flux*yield"""
        esamp = self.esamp(enu, accuracy)
        mothers = self.categ_to_mothers(categ, daughter)
        nums = np.zeros((len(esamp), len(self.X_vec)))
        dens = np.zeros((len(esamp), len(self.X_vec)))
        for mother in mothers:
            dNdEE = self.get_dNdEE(mother, daughter)[-1]
            rescale_phi = self.get_rescale_phi(mother, ecr, particle)
            # DEBUG
            # from matplotlib import pyplot as plt
            # plt.plot(np.log(self.mceq.e_grid[rescale_phi[:,0]>0]),
            #          np.log(rescale_phi[:,0][rescale_phi[:,0]>0]))
            # rescale_phi = np.array([interpolate.interp1d(self.mceq.e_grid, rescale_phi[:,i], kind='quadratic', bounds_error=False, fill_value=0)(esamp) for i in range(rescale_phi.shape[1])]).T
            ###
            # TODO: optimize to only run when esamp[0] is non-zero
            rescale_phi = np.exp(
                np.array([
                    interpolate.interp1d(
                        np.log(self.mceq.e_grid[rescale_phi[:, i] > 0]),
                        np.log(rescale_phi[:, i][rescale_phi[:, i] > 0]),
                        kind='quadratic',
                        bounds_error=False,
                        fill_value=-np.inf)(np.log(esamp))
                    if np.count_nonzero(rescale_phi[:, i] > 0) > 2 else [
                        -np.inf,
                    ] * esamp.shape[0] for i in range(rescale_phi.shape[1])
                ])).T
            # DEBUG
            # print rescale_phi.min(), rescale_phi.max()
            # print np.log(esamp)
            # plt.plot(np.log(esamp),
            #          np.log(rescale_phi[:,0]), label='intp')
            # plt.legend()
            # import pdb
            # pdb.set_trace()
            ###
            if 'nu_mu' in daughter:
                # muon accompanies nu_mu only
                pnmsib = self.psib(self.geom.overburden(self.costh), mother,
                                   enu, accuracy, prpl)
            else:
                pnmsib = np.ones(len(esamp))
            dnde = dNdEE(enu / esamp) / esamp
            nums += (dnde * pnmsib)[:, None] * rescale_phi
            dens += (dnde)[:, None] * rescale_phi

        return nums, dens

    def get_solution(self, particle_name, grid_sol, mag=0., grid_idx=None):
        """Retrieves solution of the calculation on the energy grid.

        Args:
          particle_name (str): The name of the particle such, e.g.
            ``total_mu+`` for the total flux spectrum of positive muons or
            ``pr_antinumu`` for the flux spectrum of prompt anti muon neutrinos
          mag (float, optional): 'magnification factor': the solution is
            multiplied by ``sol`` :math:`= \\Phi \\cdot E^{mag}`
          grid_idx (int, optional): if the integrator has been configured to save
            intermediate solutions on a depth grid, then ``grid_idx`` specifies
            the index of the depth grid for which the solution is retrieved. If
            not specified the flux at the surface is returned
          integrate (bool, optional): return averge particle number instead of
          flux (multiply by bin width)

        Returns:
          (numpy.array): flux of particles on energy grid :attr:`e_grid`
        """

        # MCEq index conversion
        ref = self.mceq.pman.pname2pref
        p_pdg = ParticleProperties.pdg_id[particle_name]
        reduce_res = True

        if grid_idx is None:  # Surface only case
            sol = np.array([grid_sol[-1]])
            xv = np.array([self.X_vec[-1]])
        elif isinstance(grid_idx,
                        bool) and not grid_idx:  # Whole solution case
            sol = np.asarray(grid_sol)
            xv = np.asarray(self.X_vec)
            reduce_res = False
        elif grid_idx >= len(self.mceq.grid_sol):  # Surface only case
            sol = np.array([grid_sol[-1]])
            xv = np.array([self.X_vec[-1]])
        else:  # Particular height case
            sol = np.array([grid_sol[grid_idx]])
            xv = np.array([self.X_vec[grid_idx]])

        # MCEq solution for particle
        direct = sol[:, ref[particle_name].lidx:ref[particle_name].uidx]
        res = np.zeros(direct.shape)
        rho_air = 1. / self.mceq.density_model.r_X2rho(xv)

        # meson decay length
        decayl = ((self.mceq.e_grid * Units.GeV) /
                  ParticleProperties.mass_dict[particle_name] *
                  ParticleProperties.lifetime_dict[particle_name] / Units.cm)

        # number of targets per cm2
        ndens = rho_air * Units.Na / Units.mol_air
        sec = self.mceq.pman[p_pdg]
        prim2mceq = {
            'p+-bar': 'pbar-',
            'n0-bar': 'nbar0',
            'D0-bar': 'Dbar0',
            'Lambda0-bar': 'Lambdabar0'
        }
        for prim in self.projectiles():
            if prim in prim2mceq:
                _ = prim2mceq[prim]
            else:
                _ = prim
            prim_flux = sol[:, ref[_].lidx:ref[_].uidx]
            proj = self.mceq.pman[ParticleProperties.pdg_id[prim]]
            prim_xs = proj.inel_cross_section()
            try:
                int_yields = proj.hadr_yields[sec]
                res += np.sum(int_yields[None, :, :] * prim_flux[:, None, :] *
                              prim_xs[None, None, :] * ndens[:, None, None],
                              axis=2)
            except KeyError as e:
                continue

        res *= decayl[None, :]
        # combine with direct
        res[direct != 0] = direct[direct != 0]

        if particle_name[:-1] == 'mu':
            for _ in ['k_' + particle_name, 'pi_' + particle_name]:
                res += sol[:, ref[_ + '_l'].lidx:ref[_ + '_l'].uidx]
                res += sol[:, ref[_ + '_r'].lidx:ref[_ + '_r'].uidx]

        res *= self.mceq.e_grid[None, :]**mag

        if reduce_res:
            res = res[0]
        return res

    def get_fluxes(self,
                   enu,
                   kind='conv nu_mu',
                   accuracy=3.5,
                   prpl='ice_allm97_step_1',
                   corr_only=False):
        """Returns the flux and passing fraction
        for a particular neutrino energy, flux, and p_light
        """
        # prpl = probability of reaching * probability of light
        # prpl -> None ==> median for muon reaching
        categ, daughter = kind.split()

        esamp = self.esamp(enu, accuracy)

        # Correlated only (no need for the unified calculation here) [really just for testing]
        passed = 0
        total = 0
        if corr_only:
            # sum performs the dX integral
            nums, dens = self.get_integrand(categ, daughter, enu, accuracy,
                                            prpl)
            num = np.sum(nums, axis=1)
            den = np.sum(dens, axis=1)
            passed = integrate.trapz(num, esamp)
            total = integrate.trapz(den, esamp)
            return passed, total

        pmodel = self.pmodel[0](self.pmodel[1])

        #loop over primary particles
        for particle in pmodel.nucleus_ids:
            # A continuous input energy range is allowed between
            # :math:`50*A~ \\text{GeV} < E_\\text{nucleus} < 10^{10}*A \\text{GeV}`.

            # ecrs --> Energy of cosmic ray primaries
            # amu --> atomic mass of primary

            # evaluation points in E_CR
            ecrs = amu(particle) * np.logspace(2, 10, int(10 * accuracy))

            # pnm --> probability of no muon (just a poisson probability)
            nmu = [self.nmu(ecr, particle, prpl) for ecr in ecrs]

            # nmufn --> fine grid interpolation of pnm
            nmufn = interpolate.interp1d(ecrs,
                                         nmu,
                                         kind='linear',
                                         assume_sorted=True,
                                         bounds_error=False,
                                         fill_value=(0, np.nan))
            # nums --> numerator
            nums = []
            # dens --> denominator
            dens = []
            # istart --> integration starting point, the lowest energy index for the integral
            istart = max(0, np.argmax(ecrs > enu) - 1)
            for ecr in ecrs[istart:]:  # integral in primary energy (E_CR)
                # cr_flux --> cosmic ray flux
                # phim2 --> units of flux * m^2 (look it up in the units)
                cr_flux = pmodel.nucleus_flux(particle,
                                              ecr.item()) * Units.phim2
                # poisson exp(-Nmu) [last term in eq 12]
                pnmarr = np.exp(-nmufn(ecr - esamp))

                num_ecr = 0  # single entry in nums
                den_ecr = 0  # single entry in dens

                # dEp
                # integral in Ep
                nums_ecr, dens_ecr = self.get_integrand(
                    categ, daughter, enu, accuracy, prpl, ecr, particle)
                num_ecr = integrate.trapz(
                    np.sum(nums_ecr, axis=1) * pnmarr, esamp)
                den_ecr = integrate.trapz(np.sum(dens_ecr, axis=1), esamp)

                nums.append(num_ecr * cr_flux / Units.phicm2)
                dens.append(den_ecr * cr_flux / Units.phicm2)
            # dEcr
            passed += integrate.trapz(nums, ecrs[istart:])
            total += integrate.trapz(dens, ecrs[istart:])

        return passed, total
示例#18
0
def Solve_mceqs():
    ### This function solves matrix cascade equations using MCEq. Please
    ### note that MCEq can do a lot more than what is currently used
    ### in this script. For more information and options, visit:
    ### https://github.com/afedynitch/MCEq

    import crflux.models as crf
    from MCEq.core import config, MCEqRun

    def Convert_name(particle):
        # MCEq can't handle "bar"s in particle names. It wants "anti"s instead.
        if 'bar' in particle[0]:
            pname = (particle[0].replace('_', '_anti') if '_' in particle[0] else 'anti' + particle[0])
            pname = pname.replace('bar', '')
        else:
            pname = particle[0]
        return pname

    # Cosmic ray flux at the top of the atmosphere:
    primary_model = (HawkBPL, 0.)
    # High-energy hadronic interaction model:
    interaction_model = 'SIBYLL23C'
    # Zenith angles:
    zenith_deg = np.append(np.arange(0., 90., 10), 89)
    mceq = MCEqRun(interaction_model = interaction_model,
                   primary_model = primary_model,
                   theta_deg = 0.)
    mceq.pman.track_leptons_from([(130,0)], 'K0L_')
    mceq.pman.track_leptons_from([(310,0)], 'K0S_')
    # mceq.pman.print_particle_tables(0)
    mceq._resize_vectors_and_restore()
    mceq.regenerate_matrices()
    config.excpt_on_missing_particle = True
    energy = mceq.e_grid

    ## Solve the equation systems for all zenith angles:
    solutions = [[] for particle in particles]
    for angle in zenith_deg:
        print(
            '\n=== Solving MCEq for BPL '
            + interaction_model + ' ' + str(angle) + ' deg'
        )
        mceq.set_theta_deg(angle)
        mceq.solve()

        # Obtain solution for all chosen particles:
        print('Obtaining solution for:')
        for p, particle in enumerate(particles):
            print(particle[0])
            solutions[p].append(mceq.get_solution(Convert_name(particle), mag=0))
            # mag is a multiplication factor in order to stress steaper
            # parts of the spectrum. Don't store magnified fluxes in nuflux
            # (keep mag=0)!

    # Save solutions to file particle-wise:
    for p, particle in enumerate(particles):
        savename = name + '_' + particle[0]
        headr = (
            savename.replace('_', '\t') + '\n'
            'energy [GeV]\t' + ' '.join([str(z) + ' deg\t' for z in zenith_deg])
        )
        solutions[p].insert(0, energy)
        solutions[p] = np.array(solutions[p])
        np.savetxt(
            dirname + '/data/' + savename + '.dat', np.transpose(solutions[p]),
            fmt='%.8e', header=headr, delimiter='\t'
        )