Fortran 如何在FFTW中以2个或更多维度进行规格化?
我试图弄清楚如何使用FFTW正确地规范化DFT的结果。表示大小为n的一维复杂阵列X的正向(FFTW_正向)离散傅里叶变换计算阵列Y,其中 Y_k=\sum\limits_{j=0}{n-1}X_j e^{-2\pi j k\sqrt{-1}/n} 向后DFT计算: Y_k=\sum\limits_{j=0}{n-1}X_j e^{+2\pi j k\sqrt{-1}/n} 这些定义与实到复转换的定义相同 此外,本教程还规定“FFTW计算非规范化变换,因为DFT中的求和前面没有系数。换句话说,应用前向变换和后向变换将使输入乘以n”。,它没有具体说明需要在何处进行重新缩放。我想这可能取决于应用程序,但不确定如何正确使用它。声明它应该在前进方向上正常化,但我有我的疑问,我将详细说明 我的目标是找出如何正确地规范化FFT结果,以获得我所期望的结果。所以我首先做了一个简单的1D变换,在这里我知道确切的期望是什么:当我变换时,使用与FFTW相同的约定(归一化因子=1,振荡因子=-2*pi,用于前向傅里叶变换) 1/2(δ(1+x)-δ(1-x)) δ是狄拉克δ函数,我希望得到: 整体的_(-∞)^∞ (1/2(δ(1+x)-δ(1-x)))e^(-2πiωx)dx=i sin(2πω) 当我对I sin(2πω)进行IFFT时也是如此,只是现在我需要通过除以n进行归一化 下面是我用来演示这种行为的代码:Fortran 如何在FFTW中以2个或更多维度进行规格化?,fortran,fft,fftw,Fortran,Fft,Fftw,我试图弄清楚如何使用FFTW正确地规范化DFT的结果。表示大小为n的一维复杂阵列X的正向(FFTW_正向)离散傅里叶变换计算阵列Y,其中 Y_k=\sum\limits_{j=0}{n-1}X_j e^{-2\pi j k\sqrt{-1}/n} 向后DFT计算: Y_k=\sum\limits_{j=0}{n-1}X_j e^{+2\pi j k\sqrt{-1}/n} 这些定义与实到复转换的定义相同 此外,本教程还规定“FFTW计算非规范化变换,因为DFT中的求和前面没有系数。换句话说,应用
program use_fftw
use,intrinsic :: iso_c_binding
implicit none
include 'fftw3.f03'
integer, parameter :: N = 1000
integer, parameter :: dp = kind(1.d0)
real(dp), parameter :: pi = 3.1415926d0
real(dp), parameter :: physical_length = 500
real(dp), parameter :: dx = physical_length/real(N)
real(dp), parameter :: dk = 1.d0 / physical_length
integer :: i, ind1, ind2
! for double precision: use double complex & call dfftw_plan_dft_1d
complex(C_DOUBLE_COMPLEX), allocatable, dimension(:) :: arr_out
real(C_DOUBLE), allocatable, dimension(:) :: arr_in
type(C_PTR) :: plan_forward, plan_backward
allocate(arr_in(1:N))
allocate(arr_out(1:N/2+1))
plan_forward = fftw_plan_dft_r2c_1d(N, arr_in, arr_out, FFTW_ESTIMATE)
plan_backward = fftw_plan_dft_c2r_1d(N, arr_out, arr_in, FFTW_ESTIMATE)
!----------------------
! Setup
!----------------------
! add +1: index = 1 corresponds to x=0
ind1 = int(1.d0/dx)+1 ! index where x=1
ind2 = int((physical_length-1.d0)/dx)+1 ! index where x=-1
arr_in = 0
arr_in(ind1) = -0.5d0
arr_in(ind2) = 0.5d0
!----------------------
! Forward
!----------------------
call fftw_execute_dft_r2c(plan_forward, arr_in, arr_out)
write(*,*) "Verification: Max real part of arr_out:", maxval(real(arr_out))
open(unit=666,file='./fftw_output_norm1d_fft.txt', form='formatted')
do i = 1, N/2+1
write(666, '(2E14.5,x)') (i-1)*dk, aimag(arr_out(i))
enddo
close(666)
write(*,*) "Finished! Written results to fftw_output_norm1d_fft.txt"
!----------------------
! Backward
!----------------------
call fftw_execute_dft_c2r(plan_backward, arr_out, arr_in)
arr_in = arr_in/N
open(unit=666,file='./fftw_output_norm1d_real.txt', form='formatted')
do i = 1, N
write(666, '(2E14.5,x)') (i-1)*dx, arr_in(i)
enddo
close(666)
write(*,*) "Finished! Written results to fftw_output_norm1d_real.txt"
deallocate(arr_in, arr_out)
call fftw_destroy_plan(plan_forward)
call fftw_destroy_plan(plan_backward)
end program use_fftw
结果完全符合我的预期:
所以在这个例子中,当从傅里叶空间回到实空间时,我只归一化了(除以n),得到了我想要的
但当我尝试对多个维度做同样的事情时。
这一次,我试图改变
sqrt(π/2)((δ(-1+x)-δ(1+x))δ(y)+δ(x)(δ(-1+y)-δ(1+y)))
应该给谁
整体的_(-∞)^∞ (sqrt(π/2)((δ(-1+x)-δ(1+x))δ(y)+δ(x)(δ(-1+y)-δ(1+y)))e^(-2πi{x,y}{a,b})d{x,y}=+i sin(a)+i sin(b)
我绘制x=0(k_x=0)的结果:
这似乎是完全错误的,无论是在窦波的频率还是振幅上
但是,通过除以n^2进行反向变换和归一化,可以在x和y方向上得到预期的初始条件。以下是x=0的曲线图:
我不知道我做错了什么
以下是2d代码:
program use_fftw
use,intrinsic :: iso_c_binding
implicit none
include 'fftw3.f03'
integer, parameter :: N = 1000
integer, parameter :: dp = kind(1.d0)
real(dp), parameter :: pi = 3.1415926d0
real(dp), parameter :: physical_length = 500
real(dp), parameter :: dx = physical_length/real(N)
real(dp), parameter :: dk = 1.d0 / physical_length
integer :: i, ind1, ind2
! for double precision: use double complex & call dfftw_plan_dft_1d
complex(C_DOUBLE_COMPLEX), allocatable, dimension(:,:) :: arr_out
real(C_DOUBLE), allocatable, dimension(:,:) :: arr_in
type(C_PTR) :: plan_forward, plan_backward
allocate(arr_in(1:N, 1:N))
allocate(arr_out(1:N/2+1, 1:N))
plan_forward = fftw_plan_dft_r2c_2d(N, N, arr_in, arr_out, FFTW_ESTIMATE)
plan_backward = fftw_plan_dft_c2r_2d(N, N, arr_out, arr_in, FFTW_ESTIMATE)
!----------------------
! Setup
!----------------------
! add +1: index = 1 corresponds to x=0
ind1 = int(1.d0/dx)+1 ! get index where x = 1
ind2 = int((physical_length-1.d0)/dx)+1 ! get index where x = -1
arr_in = 0
! y=0:
arr_in(ind1, 1) = sqrt(pi/2)
arr_in(ind2, 1) = -sqrt(pi/2)
! x=0:
arr_in(1, ind1) = sqrt(pi/2)
arr_in(1, ind2) = -sqrt(pi/2)
!----------------------
! Forward
!----------------------
call fftw_execute_dft_r2c(plan_forward, arr_in, arr_out)
write(*,*) "Verification: Max real part of arr_out:", maxval(real(arr_out))
open(unit=666,file='./fftw_output_norm2d_fft_x=0.txt', form='formatted')
open(unit=667,file='./fftw_output_norm2d_fft_y=0.txt', form='formatted')
do i = 1, N
write(666, '(2E14.5,x)') (i-1)*dk, aimag(arr_out(1,i))
enddo
do i = 1, N/2+1
write(667, '(2E14.5,x)') (i-1)*dk, aimag(arr_out(i,1))
enddo
close(666)
close(667)
write(*,*) "Finished! Written results to fftw_output_normalisation_fft_x.txt and fftw_output_normalisation_fft_y.txt"
!----------------------
! Backward
!----------------------
call fftw_execute_dft_c2r(plan_backward, arr_out, arr_in)
! Normalisation happens here!
arr_in = arr_in/N**2
open(unit=666,file='./fftw_output_norm2d_real_x=0.txt', form='formatted')
open(unit=667,file='./fftw_output_norm2d_real_y=0.txt', form='formatted')
do i = 1, N
write(666, '(2E14.5,x)') (i-1)*dx, arr_in(1, i)
write(667, '(2E14.5,x)') (i-1)*dx, arr_in(i, 1)
enddo
close(666)
close(667)
write(*,*) "Finished! Written results to fftw_output_norm2d_real_x=0.txt and fftw_output_norm2d_real_y=0.txt"
deallocate(arr_in, arr_out)
call fftw_destroy_plan(plan_forward)
call fftw_destroy_plan( plan_backward)
end program use_fftw
以及python绘图工具:
#!/usr/bin/python3
#====================================
# Plots the results of the FFTW
# example programs.
#====================================
import numpy as np
import matplotlib.pyplot as plt
from sys import argv
from time import sleep
errormessage="""
I require an argument: Which output file to plot.
Usage: ./plot_fftw.py <case>
options for case:
1 fftw_output_norm1d_fft.txt
2 fftw_output_norm1d_real.txt
3 fftw_output_norm2d_fft_x=0.txt
4 fftw_output_norm2d_real_x=0.txt
5 fftw_output_norm2d_fft_y=0.txt
6 fftw_output_norm2d_real_y=0.txt
Please select a case: """
#----------------------
# Hardcoded stuff
#----------------------
file_dict={}
file_dict['1'] = ('fftw_output_norm1d_fft.txt', '1d Fourier transform')
file_dict['2'] = ('fftw_output_norm1d_real.txt', '1d Full circle')
file_dict['3'] = ('fftw_output_norm2d_fft_x=0.txt', '2d Fourier transform, x=0')
file_dict['4'] = ('fftw_output_norm2d_real_x=0.txt', '2d Full circle, x=0')
file_dict['5'] = ('fftw_output_norm2d_fft_y=0.txt', '2d Fourier transform, y=0')
file_dict['6'] = ('fftw_output_norm2d_real_y=0.txt', '2d Full circle, y=0')
#------------------------
# Get case from cmdline
#------------------------
case = ''
def enforce_integer():
global case
while True:
case = input(errormessage)
try:
int(case)
break
except ValueError:
print("\n\n!!! Error: Case must be an integer !!!\n\n")
sleep(2)
if len(argv) != 2:
enforce_integer()
else:
try:
int(argv[1])
case = argv[1]
except ValueError:
enforce_integer()
filename,title=file_dict[case]
#-------------------------------
# Read and plot data
#-------------------------------
k, Pk = np.loadtxt(filename, dtype=float, unpack=True)
fig = plt.figure()
ax = fig.add_subplot(111)
# ax.plot(k, Pk, label='power spectrum')
if case in ['1', '3', '5']:
ax.plot(k, Pk, label='recovered wave', lw=3) # ignore negative k
x = np.linspace(k.min(), k.max(), 1000)
if case=='1':
ax.plot(x, np.sin(2*np.pi*x), ':', label='expected wave', lw=3)
if case in ['3', '5']:
ax.plot(x, np.sin(x), ':', label='expected wave', lw=3)
ax.set_title(title)
ax.set_xlabel("k")
ax.set_ylabel("F(k)")
if case in ['2', '4', '6']:
# in this case: k=x, Pk=f(x)
ax.plot(k, Pk, label='recovered original', lw=3) # ignore negative k
N=1000
plen=500
dx=plen/N
x = np.linspace(k.min(), k.max(), 1000)
y = np.zeros(1000)
ind = int(1.0/dx)
if case=='2':
y[ind] = -0.5
y[-ind] = 0.5
if case in ['4', '6']:
y[ind] = np.sqrt(np.pi/2)
y[-ind] = -np.sqrt(np.pi/2)
ax.plot(x, y, ':', label='expected original', lw=3)
ax.set_title(title)
ax.set_xlabel("x")
ax.set_ylabel("f(x)")
ax.legend()
plt.show()
!/usr/bin/python3
#====================================
#绘制FFTW的结果
#示例程序。
#====================================
将numpy作为np导入
将matplotlib.pyplot作为plt导入
从系统导入argv
从时间上导入睡眠
errormessage=“”
我需要一个参数:打印哪个输出文件。
用法:./plot\u fftw.py
案例选项:
1 fftw_输出_norm1d_fft.txt
2 fftw_output_norm1d_real.txt
3 fftw_输出_norm2d_fft_x=0.txt
4 fftw_输出_norm2d_real_x=0.txt
5 fftw_输出_norm2d_fft_y=0.txt
6 fftw_输出_norm2d_real_y=0.txt
请选择一个案例:“”
#----------------------
#硬编码的东西
#----------------------
文件_dict={}
文件dict['1']=('fftw\u output\u norm1d\u fft.txt','1d Fourier transform')
文件dict['2']=('fftw\u output\u norm1d\u real.txt','1d Full circle')
文件\u dict['3']=('fftw\u output\u norm2d\u fft\u x=0.txt','2d Fourier transform,x=0')
文件\u dict['4']=('fftw\u output\u norm2d\u real\u x=0.txt','2d Full circle,x=0')
文件_dict['5']=('fftw_output_norm2d_fft_y=0.txt','2d Fourier transform,y=0')
文件dict['6']=('fftw_output_norm2d_real_y=0.txt','2d Full circle,y=0')
#------------------------
#从cmdline获取案例
#------------------------
案例=“”
def enforce_integer():
全球案例
尽管如此:
案例=输入(错误消息)
尝试:
内部(案例)
打破
除值错误外:
打印(“\n\n!!!错误:大小写必须是整数!!!\n\n”)
睡眠(2)
如果len(argv)!=2:
强制执行_整数()
其他:
尝试:
int(argv[1])
case=argv[1]
除值错误外:
强制执行_整数()
文件名,title=file\u dict[大小写]
#-------------------------------
#读取和打印数据
#-------------------------------
k、 Pk=np.loadtxt(文件名,dtype=float,unpack=True)
图=plt.图()
ax=图添加_子批次(111)
#ax.图(k,Pk,label='power spectrum')
如果在['1','3','5']中出现大小写:
ax.plot(k,Pk,label='recovered wave',lw=3)#忽略负k
x=np.linspace(k.min(),k.max(),1000)
如果案例=='1':
ax.plot(x,np.sin(2*np.pi*x),“:”,label='expected wave',lw=3)
如果在['3','5']中出现大小写:
ax.plot(x,np.sin(x),“:”,label='expected wave',lw=3)
ax.设置标题(标题)
ax.集合标签(“k”)
ax.set_ylabel(“F(k)”)
如果在['2','4','6']中出现大小写:
#在这种情况下:k=x,Pk=f(x)
ax.plot(k,Pk,label='recovered original',lw=3)#忽略负k
N=1000
普兰=500
dx=正压/正压
x=np.linspace(k.min(),k.max(),1000)
y=np.零(1000)
ind=int(1.0/dx)
如果案例=='2':
y[ind]=-0.5
y[-ind]=0.5
如果在['4','6']中出现大小写:
y[ind]=np.sqrt(np.pi/2)
y[-ind]=-np.sqrt(np.pi/2)
ax.plot(x,y,,:',label='expected original',lw=3)
ax.设置标题(标题)
ax.集合标签(“x”)
ax.set_ylabel(“f(x)”)
ax.图例()
plt.show()
为什么你认为这是一个规范化问题?当波数错误时,这不仅仅是规范化问题。@VladimirF回答你所有的问题:主要是因为我在这方面是新手。我将函数更改为fftw
,但结果保持不变。我能想到的另一件事是,我从根本上误解了fftw修道院离子,这就是为什么我