Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 定义cython类内函数的参数和cython中的快速积分计算_Python_Arrays_Numpy_Scipy_Cython - Fatal编程技术网

Python 定义cython类内函数的参数和cython中的快速积分计算

Python 定义cython类内函数的参数和cython中的快速积分计算,python,arrays,numpy,scipy,cython,Python,Arrays,Numpy,Scipy,Cython,我是cython的新手,正在尝试将python类转换为cython。我不知道应该如何在实例Da中定义参数z,使其既能处理numpy.array又能处理单个float数字 cdef class Cosmology(object): cdef double omega_m, omega_lam, omega_c def __init__(self,double omega_m=0.3,double omega_lam=0.7): self.omega_m = o

我是cython的新手,正在尝试将python类转换为cython。我不知道应该如何在实例Da中定义参数
z
,使其既能处理numpy.array又能处理单个
float
数字

cdef class Cosmology(object):
    cdef double omega_m, omega_lam, omega_c  

    def __init__(self,double omega_m=0.3,double omega_lam=0.7):
        self.omega_m = omega_m
        self.omega_lam = omega_lam
        self.omega_c = (1. - omega_m - omega_lam)


    cpdef double a(self, double z):
        cdef double a
        return 1./(1+z)

    cpdef double E(self, double a):
        cdef double E
        return (self.omega_m*a**(-3) + self.omega_c*a**(-2) + self.omega_lam)**0.5

    cpdef double __angKernel(self, double x):
        cdef __angKernel:
        """Integration kernel"""
        return self.E(x**-1)**-1

    cpdef double Da(self, double z, double z_ref=0):
        cdef double Da
        if isinstance(z, np.ndarray):
            da = np.zeros_like(z)
            for i in range(len(da)):
                da[i] = self.Da(z[i], z_ref)
            return da
        else:
            if z < 0:
                raise ValueError("Redshift z must not be negative")
            if z < z_ref:
                raise ValueError("Redshift z must not be smaller than the reference redshift")

            d = integrate.quad(self.__angKernel, z_ref+1, z+1,epsrel=1.e-6, epsabs=1.e-12)
            rk = (abs(self.omega_c))**0.5
            if (rk*d[0] > 0.01):
                if self.omega_c > 0:
                    d[0] = sinh(rk*d[0])/rk
                if self.omega_c < 0:
                    d[0] = sin(rk*d[0])/rk
            return d[0]/(1+z)

如果我想将数组传递给
halo_positions
实例,这是正确的方法吗?

如果您的类被定义为
cdef
,则只能在Cython中(而不是在Python中)访问它,这使得对类方法使用
cpdef
def
是不必要的,也没有效率的。您可以将它们全部转换为
cdef

当您告诉
z
double
时,它将只接受
double
。如果希望此参数具有两种不同的类型,则应保持其类型未声明,但当
z
ndarray
时,这将直接影响循环性能

或者,您可以使用
double*
并传递它的大小,当大小为
1
时,它是一个double,当大小为
>1
数组时。其职能是:

cdef double Da(self, int size, double *z, double z_ref=0):
    if size>1:
        da = np.zeros(size)
        for i in range(size):
            da[i] = self.Da(1, &z[i], z_ref)
        return da
    else:
        if z[0] < 0:
            raise ValueError("Redshift z must not be negative")
        if z[0] < z_ref:
            raise ValueError("Redshift z must not be smaller than the reference redshift")

        d = integrate.quad(self.__angKernel, z_ref+1, z[0]+1,
                           epsrel=1.e-6, epsabs=1.e-12)
        rk = (abs(self.omega_c))**0.5
        if (rk*d[0] > 0.01):
            if self.omega_c > 0:
                d[0] = sinh(rk*d[0])/rk
            if self.omega_c < 0:
                d[0] = sin(rk*d[0])/rk
        return d[0]/(1+z[0])
cdef double Da(self,int size,double*z,double z_ref=0):
如果大小>1:
da=np.零(尺寸)
对于范围内的i(尺寸):
da[i]=self.da(1,&z[i],z_-ref)
返回da
其他:
如果z[0]<0:
提升值错误(“红移z不得为负”)
如果z[0]0.01):
如果self.omega_c>0:
d[0]=sinh(rk*d[0])/rk
如果self.omega_c<0:
d[0]=sin(rk*d[0])/rk
返回d[0]/(1+z[0])

所以我假设我必须声明
double rk
,那么
epsrel
epsabs
呢。我的另一个问题是scipy积分是否可以用cython中的等价物代替?因为到目前为止,我认为这就是我的代码速度非常低的原因。@Dalek你实际上必须回答问题,第一个问题在这个答案中被注释了。对于第二个,如果我理解的话,你想积分一个向量值函数吗?()@Dalek
epsrel
epsabs
是数值积分误差的公差,这些值越低,数值积分就越精确……实际上
z
实际上是一个
1D
数组,形状为(1500,)并且我需要在
范围的循环中对该数组的每个组件进行积分(24000)
,因此我的代码速度非常低,因此我想将其转换为cython。@Dalek我有一个使用梯形规则或N阶多项式规则执行向量值积分的实现,
cdef double Da(self, int size, double *z, double z_ref=0):
    if size>1:
        da = np.zeros(size)
        for i in range(size):
            da[i] = self.Da(1, &z[i], z_ref)
        return da
    else:
        if z[0] < 0:
            raise ValueError("Redshift z must not be negative")
        if z[0] < z_ref:
            raise ValueError("Redshift z must not be smaller than the reference redshift")

        d = integrate.quad(self.__angKernel, z_ref+1, z[0]+1,
                           epsrel=1.e-6, epsabs=1.e-12)
        rk = (abs(self.omega_c))**0.5
        if (rk*d[0] > 0.01):
            if self.omega_c > 0:
                d[0] = sinh(rk*d[0])/rk
            if self.omega_c < 0:
                d[0] = sin(rk*d[0])/rk
        return d[0]/(1+z[0])