使用FFTW3(FORTRAN)计算导数的精度损失

时间:2015-04-02 09:44:20

标签: fortran precision fftw derivative

以下代码使用FFTW3函数计算任何正弦或余弦三角函数的导数。

program oned

implicit none

include "fftw3.f"

integer, parameter :: nx = 128  
integer :: i
double complex, dimension(0:nx-1) :: input, solution
double precision, dimension(0:nx-1) :: x
double precision, parameter :: pi = acos(-1.0d0), dx = 2.0d0*pi/(nx)
double complex :: wrap_variable, num = (0, 1.0d0)
integer*8 :: plan_x_fwd, plan_x_bwd

call dfftw_plan_dft_1d(plan_x_fwd, nx, input, input, fftw_forward, fftw_measure)
call dfftw_plan_dft_1d(plan_x_bwd, nx, input, input, fftw_backward, fftw_measure)

do i = 0, nx-1                                      
    x(i) = i*dx
    ! function whose derivative is to be calculated.
    input(i) = sin(8*x(i))                              
end do

! call fftw subroutine to calculate fourier coefficients of array
call dfftw_execute_dft(plan_x_fwd, input, input)            

! normalization of array
input = input/nx

do i = 0, nx-1
    if ( i .ge. 0 .and. i .le. nx/2-1 )  then
! calculating first derivatve. This involves multiplying by i*k
! where i**2 = -1 and k is the wavenumber
        input(i) = input(i)*num*i                   
    else if ( i .ge. nx/2 .and. i .le. nx-1) then                   
        input(i) = input(i)*num*(i-nx)                      
    end if                                      
end do

do i = 0, nx-1
    if ( i .gt. 0 .and. i .le. nx/2-1)  then
! calculating second derivative.
        input(i) = input(i)*num*i                       
    else if ( i .ge. nx/2 .and. i .le. nx-1) then   
        input(i) = input(i)*num*(i-nx)
    end if
end do

do i = 0, nx-1
    if ( i .gt. 0 .and. i .le. nx/2-1)  then
! calculating third derivative.
        input(i) = input(i)*num*i                       .
    else if ( i .ge. nx/2 .and. i .le. nx-1) then
        input(i) = input(i)*num*(i-nx)
    end if
end do

input(nx/2) = 0.0d0 

call dfftw_execute_dft(plan_x_bwd, input, input)

! print the error in calculation.
print *, maxval(abs(real(solution - input)))                        

call dfftw_destroy_plan(plan_x_fwd)
call dfftw_destroy_plan(plan_x_bwd)

end program

我正在使用的功能"输入"是sin(8x)。当我如上所述计算导数并与8*cos(8x)的答案进行比较时,我得到的最大误差为E-14。当我计算二阶导数并与-64*sin(8x)的答案进行比较时,我得到了E-12的错误。类似地,对于三阶导数,我得到E-10

我觉得这很令人不安。我不明白为什么将数字乘以i*k,其中i**2 = -1k是波数导致精度损失。 这是我的代码的问题吗?或者它与浮点数的性质有关,如果是,为什么呢?

0 个答案:

没有答案