Beispiel #1
0
def nu_masses(OmNuh2, mass_split, ccl_TCMB=2.725):
    """nu_masses
		Returns the neutrinos mass(es) for a given OmNuh2, according to the 
		splitting convention specified by the user.

    Args:
        OmNuh2 (float): Neutrino energy density at z=0 times h^2
        mass_split: indicates how the masses should be split up
        TCMB (float, optional): Temperature of the CMB (K). Default: 2.725.

    Returns:
        Neutrino mass(es) corresponding to this Omeganuh2
    
    """
    status = 0
    
    if mass_split not in neutrino_mass_splits.keys() :
        raise ValueError( "'%s' is not a valid species type. "
                          "Available options are: %s" \
                         % (mass_split,neutrino_mass_splits.keys()) )
    
    # Call function
    if ((mass_split=='normal') or (mass_split=='inverted') or (mass_split=='equal')):
        mnu, status = lib.nu_masses_vec(OmNuh2, neutrino_mass_splits[mass_split], ccl_TCMB, 3, status)
    elif mass_split=='sum':
        mnu, status = lib.nu_masses_vec(OmNuh2, neutrino_mass_splits[mass_split], ccl_TCMB, 1, status)
        mnu = mnu[0]
        
	
    # Check status and return
    check(status)
    return mnu
Beispiel #2
0
def correlation_3d(cosmo, a, r):
    """
    Compute the 3D correlation function.

    Args:
        cosmo (:obj:`Cosmology`): A Cosmology object.
        a (float): scale factor.
        r (float or array_like): distance(s) at which to calculate the 3D correlation function (in Mpc).        
    Returns:
        Value(s) of the correlation function at the input distance(s).
    """
    cosmo_in = cosmo
    cosmo = _cosmology_obj(cosmo)
    status = 0

    # Convert scalar input into an array
    scalar = False
    if isinstance(r, float) or isinstance(r, int):
        scalar = True
        r = np.array([
            r,
        ])

    # Call 3D correlation function
    xi, status = lib.correlation_3d_vec(cosmo, a, r, len(r), status)
    check(status, cosmo_in)
    if scalar: return xi[0]
    return xi
Beispiel #3
0
def Omeganuh2(a, mnu, TCMB=2.725):
    """Omeganuh2

    .. note:: for all practical purposes, Neff is simply N_nu_mass.

    Args:
        a (float): Scale factor, normalized to 1 today.
        mnu (float or array_like): Neutrino mass (in eV)
        TCMB (float, optional): Temperature of the CMB (K). Default: 2.725.

    Returns:
        float or array_like: corresponding to a given neutrino mass.

    """
    status = 0
    scalar = True if isinstance(a, float) else False
    
    # Convert to array if it's not already an array
    if not isinstance(a, np.ndarray):
        a = np.array([a,]).flatten()
    if not isinstance(mnu, np.ndarray):
        mnu = np.array([mnu,]).flatten()
        
    N_nu_mass = len(mnu)
    
    # Call function
    OmNuh2, status = lib.Omeganuh2_vec(N_nu_mass, TCMB, a, mnu, a.size, status)
    
    # Check status and return
    check(status)
    if scalar: return OmNuh2[0]
    return OmNuh2
Beispiel #4
0
def dNdz_tomog(z, dNdz_type, zmin, zmax, pz_func):
    """Calculates dNdz in a particular tomographic bin, convolved
    with a photo-z model (defined by the user), and normalized.

    Args:
        z (float or array_like): Spectroscopic redshifts to evaluate dNdz at.
        dNdz_type (:obj:`str`): Type of redshift distribution.
        zmin (float): Minimum photo-z of the bin.
        zmax (float): Maximum photo-z of the bin.
        pz_func (callable): User-defined photo-z function.

    Return:
        dNdz (float or array_like): dNdz values evalued at each z.

    """
    # Ensure that an array will be passed to specs_dNdz_tomog_vec
    z = np.atleast_1d(z)

    # Do type-check for pz_func argument
    if not isinstance(pz_func, PhotoZFunction):
        raise TypeError("pz_func must be a PhotoZFunction instance.")

    # Get dNdz type
    if dNdz_type not in dNdz_types.keys():
        raise ValueError("'%s' not a valid dNdz_type." % dNdz_type)

    # Call dNdz tomography function
    status = 0
    dNdz, status = lib.specs_dNdz_tomog_vec(dNdz_types[dNdz_type], zmin, zmax,
                                            pz_func.pz_func, z, z.size, status)
    check(status)
    return dNdz
Beispiel #5
0
    def compute_growth(self):
        """Interfaces with src/ccl_background.c: ccl_cosmology_compute_growth().
        Sets up the splines for the growth function.

        """
        status = 0
        status = lib.cosmology_compute_growth(self.cosmo, status)
        check(status, self.cosmo)
Beispiel #6
0
    def compute_power(self):
        """Interfaces with src/ccl_power.c: ccl_cosmology_compute_power().
        Sets up the splines for the power spectrum.

        """
        status = 0
        status = lib.cosmology_compute_power(self.cosmo, status)
        check(status, self.cosmo)
Beispiel #7
0
    def compute_distances(self):
        """Interfaces with src/compute_background.c: ccl_cosmology_compute_distances(). 
        Sets up the splines for the distances.

        """
        status = 0
        status = lib.cosmology_compute_distances(self.cosmo, status)
        check(status, self.cosmo)
Beispiel #8
0
Datei: cls.py Projekt: EiffL/CCL
    def get_internal_function(self, cosmo, function, a):
        """
        Method to evaluate any internal function of redshift for this tracer.

        Args:
            cosmo (:obj:`Cosmology`): Cosmology object.
            function (:obj:`str`): Specifies which function to evaluate. Must 
                be one of the types specified in the `pyccl.cls.function_types` 
                dictionary.
            a (:obj: float or array-like): list of scale factors at which to 
                evaluate the function.
            
        Returns:
            Array of function values at the input scale factors.
        """
        # Access ccl_cosmology object
        cosmo_in = cosmo
        cosmo = _cosmology_obj(cosmo)

        # Access CCL_ClTracer objects
        clt = self.cltracer

        # Check that specified function type exists
        if function not in function_types.keys():
            raise KeyError("Internal function type '%s' not recognized." %
                           function)

        # Check input types
        status = 0
        is_scalar = False
        if isinstance(a, float):
            is_scalar = True
            aarr = np.array([a])
            na = 1
        elif isinstance(a, np.ndarray):
            aarr = a
            na = a.size
        else:
            aarr = a
            na = len(a)

        # Evaluate function
        farr, status = lib.clt_fa_vec(cosmo, self.cltracer,
                                      function_types[function], aarr, na,
                                      status)
        check(status, cosmo_in)
        if is_scalar:
            return farr[0]
        else:
            return farr
Beispiel #9
0
def correlation(cosmo, ell, C_ell, theta, corr_type='gg', method='fftlog'):
    """Compute the angular correlation function.

    Args:
        cosmo (:obj:`Cosmology`): A Cosmology object.
        ell (array_like): Multipoles corresponding to the input angular power spectrum.
        C_ell (array_like): Input angular power spectrum.
        theta (float or array_like): Angular separation(s) at which to calculate the angular correlation function (in degrees).
        corr_type (string): Type of correlation function. Choices: 'GG' (galaxy-galaxy), 'GL' (galaxy-shear), 'L+' (shear-shear, xi+), 'L-' (shear-shear, xi-).
        method (string, optional): Method to compute the correlation function. Choices: 'Bessel' (direct integration over Bessel function), 'FFTLog' (fast integration with FFTLog), 'Legendre' (brute-force sum over Legendre polynomials).
    
    Returns:
        float or array_like: Value(s) of the correlation function at the input angular separations.

    """
    cosmo_in = cosmo
    cosmo = _cosmology_obj(cosmo)
    status = 0

    # Convert to lower case
    corr_type = corr_type.lower()
    method = method.lower()

    if corr_type not in correlation_types.keys():
        raise KeyError("'%s' is not a valid correlation type." % corr_type)

    if method.lower() not in correlation_methods.keys():
        raise KeyError("'%s' is not a valid correlation method." % method)

    # Convert scalar input into an array
    scalar = False
    if isinstance(theta, float) or isinstance(theta, int):
        scalar = True
        theta = np.array([
            theta,
        ])

    # Call correlation function
    wth, status = lib.correlation_vec(cosmo, ell, C_ell, theta,
                                      correlation_types[corr_type],
                                      correlation_methods[method], len(theta),
                                      status)
    check(status, cosmo_in)
    if scalar: return wth[0]
    return wth
Beispiel #10
0
Datei: cls.py Projekt: zdu863/CCL
def angular_cl(cosmo, cltracer1, cltracer2, ell):
    """
    Calculate the angular (cross-)power spectrum for a pair of tracers.

    Args:
        cosmo (:obj:`Cosmology`): A Cosmology object.
        cltracer1, cltracer2 (:obj:): ClTracer objects, of any kind.
        ell (float or array_like): Angular wavenumber(s) to evaluate the
            angular power spectrum at.

    Returns:
        cl (float or array_like): Angular (cross-)power spectrum values, C_ell,
            for the pair of tracers, as a function of `ell`.

    """
    # Access ccl_cosmology object
    cosmo_in = cosmo
    cosmo = _cosmology_obj(cosmo)

    # Access CCL_ClTracer objects
    clt1 = _cltracer_obj(cltracer1)
    clt2 = _cltracer_obj(cltracer2)

    status = 0
    # Return Cl values, according to whether ell is an array or not
    if isinstance(ell, float) or isinstance(ell, int) :
        # Use single-value function
        cl, status = lib.angular_cl(cosmo, ell, clt1, clt2, status)
    elif isinstance(ell, np.ndarray):
        # Use vectorised function
        cl, status = lib.angular_cl_vec(cosmo, clt1, clt2, ell, ell.size, status)
    else:
        # Use vectorised function
        cl, status = lib.angular_cl_vec(cosmo, clt1, clt2, ell, len(ell), status)
    check(status, cosmo_in)
    return cl
Beispiel #11
0
    def __init__(self,
                 Omega_c=None,
                 Omega_b=None,
                 h=None,
                 A_s=None,
                 n_s=None,
                 Omega_k=0.,
                 Neff=3.046,
                 m_nu=0.,
                 mnu_type=None,
                 w0=-1.,
                 wa=0.,
                 bcm_log10Mc=np.log10(1.2e14),
                 bcm_etab=0.5,
                 bcm_ks=55.,
                 sigma8=None,
                 z_mg=None,
                 df_mg=None):
        """
        Creates a set of cosmological parameters.

        .. note:: Although some arguments default to `None`, they will raise a ValueError inside this function if not specified, so they are not optional.
        
        Args:
            Omega_c (float): Cold dark matter density fraction.
            Omega_b (float): Baryonic matter density fraction.
            h (float): Hubble constant divided by 100 km/s/Mpc; unitless.
            A_s (float): Power spectrum normalization. Optional if sigma8 is 
                         specified.
            n_s (float): Primordial scalar perturbation spectral index.
            Omega_k (float, optional): Curvature density fraction. Defaults to 0.
            Neff (float, optional): Effective number of neutrino species. 
                                    Defaults to 3.046
            m_nu (float or array-like, optional): If float: total mass in eV of 
            the massive neutrinos present. If array-like, masses of 3 neutrino
            species (must have length 3).
			mnu_type (string): treatment for neutrinos. 
			        Available: 'sum', 'sum_inverted', 'sum_equal', 'list'. 
			        Default if m_nu is a float is 'sum', default if m_nu is 
			        array-like with length 3 is 'list'.
            w0 (float, optional): First order term of dark energy equation of 
                                  state. Defaults to -1.
            wa (float, optional): Second order term of dark energy equation of 
                                  state. Defaults to 0.
            bcm_log10Mc (float, optional): One of the parameters of the BCM model.
            bcm_etab (float, optional): One of the parameters of the BCM model.
            bcm_ks (float, optional): One of the parameters of the BCM model.
            sigma8 (float): Variance of matter density perturbations at 8 Mpc/h
                            scale. Optional if A_s is specified.
            df_mg (:obj: array_like): Perturbations to the GR growth rate as a 
                                      function of redshift, Delta f. Used to 
                                      implement simple modified growth 
                                      scenarios.
            z_mg (:obj: array_like): Array of redshifts corresponding to df_mg.

        """
        # Set current ccl_parameters object to None
        self.parameters = None

        # Set nz_mg (no. of redshift bins for modified growth fns.)
        if z_mg is not None and df_mg is not None:
            # Get growth array size and do sanity check
            z_mg = np.atleast_1d(z_mg)
            df_mg = np.atleast_1d(df_mg)
            assert z_mg.size == df_mg.size
            nz_mg = z_mg.size
        else:
            # If one or both of the MG growth arrays are set to zero, disable
            # all of them
            if z_mg is not None or df_mg is not None:
                raise ValueError("Must specify both z_mg and df_mg.")
            z_mg = None
            df_mg = None
            nz_mg = -1

        # Check to make sure specified amplitude parameter is consistent
        if (A_s is None and sigma8 is None) \
        or (A_s is not None and sigma8 is not None):
            raise ValueError("Must set either A_s or sigma8.")

        # Set norm_pk to either A_s or sigma8
        norm_pk = A_s if A_s is not None else sigma8

        # The C library decides whether A_s or sigma8 was the input parameter
        # based on value, so we need to make sure this is consistent too
        if norm_pk >= 1e-5 and A_s is not None:
            raise ValueError("A_s must be less than 1e-5.")

        if norm_pk < 1e-5 and sigma8 is not None:
            raise ValueError("sigma8 must be greater than 1e-5.")

        if isinstance(m_nu, float):
            if mnu_type == None: mnu_type = 'sum'
            m_nu = [m_nu]
        elif hasattr(m_nu, "__len__"):
            if (len(m_nu) != 3):
                raise ValueError("m_nu must be a float or array-like object "
                                 "with length 3.")
            elif ((mnu_type=='sum') \
               or (mnu_type=='sum_inverted') \
               or (mnu_type=='sum_equal')):
                raise ValueError("mnu type '%s' cannot be passed with a list "
                                 "of neutrino masses, only with a sum." \
                                 % mnu_type)
            elif (mnu_type == None):
                mnu_type = 'list'  # False
        else:
            raise ValueError("m_nu must be a float or array-like object with "
                             "length 3.")

        # Check if any compulsory parameters are not set
        compul = [Omega_c, Omega_b, Omega_k, w0, wa, h, norm_pk, n_s]
        names = [
            'Omega_c', 'Omega_b', 'Omega_k', 'w0', 'wa', 'h', 'norm_pk', 'n_s'
        ]

        for nm, item in zip(names, compul):
            if item is None:
                raise ValueError("Necessary parameter '%s' was not set "
                                 "(or set to None)." % nm)

        # Create new instance of ccl_parameters object
        status = 0  # Create an internal status variable; needed to check massive neutrino integral.
        if (nz_mg == -1):
            # Create ccl_parameters without modified growth
            self.parameters, status \
            = lib.parameters_create_nu( Omega_c, Omega_b, Omega_k, Neff,
                                             w0, wa, h, norm_pk,
                                             n_s, bcm_log10Mc, bcm_etab, bcm_ks,
                                             mnu_types[mnu_type], m_nu, status )

        else:
            # Create ccl_parameters with modified growth arrays
            self.parameters, status \
            = lib.parameters_create_nu_vec( Omega_c, Omega_b, Omega_k, Neff,
                                             w0, wa, h, norm_pk,
                                             n_s, bcm_log10Mc, bcm_etab, bcm_ks,
                                             z_mg, df_mg, mnu_types[mnu_type], m_nu, status )
        check(status)
Beispiel #12
0
Datei: cls.py Projekt: EiffL/CCL
    def __init__(self,
                 cosmo,
                 tracer_type=None,
                 has_rsd=False,
                 has_magnification=False,
                 has_intrinsic_alignment=False,
                 z=None,
                 n=None,
                 bias=None,
                 mag_bias=None,
                 bias_ia=None,
                 f_red=None,
                 z_source=1100.):
        """
        ClTracer is a class for handling tracers that have an angular power
        spectrum.

        Note: unless otherwise stated, defaults are None.

        Args:
            cosmo (:obj:`Cosmology`): Cosmology object.
            tracer_type (:obj:`str`): Specifies which type of tracer is being
                specified. Must be one of the types specified in the
                `tracer_types` dict in `cls.py`.
            has_rsd (bool, optional): Flag for whether the tracer has a
                redshift-space distortion term. Defaults to False.
            has_magnification (bool, optional): Flag for whether the tracer has
                a magnification term. Defaults to False.
            has_intrinsic_alignment (bool, optional): Flag for whether the
                tracer has an intrinsic alignment term. Defaults to False.
            z (array_like, optional): Array of redshifts that the following
                functions are sampled at. This is overriden if tuples of the
                form (z, fn(z)) are specified for those kwargs instead (this
                allows the functions to be sampled differently in z).
            n (array_like or tuple, optional): Array of N(z) sampled at the
                redshifts given in the z array, or a tuple of arrays (z, N(z)).
                The units are arbitrary; N(z) will be normalized to unity.
            bias (array_like or tuple, optional): Array of galaxy bias b(z)
                sampled at the redshifts given in the z array, or a tuple of
                arrays (z, b(z)).
            mag_bias (array_like or tuple, optional): Array of magnification
                bias s(z) sampled at the redshifts given in the z array, or a
                tuple of arrays (z, s(z)).
            bias_ia (array_like or tuple, optional): Array of intrinsic
                alignment amplitudes b_IA(z), or a tuple of arrays (z, b_IA(z)).
            f_red (array_like or tuple, optional): Array of red galaxy
                fractions f_red(z), or a tuple of arrays (z, f_red(z)).
            z_source (float, optional): Redshift of source plane for CMB lensing.
        """
        # Verify cosmo object
        cosmo = _cosmology_obj(cosmo)

        # Check tracer type
        if tracer_type not in tracer_types.keys():
            raise KeyError("'%s' is not a valid tracer_type." % tracer_type)

        # Convert array arguments that are 'None' into 'NoneArr' type, and
        # check whether arrays were specified as tuples or with a common z array
        self.z_n, self.n = _check_array_params(z, n, 'n')
        self.z_b, self.b = _check_array_params(z, bias, 'bias')
        self.z_s, self.s = _check_array_params(z, mag_bias, 'mag_bias')
        self.z_ba, self.ba = _check_array_params(z, bias_ia, 'bias_ia')
        self.z_rf, self.rf = _check_array_params(z, f_red, 'f_red')
        self.z_source = z_source

        # Construct new ccl_cl_tracer
        status = 0
        return_val = lib.cl_tracer_new_wrapper(cosmo,
                                               tracer_types[tracer_type],
                                               int(has_rsd),
                                               int(has_magnification),
                                               int(has_intrinsic_alignment),
                                               self.z_n, self.n, self.z_b,
                                               self.b, self.z_s, self.s,
                                               self.z_ba, self.ba, self.z_rf,
                                               self.rf, self.z_source, status)

        if (isinstance(return_val, int)):
            self.has_cltracer = False
            check(return_val)
        else:
            self.has_cltracer = True
            self.cltracer, status = return_val
Beispiel #13
0
Datei: cls.py Projekt: EiffL/CCL
def angular_cl(cosmo,
               cltracer1,
               cltracer2,
               ell,
               l_limber=-1.,
               l_logstep=1.05,
               l_linstep=20.,
               dchi=3.,
               dlk=0.003,
               zmin=0.05,
               non_limber_method="native"):
    """
    Calculate the angular (cross-)power spectrum for a pair of tracers.

    Args:
        cosmo (:obj:`Cosmology`): A Cosmology object.
        cltracer1, cltracer2 (:obj:): ClTracer objects, of any kind.
        ell (float or array_like): Angular wavenumber(s) to evaluate the
            angular power spectrum at.
        l_limber (float) : Angular wavenumber beyond which Limber's
            approximation will be used
        l_logstep (float) : logarithmic step in ell at low multipoles
        l_linstep (float) : linear step in ell at high multipoles
        dchi (float) : comoving distance step size in non-limber native integrals
        dlk (float) : logarithmic step for the k non-limber native integral
        zmin (float) : minimal redshift for the integrals
        non_limber_method (str) : non-Limber integration method. Supported:
            "native" and "angpow"

    Returns:
        cl (float or array_like): Angular (cross-)power spectrum values, C_ell,
            for the pair of tracers, as a function of `ell`.

    """
    # Access ccl_cosmology object
    cosmo_in = cosmo
    cosmo = _cosmology_obj(cosmo)

    if non_limber_method not in nonlimber_methods.keys():
        raise KeyError("'%s' is not a valid non-Limber integration method." %
                       non_limber_method)

    # Access CCL_ClTracer objects
    clt1 = _cltracer_obj(cltracer1)
    clt2 = _cltracer_obj(cltracer2)

    status = 0
    # Return Cl values, according to whether ell is an array or not
    if isinstance(ell, float) or isinstance(ell, int):
        # Use single-value function
        cl_one, status = lib.angular_cl_vec(
            cosmo, clt1, clt2, l_limber, l_logstep, l_linstep, dchi, dlk, zmin,
            nonlimber_methods[non_limber_method], [ell], 1, status)
        cl = cl_one[0]
    elif isinstance(ell, np.ndarray):
        # Use vectorised function
        cl, status = lib.angular_cl_vec(cosmo, clt1, clt2, l_limber, l_logstep,
                                        l_linstep, dchi, dlk, zmin,
                                        nonlimber_methods[non_limber_method],
                                        ell, ell.size, status)
    else:
        # Use vectorised function
        cl, status = lib.angular_cl_vec(cosmo, clt1, clt2, l_limber, l_logstep,
                                        l_linstep, dchi, dlk, zmin,
                                        nonlimber_methods[non_limber_method],
                                        ell, len(ell), status)
    check(status)
    return cl
Beispiel #14
0
    def __init__(self, Omega_c=None, Omega_b=None, h=None, A_s=None, n_s=None, 
                 Omega_k=0., N_nu_rel=3.046, N_nu_mass=0., m_nu=0.,w0=-1., wa=0.,
                 bcm_log10Mc=math.log10(1.2e14), bcm_etab=0.5, bcm_ks=55., sigma8=None,
                 z_mg=None, df_mg=None):
        """
        Creates a set of cosmological parameters.

        Note:
            Although some arguments default to `None`, they will raise a 
            ValueError inside this function if not specified, so they are not 
            optional.
        
        Args:
            Omega_c (float): Cold dark matter density fraction.
            Omega_b (float): Baryonic matter density fraction.
            h (float): Hubble constant divided by 100 km/s/Mpc; unitless.
            A_s (float): Power spectrum normalization. Optional if sigma8 is 
                         specified.
            n_s (float): Primordial scalar perturbation spectral index.
            Omega_k (float, optional): Curvature density fraction. Defaults to 0.
            N_nu_rel (float, optional): Number of massless neutrinos present. Defaults to 3.046
            N_nu_mass (float, optional): Number of massive neutrinos present. Defaults to 0.
            m_nu (float, optional): total mass in eV of the massive neutrinos present (current must be equal mass). Defaults to 0.
            w0 (float, optional): First order term of dark energy equation of 
                                  state. Defaults to -1.
            wa (float, optional): Second order term of dark energy equation of 
                                  state. Defaults to 0.
            log10Mc (float, optional): One of the parameters of the BCM model.
            etab (float, optional): One of the parameters of the BCM model.
            ks (float, optional): One of the parameters of the BCM model.
            sigma8 (float): Variance of matter density perturbations at 8 Mpc/h
                            scale. Optional if A_s is specified.
            df_mg (:obj: array_like): Perturbations to the GR growth rate as a 
                                      function of redshift, Delta f. Used to 
                                      implement simple modified growth 
                                      scenarios.
            z_mg (:obj: array_like): Array of redshifts corresponding to df_mg.

        """
        # Set current ccl_parameters object to None
        self.parameters = None
        
         # Set nz_mg (no. of redshift bins for modified growth fns.)
        if z_mg is not None and df_mg is not None:
            # Get growth array size and do sanity check
            z_mg = np.atleast_1d(z_mg)
            df_mg = np.atleast_1d(df_mg)
            assert z_mg.size == df_mg.size
            nz_mg = z_mg.size
        else:
            # If one or both of the MG growth arrays are set to zero, disable 
            # all of them
            if z_mg is not None or df_mg is not None:
                raise ValueError("Must specify both z_mg and df_mg.")
            z_mg = None
            df_mg = None
            nz_mg = -1
        
        # Check to make sure specified amplitude parameter is consistent
        if (A_s is None and sigma8 is None) \
        or (A_s is not None and sigma8 is not None):
            raise ValueError("Must set either A_s or sigma8.")
        
        # Set norm_pk to either A_s or sigma8
        norm_pk = A_s if A_s is not None else sigma8
        
        # The C library decides whether A_s or sigma8 was the input parameter 
        # based on value, so we need to make sure this is consistent too
        if norm_pk >= 1e-5 and A_s is not None:
            raise ValueError("A_s must be less than 1e-5.")
            
        if norm_pk < 1e-5 and sigma8 is not None:
            raise ValueError("sigma8 must be greater than 1e-5.")
        
        # Check if any compulsory parameters are not set
        compul = [Omega_c, Omega_b, Omega_k, N_nu_rel, N_nu_mass, m_nu, w0, wa, h, norm_pk, n_s]
        names = ['Omega_c', 'Omega_b', 'Omega_k', 'N_nu_rel', 'N_nu_mass', 'mnu', 'w0', 'wa', 
                 'h', 'norm_pk', 'n_s']
        for nm, item in zip(names, compul):
            if item is None:
                raise ValueError("Necessary parameter '%s' was not set "
                                 "(or set to None)." % nm)
        
        # Create new instance of ccl_parameters object
        status = 0 # Create an internal status variable; needed to check massive neutrino integral.
        if nz_mg == -1:
            # Create ccl_parameters without modified growth
            self.parameters, status \
                = lib.parameters_create( Omega_c, Omega_b, Omega_k, N_nu_rel, 
                                         N_nu_mass, m_nu, w0, wa, h, norm_pk, 
                                         n_s, bcm_log10Mc, bcm_etab, bcm_ks, -1,
                                         None, None, status )
        else:
            # Create ccl_parameters with modified growth arrays
            self.parameters, status \
                = lib.parameters_create_vec( Omega_c, Omega_b, Omega_k, N_nu_rel, 
                                             N_nu_mass, m_nu, w0, wa, h, norm_pk, 
                                             n_s, bcm_log10Mc, bcm_etab, bcm_ks,
                                             z_mg, df_mg, status )
        check(status)