简体   繁体   English

python numpy.convolve 求解从 0 到 t 的卷积积分,而不是 -t 到 t

[英]python numpy.convolve to solve convolution integral with limits from 0 to t instead -t to t

I have a convolution integral of the type:我有一个类型的卷积积分:

卷积积分\int_0^t

To solve this integral numerically, I would like to use numpy.convolve() .为了在数值上求解这个积分,我想使用numpy.convolve() Now, as you can see in the online help , the convolution is formally done from -infinity to +infinity meaning that the arrays are moved along each other completely for evaluation - which is not what I need.现在,正如您在联机帮助中看到的那样,卷积正式从 -infinity 到 +infinity 完成,这意味着 arrays 完全相互移动以进行评估 - 这不是我需要的。 I obviously need to be sure to pick the correct part of the convolution - can you confirm that this is the right way to do it or alternatively tell me how to do it right and (maybe even more important) why?我显然需要确保选择卷积的正确部分——你能确认这是正确的方法吗,或者告诉我如何正确地做它以及(可能更重要)为什么?

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

J_t is an analytical function and I can evaluate as many points as I need, dF are derivatives of measurement data. J_t 是一个分析 function,我可以根据需要评估尽可能多的点,dF 是测量数据的导数。 for this attempt I choose len(J_t) = len(dF) because from my understanding I do not need more.对于这次尝试,我选择len(J_t) = len(dF)因为根据我的理解我不需要更多。

Thank you for your thoughts, as always, I appreciate your help!一如既往地感谢您的想法,感谢您的帮助!


Background information (for those who might be interested)背景信息(对于那些可能感兴趣的人)

These type of integrals can be used to evaluate viscoelastic behaviour of bodies (or the response of an electric circuit during change of voltage, if you feel more familiar on this topic).这些类型的积分可用于评估物体的粘弹性行为(或电路在电压变化期间的响应,如果您对这个主题更熟悉的话)。 For viscoelasticity, J(t) is the creep compliance function and F(t) can be the deviatoric strains over time, then this integral would yield the deviatoric stresses.对于粘弹性,J(t) 是蠕变柔量 function,F(t) 可以是随时间变化的偏应变,则此积分将产生偏应力。 If you now eg have a J(t) of the form:例如,如果您现在有一个 J(t) 的形式:

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

with p = [J_elastic, J_viscous, tau] this would be the "famous" standard linear solid . p = [J_elastic, J_viscous, tau]这将是“著名的”标准线性固体 The integral limits are the start of the measurement t_0 = 0 and the moment of interest, t.积分限制是测量的开始 t_0 = 0 和感兴趣的时刻 t。

To get it right, I have chosen the following two functions: 为了做到这一点,我选择了以下两个功能:

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

It is easy to do the math and find that their "convolution" as defined in your case, takes on the values: 很容易做数学并发现它们在你的情况下定义的“卷积”具有以下值:

c(t) = t**4 / 12

So lets try them out: 所以让我们尝试一下:

>>> 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()

在此输入图像描述

So by doing the above, if both your a and b have n elements, you get the right convolution values in the first n elements of c . 因此,通过执行上述操作,如果ab都有n元素,则在c的前n元素中得到正确的卷积值。

Not sure if the following explanation will make any sense, but here it goes... If you think of convolution as mirroring one of the functions along the y-axis, then sliding it along the x axis and computing the integral of the product at each point, it is easy to see how, since outside of the area of definition numpy takes them as if padded with zeros, you are effectively setting an integration interval from 0 to t, since the first function is zero below zero, and the second is zero above t, since it originally was zero below zero, but has been mirrored and moved t to the right. 不确定下面的解释是否有意义,但在这里......如果你认为卷积是沿着y轴镜像其中一个函数,那么沿着x轴滑动它并计算产品的积分每一点,很容易看出如何,因为在定义numpy区域之外将它们视为用零填充,你有效地设置从0到t的积分间隔,​​因为第一个函数是零以下零,而第二个函数是零是零以上,因为它原来是零以下零,但已被镜像并向右移动t。

I was tackling this same problem and solved it using a highly inefficient but functionally correct algorithm: 我正在解决同样的问题并使用效率极低但功能正确的算法解决它:

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

Thanks to this question and its answers, I was able to implement a much better solution based on the numpy convolution function suggested above. 感谢这个问题及其答案,我能够基于上面提出的numpy卷积函数实现更好的解决方案。 In case the OP was curious I did a time comparison of the two methods. 如果OP很好奇,我会对这两种方法进行时间比较。

For an SLS (three parameter J function) with 20,000 time points: 对于具有20,000个时间点的SLS(三参数J函数):

Using Numpy convolution: ~0.1 seconds 使用Numpy卷积:约0.1秒

Using Brute Force method: ~7.2 seconds 使用蛮力方法:~7.2秒

If if helps to get a feeling for the alignment, try convolving a pair of impulses. 如果有助于获得对齐的感觉,请尝试卷积一对冲动。 With matplotlib (using ipython --pylab ): 使用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)

You can see from the resultant plot that the first sample in c corresponds to the first position of overlap. 您可以从结果图中看到c中的第一个样本对应于第一个重叠位置。 In this case, only the first samples of a and b overlap. 在这种情况下, 只有 ab的第一个样本重叠。 All the rest are floating in undefined space. 所有其余的都漂浮在未定义的空间中。 numpy.convolve effectively replaces this undefined space with zeros, which you can see if you set a second non-zero value: numpy.convolve用零有效地替换了这个未定义的空间,如果你设置了第二个非零值,你可以看到它:

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

In this case, the first value of the plot is 1, as before (showing that the second value of b is not contributing at all). 在这种情况下,绘图的第一个值是1,与之前一样(显示b的第二个值根本没有贡献)。

I have been struggling with similar question for past 2 days.在过去的两天里,我一直在为类似的问题而苦苦挣扎。 The OP may have moved on, but I am still presenting my analysis here. OP 可能已经继续,但我仍然在这里展示我的分析。 Following two sources helped me:以下两个来源帮助了我:

  1. Discussion on stackoverflow关于stackoverflow的讨论
  2. These notes这些笔记

I will consider time-series data defined on the same time series starting from time我将考虑从时间开始在同一时间序列上定义的时间序列数据. . Let the two series be A and B .设这两个系列为AB Their (continuous) convolution is他们的(连续)卷积是

Substituting代入with in the above equation we get what np.convolve(A,B) returns:在上面的等式中,我们得到np.convolve(A,B)返回的内容:

What you want is你想要的是

Again making the same substitution, we get再次进行相同的替换,我们得到

which is same as这与above because A for negative indices is extrapolated to zero and for i > ( j + m ) B[j - i + m] is zero.上面是因为负指数的A外推为零,而i > ( j + m ) B[j - i + m]为零。

If you look at the notes cited above, you can figure out that如果您查看上面引用的注释,您会发现corresponds to time对应时间for our time series.对于我们的时间序列。 The next value in the list will correspond to列表中的下一个值将对应于 and so on.等等。 Therefore, the correct answer will be因此,正确答案将是

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

Here keep in mind that M*dt = T , where T is the last element of time array.请记住M*dt = T ,其中T是时间数组的最后一个元素。

Disclaimer: I am not a programmer, mathematician or an engineer.免责声明:我不是程序员、数学家或工程师。 I had to use convolution somewhere and have derived these conclusions from my own struggle with the problem.我不得不在某个地方使用卷积,并从我自己与问题的斗争中得出这些结论。 I will be happy to cite any book which has this analysis if someone can point it out.如果有人能指出,我很乐意引用任何有这种分析的书。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM