【问题标题】:python numpy.convolve to solve convolution integral with limits from 0 to t instead -t to tpython numpy.convolve 解决卷积积分限制从 0 到 t 而不是 -t 到 t
【发布时间】:2013-04-12 06:59:30
【问题描述】:

我有一个卷积积分类型:

为了用数值求解这个积分,我想使用numpy.convolve()。现在,正如您在online help 中看到的那样,卷积是从 -infinity 到 +infinity 正式完成的,这意味着数组完全相互移动以进行评估 - 这不是我需要的。我显然需要确保选择正确的卷积部分 - 您能否确认这是正确的方法,或者告诉我如何正确地做以及(可能更重要)为什么?

res = np.convolve(J_t, dF, mode="full")[:len(dF)]

J_t 是一个分析函数,我可以根据需要评估尽可能多的点,dF 是测量数据的导数。对于这次尝试,我选择len(J_t) = len(dF),因为据我了解,我不需要更多。

感谢您的想法,一如既往,感谢您的帮助!


背景信息(供可能感兴趣的人使用)

这些类型的积分可用于评估物体的粘弹性行为(或电压变化期间电路的响应,如果您对此主题更熟悉的话)。对于粘弹性,J(t) 是蠕变柔量函数,F(t) 可以是随时间变化的偏应变,那么这个积分将产生偏应力。 如果你现在例如有一个 J(t) 的形式:

J_t = lambda p, t: p[0] + p[1]*N.exp(-t/p[2])

p = [J_elastic, J_viscous, tau] 将是“著名的”standard linear solid。积分限制是测量的开始 t_0 = 0 和感兴趣的时刻 t。

【问题讨论】:

    标签: python numpy numeric


    【解决方案1】:

    为了正确起见,我选择了以下两个函数:

    a(t) = t
    b(t) = t**2
    

    很容易进行数学运算并发现它们在您的案例中定义的“卷积”需要 关于价值观:

    c(t) = t**4 / 12
    

    那么让我们试试吧:

    >>> delta = 0.001
    >>> t = np.arange(1000) * delta
    >>> a = t
    >>> b = t**2
    >>> c = np.convolve(a, b) * delta
    >>> d = t**4 / 12
    >>> plt.plot(np.arange(len(c)) * delta, c)
    [<matplotlib.lines.Line2D object at 0x00000000025C37B8>]
    >>> plt.plot(t[::50], d[::50], 'o')
    [<matplotlib.lines.Line2D object at 0x000000000637AB38>]
    >>> plt.show()
    

    因此,通过执行上述操作,如果您的 ab 都具有 n 元素,您将在 c 的第一个 n 元素中获得正确的卷积值。

    不确定下面的解释是否有意义,但它是这样的......如果你认为卷积是沿着 y 轴镜像函数之一,然后沿着 x 轴滑动它并计算积分每个点的乘积,很容易看出,由于在定义区域之外 numpy 将它们视为用零填充,因此您有效地设置了从 0 到 t 的积分区间,因为第一个函数在零以下为零,第二个在 t 之上为零,因为它最初在零之下为零,但已被镜像并向右移动 t。

    【讨论】:

    • 我认为我们的努力没有价值 :(
    【解决方案2】:

    我正在解决同样的问题,并使用一种效率极低但功能正确的算法解决了它:

    def Jfunk(inz,t):
    
        c0 = inz[0]
        c1 = inz[1]
        c2 = inz[2]
    
        J = c0 - c1*np.exp(-t/c2)
    
        return J
    
    def SLS_funk(inz, t, dl_dt):
    
        boltz_int = np.empty(shape=(0,))
    
        for i,v in enumerate(t, start=1):
    
            t_int = t[0:i]
    
            Jarg = v - t[0:i]
    
            J_int = Jfunk(inz,Jarg)
    
            dl_dt_int = dl_dt[0:i]
    
            inter_grand = np.multiply(J_int, dl_dt_int)
    
            boltz_int = np.append(boltz_int, simps (inter_grand, x=t_int) )
    
        return boltz_int
    

    感谢这个问题及其答案,我能够根据上面建议的 numpy 卷积函数实现更好的解决方案。如果 OP 很好奇,我对这两种方法进行了时间比较。

    对于具有 20,000 个时间点的 SLS(三参数 J 函数):

    使用 Numpy 卷积:~0.1 秒

    使用蛮力方法:~7.2 秒

    【讨论】:

      【解决方案3】:

      如果有助于了解对齐方式,请尝试将一对冲动进行卷积。使用 matplotlib(使用 ipython --pylab):

      In [1]: a = numpy.zeros(20)
      In [2]: b = numpy.zeros(20)
      In [3]: a[0] = 1
      In [4]: b[0] = 1
      In [5]: c = numpy.convolve(a, b, mode='full')
      In [6]: plot(c)
      

      您可以从结果图中看到c 中的第一个样本对应于重叠的第一个位置。在这种情况下,只有ab 的第一个样本重叠。其余的都漂浮在未定义的空间中。 numpy.convolve 有效地用零替换了这个未定义的空间,如果你设置了第二个非零值,你可以看到:

      In [9]: b[1] = 1
      In [10]: plot(numpy.convolve(a, b, mode='full'))
      

      在这种情况下,绘图的第一个值是 1,和以前一样(表明 b 的第二个值根本没有贡献)。

      【讨论】:

      • 抱歉,Henry 回复晚了 - 我在工作 atm 的各个方面都在灭火;对它的原因感到不适。
      【解决方案4】:

      过去 2 天我一直在为类似的问题而苦苦挣扎。 OP 可能已经继续,但我仍然在这里展示我的分析。 以下两个来源帮助了我:

      1. 讨论stackoverflow
      2. These notes

      我将考虑从时间 开始在同一时间序列上定义的时间序列数据。 让这两个系列为AB。 他们的(连续)卷积是

      在上面的等式中将 替换为,我们得到np.convolve(A,B) 返回的结果:

      你想要的是

      再次进行相同的替换,我们得到

      这与上面的 相同,因为负索引的A 被外推为零并且对于i > (j + m) B[j - i + m] 为零。

      如果您查看上面引用的注释,您可以发现 对应于我们时间序列的时间。 列表中的下一个值将对应于,依此类推。 因此,正确答案将是

      等于np.convolve(A,B)[0:M],其中M = len(A) = len(B)

      这里记住M*dt = T,其中T是时间数组的最后一个元素。

      免责声明:我不是程序员、数学家或工程师。我不得不在某处使用卷积,并从我自己与这个问题的斗争中得出这些结论。如果有人能指出,我很乐意引用任何有这种分析的书。

      【讨论】:

      • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-25
      • 2019-01-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多