numpy.irfftn对rfft变换数组乘标量后返回错误形状问题咨询
3D实傅里叶变换微分后反变换形状不匹配的问题解析
这不是numpy的bug,问题出在你调用numpy.irfftn时没有指定原信号的形状参数s,同时需要注意实傅里叶变换的对称性要求。
核心原因
rfftn/irfftn的默认形状推断规则
numpy.rfftn对形状为(Ng,Ng,Ng)的实数组做变换,输出形状为(Ng,Ng, Ng//2 +1)(这里Ng=5,最后一维长度为3),这是利用实信号的Hermitian对称性,只存储非负频率分量。- 调用
numpy.irfftn时如果不指定s参数,numpy会默认推断输出形状为(n1, n2, 2*(m-1)),其中m是输入最后一维的长度。这里m=3,所以最后一维长度为2*(3-1)=4,导致输出形状为(5,5,4),和原数组(5,5,5)无法广播。
实傅里叶变换的对称性要求(针对微分操作)
执行微分操作时,傅里叶空间的乘子需要满足Hermitian对称性,才能保证反变换后得到实数组:
比如对z方向求导,对应傅里叶空间乘子是1j * kz,其中kz是频率数组。对于实信号,kz的负频率分量对应乘子1j*(-kz),刚好等于conj(1j*kz),因此乘该因子不会破坏对称性,反变换后会得到实数组。如果乘子破坏了这个对称,反变换会得到复数组,但形状不匹配的核心原因还是s参数未指定。
解决方法
调用irfftn时指定原信号的形状
s:
明确告诉numpy你要还原的数组形状是原field的形状(Ng,Ng,Ng),这样irfftn会正确处理对称分量,返回和原数组形状一致的结果:import numpy as np Ng = 5 field = np.random.rand(Ng, Ng, Ng) # 实傅里叶变换 velk = np.rfftn(field) # 构造频率数组(以z方向微分为例) kx = np.fft.fftfreq(Ng) * 2 * np.pi ky = np.fft.fftfreq(Ng) * 2 * np.pi kz = np.fft.rfftfreq(Ng) * 2 * np.pi # 执行微分操作(对z求导) velk *= 1j * kz[np.newaxis, np.newaxis, :] # 指定s参数反变换,保证形状匹配 field_deriv = np.irfftn(velk, s=(Ng, Ng, Ng)) print(field_deriv.shape) # 输出(5,5,5),可与原数组正常广播验证对称性(可选):
如果微分操作涉及多个方向,确保乘子组合后仍满足Hermitian对称性,避免反变换后出现微小虚部(可通过np.real取实部)。
为什么复傅里叶变换正常?
使用numpy.fftn和numpy.ifftn时,输入输出形状都是(Ng,Ng,Ng),不需要额外指定形状参数,且复傅里叶变换不需要维护Hermitian对称性,因此不会出现形状不匹配的问题。
内容的提问来源于stack exchange,提问作者Matteo Peron
相关产品推荐
相关产品推荐

