以下代码使用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 = -1
和k
是波数导致精度损失。
这是我的代码的问题吗?或者它与浮点数的性质有关,如果是,为什么呢?