Problem with big matrices using fftw3 in Fortran (example code) - fortran

this question follows from my last question, but now with the code.
I have problems with the "Fastest Fourier Transform in the West" (link) implemented in Fortran, in particular calculating the inverse of the fft. When I test with small matrices the result is perfect, but from 8x8 on the result is wrong.
Here is my code here. I written it with comments inside. The example matrices are in the files ex1.dat,... ex5.dat, so it is easy to test (I use the intel compiler, I'm not sure that runs with gfortran). Examples ex2 and ex3 works perfect (5x5 and 7x7), but the other examples give wrong results, so I can't understand the error or where looking for.
Inside the code: to verify that all is right I calculate
PRINT*, MINVAL( AA - AA_new ), MAXVAL( AA-AA_new )
where AA is the original matrix, and AA_new is the matrix AA after calculate the fft and then the inverse of the fft. We expect that AA==AA_new, so we expect that MINVAL( AA - AA_new ), MAXVAL( AA-AA_new ) be zero. But for bigger matrices these numbers are big, so AA and AA_new are very different.
Also I'm comparing the result with the command fft2 of matlab, because uses the same library according its documentation.
About the code:
the main file is fft_test.f90,
and all corresponding to the calculus of the fft using fftw3 is in fft_modules.f90.
-The definition of _dp (the precision) is in decimal.f90.
You can download the code from the last link, but also I write below:
PROGRAM fftw_test
!
USE decimal
USE fftw_module
!
IMPLICIT NONE
!
REAL(KIND=dp), ALLOCATABLE :: AA(:,:), AA_new(:,:)
COMPLEX(KIND=dp), ALLOCATABLE :: ATF(:,:)
INTEGER :: NN, MM, ii, jj
!
OPEN(unit=10,file='ex2.dat',status='old',action='read')
READ(10,*) NN,MM ! <- NNxMM is the size of the matrix inside the file vel1.dat
!
ALLOCATE( AA(NN,MM), AA_new(NN,MM), ATF(NN,MM) )
AA = 0.0_dp; AA_new = 0.0_dp; ATF = 0.0_dp
!
DO ii=1,NN
READ(10,*) ( AA(ii,jj), jj=1,NN ) ! AA is the original matrix (real)
END DO
CLOSE(10)
!
PRINT*,'MIN and MAX value of AA' !<- just to verify that is not null
PRINT*, MINVAL( AA ), MAXVAL( AA )
!
CALL fft(NN,MM,AA,ATF) ! ATF (complex) is the fft of AA (real)
!
CALL ifft(NN,MM,ATF,AA_new) ! AA_new is the inverse fft AA, so must be == AA
!
PRINT*,'MIN and MAX value of AA_new' !<- just to verify that is not null
PRINT*, MINVAL( AA_new ), MAXVAL( AA_new )
!
PRINT*,'Max and min val of (AA-AA_new)'!<- just to compare some way the result
PRINT*, MINVAL( AA - AA_new ), MAXVAL( AA-AA_new )
PRINT*,' ------------------------------------------------------------------- '
!
DEALLOCATE( AA, ATF )
!
END PROGRAM fftw_test
MODULE fftw_module
!
! Contains the forward and inverse discrete fourier transform of a matrix
! using the library fftw3
!
USE decimal
!
CONTAINS
!
SUBROUTINE fft(NX,NY,AA,ATF)
!
! Calculate the forward Discrete Fourier transform ATF of the matriz AA
! Both matrices have the same size, but AA (the input) is real
! and ATF (the output) is complex
!
USE, INTRINSIC :: iso_c_binding
IMPLICIT none
INCLUDE 'fftw3.f03'
! include 'aslfftw3.f03'
!
INTEGER(C_INT), INTENT(in) :: Nx, Ny
COMPLEX(C_DOUBLE_COMPLEX), ALLOCATABLE :: zin(:), zout(:)
TYPE(C_PTR) :: planf
!
INTEGER :: ii, yy, ix, iy
REAL(KIND=dp) :: AA(:,:)
COMPLEX(KIND=dp) :: ATF(:,:)
!
ALLOCATE( zin(NX * NY), zout(NX * NY) )
!
! Plan Creation (out-of-place forward and backward FFT)
planf = fftw_plan_dft_2d(NY, NX, zin, zout, FFTW_FORWARD, FFTW_ESTIMATE)
IF ( .NOT. C_ASSOCIATED(planf) ) THEN
PRINT*, "plan creation error!!"
STOP
END IF
!
zin = CMPLX( RESHAPE( AA, (/ NX*NY /) ) , KIND=dp )
!
! FFT Execution (forward)
CALL FFTW_EXECUTE_DFT(planf, zin, zout)
!
DO iy = 1, Ny
DO ix = 1, Nx
ii = ix + nx*(iy-1)
ATF(ix,iy) = zout(ii)
END DO
END DO
!
! Plan Destruction
CALL FFTW_DESTROY_PLAN(planf)
CALL FFTW_CLEANUP
!
DEALLOCATE( zin, zout )
!
END SUBROUTINE fft
!
!
SUBROUTINE ifft(NX,NY,ATF,AA)
!
! Calculate the inverse Discrete Fourier transform ATF of the matriz AA
! Both matrices have the same size, but AA ATF (the input) is complex
! and AA (the output) is real
!
USE, INTRINSIC :: iso_c_binding
IMPLICIT none
INCLUDE 'fftw3.f03'
! include 'aslfftw3.f03'
!
INTEGER(C_INT), INTENT(in) :: Nx, Ny
COMPLEX(C_DOUBLE_COMPLEX), ALLOCATABLE :: zin(:), zout(:)
TYPE(C_PTR) :: planb
!
INTEGER :: ii, yy, ix, iy
REAL(KIND=dp) :: AA(:,:)
COMPLEX(KIND=dp) :: ATF(:,:)
!
ALLOCATE( zin(NX * NY), zout(NX * NY) )
!
! Plan Creation (out-of-place forward and backward FFT)
planb = fftw_plan_dft_2d(NY, NX, zin, zout, FFTW_BACKWARD, FFTW_ESTIMATE)
IF ( .NOT. C_ASSOCIATED(planb) ) THEN
PRINT*, "plan creation error!!"
STOP
END IF
!
zin = RESHAPE( ATF, (/ NX*NY /) )
!
! FFT Execution (backward)
! CALL FFTW_EXECUTE_DFT(planb, zout, zin)
CALL FFTW_EXECUTE_DFT(planb, zin, zout)
!
DO iy = 1, Ny
DO ix = 1, Nx
ii = ix + nx*(iy-1)
AA(ix,iy) = dble( zout(ii) )
END DO
END DO
!
! Plan Destruction
CALL FFTW_DESTROY_PLAN(planb)
CALL FFTW_CLEANUP
!
DEALLOCATE( zin, zout )
!
END SUBROUTINE ifft
!
END MODULE fftw_module
MODULE decimal
!
! Precision in the whole program
!
! dp : double precision
! sp : simple precision
!
IMPLICIT NONE
!
INTEGER, PARAMETER :: dp = KIND(1.D0)
INTEGER, PARAMETER :: sp = KIND(1.0)
!
END MODULE decimal
A matrix example (that works because is small), corresponding on the ex2.dat input file:
5 5
1 2 3 4 5.3
6 7 8 9 10
11 12 3 5 3
0.1 -0.32 0.4 70 12
0 1 0 -1 0 -70

When you perform a forward and then a back discrete Fourier Transform on some data the normalisation of the result is conventional, usually you either get the data back as it was (to floating point accuracy), or if you are using an unnormalised transform the data will be scaled by the number of points in the data set, or you provide the normalisation as an argument. To find out which you will have read the documentation of whatever software you are using to do the transforms; fftw uses unnormalised transforms . Thus in your code you will need to preform the appropriate scaling. And if you run your code on your datasets you find the scaling is as described - on a 10x10 dataset the final data is 100 times the original data.
I cannot reproduce your claim that the code as given works for the smaller data sets. I get the expected scaling.

Related

Solving a linear system with 0s on the main diagonal in Fortran

As per title, what's the best algorithm to numerically solve a linear system in Fortran, if this system has 0s along the main diagonal?
Up to now, I had been fine using simple Gaussian elimination:
SUBROUTINE solve_lin_sys(A, c, x, n)
! =====================================================
! Uses gauss elimination and backwards substitution
! to reduce a linear system and solve it.
! Problem (0-div) can arise if there are 0s on main diag.
! =====================================================
IMPLICIT NONE
INTEGER:: i, j, k
REAL*8::fakt, summ
INTEGER, INTENT(in):: n
REAL*8, INTENT(inout):: A(n,n)
REAL*8, INTENT(inout):: c(n)
REAL*8, INTENT(out):: x(n)
DO i = 1, n-1 ! pick the var to eliminate
DO j = i+1, n ! pick the row where to eliminate
fakt = A(j,i) / A(i,i) ! elimination factor
DO k = 1, n ! eliminate
A(j,k) = A(j,k) - A(i,k)*fakt
END DO
c(j)=c(j)-c(i)*fakt ! iterate on known terms
END DO
END DO
! Actual solving:
x(n) = c(n) / A(n,n) ! last variable being solved
DO i = n-1, 1, -1
summ = 0.d0
DO j = i+1, n
summ = summ + A(i,j)*x(j)
END DO
x(i) = (c(i) - summ) / A(i,i)
END DO
END SUBROUTINE solve_lin_sys
As you can see I'm dividing by A(i,i) in the calculations. Same problem arises using Gauss-Jordan transformation or Gauss-Seidel elimination.
What's the best solution? I know i'm probably missing some really basic step but I'm a beginner programmer and apparently my linear algebra is getting rusty.

I got a message with this erro Function ‘areacircle’ requires an argument list ,Why?

this is the program. and I got an error why?
''''code'''''
I don't know why the whole doesn't appear, I tried to determine the area and volume for a random number.
----------------why-------------
'''Fortran
'program exercise2'
!
integer :: N,i
type :: Values
double precision :: radius,area,volume
end type
!
!
type(Values),allocatable, dimension(:) :: s
integer :: bi
!
!Read the data to create the random number
write(6,*) 'write your number '
read(5,*) N
allocate(s(N))
bi = 3.14
!create the random number
call random_seed()
do i=1,N
call random_number(s(i)%radius)
s(i)%area=areacircle(s(i)%radius)
s(i)%volume=volumesphere(s(i)%radius)
end do
!
open(15,file='radius.out',status='new')
write(15,*) s(i)%radius
open(16,file='output2.out',status='new')
r = real(s(i)%radius)
!Two function
contains
double precision function areacircle (s)
implicit none
double precision :: s
do i=1 , N
areacircle=bi*r**2
end do
return
end function areacircle
!
!
double precision function volumesphere (s)
implicit none
double precision :: s
do i=1,N
volumesphere=4/3*bi*r**3
end do
return
write(16,*) r , areacircle , volumesphere
end function volumesphere
'end program exercise2'
'''''''
so anyone know why?
This likely does what you want. As the computation of area and volume involve a single input that does not change, I've changed your functions to be elemental. This allows an array argument where the function is executed for each element of the array. I also changed double precision to use Fortran kind type parameter mechanism, because typing is real(dp) is much shorter.
Finally, never write a Fortran program without the implicit none statement.
program exercise2
implicit none ! Never write a program without this statement
integer, parameter :: dp = kind(1.d0) ! kind type parameter
integer n, i
type values
real(dp) radius, area, volume
end type
type(values), allocatable :: s(:)
real(dp) bi ! integer :: bi?
! Read the data to create the random number
write(6,*) 'write your number '
read(5,*) n
! Validate n is validate.
if (n < 1) stop 'Invalid number'
allocate(s(n))
bi = 4 * atan(1.d0) ! bi = 3.14? correctly determine pi
call random_seed() ! Use default seeding
call random_number(s%radius) ! Fill radii with random numbers
s%area = areacircle(s%radius) ! Compute area
s%volume = volumesphere(s%radius) ! Compute volume
write(*,'(A)') ' Radii Area Volume'
do i = 1, n
write(*, '(3F9.5)') s(i)
end do
contains
elemental function areacircle(s) result(area)
real(dp) area
real(dp), intent(in) :: s
area = bi * s**2
end function areacircle
elemental function volumesphere(s) result(volume)
real(dp) volume
real(dp), intent(in) :: s
volume = (4 * bi / 3) * s**3
end function volumesphere
end program exercise2

Cannot call a function from the same scope

I'm confused about the scope. I downloaded a Fortran file which has 1 main program, 1 subroutine and 1 function in 1 source file. The main program does not contain the subprograms, and the function is called by the subroutine. It works fine, but when I modified the main program to contain those 2 subprograms using "contains", it gives compile error, saying the function is not defined. However, if I create a small function within the same contained section and call from the subroutine, it does not give an error.
What is the difference between those 2 functions? Why do I get the error?
I created a small program with the same structure, 1 main that contains a subroutine and a func and it did not give an error.
My environment is ubuntu 14.04 and using gfortran compiler.
Building target: QRbasic
Invoking: GNU Fortran Linker
gfortran -o "QRbasic" ./main.o
./main.o: In function qrbasic':
/*/QRbasic/Debug/../main.f95:79: undefined reference toajnorm_'
/home/kenji/workspace/QRbasic/Debug/../main.f95:104: undefined reference to `ajnorm_'
collect2: error: ld returned 1 exit status
make: *** [QRbasic] Error 1
Program Main
!====================================================================
! QR basic method to find the eigenvalues
! of matrix A
!====================================================================
implicit none
integer, parameter :: n=3
double precision, parameter:: eps=1.0e-07
double precision :: a(n,n), e(n)
integer i, j, iter
! matrix A
! data (a(1,i), i=1,3) / 8.0, -2.0, -2.0 /
! data (a(2,i), i=1,3) / -2.0, 4.0, -2.0 /
! data (a(3,i), i=1,3) / -2.0, -2.0, 13.0 /
data (a(1,i), i=1,3) / 1.0, 2.0, 3.0 /
data (a(2,i), i=1,3) / 2.0, 2.0, -2.0 /
data (a(3,i), i=1,3) / 3.0, -2.0, 4.0 /
! print a header and the original matrix
write (*,200)
do i=1,n
write (*,201) (a(i,j),j=1,n)
end do
! print: guess vector x(i)
! write (*,204)
! write (*,201) (y(i),i=1,3)
call QRbasic(a,e,eps,n,iter)
! print solutions
write (*,202)
write (*,201) (e(i),i=1,n)
write (*,205) iter
200 format (' QR basic method - eigenvalues for A(n,n)',/, &
' Matrix A')
201 format (6f12.6)
202 format (/,' The eigenvalues')
205 format (/,' iterations = ',i5)
!end program main
contains
subroutine QRbasic(a,e,eps,n,iter)
!==============================================================
! Compute all eigenvalues: real symmetric matrix a(n,n,)
! a*x = lambda*x
! method: the basic QR method
! Alex G. (January 2010)
!--------------------------------------------------------------
! input ...
! a(n,n) - array of coefficients for matrix A
! n - dimension
! eps - convergence tolerance
! output ...
! e(n) - eigenvalues
! iter - number of iterations to achieve the tolerance
! comments ...
! kmax - max number of allowed iterations
!==============================================================
implicit none
integer n, iter
double precision a(n,n), e(n), eps
double precision q(n,n), r(n,n), w(n), an, Ajnorm, sum, e0,e1
integer k, i, j, m
integer, parameter::kmax=1000
! initialization
q = 0.0
r = 0.0
e0 = 0.0
do k=1,kmax ! iterations
! step 1: compute Q(n,n) and R(n,n)
! column 1
an = Ajnorm(a,n,1)
r(1,1) = an
do i=1,n
q(i,1) = a(i,1)/an
end do
! columns 2,...,n
do j=2,n
w = 0.0
do m=1,j-1
! product q^T*a result = scalar
sum = 0.0
do i=1,n
sum = sum + q(i,m)*a(i,j)
end do
r(m,j) = sum
! product (q^T*a)*q result = vector w(n)
do i=1,n
w(i) = w(i) + sum*q(i,m)
end do
end do
! new a'(j)
do i =1,n
a(i,j) = a(i,j) - w(i)
end do
! evaluate the norm for a'(j)
an = Ajnorm(a,n,j)
r(j,j) = an
! vector q(j)
do i=1,n
q(i,j) = a(i,j)/an
end do
end do
! step 2: compute A=R(n,n)*Q(n,n)
a = matmul(r,q)
! egenvalues and the average eigenvale
sum = 0.0
do i=1,n
e(i) = a(i,i)
sum = sum+e(i)*e(i)
end do
e1 = sqrt(sum)
! print here eigenvalues
! write (*,201) (e(i),i=1,n)
!201 format (6f12.6)
! check for convergence
if (abs(e1-e0) < eps) exit
! prepare for the next iteration
e0 = e1
end do
iter = k
if(k == kmax) write (*,*)'The eigenvlue failed to converge'
print *, func1()
end subroutine QRbasic
function Ajnorm(a,n,j)
implicit none
integer n, j, i
double precision a(n,n), Ajnorm
double precision sum
sum = 0.0
do i=1,n
sum = sum + a(i,j)*a(i,j)
end do
Ajnorm = sqrt(sum)
end function Ajnorm
integer function func1()
print *, "dummy"
func1=1
end function
end program
The original program did not contain those 2 programs. This is the version I get an error.
Your main program contains a declaration of the type of function Ajnorm(). As a result, when the compiler finds that name to be used as a function name, it interprets it as an external function. That's quite correct in the original form of the program, with the function defined as an independent unit, but it is wrong for an internal (contained) function. Your program compiles cleanly for me once I remove the unneeded declaration.

.f95 programme for seismic absorption band - debugging

I am trying to write a programme to calculate an absorption band model for seismic waves. The whole calculation is based on 3 equations. If interested, see equations 3, 4, 5 on p.2 here:
http://www.eri.u-tokyo.ac.jp/people/takeuchi/publications/14EPSL-Iritani.pdf
However, I have debugged this programme several times now but I do not seem to get the expected answer. I am specifically trying to calculate Q_1 variable (seismic attenuation) in the following programme, which should be a REAL positive value on the order of 10^-3. However, I am getting negative values. I need a fresh pair of eyes to take a look at the programme and to check where I have done a mistake if any. Could someone please check? Many thanks !
PROGRAM absorp
! Calculate an absorption band model and output
! files for plotting.
! Ref. Iritani et al. (2014), EPSL, 405, 231-243.
! Variable Definition
! Corners - cf1, cf2
! Frequency range - [10^f_strt, 10^(f_end-f_strt)]
! Number of points to be sampled - n
! Angular frequency - w
! Frequency dependent Attenuation 1/Q - Q_1
! Relaxation times - tau1=1/(2*pi*cf1), tau2=1/(2*pi*cf2)
! Reference velocity - V0 (km/s)
! Attenuation (1/Q) at 1 Hz - Q1_1
! Frequency dependent peak Attenuation (1/Qm) - Qm_1
! Frequency dependent velocity - V_w
! D(omega) numerator - Dw1
! D(omega) denominator - Dw2
! D(omega) - D_w
! D(2pi) - D_2pi
IMPLICIT NONE
REAL :: cf1 = 2.0e0, cf2 = 1.0e+5
REAL, PARAMETER :: f_strt=-5, f_end=12
INTEGER :: indx
INTEGER, PARAMETER :: n=1e3
REAL, PARAMETER :: pi=4.0*atan(1.0)
REAL, DIMENSION(1:n) :: w, Q_1
REAL :: tau1, tau2, V0, freq, pow
REAL :: Q1_1=0.003, Qm_1
COMPLEX, DIMENSION(1:n) :: V_w
COMPLEX, PARAMETER :: i=(0.0,1.0)
COMPLEX :: D_2pi, D_w, Dw1, Dw2
! Reference Velocity km/s
V0 = 12.0
print *, "F1=", cf1, "F2=", cf2, "V0=",V0
! Relaxation times from corners
tau1 = 1.0/(2.0*pi*cf1)
tau2 = 1.0/(2.0*pi*cf2)
PRINT*, "tau1=",tau1, "tau2=",tau2
! Populate angular frequency array (non-linear)
DO indx = 1,n+1
pow = f_strt + f_end*REAL(indx-1)/n
freq=10**pow
w(indx) = 2*pi*freq
print *, w(indx)
END DO
! D(2pi) value
D_2pi = LOG((i*2.0*pi + 1/tau1)/(i*2.0*pi + 1/tau2))
! Calculate 1/Q from eq. 3 and 4
DO indx=1,n
!D(omega)
Dw1 = (i*w(indx) + 1.0/tau1)
Dw2 = (i*w(indx) + 1.0/tau2)
D_w = LOG(Dw1/Dw2)
!This is eq. 5 for 1/Qm
Qm_1 = 2.0*pi*Q1_1*IMAG(D_w)/ &
((Q1_1**2-4)*IMAG(D_w)**2 &
+ 4*Q1_1*IMAG(D_w)*REAL(D_w))
!This is eq. 3 for Alpha(omega)
V_w(indx) = V0*(SQRT(1.0 + 2.0/pi*Qm_1*D_w)/ &
REAL(SQRT(1.0 + 2.0/pi*Qm_1*D_2pi)))
!This is eq. 4 for 1/Q
Q_1(indx) = 2*IMAG(V_w(indx))/REAL(V_w(indx))
PRINT *, w(indx)/(2.0*pi), (V_w(indx)), Q_1(indx)
END DO
! write the results out
100 FORMAT(F12.3,3X,F7.3,3X,F8.5)
OPEN(UNIT=1, FILE='absorp.txt', STATUS='replace')
DO indx=1,n
WRITE(UNIT=1,FMT=100), w(indx)/(2.0*pi), REAL(V_w(indx)), Q_1(indx)
END DO
CLOSE(UNIT=1)
END PROGRAM
More of an extended comment with formatting than an answer ...
I haven't checked the equations you refer to, and I'm not going to, but looking at your code makes me suspect misplaced brackets as a likely cause of errors. The code, certainly as you've shown it here, isn't well formatted to reveal its logical structure. Whatever you do next invest in some indents and some longer lines to avoid breaking too frequently.
Personally I'm suspicious in particular of
!This is eq. 5 for 1/Qm
Qm_1 = 2.0*pi*Q1_1*IMAG(D_w)/ &
((Q1_1**2-4)*IMAG(D_w)**2 &
+ 4*Q1_1*IMAG(D_w)*REAL(D_w))

FFTW, simple derivative in fortran

I am struggling with this simple derivative of a sine with FFTW. At a first look it seems ok but then there is a quite big error (5e-6) when compared with the exact solution...
I do see that after taking the c2r the complex input is all messed up, but it seems to me that same complex input is the cause of my problem... What am I doing wrong? I didn't use any pointer and tried to keep everything as simple as possible; still I can't figure out what's wrong.
Any help is appreciated! Thanks!!!
program main
! C binding
use, intrinsic :: iso_c_binding
implicit none
double precision, parameter :: pi = 4*ATAN(1.0)
complex, parameter :: ii =(0.0,1.0)
integer(C_INT), parameter :: Nx = 32
integer(C_INT), parameter :: Ny = Nx
double precision, parameter :: Lx = 2*pi, Ly = 2*pi
! Derived paramenter
double precision, parameter :: dx = Lx/Nx, dy = Ly/Ny
real(C_DOUBLE), dimension(Nx,Ny) :: x,y, u0,in,dudx,dudxE, errdU
real(C_DOUBLE), dimension(Nx/2+1,Ny) :: kx, ky
! Fourier space variables
complex(C_DOUBLE_COMPLEX), dimension(Nx/2+1,Ny) :: u_hat_x, out
! indices
integer :: i, j
!---FFTW plans
type(C_PTR) :: pf, pb
! FFTW include
include 'fftw3.f03'
write(*,'(A)') 'Starting...'
! Grid
forall(i=1:Nx,j=1:Ny)
x(i,j) = (i-1)*dx
y(i,j) = (j-1)*dy
end forall
! Compute the wavenumbers
forall(i=1:Nx/2,j=1:Ny) kx(i,j)=2*pi*(i-1)/Lx
kx(Nx/2+1,:) = 0.0
forall(i=1:Nx/2+1,j=1:Ny/2) ky(i,j)=2*pi*(j-1)/Ly
forall(i=1:Nx/2+1,j=Ny/2+1:Ny) ky(i,j)=2*pi*(j-Ny-1)/Ly
! Initial Condition
u0 = sin(2*x)
dudxE = 2*cos(2*x)
! Go to Fourier Space
in = u0
pf = fftw_plan_dft_r2c_2d(Ny, Nx, in,out ,FFTW_ESTIMATE)
call fftw_execute_dft_r2c(pf,in,out)
u_hat_x = out
! Derivative
out = ii*kx*out
! Back to physical space
pb = fftw_plan_dft_c2r_2d(Ny, Nx, out,in,FFTW_ESTIMATE)
call fftw_execute_dft_c2r(pb,out,in)
! rescale
dudx = in/Nx/Ny
! check the derivative
errdU = dudx - dudxE
! Write file
write(*,*) 'Writing to files...'
OPEN(UNIT=1, FILE="out_for.dat", ACTION="write", STATUS="replace", &
FORM="unformatted")
WRITE(1) kx,u0,dudx,errdU,abs(u_hat_x)
CLOSE(UNIT=1)
call fftw_destroy_plan(pf)
call fftw_destroy_plan(pb)
write(*,'(A)') 'Done!'
end program main
steabert was right! the problem was simply with the pi definition which was only single precision! Thank you so much!