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

偶尔善良 提交于 2019-12-05 08:54:05

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.

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.

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. In case the OP was curious I did a time comparison of the two methods.

For an SLS (three parameter J function) with 20,000 time points:

Using Numpy convolution: ~0.1 seconds

Using Brute Force method: ~7.2 seconds

If if helps to get a feeling for the alignment, try convolving a pair of impulses. With matplotlib (using 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. In this case, only the first samples of a and b overlap. 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:

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!