好的,所以我一直在尝试编码一种“天真的”方法来计算复杂形式的标准傅里叶级数的系数。我想我离得很近,但是有一些奇怪的行为。这可能比编程问题更像是一个数学问题,但是我在math.stackexchange上already asked并得到了零答案。这是我的工作代码:

import matplotlib.pyplot as plt
import numpy as np


def coefficients(fn, dx, m, L):
    """
    Calculate the complex form fourier series coefficients for the first M
    waves.

    :param fn: function to sample
    :param dx: sampling frequency
    :param m: number of waves to compute
    :param L: We are solving on the interval [-L, L]
    :return: an array containing M Fourier coefficients c_m
    """

    N = 2*L / dx
    coeffs = np.zeros(m, dtype=np.complex_)
    xk = np.arange(-L, L + dx, dx)

    # Calculate the coefficients for each wave
    for mi in range(m):
        coeffs[mi] = 1/N * sum(fn(xk)*np.exp(-1j * mi * np.pi * xk / L))

    return coeffs


def fourier_graph(range, L, c_coef, function=None, plot=True, err_plot=False):
    """
    Given a range to plot and an array of complex fourier series coefficients,
    this function plots the representation.


    :param range: the x-axis values to plot
    :param c_coef: the complex fourier coefficients, calculated by coefficients()
    :param plot: Default True. Plot the fourier representation
    :param function: For calculating relative error, provide function definition
    :param err_plot: relative error plotted. requires a function to compare solution to
    :return: the fourier series values for the given range
    """
    # Number of coefficients to sum over
    w = len(c_coef)

    # Initialize solution array
    s = np.zeros(len(range))
    for i, ix in enumerate(range):
        for iw in np.arange(w):
            s[i] += c_coef[iw] * np.exp(1j * iw * np.pi * ix / L)

    # If a plot is desired:
    if plot:
        plt.suptitle("Fourier Series Plot")
        plt.xlabel(r"$t$")
        plt.ylabel(r"$f(x)$")
        plt.plot(range, s, label="Fourier Series")

        if err_plot:
            plt.plot(range, function(range), label="Actual Solution")
            plt.legend()

        plt.show()

    # If error plot is desired:
    if err_plot:
        err = abs(function(range) - s) / function(range)
        plt.suptitle("Plot of Relative Error")
        plt.xlabel("Steps")
        plt.ylabel("Relative Error")
        plt.plot(range, err)
        plt.show()

    return s


if __name__ == '__main__':

    # Assuming the interval [-l, l] apply discrete fourier transform:

    # number of waves to sum
    wvs = 50

    # step size for calculating c_m coefficients (trap rule)
    deltax = .025 * np.pi

    # length of interval for Fourier Series is 2*l
    l = 2 * np.pi

    c_m = coefficients(np.exp, deltax, wvs, l)

    # The x range we would like to interpolate function values
    x = np.arange(-l, l, .01)
    sol = fourier_graph(x, l, c_m, np.exp, err_plot=True)


现在,每个系数乘以2 / N的系数。但是,我在我教授的打字笔记中得到了这一和的推导,其中不包括2 / N的因数。当我导出the form myself时,我得出的公式的系数是1 / N,无论我尝试了什么技巧,都不能取消。我在math.stackexchange上问过发生了什么,但没有得到答案。

我确实注意到的是,添加1 / N会实际减少实际解和傅立叶级数之间的差异,但这仍然不正确。所以我尝试了2 / N并获得更好的结果。我真的想弄清楚这一点,所以在尝试学习快速傅立叶变换之前,我可以为基本的傅立叶级数写一个漂亮,干净的算法。

那我在做什么错呢?

最佳答案

假设c_nA_n给出,如mathworld

同上c_n = 1/T \int_{-T/2}^{T/2}f(x)e^{-2ipinx/T}dx

我们可以解析地计算coeffs c_n(这是与梯形积分进行比较的好方法)

k = (1-2in)/2
c_n = 1/(4*pi*k)*(e^{2pik} - e^{-2pik})


因此,您的系数可能正确计算了(两条错误曲线看起来都一样)

现在请注意,重构f时,您将coeff c_0最多添加到c_m

但是重构应该在c_{-m}c_m时进行

因此,您缺少一半的系数。

修正后的系数函数和理论系数

import matplotlib.pyplot as plt
import numpy as np


def coefficients(fn, dx, m, L):
    """
    Calculate the complex form fourier series coefficients for the first M
    waves.

    :param fn: function to sample
    :param dx: sampling frequency
    :param m: number of waves to compute
    :param L: We are solving on the interval [-L, L]
    :return: an array containing M Fourier coefficients c_m
    """

    N = 2*L / dx
    coeffs = np.zeros(m, dtype=np.complex_)
    xk = np.arange(-L, L + dx, dx)

    # Calculate the coefficients for each wave
    for mi in range(m):
        n = mi - m/2
        coeffs[mi] = 1/N * sum(fn(xk)*np.exp(-1j * n * np.pi * xk / L))

    return coeffs


def fourier_graph(range, L, c_coef, ref, function=None, plot=True, err_plot=False):
    """
    Given a range to plot and an array of complex fourier series coefficients,
    this function plots the representation.


    :param range: the x-axis values to plot
    :param c_coef: the complex fourier coefficients, calculated by coefficients()
    :param plot: Default True. Plot the fourier representation
    :param function: For calculating relative error, provide function definition
    :param err_plot: relative error plotted. requires a function to compare solution to
    :return: the fourier series values for the given range
    """
    # Number of coefficients to sum over
    w = len(c_coef)

    # Initialize solution array
    s = np.zeros(len(range), dtype=complex)
    t = np.zeros(len(range), dtype=complex)

    for i, ix in enumerate(range):
        for iw in np.arange(w):
            n = iw - w/2
            s[i] += c_coef[iw] * (np.exp(1j * n * ix * 2 * np.pi / L))
            t[i] += ref[iw] * (np.exp(1j * n * ix * 2 * np.pi / L))

    # If a plot is desired:
    if plot:
        plt.suptitle("Fourier Series Plot")
        plt.xlabel(r"$t$")
        plt.ylabel(r"$f(x)$")
        plt.plot(range, s, label="Fourier Series")

        plt.plot(range, t, label="expected Solution")
        plt.legend()

        if err_plot:
            plt.plot(range, function(range), label="Actual Solution")
            plt.legend()

        plt.show()

    return s

def ref_coefficients(m):
    """
    Calculate the complex form fourier series coefficients for the first M
    waves.

    :param fn: function to sample
    :param dx: sampling frequency
    :param m: number of waves to compute
    :param L: We are solving on the interval [-L, L]
    :return: an array containing M Fourier coefficients c_m
    """

    coeffs = np.zeros(m, dtype=np.complex_)

    # Calculate the coefficients for each wave
    for iw in range(m):
        n = iw - m/2
        k = (1-(1j*n)/2)
        coeffs[iw] = 1/(4*np.pi*k)* (np.exp(2*np.pi*k) - np.exp(-2*np.pi*k))
    return coeffs

if __name__ == '__main__':

    # Assuming the interval [-l, l] apply discrete fourier transform:

    # number of waves to sum
    wvs = 50

    # step size for calculating c_m coefficients (trap rule)
    deltax = .025 * np.pi

    # length of interval for Fourier Series is 2*l
    l = 2 * np.pi

    c_m = coefficients(np.exp, deltax, wvs, l)

    # The x range we would like to interpolate function values
    x = np.arange(-l, l, .01)
    ref = ref_coefficients(wvs)
    sol = fourier_graph(x, 2*l, c_m, ref, np.exp, err_plot=True)

关于python - 寻找傅立叶系数算法,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58808303/

10-12 21:46