【问题标题】:Adding up all the values for each frequency from FFTW将 FFTW 中每个频率的所有值相加
【发布时间】:2016-07-28 05:16:48
【问题描述】:

我已经使用 FFTW (fftw_plan_dft_r2c_3d) 运行了一个 3D 傅里叶变换,我想总结每个频率的变换值(对数),包括实际未存储在输出数组(我知道大小是Nx x Ny x (Nz/2 + 1))。如何在不重复计算的情况下做到这一点?

【问题讨论】:

    标签: fft fftw


    【解决方案1】:

    很好的问题。抱歉我的回答有点啰嗦,我想确保我没有犯任何错误。来了——

    如果您对所有“切片”进行双重计算,复数到复数 3D FFT 的对数幅度之和将等于实数到复数 3D FFT 的对数幅度之和(最后一个维度的)后者缺少前者。

    • 如果Nz 是偶数,则意味着重复计算除第一个和最后一个切片之外的所有切片。
    • 如果 Nz 是奇数,则重复计算除第一个以外的所有切片。

    (这是因为偶数长度的实数到复数 DFT 包括 -π 弧度角频率(对应于 -1 的相量),而奇数长度的 DFT 则缺少它。我不记得这种模式, 所以我总是在单位圆周围画出 N=4 vs N=3 相量来提醒自己奇数或偶数是否包含-π弧度。)

    这是使用 Numpy/Python 对该想法的实验验证,我相信它的实数到复数 FFT 表示法与 FFTW 相匹配:通过Ny = 20Nz = 8 实数数组生成一个Nx = 10。计算其复数到复数 3D FFT(产生 Nx 乘 Ny 乘 Nz 复数数组)其实数到复数 3D FFT(产生 Nx 乘 Ny 乘 (Nz/2+1) 复数)大批)。如果您重复计算除第一个和最后一个切片之外的所有切片,请验证前者的对数大小之和与后者的对数大小之和 相同,因为 @ 987654328@是偶数。

    代码:

    import numpy as np
    import numpy.fft as fft
    
    Nx = 10
    Ny = 20
    Nz = 8
    
    x = np.random.randn(Nx, Ny, Nz)
    
    Xf = fft.fftn(x)
    Xfr = fft.rfftn(x)
    
    energyProduct1 = np.log10(np.abs(Xf)).sum()
    
    lastSlice = -1 if Nz % 2 is 0 else None
    energyProduct2 = np.log10(np.abs(np.dstack((Xfr, Xfr[:, :, 1:lastSlice])))).sum()
    
    print('Difference: %g' % (energyProduct1 - energyProduct2))
    # Difference: -4.54747e-13
    

    如果你用奇数Nz 重新运行它,你会看到复数到复数和实数到复数之间的差异保持在 0 的机器精度内。

    np.dstack((Xfr, Xfr[:, :, 1:lastSlice))dstackfft.rfftn 的文档)将rfftn 输出与第三维中的倒数第二个切片堆叠在一起——倒数第二个,因为Nz 是偶数,而您不想这样做重复计算 0 或 -π DFT bin。

    当然,另一种方法是计算实数到复数数组的对数幅度之和,加倍,然后第一个切片和(如果Nz 是偶数)最后一个切片的对数幅度之和。

    tl;dr 将实数到复数输出的对数幅度相加。加倍。从此结果中减去第一个切片(在第 3 维中)的总和对数幅度。如果Nz 是奇怪的,你就完成了。如果Nz 是偶数,还减去最后一个切片的 sum-log-magnitudes。

    【讨论】:

    • 太棒了!我昨晚深夜发现了这个解决方案,但这很好地解释了原因。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-01
    • 1970-01-01
    • 2011-05-20
    相关资源
    最近更新 更多