Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/317.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 使用叠加模拟球体周围的扬声器-需要提高速度_Python_Numpy_Vector_Polar Coordinates_Cartesian Coordinates - Fatal编程技术网

Python 使用叠加模拟球体周围的扬声器-需要提高速度

Python 使用叠加模拟球体周围的扬声器-需要提高速度,python,numpy,vector,polar-coordinates,cartesian-coordinates,Python,Numpy,Vector,Polar Coordinates,Cartesian Coordinates,注意:发布后速度大幅提高,请参见底部的编辑。 我有一些在循环上运行的代码,我很确定应该有一种更快的方法来实现它。输出数组的大小最终相当大,因此当我尝试使其他数组与输出数组的大小相同时,我会很快耗尽内存 我正在模拟许多扬声器围绕一个球体放置,所有扬声器都指向中心。我有一个单一扬声器的模拟,我想利用叠加原理利用这个单一模拟。基本上,我想总结单传感器模拟的旋转副本,以得到最终结果 我有一个圆柱坐标系下的轴对称声压数据模拟(“polar_coord_r”,“polar_coord_z”)。模拟得到的压力

注意:发布后速度大幅提高,请参见底部的编辑。

我有一些在循环上运行的代码,我很确定应该有一种更快的方法来实现它。输出数组的大小最终相当大,因此当我尝试使其他数组与输出数组的大小相同时,我会很快耗尽内存

我正在模拟许多扬声器围绕一个球体放置,所有扬声器都指向中心。我有一个单一扬声器的模拟,我想利用叠加原理利用这个单一模拟。基本上,我想总结单传感器模拟的旋转副本,以得到最终结果

我有一个圆柱坐标系下的轴对称声压数据模拟(“polar_coord_r”,“polar_coord_z”)。模拟得到的压力场在每个R和Z值处都是唯一的,完全由2D阵列(“P_real_RZ”)描述

我想将这个压力场的多个旋转副本相加到一个三维笛卡尔输出阵列上。每个副本都会旋转到球体上的不同位置。目前,我用一个x,y,z点来指定旋转,因为它允许我做向量数学(球坐标不允许我这么优雅地做)。输出阵列相当大(770×770×804)

我有一些工作代码,可以从扬声器的单个副本(“传感器”)获得输出。每个片段大约需要12秒,因此添加每个新扬声器需要两个多小时!!我想要一打左右的演讲者的副本,这样会花很长时间

该代码获取一个具有常数X的切片,并计算该切片中每个位置的R和Z位置。“r_距离”是一个二维数组,包含从原点和点(“点”)之间通过的直线的径向距离。相似性,“z_距离”是一个二维数组,包含沿同一直线的距离

为了得到切片的压力,我找到了与计算的r距离和z距离最匹配的“极坐标r”和“极坐标z”的指数。我使用这些指数来找出压力值(从P_ureal_urz)到输出中的每个值

一些定义:

  • xxyyzz是通过输出体积描述切片的一维数组
  • XXXYYYZZZ是由numpy.meshgrid生成的三维阵列
  • 是定义扬声器旋转方向的点。基本上它只是扬声器中心的一个位置向量
  • P_real_RZ是一个2D数组,指定每个唯一R和Z值处的实际压力
  • polar_-coord_-rpolar_-coord_-z是1D数组,定义了r和z的唯一值,并在其上定义了P_-real_-RZ
  • 电流传感器(到目前为止,本代码中仅表示了一个传感器)是当前点的压力值计算机
  • 输出是将多个扬声器/传感器相加的结果
任何加速此代码的建议都将不胜感激

工作循环:

for i, x in enumerate(xx):
    # Creates a unit vector from origin to a point
    vector = normalize(point)

    # Create a slice of the cartesian space with constant X
    xyz_slice = np.array([x*np.ones_like(XXX[i,:,:]), YYY[i,:,:], ZZZ[i,:,:]])

    # Projects the position vector of each point of the slice onto the unit vector.
    projection = np.array(list(map(np.dot, xyz_slice, vector )))

    # Normalizes the projection which results in the Z distance along the line passing through the point
    #z_distance = np.apply_along_axis(np.linalg.norm, 0, projection) # this is the slow bit
    z_distance = np.linalg.norm(projection, axis=0) # I'm an idiot

    # Uses vector math to determine the distance from the line
    # Each point in the XYZ slice is the sum of vector along the line and the vector away from the line (radial vector).
    # By extension the position of the xyz point minus the projection of the point against the unit vector, results in the radial vector
    # Norm the radial vector to get the R value for everywhere in the slice
    #r_distance = np.apply_along_axis(np.linalg.norm, 0, xyz_slice - projection) # this is the slow bit
    r_distance = np.linalg.norm(xyz_slice - projection, axis=0) # I'm an idiot

    # Map the pressure data to each point in the slice using the R and Z distance with the RZ pressure slice.
    # look for a more efficient way to do this perhaps. currently takes about 12 seconds per slice
    r_indices = r_map_v(r_distance) # 1.3 seconds by itself
    z_indices = z_map_v(z_distance)
    r_indices[r_indices>384] = 384 # find and remove indicies above the max for r_distance
    z_indices[r_indices>803] = 803
    current_transducer[i,:,:] = P_real_RZ[z_indices, r_indices]

    # Sum the mapped pressure data into the output.
    output += current_transducer
我还尝试以三维笛卡尔阵列的形式处理模拟数据。这是来自模拟的所有x、y和z值的压力数据,其大小与输出值相同。我可以沿一个方向旋转此3D阵列(对于布置在球体上的扬声器,不需要两次旋转)。这占用了Waaay太多的内存,速度仍然非常缓慢。使用这种方法,我最终会出现内存错误

编辑:我找到了一种稍微简单一点的方法,但速度仍然很慢。我已经更新了上面的代码,这样就不再有嵌套循环了

我运行了一个测线分析器,到目前为止,最慢的两行是包含np.apply_沿_轴()的两行。恐怕我得重新考虑我是如何做到这一点的


最终编辑:我最初有一个嵌套循环,我认为这是问题所在。我不知道是什么让我觉得我需要用linalg.norm沿_轴应用_。无论如何,这就是问题所在

我还没有找到所有优化此代码的方法,但这个问题突然出现在我面前:“我运行了一个行分析器,到目前为止最慢的行是包含np.apply_沿_轴()的两行。”
np.linalg.norm
接受一个
axis
参数。你可以换线

z_distance = np.apply_along_axis(np.linalg.norm, 0, projection)

(同样地,对于
np.application\u沿_轴
np.linalg.norm
)的其他用法也是如此)。
这应该会稍微提高性能。

输出+=电流传感器应该在环路外,不是吗?是的,你是对的。当我需要在每个点上写一个循环时,我就把它放在那里了。@Dyslexic Username检查出来
z_distance = np.linalg.norm(projection, axis=0)