Search code examples
python-3.xintegrationinterpolationnumerical-integrationcubic-spline

Numerical integration of convolution of interpolating function


I have x and y arrays of data points that I have used to create an interpolating function func_spline as shown below.

 import numpy
 from numpy import loadtxt
 from scipy.interpolate import *
 x_given = numpy.arange(1,21400,21400/25000)
 y_given  = loadtxt("Yvalues.txt", comments="#", delimiter=",", unpack=False)

 func_spline = interp1d(x_given,y_given, kind='cubic')
 y_is = func_spline(x_given)

 def alphasinterp(ktsq):
 return func_spline(ktsq)

 import sympy as sp
 import scipy.integrate.quadrature as sciquad

 result = sciquad(alphasinterp,0,21400)
 print(result)

The code successfully does the integration however I would like to amend the code to allow integrations of the form

   result = sciquad(alphasinterp*f1,0,21400)

where f1 is any function (function of ktsq and other variables that do not partake in integration) that I convolute with alphasinterp in the integration. E.g for a particular f1 I obtain the error

TypeError: unsupported operand type(s) for *: 'function' and 'FunctionClass'

How to resolve? Thanks! (as can be seen from the code, the y array contains around 21000 points so a copy and paste of my data here is probably not permissible or advisable. I am happy to upload the text file 'Yvalues.txt' containing the data but I don't see a way to do this yet)


Solution

  • You have to define the product of the two functions as another function which you can use in the integration. So in your code it would look like:

    def alphasinterp(ktsq):
        return func_spline(ktsq)
    
    def f1(ktsq, a1, a2):
        return a1*ktsq+a2# some value
    
    def f_product(ktsq, a1, a2):
        return alphasinterp(ktsq)*f1(ktsq, a1, a2)
    
    def integrated_f(a1, a2):
        return sciquad(f_product,0,21400, args=(a1, a2))
    
    a1=5.0 # just some numbers
    a2=3.2
    result = integrated_f(a1, a2)
    

    If you want to compute the convolution you have to take this a step further. With (f*g)(x)=\int f(t)g(x-t) dt it would be something like

    def conv_without_int(t, x):
        return alphasinterp(t)*f1(x-t)
    def convolution(x):
        return sciquad(conv_without_int,0,21400, args=(x))
    

    You could shorten that by using the lambda notation