Source code for pyccl.emulators.baccoemu_nonlinear_pk

__all__ = ("BaccoemuNonlinear",)

import numpy as np

from .. import Pk2D
from . import EmulatorPk


[docs]class BaccoemuNonlinear(EmulatorPk): """ Nonlinear power spectrum emulator from baccoemu This is an emulator of the non-linear matter power spectrum as a function of 8 cosmological parameters (:math:`\\omega_c`, :math:`\\omega_b`, :math:`A_s` or :math:`\\sigma_{8,c}`, :math:`n_s`, :math:`h`, :math:`M_\\nu`, :math:`w_0`, :math:`w_a`) and the scale factor. If `nonlinear_emu_path` and `nonlinear_emu_details` are not specified, the installed public version of the emulator is used. If the user has access to a locally saved baccoemu version, the path can be specified with these two keyword arguments. See `Angulo et al. 2020 <https://arxiv.org/pdf/2004.06245.pdf>`_ and https://bacco.dipc.org/emulator.html. Args: nonlinear_emu_path (:obj:`str`): path to a folder containing a specific baccoemu version nonlinear_emu_details (:obj:`str`): name of the details file in the given baccoemu version n_sampling_a (:obj:`int`): number of scale factor values used for building the 2d pk interpolator """ def __init__(self, nonlinear_emu_path=None, nonlinear_emu_details=None, n_sampling_a=100): # avoid tensorflow warnings import warnings with warnings.catch_warnings(): warnings.filterwarnings('ignore', category=UserWarning) import baccoemu self.mpk = baccoemu.Matter_powerspectrum( nonlinear_emu_path=nonlinear_emu_path, nonlinear_emu_details=nonlinear_emu_details) self.a_min = self.mpk.emulator['nonlinear']['bounds'][-1][0] self.a_max = self.mpk.emulator['nonlinear']['bounds'][-1][1] self.k_min = self.mpk.emulator['nonlinear']['k'][0] self.k_max = self.mpk.emulator['nonlinear']['k'][-1] self.n_sampling_a = n_sampling_a def __str__(self) -> str: return """baccoemu nonlinear Pk module, k_min,k_max = ({}, {}), a_min,a_max = ({}, {})""".format( self.k_min, self.k_max, self.a_min, self.a_max) def _sigma8tot_2_sigma8cold(self, emupars, sigma8tot): """Use baccoemu to convert sigma8 total matter to sigma8 cdm+baryons """ if hasattr(emupars['omega_cold'], '__len__'): _emupars = {} for pname in emupars: _emupars[pname] = emupars[pname][0] else: _emupars = emupars A_s_fid = 2.1e-9 sigma8tot_fid = self.mpk.get_sigma8(cold=False, A_s=A_s_fid, **_emupars) A_s = (sigma8tot / sigma8tot_fid)**2 * A_s_fid return self.mpk.get_sigma8(cold=True, A_s=A_s, **_emupars) def _get_pk_at_a(self, cosmo, a): # First create the dictionary passed to baccoemu # if a is an array, make sure all the other parameters passed to the # emulator have the same len if hasattr(a, '__len__'): emupars = dict( omega_cold=np.full((len(a)), cosmo['Omega_c'] + cosmo['Omega_b']), omega_baryon=np.full((len(a)), cosmo['Omega_b']), ns=np.full((len(a)), cosmo['n_s']), hubble=np.full((len(a)), cosmo['h']), neutrino_mass=np.full((len(a)), np.sum(cosmo['m_nu'])), w0=np.full((len(a)), cosmo['w0']), wa=np.full((len(a)), cosmo['wa']), expfactor=a ) else: emupars = dict( omega_cold=cosmo['Omega_c'] + cosmo['Omega_b'], omega_baryon=cosmo['Omega_b'], ns=cosmo['n_s'], hubble=cosmo['h'], neutrino_mass=np.sum(cosmo['m_nu']), w0=cosmo['w0'], wa=cosmo['wa'], expfactor=a ) # if cosmo contains sigma8, we use it for baccoemu, otherwise we pass # A_s to the emulator if np.isnan(cosmo['A_s']): sigma8tot = cosmo['sigma8'] sigma8cold = self._sigma8tot_2_sigma8cold(emupars, sigma8tot) if hasattr(a, '__len__'): emupars['sigma8_cold'] = np.full((len(a)), sigma8cold) else: emupars['sigma8_cold'] = sigma8cold else: if hasattr(a, '__len__'): emupars['A_s'] = np.full((len(a)), cosmo['A_s']) else: emupars['A_s'] = cosmo['A_s'] h = cosmo['h'] k_hubble, pk_hubble = self.mpk.get_nonlinear_pk(cold=False, **emupars) return k_hubble * h, pk_hubble / h**3 def _get_pk2d(self, cosmo): a = np.linspace(self.a_min, 1, self.n_sampling_a) k, pk = self.get_pk_at_a(cosmo, a) return Pk2D(a_arr=a, lk_arr=np.log(k), pk_arr=np.log(pk), is_logp=True, extrap_order_lok=1, extrap_order_hik=2)