Вычисление числовой c производной с помощью БПФ - SciPy - PullRequest
0 голосов
/ 30 мая 2020

Я написал следующий код для вычисления приблизительной производной функции с использованием БПФ:

from scipy.fftpack import fft, ifft, dct, idct, dst, idst, fftshift, fftfreq
from numpy import linspace, zeros, array, pi, sin, cos, exp
import matplotlib.pyplot as plt

N = 100
x = linspace(0,2*pi,N)

dx = x[1]-x[0]
y = sin(2*x)+cos(5*x)
dydx = 2*cos(2*x)-5*sin(5*x)

k = fftfreq(N,dx)
k = fftshift(k)

dydx1 = ifft(-k*1j*fft(y)).real

plt.plot(x,dydx,'b',label='Exact value')
plt.plot(x,dydx1,'r',label='Derivative by FFT')
plt.legend()
plt.show()

Однако он дает неожиданные результаты, которые, как я считаю, связаны с неправильным вводом волновых чисел, заданных массив k:

Comparison of the exact and approximate derivative

Я знаю, что разные реализации БПФ по-разному обрабатывают порядок волновых чисел, так что мне здесь не хватает? Будем очень признательны за любые идеи.

1 Ответ

0 голосов
/ 20 июля 2020

Я думаю, что проблема исходит от fftfreq, который не делает то, что вы думаете, как вы можете прочитать в do c.

Кроме того, существует анекдотический отрицательный знак, которого я не понимаю в вашем коде.

О, и, для информации, fftpack.diff делает именно то, что вы хотите достичь.

Вот пример кода, работа:

import numpy as np
import matplotlib.pyplot as plt

from scipy import fftpack

N = 100
L = 2*np.pi
dx = L/N
x = np.linspace(0,L,N)

y = np.sin(2*x)+np.cos(5*x)
dydx = 2*np.cos(2*x)-5*np.sin(5*x)

fhat = np.fft.fft(y)

k = (2*np.pi/L)*np.arange(0,N)
k = fftpack.fftshift(k)

dydx1 = fftpack.ifft(k*1j*fftpack.fft(y)).real

plt.plot(x,dydx,'b',label='Exact value')
plt.plot(x,dydx1,'r',label='Derivative by FFT')
plt.plot(x,fftpack.diff(y),'g',label='Derivative by FFT 2')
plt.legend()
plt.show()
...