Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.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 Scipy和x27的性能问题;s解_-bvp与耦合微分方程_Python_Performance_Matlab_Scipy_Differential Equations - Fatal编程技术网

Python Scipy和x27的性能问题;s解_-bvp与耦合微分方程

Python Scipy和x27的性能问题;s解_-bvp与耦合微分方程,python,performance,matlab,scipy,differential-equations,Python,Performance,Matlab,Scipy,Differential Equations,在Python 3.8.3中实现下面的耦合微分方程(也称为单模耦合方程)时,我遇到了一个问题。至于解算器,我正在使用Scipy的函数Scipy.integrate.solve_bvp,其文档可以阅读。我想求解复域中的方程,对于不同的传播轴值(z)和不同的β值(beta_分析) 问题在于,与使用函数bvp4c、bvpnit和bvpset在Matlab中的等效实现相比,它的速度非常慢(无法管理)。对两次执行的前几次迭代进行评估后,它们返回相同的结果,除了生成的网格(在Scipy情况下要大得多)。网格

在Python 3.8.3中实现下面的耦合微分方程(也称为单模耦合方程)时,我遇到了一个问题。至于解算器,我正在使用Scipy的函数
Scipy.integrate.solve_bvp
,其文档可以阅读。我想求解复域中的方程,对于不同的传播轴值(
z
)和不同的β值(
beta_分析

问题在于,与使用函数
bvp4c
bvpnit
bvpset
在Matlab中的等效实现相比,它的速度非常慢(无法管理)。对两次执行的前几次迭代进行评估后,它们返回相同的结果,除了生成的网格(在Scipy情况下要大得多)。网格有时甚至饱和到最大值

要求解的方程以及边界条件函数如下所示

import h5py
import numpy as np
from scipy import integrate
    
def coupling_equation(z_mesh, a):
    ka_z = k    # Global
    z_a = z     # Global
    a_p = np.empty_like(a).astype(complex)

    for idx, z_i in enumerate(z_mesh): 
        beta_zf_i = np.interp(z_i, z_a, beta_zf)    # Get beta at the desired point of the mesh
        ka_z_i = np.interp(z_i, z_a, ka_z)          # Get ka at the desired point of the mesh

        coupling_matrix = np.empty((2, 2), complex)
        coupling_matrix[0] = [-1j * beta_zf_i, ka_z_i]
        coupling_matrix[1] = [ka_z_i, 1j * beta_zf_i]

        a_p[:, idx] = np.matmul(coupling_matrix, a[:, idx])    # Solve the coupling matrix

    return a_p

def boundary_conditions(a_a, a_b):
    return np.hstack(((a_a[0]-1), a_b[1]))
此外,考虑到
solve_bpv
函数的
fun
参数必须是可调用的,因此我无法找到将
k
z
beta_zf
作为函数
耦合方程
的参数传递的方法。我的方法是定义一些全局变量,但如果有更好的解决方案,我也将非常感谢在这方面的任何帮助

我试图编写的分析函数是:

def analysis(k, z, beta_analysis, max_mesh):
    s11_analysis = np.empty_like(beta_analysis, dtype=complex)
    s21_analysis = np.empty_like(beta_analysis, dtype=complex)
    
    initial_mesh = np.linspace(z[0], z[-1], 10)    # Initial mesh of 10 samples along L
    mesh = initial_mesh
    
    # a_init must be complex in order to solve the problem in a complex domain
    a_init = np.vstack((np.ones(np.size(initial_mesh)).astype(complex), 
                        np.zeros(np.size(initial_mesh)).astype(complex)))
    
    for idx, beta in enumerate(beta_analysis):
        print(f"Iteration {idx}: beta_analysis = {beta}")
        global beta_zf 
        beta_zf = beta * np.ones(len(z))    # Global variable so as to use it in coupling_equation(x, y)
        
        a = integrate.solve_bvp(fun=coupling_equation, 
                                bc=boundary_conditions, 
                                x=mesh, 
                                y=a_init, 
                                max_nodes=max_mesh,
                                verbose=1)
#         mesh = a.x      # Mesh for the next iteration
#         a_init = a.y    # Initial guess for the next iteration, corresponding to the current solution
        s11_analysis[idx] = a.y[1][0]
        s21_analysis[idx] = a.y[0][-1]
    return s11_analysis, s21_analysis
我怀疑问题与传递给不同迭代的初始猜测有关(请参见
分析
函数中循环内的注释行)。我尝试将迭代的解设置为以下内容的初始猜测(这必须减少解算器所需的时间),但它甚至更慢,我不理解这一点。也许我错过了什么,因为这是我第一次尝试解微分方程

用于执行的参数如下所示:

f2 = h5py.File(r'path/to/file', 'r')
k = np.array(f2['k']).squeeze()
z = np.array(f2['z']).squeeze()
f2.close()

analysis_points = 501
max_mesh = 1e6 

beta_0 = 3e2; 
beta_low = 0;       # Lower value of the frequency for the analysis
beta_up = beta_0;   # Upper value of the frequency for the analysis
beta_analysis = np.linspace(beta_low, beta_up, analysis_points);

s11_analysis, s21_analysis = analysis(k, z, beta_analysis, max_mesh)
关于如何提高这些功能的性能有什么想法吗?提前谢谢大家,如果问题没有很好地表述,我接受任何有关这方面的建议

编辑:添加了一些有关问题性能和大小的信息

  • 在实践中,我找不到一个关系来决定调用耦合方程的次数。这必须是解算器的内部操作问题。我通过打印一行来检查一次迭代中的呼叫次数,它发生在133个地方(这是最快的一次)。这必须乘以beta的迭代次数。对于分析的一个,解算器返回以下内容:
在11次迭代中求解,节点数529。 最大相对残留量:9.99e-04 最大边界剩余:0.00e+00

  • a
    z_网格
    的形状是相关的,因为z_网格是一个向量,其长度与网格的大小相对应,解算器每次调用
    耦合_方程时都会重新计算。假设
    a
    包含
    z_网格
    每个点处的渐进波和回归波的振幅,
    a
    的形状为
    (2,len(z_网格))
  • 就计算时间而言,我只用Python在大约2小时内完成了19次迭代。在这种情况下,初始迭代速度更快,但随着网格的增长,迭代开始需要更多的时间,直到网格饱和到允许的最大值为止。我认为这是因为该点的输入耦合系数的值,因为在
    beta_分析
    中没有执行循环时也会发生这种情况(只需使用
    solve_bvp
    函数来计算beta的中间值)。相反,Matlab设法在大约6分钟内返回整个问题的解决方案。如果我将上一次迭代的结果作为
    initial\u guess
    (在
    analysis
    函数中的注释行)传递,网格溢出速度会更快,并且不可能获得超过两次迭代的结果

基于半随机输入,我们可以看到有时会达到
max\u mesh
。这意味着
coupling\u方程
可以用相当大的
z\u mesh
a
数组调用。问题是
coupling\u方程
包含一个缓慢的纯Python循环在每个列上迭代使用Numpy矢量化可以大大加快计算速度。以下是一个实现:

def耦合方程快(z网格,a):
ka_z=k#全局
z_a=z#全局
a_p=np.empty(a.shape,dtype=np.complex128)
beta_zf_i=np.interp(z_网格,z_a,beta_zf)#在网格的所需点获取beta
ka_z_i=np.interp(z_网格,z_a,ka_z)#在网格的所需点处获取ka
#快速手动矩阵乘法
a_p[0]=(-1j*beta_zf_i)*a[0]+ka_z_i*a[1]
a_p[1]=ka_z_i*a[0]+(1j*beta_zf_i)*a[1]
退
与原始实现相比,此代码提供了类似的半随机输入输出,但在我的机器上大约快了20倍


此外,我不知道您输入的
max\u mesh
是否碰巧也很大,即使这是正常的/有意的。降低
max\u mesh
的值以进一步减少执行时间可能是有意义的。

在实践中调用了多少次
耦合方程
z_网格
a
耦合_方程
中?整个计算需要多少时间?(请直接在问题中给出答案)@JérômeRichard谢谢你的快速评论!我编辑了这篇文章,以便添加你需要的信息。我希望这对你有所帮助