I am learning how to call fftw from fortran. My test program is the following:
Program Single_Thread_FFTW
use, intrinsic :: iso_c_binding
implicit none
integer, parameter :: N=16
type (c_ptr) :: plan_forward
integer :: k
complex (kind=8) :: in(N), out(N)
include 'fftw3.f03'
in=(/(sin(3.14159d0*k),k=1,N)/)
print *,in
plan_forward=fftw_plan_dft_1d(N,in,out,FFTW_FORWARD,FFTW_ESTIMATE)
call fftw_execute_dft(plan_forward,in,out)
print *,out
call fftw_destroy_plan(plan_forward)
End Program Single_Thread_FFTW
The first confusion came about because the fftw website suggests all the fftw call should be prefaced with the letter d, as in 'dfftw_plan_dft_1d'. However none of the functions/subroutines in fftw3.f03 (located in /usr/include) have the d prefix. When I try to compile/link with either
gfortran -I/usr/include -o example1 example1.f90 or
gfortran -I/usr/include -L/usr/lib/x86_64-linux-gnu -o example1 example1.f90
the linker throws the errors:
example1.f90:(.text+0xf3): undefined reference to `fftw_plan_dft_1d'
example1.f90:(.text+0x114): undefined reference to `fftw_execute_dft'
example1.f90:(.text+0x1cc): undefined reference to `fftw_destroy_plan'
even though the libraries are in /usr/lib/x86_64-linux-gnu. A separate point is that I would like to lear how to declare double precision complex variables without using the (kind=8) modifier. My compiler (gfortran) doesnt know about double complex.
Related
I am getting the following error while trying to compile a Fortran program with gfortran and FFTW3 library. The program however compiles successfully with the Intel compiler ifort.
Error
Undefined symbols for architecture x86_64:
"__gfortran_os_error_at", referenced from:
_MAIN__ in ccAVlghr.o
ld: symbol(s) not found for architecture x86_64
Compile Command
gfortran -I/usr/local/include -L/usr/local/lib pois.f90 -lfftw3 -lm
pois.f90 is the program which contains FFTW3 commands to solve a Poisson equation through Fourier transform.
The equivalent C program also compiles and executes successfully. The FFTW3 statements are inserted in Poisson.f90 as per FFTW3 documents. The routine which uses FFTW3 commands is given below
subroutine fft_forward(j,f,Fr,Fi)
use, intrinsic :: iso_c_binding
implicit none
include 'fftw3.f03'
double precision :: f(j),Fr(j),Fi(j)
integer :: i,j
type(C_PTR) :: plan
complex(C_DOUBLE_COMPLEX) :: FF(j)
plan = fftw_plan_dft_r2c_1d(j,f,FF,FFTW_ESTIMATE)
call fftw_execute_dft_r2c(plan,f,FF)
call fftw_destroy_plan(plan)
do i = 1,j
Fr(i) = real(FF(i))/j
Fi(i) = aimag(FF(i))/j
enddo
Fr = Fr/j; Fi = Fi/j
end
I also tried using a compiler flag -lgfortran but got the same error. Any suggestion will be of great help.
It probably depends on what you did while installing GNU Fortran, FFTW, et al.
In my case, it works as expected.
I have GNU Fortran installed from sources: gcc-9-2-0
Then, I have built FFTW using my own installation of GNU Fortran
./configure --prefix=$HOME/opt/usr/local/fftw/fftw-3.3.10 CC=gcc-9.2.0 MPICC=mpicc F77=gfortran-9.2.0
make
make install
and then, I have compiled your sample using
gfortran-9.2.0 -I$HOME/opt/usr/local/fftw/fftw-3.3.10/include -L$HOME/opt/usr/local/fftw/fftw-3.3.10/lib -lfftw3 -lm -c simple.f90
I have also added short _main stuff like so to double check it links with the stuff
program main
print *, 'Hello'
end program main
after building, it runs as expected
gfortran-9.2.0 -I$HOME/opt/usr/local/fftw/fftw-3.3.10/include -L$HOME/opt/usr/local/fftw/fftw-3.3.10/lib -lfftw3 -lm simple.f90 -o main
./main
Hello
I guess you have sort of a messy GNU Fortran + FFTW installation.
This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it in Fortran?
(5 answers)
Fortran 90 compiling issue: undefined reference to <modulename>
(1 answer)
Closed 1 year ago.
I am trying to write two simple functions, one which contains the definition of a real function and the other one uses the previous function to find its derivative. However i keep getting the undefined reference error.
my module:
module module_name
contains
function f(x)
implicit none
real(8) :: x
real(8) :: f
f= 2.71**x
endfunction
function f_p_def(x)
implicit none
real(8) :: x, dx, f
real(8) :: f_p_def
dx= 0.1
f_p_def= (f(x+dx)-f(x))/dx
endfunction
endmodule
then in my main program I have this:
program test
use module_name
real(8) :: f1, x
x=0
f1= f_p_def(x)
write(*,*) f1
endprogram
and this is the error:
.\principal.o:principal.f95:(.text+0x27): undefined reference to `__module_name_MOD_f_p_def'
collect2.exe: error: ld returned 1 exit status
Seems like you have your module defined in a separate file. This means that when producing the final executable you must add the object file as well.
EDIT To clarify, you need to compile each source file, producing an object file. Then at the end you link them together. The compiler driver program (gfortran in this case) can run the linker for you automatically.
Separating out all these steps, you need to do something like:
gfortran -O2 -g -fcheck=all -c principal.f95
gfortran -O2 -g -fcheck=all -c module_name.f95
gfortran -O2 -g -fcheck=all principal.o module_name.o -o myprogram
./myprogram
where module_name.f95 is the name of the file where module_name is defined. If not, modify appropriately. In the above, the first two commands compile the source files, producing object files. The third command doesn't actually compile anything, but rather links together your two object files, producing the executable. Then the final command executes the executable.
A simple code:
program main
integer, allocatable :: A(:,:)
integer :: B(3,4)
B=1
A = B !A will get allocated, with the same shape and bounds as B
end program main
Compiling the above code with: gfortran-8 -std=f2008 -fcheck=all -Wall -Wextra -fbounds-check -fimplicit-none array.f90
I got the following warning:
Warning: ‘a.offset’ may be used uninitialized in this function
Warning: ‘a.dim[0].lbound’ may be used uninitialized in this function
Warning: ‘a.dim[0].ubound’ may be used uninitialized in this function [-Wmaybe-uninitialized]
Is there somebody having an idea of why I got these warnings?
This is a well known GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77504 that has been reported in many duplicates to the bugzilla (even by myself) - see the Duplicates section for the other incarnations.
As far as I understand it the actual code generated by the compiler should work correctly and it is just an incorrect warning. As Steve pointed out in the comment, use -Wno-maybe-uninitialized to hide this warning. I have included it into my build scripts as well.
I'm trying to understand how BLAS and LAPACK in Fortran work and so on, so I made a code that generates a matrix and inverts it.
Here's the code
program test
Implicit none
external ZGETRF
external ZGETRI
integer ::M
complex*16,allocatable,dimension(:,:)::A
complex*16,allocatable,dimension(:)::WORK
integer,allocatable,dimension(:)::IPIV
integer i,j,info,error
Print*, 'Enter size of the matrix'
Read*, M
Print*, 'Enter file of the matrix'
READ(*,*), A
OPEN(UNIT=10,FILE = '(/A/)' ,STATUS='OLD',ACTION='READ')
allocate(A(M,M),WORK(M),IPIV(M),stat=error)
if (error.ne.0)then
print *,"error:not enough memory"
stop
end if
!definition of the test matrix A
do i=1,M
do j=1,M
if(j.eq.i)then
A(i,j)=(1,0)
else
A(i,j)=0
end if
end do
end do
call ZGETRF(M,M,A,M,IPIV,info)
if(info .eq. 0) then
write(*,*)"succeded"
else
write(*,*)"failed"
end if
call ZGETRI(M,A,M,IPIV,WORK,M,info)
if(info .eq. 0) then
write(*,*)"succeded"
else
write(*,*)"failed"
end if
deallocate(A,IPIV,WORK,stat=error)
if (error.ne.0)then
print *,"error:fail to release"
stop
end if
close (10)
end program test
The matrix A is in a file, which I'm calling, and also I say the size of the matrix (M ). When I copile them with gfortran I get these message
/tmp/ccVkb1zY.o: In function MAIN__':
test.f03:(.text+0x751): undefined reference tozgetrf_'
test.f03:(.text+0x85d): undefined reference to `zgetri_'
collect2: error: ld returned 1 exit status
I have installed BLAS and LAPACK installed so I don't know if I'm calling in a right way the library.
Any suggestion?
It looks like you might not have linked to the libraries. Try:
gfortran -o test test.f03 -llapack -lblas
This causes the linker (the program which joins all the program parts together; usually called "ld" on UNIX) to include the library code for the LAPACK call (or a dynamic link to it) in your program.
If the result of the above line is "cannot find -llapack" or similar, there are two common problems:
Libraries can be "shared" (names ending ".so") or "static" (names ending ".a"); the linker will look for the shared one, so if you only have the static one you should add "-static" before the library link:
gfortran -o test test.f03 -static -llapack -lblas
This will also make it look for the static version of BLAS; if you need the shared version, add "-shared" in front of the "-lblas":
gfortran -o test test.f03 -static -llapack -shared -lblas
You might find this page helpful.
The linker isn't looking in the right directory for the libraries. You need to locate the actual library (called something like "liblapack.so" or "liblapack.a") and make sure the directory it's in is included in the directories the linker looks in, e.g. to get it to look in "/mylibs/maths" as well:
gfortran -o test test.f03 -L/mylibs/maths -llapack -lblas
How can I multiply two matrices by Lapack package for Fortran? I use gfortran compiler in ubuntu.
My code which doesn't work is:
program main
integer, parameter :: n = 10
double precision :: alpha = 1.0, beta = 0.0
real, dimension(10,10) :: a
do i1 = 1,n
do j1 = 1,n
a(i1,j1) = j1 + (i1-1)*n
end do
end do
call cpu_time(start)
call DGEMM('N', 'N', n, n, n, alpha, a, n, a, n, beta, a, n)
call cpu_time(end)
print *, end - start
end program main
I used:
gfortran 0.f90 -llapack
It returned:
/tmp/ccPy78g5.o: In function `MAIN__':
0.f90:(.text+0x110): undefined reference to `dgemm_'
collect2: ld returned 1 exit status
The error message means, that your compiler (gfortran) cannot find lapack or rather dgemm. Please make sure, that lapack is in your path. Alternatively (I assume you are using Ubuntu Linux) you could try -lblas instead (after installing it, of course - afaik ubuntu follows a different naming convention):
gfortran 0.f90 -lblas -llapack
Edit
Alternatively, you may pass the path to the library directly as an argument. By default, gfortran will look in `/usr/local/lib/``for the specified libraries. If the library is located somewhere else, you may instead use something like
gfortran 0.f90 /path/to/my/library.a