Ejemplo n.º 1
0
    def cambfile(self) -> str:
        """
        Generate the IC power spectrum using classylss.
        
        Basically is using pre_params feed into class and compute the powerspec
        files based on the range of redshift and redend. All files are stored in
        the directory camb_out.

        Return:
        ----
        camb_output (str) : power specs directory. default: "camb_linear/"
        """
        #Load high precision defaults
        pre_params = {
            'tol_background_integration': 1e-9, 'tol_perturb_integration' : 1.e-7,
            'tol_thermo_integration':1.e-5, 'k_per_decade_for_pk': 50,'k_bao_width': 8,
            'k_per_decade_for_bao':  200, 'neglect_CMB_sources_below_visibility' : 1.e-30,
            'transfer_neglect_late_source': 3000., 'l_max_g' : 50,
            'l_max_ur':150, 'extra metric transfer functions': 'y'}

        #Set the neutrino density and subtract it from omega0
        omeganu = self.m_nu/93.14/self.hubble**2
        omcdm   = (self.omega0 - self.omegab) - omeganu
        gparams = {'h': self.hubble, 'Omega_cdm': omcdm,'Omega_b': self.omegab,
            'Omega_k': 0, 'n_s': self.ns, 'A_s': self.scalar_amp}

        #Lambda is computed self-consistently
        gparams['Omega_fld'] = 0
        numass = get_neutrino_masses(self.m_nu, self.nu_hierarchy)

        #Set up massive neutrinos
        if self.m_nu > 0:
            gparams['m_ncdm'] = '%.8f,%.8f,%.8f' % (numass[2], numass[1], numass[0])
            gparams['N_ncdm'] = 3
            gparams['N_ur'] = 0.00641
            #Neutrino accuracy: Default pk_ref.pre has tol_ncdm_* = 1e-10,
            #which takes 45 minutes (!) on my laptop.
            #tol_ncdm_* = 1e-8 takes 20 minutes and is machine-accurate.
            #Default parameters are fast but off by 2%.
            #I chose 1e-5, which takes 6 minutes and is accurate to 1e-5
            gparams['tol_ncdm_newtonian'] = min(self.nu_acc,1e-5)
            gparams['tol_ncdm_synchronous'] = self.nu_acc
            gparams['tol_ncdm_bg'] = 1e-10
            gparams['l_max_ncdm'] = 50
            #This disables the fluid approximations, which make P_nu not match 
            # camb on small scales.
            #We need accurate P_nu to initialise our neutrino code.
            gparams['ncdm_fluid_approximation'] = 2
            #Does nothing unless ncdm_fluid_approximation = 2
            #Spend less time on neutrino power for smaller neutrino mass
            gparams['ncdm_fluid_trigger_tau_over_tau_k'] = 30000.* (self.m_nu / 0.4)
        else:
            gparams['N_ur'] = 3.046

        #Initial cosmology
        pre_params.update(gparams)

        maxk        = 2 * math.pi / self.box * self.npart * 8
        powerparams = {'output': 'dTk vTk mPk', 'P_k_max_h/Mpc' : maxk, 
            "z_max_pk" : self.redshift + 1}
        pre_params.update(powerparams)

        #At which redshifts should we produce CAMB output: we want the start and
        # end redshifts of the simulation, but we also want some other values
        # for checking purposes
        camb_zz = np.concatenate(
            [ [self.redshift,], 
             1 / self.generate_times() - 1,
              [self.redend,] ] )

        cambpars  = os.path.join(self.outdir, "_class_params.ini")
        classconf = configobj.ConfigObj()
        classconf.filename = cambpars
        classconf.update(pre_params)
        classconf['z_pk'] = camb_zz
        classconf.write()

        # feed in the parameters and generate the powerspec object
        engine  = CLASS.ClassEngine(pre_params)
        powspec = CLASS.Spectra(engine) # powerspec is an object

        #Save directory
        camb_output = "camb_linear/"
        camb_outdir = os.path.join(self.outdir, camb_output)
        try:
            os.mkdir(camb_outdir)
        except FileExistsError:
            pass

        #Save directory
        #Get and save the transfer functions
        for zz in camb_zz:
            trans = powspec.get_transfer(z=zz)

            #fp-roundoff
            trans['k'][-1] *= 0.9999
            transferfile = os.path.join(
                camb_outdir, "ics_transfer_" + self._camb_zstr(zz) + ".dat")
            save_transfer(trans, transferfile)

            pk_lin = powspec.get_pklin(k=trans['k'], z=zz)
            pkfile = os.path.join(
                camb_outdir, "ics_matterpow_" + self._camb_zstr(zz) + ".dat")

            np.savetxt(pkfile, np.vstack([trans['k'], pk_lin]).T)

        return camb_output
Ejemplo n.º 2
0
plt.loglog(1 + z, bg.Omega_m(z), label=r"$\Omega_m$")
plt.loglog(1 + z, bg.Omega_r(z), label=r"$\Omega_r$")
plt.legend()
plt.xlabel(r"$1+z$")
plt.ylabel("density parameter")
plt.show()

# initialize with proper output
engine = CLASS.ClassEngine({
    'output': 'dTk vTk mPk',
    'non linear': 'halofit',
    'P_k_max_h/Mpc': 20.,
    "z_max_pk": 100.0
})
sp = CLASS.Spectra(engine)
k = np.logspace(-2, 0, 100)
pk_nl = sp.get_pk(k=k, z=0.5)
pk_lin = sp.get_pklin(k=k, z=0.5)

plt.loglog(k, pk_nl, label='nonlinear')
plt.loglog(k, pk_lin, label='linear')
plt.legend()
plt.xlabel(r"$k$ $[h\mathrm{Mpc}^{-1}]$")
plt.ylabel(r"$P$ $[h^{-3} \mathrm{Mpc}^3]$")
plt.show()

z = np.linspace(0., 2., 1024)
plt.plot(1. + z, sp.sigma8_z(z))
plt.xlabel(r"$1+z$")
plt.ylabel(r"$\sigma_8(z)$")
Ejemplo n.º 3
0
def make_class_power(paramfile, external_pk=None, extraz=None, verbose=False):
    """Main routine: parses a parameter file and makes a matter power spectrum.
    Will not over-write power spectra if already present.
    Options are loaded from the MP-GenIC parameter file.
    Supported:
        - Omega_fld and DE parameters.
        - Massive neutrinos.
        - Using Sigma8 to set the power spectrum scale.
        - Different transfer functions.

    We use class velocity transfer functions to have accurate initial conditions
    even on superhorizon scales, and to properly support multiple species.
    The alternative is to use rescaling.

    Not supported:
        - Warm dark matter power spectra.
        - Rescaling with different transfer functions."""
    config = configobj.ConfigObj(infile=paramfile,
                                 configspec=GenICconfigspec,
                                 file_error=True)
    #Input sanitisation
    _check_genic_config(config)

    #Precision
    pre_params = {
        'tol_background_integration': 1e-9,
        'tol_perturb_integration': 1.e-7,
        'tol_thermo_integration': 1.e-5,
        'k_per_decade_for_pk': 50,
        'k_bao_width': 8,
        'k_per_decade_for_bao': 200,
        'neglect_CMB_sources_below_visibility': 1.e-30,
        'transfer_neglect_late_source': 3000.,
        'l_max_g': 50,
        'l_max_ur': 150
    }

    #Important! Densities are in synchronous gauge!
    pre_params['gauge'] = 'synchronous'

    gparams = _build_cosmology_params(config)
    pre_params.update(gparams)
    redshift = config['Redshift']
    if config['InputPowerRedshift'] >= 0:
        redshift = config['InputPowerRedshift']
    outputs = redshift
    if extraz is not None:
        outputs = [
            outputs,
        ] + extraz
    #Pass options for the power spectrum
    MPC_in_cm = 3.085678e24
    boxmpc = config['BoxSize'] / MPC_in_cm * config['UnitLength_in_cm']
    maxk = max(10, 2 * math.pi / boxmpc * config['Ngrid'] * 4)
    #CLASS needs the first redshift to be relatively high for some internal interpolation reasons
    maxz = max(1 + np.max(outputs), 99)
    powerparams = {
        'output': 'dTk vTk mPk',
        'P_k_max_h/Mpc': maxk,
        "z_max_pk": maxz,
        'z_pk': outputs,
        'extra metric transfer functions': 'y'
    }
    pre_params.update(powerparams)

    if verbose:
        verb_params = {
            'input_verbose': 1,
            'background_verbose': 1,
            'thermodynamics_verbose': 1,
            'perturbations_verbose': 1,
            'transfer_verbose': 1,
            'primordial_verbose': 1,
            'spectra_verbose': 1,
            'nonlinear_verbose': 1,
            'lensing_verbose': 1,
            'output_verbose': 1
        }
        pre_params.update(verb_params)

    #Specify an external primordial power spectrum
    if external_pk is not None:
        pre_params['P_k_ini'] = "external_pk"
        pre_params["command"] = "cat ", external_pk
    #Print the class parameters to terminal in a format
    #readable by the command line class.
    if verbose:
        for k in pre_params:
            print(k, '=', pre_params[k])

    if 'ncdm_fluid_approximation' in pre_params:
        print(
            'Starting CLASS power spectrum with accurate P(k) for massive neutrinos.'
        )
        print('Computation may take several minutes')
    #Make the power spectra module
    engine = CLASS.ClassEngine(pre_params)
    powspec = CLASS.Spectra(engine)
    print("sigma_8(z=0) = ", powspec.sigma8, "A_s = ", powspec.A_s)
    #Save directory
    sdir = os.path.split(paramfile)[0]
    #Get and save the transfer functions if needed
    trans = powspec.get_transfer(z=redshift)
    if config['DifferentTransferFunctions'] == 1.:
        tfile = os.path.join(sdir, config['FileWithTransferFunction'])
        if os.path.exists(tfile):
            raise IOError("Refusing to write to existing file: ", tfile)
        save_transfer(trans, tfile)
    #fp-roundoff
    trans['k'][-1] *= 0.9999
    #Get and save the matter power spectrum
    pk_lin = powspec.get_pklin(k=trans['k'], z=redshift)
    pkfile = os.path.join(sdir, config['FileWithInputSpectrum'])
    if os.path.exists(pkfile):
        raise IOError("Refusing to write to existing file: ", pkfile)
    np.savetxt(pkfile, np.vstack([trans['k'], pk_lin]).T)
    if extraz is not None:
        for red in extraz:
            trans = powspec.get_transfer(z=red)
            tfile = os.path.join(
                sdir, config['FileWithTransferFunction'] + "-" + str(red))
            if os.path.exists(tfile):
                raise IOError("Refusing to write to existing file: ", tfile)
            save_transfer(trans, tfile)
            trans['k'][-1] *= 0.9999
            #Get and save the matter power spectrum
            pk_lin = powspec.get_pklin(k=trans['k'], z=red)
            pkfile = os.path.join(
                sdir, config['FileWithInputSpectrum'] + "-" + str(red))
            if os.path.exists(pkfile):
                raise IOError("Refusing to write to existing file: ", pkfile)
            np.savetxt(pkfile, np.vstack([trans['k'], pk_lin]).T)