Reputation: 133
I am trying to solve numerically the following integral using NumPy and quad
from scipy.integrate
. The code is kinda working, but I get spurious notches in the resulting data:
Anybody has an idea why are they occurring and how to get the correct smooth result?
Here is the original code in Python:
#!/usr/bin/env python
import numpy as np
from scipy.integrate import quad
import matplotlib.pyplot as pl
numpts = 300
t_min = -4
t_max = 100
tt = np.linspace(t_min, t_max, numpts)
mean = 0. # ps
fwhm = .05 # ps
def gaussian(x, mean, fwhm):
return 1. / np.sqrt(np.pi) / fwhm * np.exp(-1. * (x - mean)**2 / fwhm**2)
def integrand(t_, t, mean, fwhm):
denum = np.sqrt(t - t_)
r = gaussian(t_, mean, fwhm) / denum
return r
def integrate(t, mean, fwhm, tmin):
return quad(integrand, tmin, t - 1e-9, args=(t, mean, fwhm))[0]
if __name__ == '__main__':
vec_int = np.vectorize(integrate)
y = vec_int(tt, mean, fwhm, tt.min())
fig = pl.figure()
ax = fig.add_subplot(111)
ax.plot(tt, y, 'bo-', mec='none')
ax.set_xlim(-5, 101)
pl.show()
Upvotes: 0
Views: 177
Reputation: 133
So I solved my problem by switching to the mpmath
library and its own integration quad
using the tanh-sinh
method. I also had to split the integral so that the data is monotonous. The output looks like this:
I am not 100% sure why this works, but it may have to do with the numeric precision and the behaviour of the integration method.
Here's the working code:
#!/usr/bin/env python
import numpy as np
import matplotlib.pyplot as pl
import mpmath as mp
numpts = 3000
t_min = -4
t_max = 100
tt = np.linspace(t_min, t_max, numpts)
mean = mp.mpf('0') # ps
fwhm = mp.mpf('.05') # ps
def gaussian(x, mean, fwhm):
return 1. / mp.sqrt(np.pi) / fwhm * mp.exp(-1. * (x - mean)**2 / fwhm**2)
def integrand(t_, t, mean, fwhm):
denum = np.sqrt(t - t_)
g = gaussian(t_, mean, fwhm)
r = g / denum
return r
def integrate(t, mean, fwhm, tmin):
t = mp.mpf(t)
tmin = mp.mpf(tmin)
# split the integral because it can only handle smooth functions
res = mp.quad(lambda t_: integrand(t_, t, mean, fwhm),
[tmin, mean],
method='tanh-sinh') + \
mp.quad(lambda t_: integrand(t_, t, mean, fwhm),
[mean, t],
method='tanh-sinh')
ans = res
return ans
if __name__ == '__main__':
mp.mp.dps = 15
mp.mp.pretty = True
vec_int = np.vectorize(integrate)
y = vec_int(tt, mean, fwhm, tt.min())
fig = pl.figure()
ax = fig.add_subplot(111)
# make sure we plot the real part
ax.plot(tt, map(mp.re, y), 'bo-', mec='none')
ax.set_xlim(-5, 101)
pl.show()
Upvotes: 0
Reputation: 26090
My suspicion would be that an integrable singularity is messing up the inner workings of quad(pack). I'd then try (in this order): use weights="cauchy" in quad; add and subtract the singularity; look at ways of telling quadpack that the integral has a difficult point.
Upvotes: 1